[go: nahoru, domu]

blob: 3b12a6c31436ac220e3307630a7e2f9fe99edfd5 [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"
Victor Miura29b7ea3d2017-12-19 20:23:5922#include "components/viz/common/gpu/context_provider.h"
23#include "components/viz/common/gpu/raster_context_provider.h"
ericrk7f6a27f2017-01-31 22:34:3224#include "gpu/command_buffer/client/context_support.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5825#include "gpu/command_buffer/client/gles2_interface.h"
Victor Miura3a4ad4f82017-12-13 06:03:4526#include "gpu/command_buffer/client/raster_interface.h"
hendrikw04cea972014-09-23 20:50:5327#include "third_party/skia/include/core/SkMultiPictureDraw.h"
28#include "third_party/skia/include/core/SkPictureRecorder.h"
reveman47560ab2014-09-18 19:39:2129#include "third_party/skia/include/core/SkSurface.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5830#include "third_party/skia/include/gpu/GrContext.h"
Adrienne Walker436a7752017-08-28 23:33:0931#include "ui/gfx/geometry/axis_transform2d.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5832
33namespace cc {
reveman47560ab2014-09-18 19:39:2134namespace {
35
Adrienne Walker436a7752017-08-28 23:33:0936static void RasterizeSourceOOP(
37 const RasterSource* raster_source,
38 bool resource_has_previous_content,
39 const gfx::Size& resource_size,
40 const gfx::Rect& raster_full_rect,
41 const gfx::Rect& playback_rect,
42 const gfx::AxisTransform2d& transform,
43 const RasterSource::PlaybackSettings& playback_settings,
Victor Miura29b7ea3d2017-12-19 20:23:5944 viz::RasterContextProvider* context_provider,
Victor Miura3a4ad4f82017-12-13 06:03:4545 ResourceProvider::ScopedWriteLockRaster* resource_lock,
Adrienne Walker436a7752017-08-28 23:33:0946 bool use_distance_field_text,
47 int msaa_sample_count) {
Victor Miura29b7ea3d2017-12-19 20:23:5948 gpu::raster::RasterInterface* ri = context_provider->RasterInterface();
Victor Miura3a4ad4f82017-12-13 06:03:4549 GLuint texture_id = resource_lock->ConsumeTexture(ri);
Adrienne Walker436a7752017-08-28 23:33:0950
Victor Miura3a4ad4f82017-12-13 06:03:4551 ri->BeginRasterCHROMIUM(texture_id, raster_source->background_color(),
Adrienne Walker436a7752017-08-28 23:33:0952 msaa_sample_count, playback_settings.use_lcd_text,
53 use_distance_field_text,
54 resource_lock->PixelConfig());
Adrienne Walkerbc5cd82e2017-10-31 21:58:1555 // TODO(enne): need to pass color space into this function as well.
56 float recording_to_raster_scale =
57 transform.scale() / raster_source->recording_scale_factor();
Victor Miura3a4ad4f82017-12-13 06:03:4558 ri->RasterCHROMIUM(raster_source->GetDisplayItemList().get(),
Adrienne Walkerbc5cd82e2017-10-31 21:58:1559 raster_full_rect.x(), raster_full_rect.y(),
danakjb075024f2017-09-08 17:45:4160 playback_rect.x(), playback_rect.y(),
Adrienne Walkerbc5cd82e2017-10-31 21:58:1561 playback_rect.width(), playback_rect.height(),
62 transform.translation().x(), transform.translation().y(),
63 recording_to_raster_scale);
Victor Miura3a4ad4f82017-12-13 06:03:4564 ri->EndRasterCHROMIUM();
Adrienne Walker436a7752017-08-28 23:33:0965
Victor Miura3a4ad4f82017-12-13 06:03:4566 ri->DeleteTextures(1, &texture_id);
Adrienne Walker436a7752017-08-28 23:33:0967}
68
Victor Miura406891a2017-12-16 03:58:3069// The following class is needed to correctly reset GL state when rendering to
70// SkCanvases with a GrContext on a RasterInterface enabled context.
71class ScopedGrContextAccess {
72 public:
Victor Miura29b7ea3d2017-12-19 20:23:5973 explicit ScopedGrContextAccess(viz::RasterContextProvider* context_provider)
Victor Miura406891a2017-12-16 03:58:3074 : context_provider_(context_provider) {
Victor Miura29b7ea3d2017-12-19 20:23:5975 gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
Victor Miura406891a2017-12-16 03:58:3076 ri->BeginGpuRaster();
77
78 class GrContext* gr_context = context_provider_->GrContext();
79 gr_context->resetContext();
80 }
81 ~ScopedGrContextAccess() {
Victor Miura29b7ea3d2017-12-19 20:23:5982 gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
Victor Miura406891a2017-12-16 03:58:3083 ri->EndGpuRaster();
84 }
85
86 private:
Victor Miura29b7ea3d2017-12-19 20:23:5987 viz::RasterContextProvider* context_provider_;
Victor Miura406891a2017-12-16 03:58:3088};
89
vmiuraf7c765c2016-12-03 21:02:3290static void RasterizeSource(
sunnyps5d6ff0d02016-06-28 00:40:1191 const RasterSource* raster_source,
92 bool resource_has_previous_content,
93 const gfx::Size& resource_size,
94 const gfx::Rect& raster_full_rect,
Adrienne Walker436a7752017-08-28 23:33:0995 const gfx::Rect& playback_rect,
trchen178ac912017-04-04 10:11:1096 const gfx::AxisTransform2d& transform,
vmiuraf7c765c2016-12-03 21:02:3297 const RasterSource::PlaybackSettings& playback_settings,
Victor Miura29b7ea3d2017-12-19 20:23:5998 viz::RasterContextProvider* context_provider,
Victor Miura3a4ad4f82017-12-13 06:03:4599 ResourceProvider::ScopedWriteLockRaster* resource_lock,
vmiuraf7c765c2016-12-03 21:02:32100 bool use_distance_field_text,
101 int msaa_sample_count) {
Victor Miura406891a2017-12-16 03:58:30102 ScopedGrContextAccess gr_context_access(context_provider);
sunnyps5d6ff0d02016-06-28 00:40:11103
Victor Miura29b7ea3d2017-12-19 20:23:59104 gpu::raster::RasterInterface* ri = context_provider->RasterInterface();
Victor Miura3a4ad4f82017-12-13 06:03:45105 GLuint texture_id = resource_lock->ConsumeTexture(ri);
Sunny Sachanandani0cb875e2017-08-15 02:54:52106
107 {
108 ResourceProvider::ScopedSkSurface scoped_surface(
109 context_provider->GrContext(), texture_id, resource_lock->target(),
110 resource_lock->size(), resource_lock->format(), use_distance_field_text,
111 playback_settings.use_lcd_text, msaa_sample_count);
112
113 SkSurface* surface = scoped_surface.surface();
114
115 // Allocating an SkSurface will fail after a lost context. Pretend we
116 // rasterized, as the contents of the resource don't matter anymore.
117 if (!surface) {
118 DLOG(ERROR) << "Failed to allocate raster surface";
119 return;
120 }
121
Sunny Sachanandani0cb875e2017-08-15 02:54:52122 SkCanvas* canvas = surface->getCanvas();
123
124 // As an optimization, inform Skia to discard when not doing partial raster.
125 if (raster_full_rect == playback_rect)
126 canvas->discard();
127
128 raster_source->PlaybackToCanvas(
129 canvas, resource_lock->color_space_for_raster(), raster_full_rect,
130 playback_rect, transform, playback_settings);
ccameron220942362017-02-06 20:29:19131 }
vmiuraf7c765c2016-12-03 21:02:32132
Victor Miura3a4ad4f82017-12-13 06:03:45133 ri->DeleteTextures(1, &texture_id);
sunnyps5d6ff0d02016-06-28 00:40:11134}
reveman47560ab2014-09-18 19:39:21135
136} // namespace
vmiura78b69282015-02-14 00:01:17137
sunnyps5d6ff0d02016-06-28 00:40:11138GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
139 GpuRasterBufferProvider* client,
Xu Xingb57edf32017-08-22 04:18:47140 LayerTreeResourceProvider* resource_provider,
Fady Samuelc80a4a862017-07-28 10:23:36141 viz::ResourceId resource_id,
sunnyps5d6ff0d02016-06-28 00:40:11142 bool resource_has_previous_content)
143 : client_(client),
Sunny Sachanandani0cb875e2017-08-15 02:54:52144 lock_(resource_provider, resource_id),
sunnyps5d6ff0d02016-06-28 00:40:11145 resource_has_previous_content_(resource_has_previous_content) {
146 client_->pending_raster_buffers_.insert(this);
Sunny Sachanandani0cb875e2017-08-15 02:54:52147 lock_.CreateMailbox();
sunnyps5d6ff0d02016-06-28 00:40:11148}
149
150GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
151 client_->pending_raster_buffers_.erase(this);
152}
153
154void GpuRasterBufferProvider::RasterBufferImpl::Playback(
155 const RasterSource* raster_source,
156 const gfx::Rect& raster_full_rect,
157 const gfx::Rect& raster_dirty_rect,
158 uint64_t new_content_id,
trchen178ac912017-04-04 10:11:10159 const gfx::AxisTransform2d& transform,
sunnyps5d6ff0d02016-06-28 00:40:11160 const RasterSource::PlaybackSettings& playback_settings) {
161 TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
162 client_->PlaybackOnWorkerThread(&lock_, sync_token_,
163 resource_has_previous_content_, raster_source,
164 raster_full_rect, raster_dirty_rect,
trchen178ac912017-04-04 10:11:10165 new_content_id, transform, playback_settings);
sunnyps5d6ff0d02016-06-28 00:40:11166}
167
prashant.nb4d4f492016-04-29 12:51:28168GpuRasterBufferProvider::GpuRasterBufferProvider(
Xu Xing32549162017-07-17 22:25:43169 viz::ContextProvider* compositor_context_provider,
Victor Miura29b7ea3d2017-12-19 20:23:59170 viz::RasterContextProvider* worker_context_provider,
Xu Xingb57edf32017-08-22 04:18:47171 LayerTreeResourceProvider* resource_provider,
hendrikw59d449482015-04-04 00:44:32172 bool use_distance_field_text,
sunnyps5d6ff0d02016-06-28 00:40:11173 int gpu_rasterization_msaa_sample_count,
Fady Samuel555c8d12017-07-07 23:14:09174 viz::ResourceFormat preferred_tile_format,
Adrienne Walker436a7752017-08-28 23:33:09175 bool async_worker_context_enabled,
176 bool enable_oop_rasterization)
danakj0de0c95a2016-05-25 01:42:49177 : compositor_context_provider_(compositor_context_provider),
sunnyps5d6ff0d02016-06-28 00:40:11178 worker_context_provider_(worker_context_provider),
179 resource_provider_(resource_provider),
180 use_distance_field_text_(use_distance_field_text),
181 msaa_sample_count_(gpu_rasterization_msaa_sample_count),
ericrkd03c005d2017-03-24 18:48:52182 preferred_tile_format_(preferred_tile_format),
Adrienne Walker436a7752017-08-28 23:33:09183 async_worker_context_enabled_(async_worker_context_enabled),
184 enable_oop_rasterization_(enable_oop_rasterization) {
sunnyps5d6ff0d02016-06-28 00:40:11185 DCHECK(compositor_context_provider);
186 DCHECK(worker_context_provider);
danakj0de0c95a2016-05-25 01:42:49187}
reveman@chromium.orgb5641b92014-02-15 14:21:58188
sunnyps5d6ff0d02016-06-28 00:40:11189GpuRasterBufferProvider::~GpuRasterBufferProvider() {
190 DCHECK(pending_raster_buffers_.empty());
191}
reveman@chromium.orgb5641b92014-02-15 14:21:58192
prashant.nb4d4f492016-04-29 12:51:28193std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster(
danakje0b54782015-05-29 22:47:52194 const Resource* resource,
danakj510822aa2015-06-01 20:23:02195 uint64_t resource_content_id,
danakje0b54782015-05-29 22:47:52196 uint64_t previous_content_id) {
sunnyps5d6ff0d02016-06-28 00:40:11197 bool resource_has_previous_content =
198 resource_content_id && resource_content_id == previous_content_id;
Jeremy Roman909d927b2017-08-27 18:34:09199 return std::make_unique<RasterBufferImpl>(
Sunny Sachanandani0cb875e2017-08-15 02:54:52200 this, resource_provider_, resource->id(), resource_has_previous_content);
reveman@chromium.orgb5641b92014-02-15 14:21:58201}
202
sunnyps12074d3d2016-06-21 01:57:48203void GpuRasterBufferProvider::OrderingBarrier() {
prashant.nb4d4f492016-04-29 12:51:28204 TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier");
sunnyps5d6ff0d02016-06-28 00:40:11205
206 gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
207 if (async_worker_context_enabled_) {
Sunny Sachanandani0cb875e2017-08-15 02:54:52208 gpu::SyncToken sync_token = ResourceProvider::GenerateSyncTokenHelper(gl);
sunnyps5d6ff0d02016-06-28 00:40:11209 for (RasterBufferImpl* buffer : pending_raster_buffers_)
210 buffer->set_sync_token(sync_token);
211 } else {
212 gl->OrderingBarrierCHROMIUM();
213 }
214 pending_raster_buffers_.clear();
prashant.nb4d4f492016-04-29 12:51:28215}
216
Sunny Sachanandani5f5419e22017-05-12 20:35:30217void GpuRasterBufferProvider::Flush() {
Sunny Sachanandani9b8fb342017-08-26 00:49:56218 if (async_worker_context_enabled_)
219 compositor_context_provider_->ContextSupport()->FlushPendingWork();
Sunny Sachanandani5f5419e22017-05-12 20:35:30220}
221
Fady Samuel555c8d12017-07-07 23:14:09222viz::ResourceFormat GpuRasterBufferProvider::GetResourceFormat(
prashant.nb4d4f492016-04-29 12:51:28223 bool must_support_alpha) const {
ericrkd03c005d2017-03-24 18:48:52224 if (resource_provider_->IsRenderBufferFormatSupported(
225 preferred_tile_format_) &&
226 (DoesResourceFormatSupportAlpha(preferred_tile_format_) ||
227 !must_support_alpha)) {
228 return preferred_tile_format_;
229 }
230
sunnyps5d6ff0d02016-06-28 00:40:11231 return resource_provider_->best_render_buffer_format();
prashant.nb4d4f492016-04-29 12:51:28232}
233
ericrkeeda58992016-07-07 02:34:27234bool GpuRasterBufferProvider::IsResourceSwizzleRequired(
prashant.nb4d4f492016-04-29 12:51:28235 bool must_support_alpha) const {
236 // This doesn't require a swizzle because we rasterize to the correct format.
237 return false;
238}
239
ericrk5ac42f322016-07-14 01:06:51240bool GpuRasterBufferProvider::CanPartialRasterIntoProvidedResource() const {
ericrkc9ed0832016-07-20 19:42:50241 // Partial raster doesn't support MSAA, as the MSAA resolve is unaware of clip
242 // rects.
243 // TODO(crbug.com/629683): See if we can work around this limitation.
244 return msaa_sample_count_ == 0;
ericrkeeda58992016-07-07 02:34:27245}
246
ericrk7f6a27f2017-01-31 22:34:32247bool GpuRasterBufferProvider::IsResourceReadyToDraw(
Fady Samuelc80a4a862017-07-28 10:23:36248 viz::ResourceId resource_id) const {
ericrk7f6a27f2017-01-31 22:34:32249 if (!async_worker_context_enabled_)
250 return true;
251
ericrk7f6a27f2017-01-31 22:34:32252 gpu::SyncToken sync_token =
ericrk6d7564a2017-02-02 23:55:58253 resource_provider_->GetSyncTokenForResources({resource_id});
ericrk7f6a27f2017-01-31 22:34:32254 if (!sync_token.HasData())
255 return true;
256
sunnyps74996292017-03-15 02:35:48257 // IsSyncTokenSignaled is thread-safe, no need for worker context lock.
258 return worker_context_provider_->ContextSupport()->IsSyncTokenSignaled(
ericrk7f6a27f2017-01-31 22:34:32259 sync_token);
260}
261
262uint64_t GpuRasterBufferProvider::SetReadyToDrawCallback(
263 const ResourceProvider::ResourceIdArray& resource_ids,
264 const base::Closure& callback,
265 uint64_t pending_callback_id) const {
266 if (!async_worker_context_enabled_)
267 return 0;
268
269 gpu::SyncToken sync_token =
270 resource_provider_->GetSyncTokenForResources(resource_ids);
271 uint64_t callback_id = sync_token.release_count();
272 DCHECK_NE(callback_id, 0u);
273
274 // If the callback is different from the one the caller is already waiting on,
sunnyps31c92fe2017-02-10 23:46:55275 // pass the callback through to SignalSyncToken. Otherwise the request is
ericrk7f6a27f2017-01-31 22:34:32276 // redundant.
277 if (callback_id != pending_callback_id) {
sunnyps31c92fe2017-02-10 23:46:55278 // Use the compositor context because we want this callback on the impl
279 // thread.
280 compositor_context_provider_->ContextSupport()->SignalSyncToken(sync_token,
281 callback);
ericrk7f6a27f2017-01-31 22:34:32282 }
283
284 return callback_id;
285}
286
sunnyps5d6ff0d02016-06-28 00:40:11287void GpuRasterBufferProvider::Shutdown() {
288 pending_raster_buffers_.clear();
289}
290
291void GpuRasterBufferProvider::PlaybackOnWorkerThread(
Victor Miura3a4ad4f82017-12-13 06:03:45292 ResourceProvider::ScopedWriteLockRaster* resource_lock,
sunnyps5d6ff0d02016-06-28 00:40:11293 const gpu::SyncToken& sync_token,
294 bool resource_has_previous_content,
295 const RasterSource* raster_source,
296 const gfx::Rect& raster_full_rect,
297 const gfx::Rect& raster_dirty_rect,
298 uint64_t new_content_id,
trchen178ac912017-04-04 10:11:10299 const gfx::AxisTransform2d& transform,
sunnyps5d6ff0d02016-06-28 00:40:11300 const RasterSource::PlaybackSettings& playback_settings) {
Victor Miura29b7ea3d2017-12-19 20:23:59301 viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
Xu Xing32549162017-07-17 22:25:43302 worker_context_provider_);
Victor Miura29b7ea3d2017-12-19 20:23:59303 gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
Victor Miura3a4ad4f82017-12-13 06:03:45304 DCHECK(ri);
sunnyps5d6ff0d02016-06-28 00:40:11305
Sunny Sachanandani0cb875e2017-08-15 02:54:52306 // Synchronize with compositor. Nop if sync token is empty.
Victor Miura3a4ad4f82017-12-13 06:03:45307 ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
sunnyps5d6ff0d02016-06-28 00:40:11308
Adrienne Walker436a7752017-08-28 23:33:09309 gfx::Rect playback_rect = raster_full_rect;
310 if (resource_has_previous_content) {
311 playback_rect.Intersect(raster_dirty_rect);
312 }
313 DCHECK(!playback_rect.IsEmpty())
314 << "Why are we rastering a tile that's not dirty?";
315
316 // Log a histogram of the percentage of pixels that were saved due to
317 // partial raster.
318 const char* client_name = GetClientNameForMetrics();
319 float full_rect_size = raster_full_rect.size().GetArea();
320 if (full_rect_size > 0 && client_name) {
321 float fraction_partial_rastered =
322 static_cast<float>(playback_rect.size().GetArea()) / full_rect_size;
323 float fraction_saved = 1.0f - fraction_partial_rastered;
324 UMA_HISTOGRAM_PERCENTAGE(
325 base::StringPrintf("Renderer4.%s.PartialRasterPercentageSaved.Gpu",
326 client_name),
327 100.0f * fraction_saved);
328 }
329
330 if (enable_oop_rasterization_) {
331 RasterizeSourceOOP(raster_source, resource_has_previous_content,
332 resource_lock->size(), raster_full_rect, playback_rect,
333 transform, playback_settings, worker_context_provider_,
334 resource_lock, use_distance_field_text_,
335 msaa_sample_count_);
336 } else {
337 RasterizeSource(raster_source, resource_has_previous_content,
338 resource_lock->size(), raster_full_rect, playback_rect,
339 transform, playback_settings, worker_context_provider_,
340 resource_lock, use_distance_field_text_,
341 msaa_sample_count_);
342 }
sunnyps5d6ff0d02016-06-28 00:40:11343
Sunny Sachanandani0cb875e2017-08-15 02:54:52344 // Generate sync token for cross context synchronization.
Victor Miura3a4ad4f82017-12-13 06:03:45345 resource_lock->set_sync_token(ResourceProvider::GenerateSyncTokenHelper(ri));
sunnyps5d6ff0d02016-06-28 00:40:11346
Sunny Sachanandani0cb875e2017-08-15 02:54:52347 // Mark resource as synchronized when worker and compositor are in same stream
348 // to prevent extra wait sync token calls.
349 if (!async_worker_context_enabled_)
350 resource_lock->set_synchronized();
sunnyps5d6ff0d02016-06-28 00:40:11351}
prashant.nb4d4f492016-04-29 12:51:28352
reveman@chromium.orgb5641b92014-02-15 14:21:58353} // namespace cc