[go: nahoru, domu]

blob: f1d915e92153c5be62201a7a025d88414cdb4593 [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"
Victor Miura3a4ad4f82017-12-13 06:03:4524#include "gpu/command_buffer/client/raster_interface.h"
hendrikw04cea972014-09-23 20:50:5325#include "third_party/skia/include/core/SkMultiPictureDraw.h"
26#include "third_party/skia/include/core/SkPictureRecorder.h"
reveman47560ab2014-09-18 19:39:2127#include "third_party/skia/include/core/SkSurface.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5828#include "third_party/skia/include/gpu/GrContext.h"
Adrienne Walker436a7752017-08-28 23:33:0929#include "ui/gfx/geometry/axis_transform2d.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5830
31namespace cc {
reveman47560ab2014-09-18 19:39:2132namespace {
33
Adrienne Walker436a7752017-08-28 23:33:0934static void RasterizeSourceOOP(
35 const RasterSource* raster_source,
36 bool resource_has_previous_content,
37 const gfx::Size& resource_size,
38 const gfx::Rect& raster_full_rect,
39 const gfx::Rect& playback_rect,
40 const gfx::AxisTransform2d& transform,
41 const RasterSource::PlaybackSettings& playback_settings,
42 viz::ContextProvider* context_provider,
Victor Miura3a4ad4f82017-12-13 06:03:4543 ResourceProvider::ScopedWriteLockRaster* resource_lock,
Adrienne Walker436a7752017-08-28 23:33:0944 bool use_distance_field_text,
45 int msaa_sample_count) {
Victor Miura3a4ad4f82017-12-13 06:03:4546 gpu::raster::RasterInterface* ri = context_provider->RasterContext();
47 GLuint texture_id = resource_lock->ConsumeTexture(ri);
Adrienne Walker436a7752017-08-28 23:33:0948
Victor Miura3a4ad4f82017-12-13 06:03:4549 ri->BeginRasterCHROMIUM(texture_id, raster_source->background_color(),
Adrienne Walker436a7752017-08-28 23:33:0950 msaa_sample_count, playback_settings.use_lcd_text,
51 use_distance_field_text,
52 resource_lock->PixelConfig());
Adrienne Walkerbc5cd82e2017-10-31 21:58:1553 // TODO(enne): need to pass color space into this function as well.
54 float recording_to_raster_scale =
55 transform.scale() / raster_source->recording_scale_factor();
Victor Miura3a4ad4f82017-12-13 06:03:4556 ri->RasterCHROMIUM(raster_source->GetDisplayItemList().get(),
Adrienne Walkerbc5cd82e2017-10-31 21:58:1557 raster_full_rect.x(), raster_full_rect.y(),
danakjb075024f2017-09-08 17:45:4158 playback_rect.x(), playback_rect.y(),
Adrienne Walkerbc5cd82e2017-10-31 21:58:1559 playback_rect.width(), playback_rect.height(),
60 transform.translation().x(), transform.translation().y(),
61 recording_to_raster_scale);
Victor Miura3a4ad4f82017-12-13 06:03:4562 ri->EndRasterCHROMIUM();
Adrienne Walker436a7752017-08-28 23:33:0963
Victor Miura3a4ad4f82017-12-13 06:03:4564 ri->DeleteTextures(1, &texture_id);
Adrienne Walker436a7752017-08-28 23:33:0965}
66
vmiuraf7c765c2016-12-03 21:02:3267static void RasterizeSource(
sunnyps5d6ff0d02016-06-28 00:40:1168 const RasterSource* raster_source,
69 bool resource_has_previous_content,
70 const gfx::Size& resource_size,
71 const gfx::Rect& raster_full_rect,
Adrienne Walker436a7752017-08-28 23:33:0972 const gfx::Rect& playback_rect,
trchen178ac912017-04-04 10:11:1073 const gfx::AxisTransform2d& transform,
vmiuraf7c765c2016-12-03 21:02:3274 const RasterSource::PlaybackSettings& playback_settings,
Xu Xing32549162017-07-17 22:25:4375 viz::ContextProvider* context_provider,
Victor Miura3a4ad4f82017-12-13 06:03:4576 ResourceProvider::ScopedWriteLockRaster* resource_lock,
vmiuraf7c765c2016-12-03 21:02:3277 bool use_distance_field_text,
78 int msaa_sample_count) {
79 ScopedGpuRaster gpu_raster(context_provider);
sunnyps5d6ff0d02016-06-28 00:40:1180
Victor Miura3a4ad4f82017-12-13 06:03:4581 gpu::raster::RasterInterface* ri = context_provider->RasterContext();
82 GLuint texture_id = resource_lock->ConsumeTexture(ri);
Sunny Sachanandani0cb875e2017-08-15 02:54:5283
84 {
85 ResourceProvider::ScopedSkSurface scoped_surface(
86 context_provider->GrContext(), texture_id, resource_lock->target(),
87 resource_lock->size(), resource_lock->format(), use_distance_field_text,
88 playback_settings.use_lcd_text, msaa_sample_count);
89
90 SkSurface* surface = scoped_surface.surface();
91
92 // Allocating an SkSurface will fail after a lost context. Pretend we
93 // rasterized, as the contents of the resource don't matter anymore.
94 if (!surface) {
95 DLOG(ERROR) << "Failed to allocate raster surface";
96 return;
97 }
98
Sunny Sachanandani0cb875e2017-08-15 02:54:5299 SkCanvas* canvas = surface->getCanvas();
100
101 // As an optimization, inform Skia to discard when not doing partial raster.
102 if (raster_full_rect == playback_rect)
103 canvas->discard();
104
105 raster_source->PlaybackToCanvas(
106 canvas, resource_lock->color_space_for_raster(), raster_full_rect,
107 playback_rect, transform, playback_settings);
ccameron220942362017-02-06 20:29:19108 }
vmiuraf7c765c2016-12-03 21:02:32109
Victor Miura3a4ad4f82017-12-13 06:03:45110 ri->DeleteTextures(1, &texture_id);
sunnyps5d6ff0d02016-06-28 00:40:11111}
reveman47560ab2014-09-18 19:39:21112
113} // namespace
vmiura78b69282015-02-14 00:01:17114
sunnyps5d6ff0d02016-06-28 00:40:11115GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
116 GpuRasterBufferProvider* client,
Xu Xingb57edf32017-08-22 04:18:47117 LayerTreeResourceProvider* resource_provider,
Fady Samuelc80a4a862017-07-28 10:23:36118 viz::ResourceId resource_id,
sunnyps5d6ff0d02016-06-28 00:40:11119 bool resource_has_previous_content)
120 : client_(client),
Sunny Sachanandani0cb875e2017-08-15 02:54:52121 lock_(resource_provider, resource_id),
sunnyps5d6ff0d02016-06-28 00:40:11122 resource_has_previous_content_(resource_has_previous_content) {
123 client_->pending_raster_buffers_.insert(this);
Sunny Sachanandani0cb875e2017-08-15 02:54:52124 lock_.CreateMailbox();
sunnyps5d6ff0d02016-06-28 00:40:11125}
126
127GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
128 client_->pending_raster_buffers_.erase(this);
129}
130
131void GpuRasterBufferProvider::RasterBufferImpl::Playback(
132 const RasterSource* raster_source,
133 const gfx::Rect& raster_full_rect,
134 const gfx::Rect& raster_dirty_rect,
135 uint64_t new_content_id,
trchen178ac912017-04-04 10:11:10136 const gfx::AxisTransform2d& transform,
sunnyps5d6ff0d02016-06-28 00:40:11137 const RasterSource::PlaybackSettings& playback_settings) {
138 TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
139 client_->PlaybackOnWorkerThread(&lock_, sync_token_,
140 resource_has_previous_content_, raster_source,
141 raster_full_rect, raster_dirty_rect,
trchen178ac912017-04-04 10:11:10142 new_content_id, transform, playback_settings);
sunnyps5d6ff0d02016-06-28 00:40:11143}
144
prashant.nb4d4f492016-04-29 12:51:28145GpuRasterBufferProvider::GpuRasterBufferProvider(
Xu Xing32549162017-07-17 22:25:43146 viz::ContextProvider* compositor_context_provider,
147 viz::ContextProvider* worker_context_provider,
Xu Xingb57edf32017-08-22 04:18:47148 LayerTreeResourceProvider* resource_provider,
hendrikw59d449482015-04-04 00:44:32149 bool use_distance_field_text,
sunnyps5d6ff0d02016-06-28 00:40:11150 int gpu_rasterization_msaa_sample_count,
Fady Samuel555c8d12017-07-07 23:14:09151 viz::ResourceFormat preferred_tile_format,
Adrienne Walker436a7752017-08-28 23:33:09152 bool async_worker_context_enabled,
153 bool enable_oop_rasterization)
danakj0de0c95a2016-05-25 01:42:49154 : compositor_context_provider_(compositor_context_provider),
sunnyps5d6ff0d02016-06-28 00:40:11155 worker_context_provider_(worker_context_provider),
156 resource_provider_(resource_provider),
157 use_distance_field_text_(use_distance_field_text),
158 msaa_sample_count_(gpu_rasterization_msaa_sample_count),
ericrkd03c005d2017-03-24 18:48:52159 preferred_tile_format_(preferred_tile_format),
Adrienne Walker436a7752017-08-28 23:33:09160 async_worker_context_enabled_(async_worker_context_enabled),
161 enable_oop_rasterization_(enable_oop_rasterization) {
sunnyps5d6ff0d02016-06-28 00:40:11162 DCHECK(compositor_context_provider);
163 DCHECK(worker_context_provider);
danakj0de0c95a2016-05-25 01:42:49164}
reveman@chromium.orgb5641b92014-02-15 14:21:58165
sunnyps5d6ff0d02016-06-28 00:40:11166GpuRasterBufferProvider::~GpuRasterBufferProvider() {
167 DCHECK(pending_raster_buffers_.empty());
168}
reveman@chromium.orgb5641b92014-02-15 14:21:58169
prashant.nb4d4f492016-04-29 12:51:28170std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster(
danakje0b54782015-05-29 22:47:52171 const Resource* resource,
danakj510822aa2015-06-01 20:23:02172 uint64_t resource_content_id,
danakje0b54782015-05-29 22:47:52173 uint64_t previous_content_id) {
sunnyps5d6ff0d02016-06-28 00:40:11174 bool resource_has_previous_content =
175 resource_content_id && resource_content_id == previous_content_id;
Jeremy Roman909d927b2017-08-27 18:34:09176 return std::make_unique<RasterBufferImpl>(
Sunny Sachanandani0cb875e2017-08-15 02:54:52177 this, resource_provider_, resource->id(), resource_has_previous_content);
reveman@chromium.orgb5641b92014-02-15 14:21:58178}
179
sunnyps12074d3d2016-06-21 01:57:48180void GpuRasterBufferProvider::OrderingBarrier() {
prashant.nb4d4f492016-04-29 12:51:28181 TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier");
sunnyps5d6ff0d02016-06-28 00:40:11182
183 gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
184 if (async_worker_context_enabled_) {
Sunny Sachanandani0cb875e2017-08-15 02:54:52185 gpu::SyncToken sync_token = ResourceProvider::GenerateSyncTokenHelper(gl);
sunnyps5d6ff0d02016-06-28 00:40:11186 for (RasterBufferImpl* buffer : pending_raster_buffers_)
187 buffer->set_sync_token(sync_token);
188 } else {
189 gl->OrderingBarrierCHROMIUM();
190 }
191 pending_raster_buffers_.clear();
prashant.nb4d4f492016-04-29 12:51:28192}
193
Sunny Sachanandani5f5419e22017-05-12 20:35:30194void GpuRasterBufferProvider::Flush() {
Sunny Sachanandani9b8fb342017-08-26 00:49:56195 if (async_worker_context_enabled_)
196 compositor_context_provider_->ContextSupport()->FlushPendingWork();
Sunny Sachanandani5f5419e22017-05-12 20:35:30197}
198
Fady Samuel555c8d12017-07-07 23:14:09199viz::ResourceFormat GpuRasterBufferProvider::GetResourceFormat(
prashant.nb4d4f492016-04-29 12:51:28200 bool must_support_alpha) const {
ericrkd03c005d2017-03-24 18:48:52201 if (resource_provider_->IsRenderBufferFormatSupported(
202 preferred_tile_format_) &&
203 (DoesResourceFormatSupportAlpha(preferred_tile_format_) ||
204 !must_support_alpha)) {
205 return preferred_tile_format_;
206 }
207
sunnyps5d6ff0d02016-06-28 00:40:11208 return resource_provider_->best_render_buffer_format();
prashant.nb4d4f492016-04-29 12:51:28209}
210
ericrkeeda58992016-07-07 02:34:27211bool GpuRasterBufferProvider::IsResourceSwizzleRequired(
prashant.nb4d4f492016-04-29 12:51:28212 bool must_support_alpha) const {
213 // This doesn't require a swizzle because we rasterize to the correct format.
214 return false;
215}
216
ericrk5ac42f322016-07-14 01:06:51217bool GpuRasterBufferProvider::CanPartialRasterIntoProvidedResource() const {
ericrkc9ed0832016-07-20 19:42:50218 // Partial raster doesn't support MSAA, as the MSAA resolve is unaware of clip
219 // rects.
220 // TODO(crbug.com/629683): See if we can work around this limitation.
221 return msaa_sample_count_ == 0;
ericrkeeda58992016-07-07 02:34:27222}
223
ericrk7f6a27f2017-01-31 22:34:32224bool GpuRasterBufferProvider::IsResourceReadyToDraw(
Fady Samuelc80a4a862017-07-28 10:23:36225 viz::ResourceId resource_id) const {
ericrk7f6a27f2017-01-31 22:34:32226 if (!async_worker_context_enabled_)
227 return true;
228
ericrk7f6a27f2017-01-31 22:34:32229 gpu::SyncToken sync_token =
ericrk6d7564a2017-02-02 23:55:58230 resource_provider_->GetSyncTokenForResources({resource_id});
ericrk7f6a27f2017-01-31 22:34:32231 if (!sync_token.HasData())
232 return true;
233
sunnyps74996292017-03-15 02:35:48234 // IsSyncTokenSignaled is thread-safe, no need for worker context lock.
235 return worker_context_provider_->ContextSupport()->IsSyncTokenSignaled(
ericrk7f6a27f2017-01-31 22:34:32236 sync_token);
237}
238
239uint64_t GpuRasterBufferProvider::SetReadyToDrawCallback(
240 const ResourceProvider::ResourceIdArray& resource_ids,
241 const base::Closure& callback,
242 uint64_t pending_callback_id) const {
243 if (!async_worker_context_enabled_)
244 return 0;
245
246 gpu::SyncToken sync_token =
247 resource_provider_->GetSyncTokenForResources(resource_ids);
248 uint64_t callback_id = sync_token.release_count();
249 DCHECK_NE(callback_id, 0u);
250
251 // If the callback is different from the one the caller is already waiting on,
sunnyps31c92fe2017-02-10 23:46:55252 // pass the callback through to SignalSyncToken. Otherwise the request is
ericrk7f6a27f2017-01-31 22:34:32253 // redundant.
254 if (callback_id != pending_callback_id) {
sunnyps31c92fe2017-02-10 23:46:55255 // Use the compositor context because we want this callback on the impl
256 // thread.
257 compositor_context_provider_->ContextSupport()->SignalSyncToken(sync_token,
258 callback);
ericrk7f6a27f2017-01-31 22:34:32259 }
260
261 return callback_id;
262}
263
sunnyps5d6ff0d02016-06-28 00:40:11264void GpuRasterBufferProvider::Shutdown() {
265 pending_raster_buffers_.clear();
266}
267
268void GpuRasterBufferProvider::PlaybackOnWorkerThread(
Victor Miura3a4ad4f82017-12-13 06:03:45269 ResourceProvider::ScopedWriteLockRaster* resource_lock,
sunnyps5d6ff0d02016-06-28 00:40:11270 const gpu::SyncToken& sync_token,
271 bool resource_has_previous_content,
272 const RasterSource* raster_source,
273 const gfx::Rect& raster_full_rect,
274 const gfx::Rect& raster_dirty_rect,
275 uint64_t new_content_id,
trchen178ac912017-04-04 10:11:10276 const gfx::AxisTransform2d& transform,
sunnyps5d6ff0d02016-06-28 00:40:11277 const RasterSource::PlaybackSettings& playback_settings) {
Xu Xing32549162017-07-17 22:25:43278 viz::ContextProvider::ScopedContextLock scoped_context(
279 worker_context_provider_);
Victor Miura3a4ad4f82017-12-13 06:03:45280 gpu::raster::RasterInterface* ri = scoped_context.RasterContext();
281 DCHECK(ri);
sunnyps5d6ff0d02016-06-28 00:40:11282
Sunny Sachanandani0cb875e2017-08-15 02:54:52283 // Synchronize with compositor. Nop if sync token is empty.
Victor Miura3a4ad4f82017-12-13 06:03:45284 ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
sunnyps5d6ff0d02016-06-28 00:40:11285
Adrienne Walker436a7752017-08-28 23:33:09286 gfx::Rect playback_rect = raster_full_rect;
287 if (resource_has_previous_content) {
288 playback_rect.Intersect(raster_dirty_rect);
289 }
290 DCHECK(!playback_rect.IsEmpty())
291 << "Why are we rastering a tile that's not dirty?";
292
293 // Log a histogram of the percentage of pixels that were saved due to
294 // partial raster.
295 const char* client_name = GetClientNameForMetrics();
296 float full_rect_size = raster_full_rect.size().GetArea();
297 if (full_rect_size > 0 && client_name) {
298 float fraction_partial_rastered =
299 static_cast<float>(playback_rect.size().GetArea()) / full_rect_size;
300 float fraction_saved = 1.0f - fraction_partial_rastered;
301 UMA_HISTOGRAM_PERCENTAGE(
302 base::StringPrintf("Renderer4.%s.PartialRasterPercentageSaved.Gpu",
303 client_name),
304 100.0f * fraction_saved);
305 }
306
307 if (enable_oop_rasterization_) {
308 RasterizeSourceOOP(raster_source, resource_has_previous_content,
309 resource_lock->size(), raster_full_rect, playback_rect,
310 transform, playback_settings, worker_context_provider_,
311 resource_lock, use_distance_field_text_,
312 msaa_sample_count_);
313 } else {
314 RasterizeSource(raster_source, resource_has_previous_content,
315 resource_lock->size(), raster_full_rect, playback_rect,
316 transform, playback_settings, worker_context_provider_,
317 resource_lock, use_distance_field_text_,
318 msaa_sample_count_);
319 }
sunnyps5d6ff0d02016-06-28 00:40:11320
Sunny Sachanandani0cb875e2017-08-15 02:54:52321 // Generate sync token for cross context synchronization.
Victor Miura3a4ad4f82017-12-13 06:03:45322 resource_lock->set_sync_token(ResourceProvider::GenerateSyncTokenHelper(ri));
sunnyps5d6ff0d02016-06-28 00:40:11323
Sunny Sachanandani0cb875e2017-08-15 02:54:52324 // Mark resource as synchronized when worker and compositor are in same stream
325 // to prevent extra wait sync token calls.
326 if (!async_worker_context_enabled_)
327 resource_lock->set_synchronized();
sunnyps5d6ff0d02016-06-28 00:40:11328}
prashant.nb4d4f492016-04-29 12:51:28329
reveman@chromium.orgb5641b92014-02-15 14:21:58330} // namespace cc