[go: nahoru, domu]

blob: 120b8879d593a2b43d7a6b28087f928f8fd77dac [file] [log] [blame]
reveman@chromium.orgb5641b92014-02-15 14:21:581// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
prashant.nb4d4f492016-04-29 12:51:285#include "cc/raster/gpu_raster_buffer_provider.h"
reveman@chromium.orgb5641b92014-02-15 14:21:586
avi02a4d172015-12-21 06:14:367#include <stdint.h>
8
ernstm69fedbd2014-09-18 01:23:419#include <algorithm>
10
avi02a4d172015-12-21 06:14:3611#include "base/macros.h"
danakj60bc3bc2016-04-09 00:24:4812#include "base/memory/ptr_util.h"
ericrke4027312016-06-30 00:12:4213#include "base/metrics/histogram_macros.h"
ssid904ce3b2015-01-27 15:20:1614#include "base/trace_event/trace_event.h"
vmpstr41d68f82016-03-30 01:20:2315#include "cc/playback/raster_source.h"
danakj920156852015-05-18 20:22:2916#include "cc/raster/scoped_gpu_raster.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5817#include "cc/resources/resource.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5818#include "gpu/command_buffer/client/gles2_interface.h"
hendrikw04cea972014-09-23 20:50:5319#include "third_party/skia/include/core/SkMultiPictureDraw.h"
20#include "third_party/skia/include/core/SkPictureRecorder.h"
reveman47560ab2014-09-18 19:39:2121#include "third_party/skia/include/core/SkSurface.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5822#include "third_party/skia/include/gpu/GrContext.h"
23
24namespace cc {
reveman47560ab2014-09-18 19:39:2125namespace {
26
sunnyps5d6ff0d02016-06-28 00:40:1127static sk_sp<SkPicture> PlaybackToPicture(
28 const RasterSource* raster_source,
29 bool resource_has_previous_content,
30 const gfx::Size& resource_size,
31 const gfx::Rect& raster_full_rect,
32 const gfx::Rect& raster_dirty_rect,
33 float scale,
34 const RasterSource::PlaybackSettings& playback_settings) {
35 // GPU raster doesn't do low res tiles, so should always include images.
36 DCHECK(!playback_settings.skip_images);
37
38 gfx::Rect playback_rect = raster_full_rect;
39 if (resource_has_previous_content) {
40 playback_rect.Intersect(raster_dirty_rect);
danakj05d69002015-06-02 01:42:2041 }
sunnyps5d6ff0d02016-06-28 00:40:1142 DCHECK(!playback_rect.IsEmpty())
43 << "Why are we rastering a tile that's not dirty?";
reveman47560ab2014-09-18 19:39:2144
ericrke4027312016-06-30 00:12:4245 // Log a histogram of the percentage of pixels that were saved due to
46 // partial raster.
47 float full_rect_size = raster_full_rect.size().GetArea();
48 if (full_rect_size > 0) {
49 float fraction_partial_rastered =
50 static_cast<float>(playback_rect.size().GetArea()) / full_rect_size;
51 float fraction_saved = 1.0f - fraction_partial_rastered;
52
53 UMA_HISTOGRAM_PERCENTAGE("Renderer4.PartialRasterPercentageSaved.Gpu",
54 100.0f * fraction_saved);
55 }
56
sunnyps5d6ff0d02016-06-28 00:40:1157 // Play back raster_source into temp SkPicture.
58 SkPictureRecorder recorder;
59 const int flags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
60 sk_sp<SkCanvas> canvas = sk_ref_sp(recorder.beginRecording(
61 resource_size.width(), resource_size.height(), NULL, flags));
62 canvas->save();
63 raster_source->PlaybackToCanvas(canvas.get(), raster_full_rect, playback_rect,
64 scale, playback_settings);
65 canvas->restore();
66 return recorder.finishRecordingAsPicture();
67}
vmiura78b69282015-02-14 00:01:1768
sunnyps5d6ff0d02016-06-28 00:40:1169static void RasterizePicture(SkPicture* picture,
70 ContextProvider* context_provider,
71 ResourceProvider::ScopedWriteLockGL* resource_lock,
72 bool async_worker_context_enabled,
73 bool use_distance_field_text,
74 bool can_use_lcd_text,
75 int msaa_sample_count) {
76 ScopedGpuRaster gpu_raster(context_provider);
vmiura78b69282015-02-14 00:01:1777
sunnyps5d6ff0d02016-06-28 00:40:1178 ResourceProvider::ScopedSkSurfaceProvider scoped_surface(
79 context_provider, resource_lock, async_worker_context_enabled,
80 use_distance_field_text, can_use_lcd_text, msaa_sample_count);
81 SkSurface* sk_surface = scoped_surface.sk_surface();
82 // Allocating an SkSurface will fail after a lost context. Pretend we
83 // rasterized, as the contents of the resource don't matter anymore.
84 if (!sk_surface)
85 return;
danakj05d69002015-06-02 01:42:2086
sunnyps5d6ff0d02016-06-28 00:40:1187 SkMultiPictureDraw multi_picture_draw;
88 multi_picture_draw.add(sk_surface->getCanvas(), picture);
89 multi_picture_draw.draw(false);
90}
reveman47560ab2014-09-18 19:39:2191
92} // namespace
sunnyps5d6ff0d02016-06-28 00:40:1193
94GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
95 GpuRasterBufferProvider* client,
96 ResourceProvider* resource_provider,
97 ResourceId resource_id,
98 bool async_worker_context_enabled,
99 bool resource_has_previous_content)
100 : client_(client),
101 lock_(resource_provider, resource_id, async_worker_context_enabled),
102 resource_has_previous_content_(resource_has_previous_content) {
103 client_->pending_raster_buffers_.insert(this);
104}
105
106GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
107 client_->pending_raster_buffers_.erase(this);
108}
109
110void GpuRasterBufferProvider::RasterBufferImpl::Playback(
111 const RasterSource* raster_source,
112 const gfx::Rect& raster_full_rect,
113 const gfx::Rect& raster_dirty_rect,
114 uint64_t new_content_id,
115 float scale,
116 const RasterSource::PlaybackSettings& playback_settings) {
117 TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
118 client_->PlaybackOnWorkerThread(&lock_, sync_token_,
119 resource_has_previous_content_, raster_source,
120 raster_full_rect, raster_dirty_rect,
121 new_content_id, scale, playback_settings);
122}
vmiura78b69282015-02-14 00:01:17123
prashant.nb4d4f492016-04-29 12:51:28124GpuRasterBufferProvider::GpuRasterBufferProvider(
danakj0de0c95a2016-05-25 01:42:49125 ContextProvider* compositor_context_provider,
126 ContextProvider* worker_context_provider,
hendrikw59d449482015-04-04 00:44:32127 ResourceProvider* resource_provider,
128 bool use_distance_field_text,
sunnyps5d6ff0d02016-06-28 00:40:11129 int gpu_rasterization_msaa_sample_count,
130 bool async_worker_context_enabled)
danakj0de0c95a2016-05-25 01:42:49131 : compositor_context_provider_(compositor_context_provider),
sunnyps5d6ff0d02016-06-28 00:40:11132 worker_context_provider_(worker_context_provider),
133 resource_provider_(resource_provider),
134 use_distance_field_text_(use_distance_field_text),
135 msaa_sample_count_(gpu_rasterization_msaa_sample_count),
136 async_worker_context_enabled_(async_worker_context_enabled) {
137 DCHECK(compositor_context_provider);
138 DCHECK(worker_context_provider);
danakj0de0c95a2016-05-25 01:42:49139}
reveman@chromium.orgb5641b92014-02-15 14:21:58140
sunnyps5d6ff0d02016-06-28 00:40:11141GpuRasterBufferProvider::~GpuRasterBufferProvider() {
142 DCHECK(pending_raster_buffers_.empty());
143}
reveman@chromium.orgec7541d2014-04-09 01:23:53144
prashant.nb4d4f492016-04-29 12:51:28145std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster(
danakje0b54782015-05-29 22:47:52146 const Resource* resource,
danakj510822aa2015-06-01 20:23:02147 uint64_t resource_content_id,
danakje0b54782015-05-29 22:47:52148 uint64_t previous_content_id) {
sunnyps5d6ff0d02016-06-28 00:40:11149 bool resource_has_previous_content =
150 resource_content_id && resource_content_id == previous_content_id;
151 return base::WrapUnique(new RasterBufferImpl(
152 this, resource_provider_, resource->id(), async_worker_context_enabled_,
153 resource_has_previous_content));
reveman@chromium.orgb5641b92014-02-15 14:21:58154}
155
prashant.nb4d4f492016-04-29 12:51:28156void GpuRasterBufferProvider::ReleaseBufferForRaster(
danakj60bc3bc2016-04-09 00:24:48157 std::unique_ptr<RasterBuffer> buffer) {
reveman47560ab2014-09-18 19:39:21158 // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
reveman@chromium.orgb5641b92014-02-15 14:21:58159}
160
sunnyps12074d3d2016-06-21 01:57:48161void GpuRasterBufferProvider::OrderingBarrier() {
prashant.nb4d4f492016-04-29 12:51:28162 TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier");
sunnyps5d6ff0d02016-06-28 00:40:11163
164 gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
165 if (async_worker_context_enabled_) {
166 GLuint64 fence = gl->InsertFenceSyncCHROMIUM();
167 gl->OrderingBarrierCHROMIUM();
168
169 gpu::SyncToken sync_token;
170 gl->GenUnverifiedSyncTokenCHROMIUM(fence, sync_token.GetData());
171
172 DCHECK(sync_token.HasData() ||
173 gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
174
175 for (RasterBufferImpl* buffer : pending_raster_buffers_)
176 buffer->set_sync_token(sync_token);
177 } else {
178 gl->OrderingBarrierCHROMIUM();
179 }
180 pending_raster_buffers_.clear();
prashant.nb4d4f492016-04-29 12:51:28181}
182
183ResourceFormat GpuRasterBufferProvider::GetResourceFormat(
184 bool must_support_alpha) const {
sunnyps5d6ff0d02016-06-28 00:40:11185 return resource_provider_->best_render_buffer_format();
prashant.nb4d4f492016-04-29 12:51:28186}
187
188bool GpuRasterBufferProvider::GetResourceRequiresSwizzle(
189 bool must_support_alpha) const {
190 // This doesn't require a swizzle because we rasterize to the correct format.
191 return false;
192}
193
sunnyps5d6ff0d02016-06-28 00:40:11194void GpuRasterBufferProvider::Shutdown() {
195 pending_raster_buffers_.clear();
196}
197
198void GpuRasterBufferProvider::PlaybackOnWorkerThread(
199 ResourceProvider::ScopedWriteLockGL* resource_lock,
200 const gpu::SyncToken& sync_token,
201 bool resource_has_previous_content,
202 const RasterSource* raster_source,
203 const gfx::Rect& raster_full_rect,
204 const gfx::Rect& raster_dirty_rect,
205 uint64_t new_content_id,
206 float scale,
207 const RasterSource::PlaybackSettings& playback_settings) {
208 ContextProvider::ScopedContextLock scoped_context(worker_context_provider_);
209 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
210 DCHECK(gl);
211
212 if (async_worker_context_enabled_) {
213 // Early out if sync token is invalid. This happens if the compositor
214 // context was lost before ScheduleTasks was called.
215 if (!sync_token.HasData())
216 return;
217 // Synchronize with compositor.
218 gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
219 }
220
221 sk_sp<SkPicture> picture = PlaybackToPicture(
222 raster_source, resource_has_previous_content, resource_lock->size(),
223 raster_full_rect, raster_dirty_rect, scale, playback_settings);
224
225 // Turn on distance fields for layers that have ever animated.
226 bool use_distance_field_text =
227 use_distance_field_text_ ||
228 raster_source->ShouldAttemptToUseDistanceFieldText();
229
230 RasterizePicture(picture.get(), worker_context_provider_, resource_lock,
231 async_worker_context_enabled_, use_distance_field_text,
232 raster_source->CanUseLCDText(), msaa_sample_count_);
233
234 const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
235
236 // Barrier to sync worker context output to cc context.
237 gl->OrderingBarrierCHROMIUM();
238
239 // Generate sync token after the barrier for cross context synchronization.
240 gpu::SyncToken resource_sync_token;
241 gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, resource_sync_token.GetData());
242 resource_lock->set_sync_token(resource_sync_token);
243 resource_lock->set_synchronized(!async_worker_context_enabled_);
244}
prashant.nb4d4f492016-04-29 12:51:28245
reveman@chromium.orgb5641b92014-02-15 14:21:58246} // namespace cc