[go: nahoru, domu]

blob: b2392306730d53e2101f7b6bd2430a0f7dcd7e0d [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"
ericrkc7c9e3f2016-07-01 17:30:1615#include "cc/base/histograms.h"
Adrienne Walker436a7752017-08-28 23:33:0916#include "cc/paint/display_item_list.h"
enne5a9630362017-02-24 23:41:0317#include "cc/paint/paint_canvas.h"
Adrienne Walker436a7752017-08-28 23:33:0918#include "cc/paint/paint_recorder.h"
chrishtrac41ff92017-03-17 05:07:3019#include "cc/raster/raster_source.h"
danakj920156852015-05-18 20:22:2920#include "cc/raster/scoped_gpu_raster.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5821#include "cc/resources/resource.h"
ericrk7f6a27f2017-01-31 22:34:3222#include "gpu/command_buffer/client/context_support.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5823#include "gpu/command_buffer/client/gles2_interface.h"
hendrikw04cea972014-09-23 20:50:5324#include "third_party/skia/include/core/SkMultiPictureDraw.h"
25#include "third_party/skia/include/core/SkPictureRecorder.h"
reveman47560ab2014-09-18 19:39:2126#include "third_party/skia/include/core/SkSurface.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5827#include "third_party/skia/include/gpu/GrContext.h"
Adrienne Walker436a7752017-08-28 23:33:0928#include "ui/gfx/geometry/axis_transform2d.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5829
30namespace cc {
reveman47560ab2014-09-18 19:39:2131namespace {
32
Adrienne Walker436a7752017-08-28 23:33:0933// Reuse canvas setup code from RasterSource by storing it into a PaintRecord
34// that can then be transported. This is somewhat more convoluted then it
35// should be.
36static sk_sp<PaintRecord> SetupForRaster(
37 const RasterSource* raster_source,
38 const gfx::Rect& raster_full_rect,
39 const gfx::Rect& playback_rect,
40 const gfx::AxisTransform2d& transform) {
41 PaintRecorder recorder;
42 PaintCanvas* canvas =
43 recorder.beginRecording(gfx::RectToSkRect(raster_full_rect));
44 // TODO(enne): The GLES2Decoder is guaranteeing the clear here, but it
45 // might be nice to figure out how to include the debugging clears for
46 // this mode.
47 canvas->translate(-raster_full_rect.x(), -raster_full_rect.y());
48 canvas->clipRect(SkRect::MakeFromIRect(gfx::RectToSkIRect(playback_rect)));
49 canvas->translate(transform.translation().x(), transform.translation().y());
50 canvas->scale(transform.scale(), transform.scale());
51 return recorder.finishRecordingAsPicture();
52}
53
54static void RasterizeSourceOOP(
55 const RasterSource* raster_source,
56 bool resource_has_previous_content,
57 const gfx::Size& resource_size,
58 const gfx::Rect& raster_full_rect,
59 const gfx::Rect& playback_rect,
60 const gfx::AxisTransform2d& transform,
61 const RasterSource::PlaybackSettings& playback_settings,
62 viz::ContextProvider* context_provider,
63 ResourceProvider::ScopedWriteLockGL* resource_lock,
64 bool use_distance_field_text,
65 int msaa_sample_count) {
66 gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
67 GLuint texture_id = resource_lock->ConsumeTexture(gl);
68
69 auto setup_list = make_scoped_refptr(
70 new DisplayItemList(DisplayItemList::kTopLevelDisplayItemList));
71 setup_list->StartPaint();
72 setup_list->push<DrawRecordOp>(SetupForRaster(raster_source, raster_full_rect,
73 playback_rect, transform));
74 setup_list->EndPaintOfUnpaired(raster_full_rect);
75 setup_list->Finalize();
76
77 // TODO(enne): need to pass color space and transform in the decoder.
78 gl->BeginRasterCHROMIUM(texture_id, raster_source->background_color(),
79 msaa_sample_count, playback_settings.use_lcd_text,
80 use_distance_field_text,
81 resource_lock->PixelConfig());
82 gl->RasterCHROMIUM(setup_list.get(), playback_rect.x(), playback_rect.y(),
83 playback_rect.width(), playback_rect.height());
84 gl->RasterCHROMIUM(raster_source->display_list(), playback_rect.x(),
85 playback_rect.y(), playback_rect.width(),
86 playback_rect.height());
87 gl->EndRasterCHROMIUM();
88
89 gl->DeleteTextures(1, &texture_id);
90}
91
vmiuraf7c765c2016-12-03 21:02:3292static void RasterizeSource(
sunnyps5d6ff0d02016-06-28 00:40:1193 const RasterSource* raster_source,
94 bool resource_has_previous_content,
95 const gfx::Size& resource_size,
96 const gfx::Rect& raster_full_rect,
Adrienne Walker436a7752017-08-28 23:33:0997 const gfx::Rect& playback_rect,
trchen178ac912017-04-04 10:11:1098 const gfx::AxisTransform2d& transform,
vmiuraf7c765c2016-12-03 21:02:3299 const RasterSource::PlaybackSettings& playback_settings,
Xu Xing32549162017-07-17 22:25:43100 viz::ContextProvider* context_provider,
vmiuraf7c765c2016-12-03 21:02:32101 ResourceProvider::ScopedWriteLockGL* resource_lock,
vmiuraf7c765c2016-12-03 21:02:32102 bool use_distance_field_text,
103 int msaa_sample_count) {
104 ScopedGpuRaster gpu_raster(context_provider);
sunnyps5d6ff0d02016-06-28 00:40:11105
Sunny Sachanandani0cb875e2017-08-15 02:54:52106 gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
107 GLuint texture_id = resource_lock->ConsumeTexture(gl);
108
109 {
110 ResourceProvider::ScopedSkSurface scoped_surface(
111 context_provider->GrContext(), texture_id, resource_lock->target(),
112 resource_lock->size(), resource_lock->format(), use_distance_field_text,
113 playback_settings.use_lcd_text, msaa_sample_count);
114
115 SkSurface* surface = scoped_surface.surface();
116
117 // Allocating an SkSurface will fail after a lost context. Pretend we
118 // rasterized, as the contents of the resource don't matter anymore.
119 if (!surface) {
120 DLOG(ERROR) << "Failed to allocate raster surface";
121 return;
122 }
123
Sunny Sachanandani0cb875e2017-08-15 02:54:52124 SkCanvas* canvas = surface->getCanvas();
125
126 // As an optimization, inform Skia to discard when not doing partial raster.
127 if (raster_full_rect == playback_rect)
128 canvas->discard();
129
130 raster_source->PlaybackToCanvas(
131 canvas, resource_lock->color_space_for_raster(), raster_full_rect,
132 playback_rect, transform, playback_settings);
ccameron220942362017-02-06 20:29:19133 }
vmiuraf7c765c2016-12-03 21:02:32134
Sunny Sachanandani0cb875e2017-08-15 02:54:52135 gl->DeleteTextures(1, &texture_id);
sunnyps5d6ff0d02016-06-28 00:40:11136}
reveman47560ab2014-09-18 19:39:21137
138} // namespace
vmiura78b69282015-02-14 00:01:17139
sunnyps5d6ff0d02016-06-28 00:40:11140GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
141 GpuRasterBufferProvider* client,
Xu Xingb57edf32017-08-22 04:18:47142 LayerTreeResourceProvider* resource_provider,
Fady Samuelc80a4a862017-07-28 10:23:36143 viz::ResourceId resource_id,
sunnyps5d6ff0d02016-06-28 00:40:11144 bool resource_has_previous_content)
145 : client_(client),
Sunny Sachanandani0cb875e2017-08-15 02:54:52146 lock_(resource_provider, resource_id),
sunnyps5d6ff0d02016-06-28 00:40:11147 resource_has_previous_content_(resource_has_previous_content) {
148 client_->pending_raster_buffers_.insert(this);
Sunny Sachanandani0cb875e2017-08-15 02:54:52149 lock_.CreateMailbox();
sunnyps5d6ff0d02016-06-28 00:40:11150}
151
152GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
153 client_->pending_raster_buffers_.erase(this);
154}
155
156void GpuRasterBufferProvider::RasterBufferImpl::Playback(
157 const RasterSource* raster_source,
158 const gfx::Rect& raster_full_rect,
159 const gfx::Rect& raster_dirty_rect,
160 uint64_t new_content_id,
trchen178ac912017-04-04 10:11:10161 const gfx::AxisTransform2d& transform,
sunnyps5d6ff0d02016-06-28 00:40:11162 const RasterSource::PlaybackSettings& playback_settings) {
163 TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
164 client_->PlaybackOnWorkerThread(&lock_, sync_token_,
165 resource_has_previous_content_, raster_source,
166 raster_full_rect, raster_dirty_rect,
trchen178ac912017-04-04 10:11:10167 new_content_id, transform, playback_settings);
sunnyps5d6ff0d02016-06-28 00:40:11168}
169
prashant.nb4d4f492016-04-29 12:51:28170GpuRasterBufferProvider::GpuRasterBufferProvider(
Xu Xing32549162017-07-17 22:25:43171 viz::ContextProvider* compositor_context_provider,
172 viz::ContextProvider* worker_context_provider,
Xu Xingb57edf32017-08-22 04:18:47173 LayerTreeResourceProvider* resource_provider,
hendrikw59d449482015-04-04 00:44:32174 bool use_distance_field_text,
sunnyps5d6ff0d02016-06-28 00:40:11175 int gpu_rasterization_msaa_sample_count,
Fady Samuel555c8d12017-07-07 23:14:09176 viz::ResourceFormat preferred_tile_format,
Adrienne Walker436a7752017-08-28 23:33:09177 bool async_worker_context_enabled,
178 bool enable_oop_rasterization)
danakj0de0c95a2016-05-25 01:42:49179 : compositor_context_provider_(compositor_context_provider),
sunnyps5d6ff0d02016-06-28 00:40:11180 worker_context_provider_(worker_context_provider),
181 resource_provider_(resource_provider),
182 use_distance_field_text_(use_distance_field_text),
183 msaa_sample_count_(gpu_rasterization_msaa_sample_count),
ericrkd03c005d2017-03-24 18:48:52184 preferred_tile_format_(preferred_tile_format),
Adrienne Walker436a7752017-08-28 23:33:09185 async_worker_context_enabled_(async_worker_context_enabled),
186 enable_oop_rasterization_(enable_oop_rasterization) {
sunnyps5d6ff0d02016-06-28 00:40:11187 DCHECK(compositor_context_provider);
188 DCHECK(worker_context_provider);
danakj0de0c95a2016-05-25 01:42:49189}
reveman@chromium.orgb5641b92014-02-15 14:21:58190
sunnyps5d6ff0d02016-06-28 00:40:11191GpuRasterBufferProvider::~GpuRasterBufferProvider() {
192 DCHECK(pending_raster_buffers_.empty());
193}
reveman@chromium.orgb5641b92014-02-15 14:21:58194
prashant.nb4d4f492016-04-29 12:51:28195std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster(
danakje0b54782015-05-29 22:47:52196 const Resource* resource,
danakj510822aa2015-06-01 20:23:02197 uint64_t resource_content_id,
danakje0b54782015-05-29 22:47:52198 uint64_t previous_content_id) {
sunnyps5d6ff0d02016-06-28 00:40:11199 bool resource_has_previous_content =
200 resource_content_id && resource_content_id == previous_content_id;
Jeremy Roman909d927b2017-08-27 18:34:09201 return std::make_unique<RasterBufferImpl>(
Sunny Sachanandani0cb875e2017-08-15 02:54:52202 this, resource_provider_, resource->id(), resource_has_previous_content);
reveman@chromium.orgb5641b92014-02-15 14:21:58203}
204
prashant.nb4d4f492016-04-29 12:51:28205void GpuRasterBufferProvider::ReleaseBufferForRaster(
danakj60bc3bc2016-04-09 00:24:48206 std::unique_ptr<RasterBuffer> buffer) {
reveman47560ab2014-09-18 19:39:21207 // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
reveman@chromium.orgb5641b92014-02-15 14:21:58208}
209
sunnyps12074d3d2016-06-21 01:57:48210void GpuRasterBufferProvider::OrderingBarrier() {
prashant.nb4d4f492016-04-29 12:51:28211 TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier");
sunnyps5d6ff0d02016-06-28 00:40:11212
213 gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
214 if (async_worker_context_enabled_) {
Sunny Sachanandani0cb875e2017-08-15 02:54:52215 gpu::SyncToken sync_token = ResourceProvider::GenerateSyncTokenHelper(gl);
sunnyps5d6ff0d02016-06-28 00:40:11216 for (RasterBufferImpl* buffer : pending_raster_buffers_)
217 buffer->set_sync_token(sync_token);
218 } else {
219 gl->OrderingBarrierCHROMIUM();
220 }
221 pending_raster_buffers_.clear();
prashant.nb4d4f492016-04-29 12:51:28222}
223
Sunny Sachanandani5f5419e22017-05-12 20:35:30224void GpuRasterBufferProvider::Flush() {
Sunny Sachanandani9b8fb342017-08-26 00:49:56225 if (async_worker_context_enabled_)
226 compositor_context_provider_->ContextSupport()->FlushPendingWork();
Sunny Sachanandani5f5419e22017-05-12 20:35:30227}
228
Fady Samuel555c8d12017-07-07 23:14:09229viz::ResourceFormat GpuRasterBufferProvider::GetResourceFormat(
prashant.nb4d4f492016-04-29 12:51:28230 bool must_support_alpha) const {
ericrkd03c005d2017-03-24 18:48:52231 if (resource_provider_->IsRenderBufferFormatSupported(
232 preferred_tile_format_) &&
233 (DoesResourceFormatSupportAlpha(preferred_tile_format_) ||
234 !must_support_alpha)) {
235 return preferred_tile_format_;
236 }
237
sunnyps5d6ff0d02016-06-28 00:40:11238 return resource_provider_->best_render_buffer_format();
prashant.nb4d4f492016-04-29 12:51:28239}
240
ericrkeeda58992016-07-07 02:34:27241bool GpuRasterBufferProvider::IsResourceSwizzleRequired(
prashant.nb4d4f492016-04-29 12:51:28242 bool must_support_alpha) const {
243 // This doesn't require a swizzle because we rasterize to the correct format.
244 return false;
245}
246
ericrk5ac42f322016-07-14 01:06:51247bool GpuRasterBufferProvider::CanPartialRasterIntoProvidedResource() const {
ericrkc9ed0832016-07-20 19:42:50248 // Partial raster doesn't support MSAA, as the MSAA resolve is unaware of clip
249 // rects.
250 // TODO(crbug.com/629683): See if we can work around this limitation.
251 return msaa_sample_count_ == 0;
ericrkeeda58992016-07-07 02:34:27252}
253
ericrk7f6a27f2017-01-31 22:34:32254bool GpuRasterBufferProvider::IsResourceReadyToDraw(
Fady Samuelc80a4a862017-07-28 10:23:36255 viz::ResourceId resource_id) const {
ericrk7f6a27f2017-01-31 22:34:32256 if (!async_worker_context_enabled_)
257 return true;
258
ericrk7f6a27f2017-01-31 22:34:32259 gpu::SyncToken sync_token =
ericrk6d7564a2017-02-02 23:55:58260 resource_provider_->GetSyncTokenForResources({resource_id});
ericrk7f6a27f2017-01-31 22:34:32261 if (!sync_token.HasData())
262 return true;
263
sunnyps74996292017-03-15 02:35:48264 // IsSyncTokenSignaled is thread-safe, no need for worker context lock.
265 return worker_context_provider_->ContextSupport()->IsSyncTokenSignaled(
ericrk7f6a27f2017-01-31 22:34:32266 sync_token);
267}
268
269uint64_t GpuRasterBufferProvider::SetReadyToDrawCallback(
270 const ResourceProvider::ResourceIdArray& resource_ids,
271 const base::Closure& callback,
272 uint64_t pending_callback_id) const {
273 if (!async_worker_context_enabled_)
274 return 0;
275
276 gpu::SyncToken sync_token =
277 resource_provider_->GetSyncTokenForResources(resource_ids);
278 uint64_t callback_id = sync_token.release_count();
279 DCHECK_NE(callback_id, 0u);
280
281 // If the callback is different from the one the caller is already waiting on,
sunnyps31c92fe2017-02-10 23:46:55282 // pass the callback through to SignalSyncToken. Otherwise the request is
ericrk7f6a27f2017-01-31 22:34:32283 // redundant.
284 if (callback_id != pending_callback_id) {
sunnyps31c92fe2017-02-10 23:46:55285 // Use the compositor context because we want this callback on the impl
286 // thread.
287 compositor_context_provider_->ContextSupport()->SignalSyncToken(sync_token,
288 callback);
ericrk7f6a27f2017-01-31 22:34:32289 }
290
291 return callback_id;
292}
293
sunnyps5d6ff0d02016-06-28 00:40:11294void GpuRasterBufferProvider::Shutdown() {
295 pending_raster_buffers_.clear();
296}
297
298void GpuRasterBufferProvider::PlaybackOnWorkerThread(
299 ResourceProvider::ScopedWriteLockGL* resource_lock,
300 const gpu::SyncToken& sync_token,
301 bool resource_has_previous_content,
302 const RasterSource* raster_source,
303 const gfx::Rect& raster_full_rect,
304 const gfx::Rect& raster_dirty_rect,
305 uint64_t new_content_id,
trchen178ac912017-04-04 10:11:10306 const gfx::AxisTransform2d& transform,
sunnyps5d6ff0d02016-06-28 00:40:11307 const RasterSource::PlaybackSettings& playback_settings) {
Xu Xing32549162017-07-17 22:25:43308 viz::ContextProvider::ScopedContextLock scoped_context(
309 worker_context_provider_);
sunnyps5d6ff0d02016-06-28 00:40:11310 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
311 DCHECK(gl);
312
Sunny Sachanandani0cb875e2017-08-15 02:54:52313 // Synchronize with compositor. Nop if sync token is empty.
314 gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
sunnyps5d6ff0d02016-06-28 00:40:11315
Adrienne Walker436a7752017-08-28 23:33:09316 gfx::Rect playback_rect = raster_full_rect;
317 if (resource_has_previous_content) {
318 playback_rect.Intersect(raster_dirty_rect);
319 }
320 DCHECK(!playback_rect.IsEmpty())
321 << "Why are we rastering a tile that's not dirty?";
322
323 // Log a histogram of the percentage of pixels that were saved due to
324 // partial raster.
325 const char* client_name = GetClientNameForMetrics();
326 float full_rect_size = raster_full_rect.size().GetArea();
327 if (full_rect_size > 0 && client_name) {
328 float fraction_partial_rastered =
329 static_cast<float>(playback_rect.size().GetArea()) / full_rect_size;
330 float fraction_saved = 1.0f - fraction_partial_rastered;
331 UMA_HISTOGRAM_PERCENTAGE(
332 base::StringPrintf("Renderer4.%s.PartialRasterPercentageSaved.Gpu",
333 client_name),
334 100.0f * fraction_saved);
335 }
336
337 if (enable_oop_rasterization_) {
338 RasterizeSourceOOP(raster_source, resource_has_previous_content,
339 resource_lock->size(), raster_full_rect, playback_rect,
340 transform, playback_settings, worker_context_provider_,
341 resource_lock, use_distance_field_text_,
342 msaa_sample_count_);
343 } else {
344 RasterizeSource(raster_source, resource_has_previous_content,
345 resource_lock->size(), raster_full_rect, playback_rect,
346 transform, playback_settings, worker_context_provider_,
347 resource_lock, use_distance_field_text_,
348 msaa_sample_count_);
349 }
sunnyps5d6ff0d02016-06-28 00:40:11350
Sunny Sachanandani0cb875e2017-08-15 02:54:52351 // Generate sync token for cross context synchronization.
352 resource_lock->set_sync_token(ResourceProvider::GenerateSyncTokenHelper(gl));
sunnyps5d6ff0d02016-06-28 00:40:11353
Sunny Sachanandani0cb875e2017-08-15 02:54:52354 // Mark resource as synchronized when worker and compositor are in same stream
355 // to prevent extra wait sync token calls.
356 if (!async_worker_context_enabled_)
357 resource_lock->set_synchronized();
sunnyps5d6ff0d02016-06-28 00:40:11358}
prashant.nb4d4f492016-04-29 12:51:28359
reveman@chromium.orgb5641b92014-02-15 14:21:58360} // namespace cc