[go: nahoru, domu]

blob: de489ff8fdee51ef924d4af97142ea7676b68467 [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"
enne5a9630362017-02-24 23:41:0316#include "cc/paint/paint_canvas.h"
chrishtrac41ff92017-03-17 05:07:3017#include "cc/raster/image_hijack_canvas.h"
18#include "cc/raster/raster_source.h"
danakj920156852015-05-18 20:22:2919#include "cc/raster/scoped_gpu_raster.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5820#include "cc/resources/resource.h"
ericrk7f6a27f2017-01-31 22:34:3221#include "gpu/command_buffer/client/context_support.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5822#include "gpu/command_buffer/client/gles2_interface.h"
hendrikw04cea972014-09-23 20:50:5323#include "third_party/skia/include/core/SkMultiPictureDraw.h"
24#include "third_party/skia/include/core/SkPictureRecorder.h"
reveman47560ab2014-09-18 19:39:2125#include "third_party/skia/include/core/SkSurface.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5826#include "third_party/skia/include/gpu/GrContext.h"
27
28namespace cc {
reveman47560ab2014-09-18 19:39:2129namespace {
30
vmiuraf7c765c2016-12-03 21:02:3231static void RasterizeSource(
sunnyps5d6ff0d02016-06-28 00:40:1132 const RasterSource* raster_source,
33 bool resource_has_previous_content,
34 const gfx::Size& resource_size,
35 const gfx::Rect& raster_full_rect,
36 const gfx::Rect& raster_dirty_rect,
trchen178ac912017-04-04 10:11:1037 const gfx::AxisTransform2d& transform,
vmiuraf7c765c2016-12-03 21:02:3238 const RasterSource::PlaybackSettings& playback_settings,
39 ContextProvider* context_provider,
40 ResourceProvider::ScopedWriteLockGL* resource_lock,
41 bool async_worker_context_enabled,
42 bool use_distance_field_text,
43 int msaa_sample_count) {
44 ScopedGpuRaster gpu_raster(context_provider);
sunnyps5d6ff0d02016-06-28 00:40:1145
vmiuraf7c765c2016-12-03 21:02:3246 ResourceProvider::ScopedSkSurfaceProvider scoped_surface(
47 context_provider, resource_lock, async_worker_context_enabled,
48 use_distance_field_text, raster_source->CanUseLCDText(),
ccameron76f24f02017-02-23 05:24:4449 msaa_sample_count);
vmiuraf7c765c2016-12-03 21:02:3250 SkSurface* sk_surface = scoped_surface.sk_surface();
51 // Allocating an SkSurface will fail after a lost context. Pretend we
52 // rasterized, as the contents of the resource don't matter anymore.
ccameron220942362017-02-06 20:29:1953 if (!sk_surface) {
54 DLOG(ERROR) << "Failed to allocate raster surface";
vmiuraf7c765c2016-12-03 21:02:3255 return;
ccameron220942362017-02-06 20:29:1956 }
vmiuraf7c765c2016-12-03 21:02:3257
58 // Playback
sunnyps5d6ff0d02016-06-28 00:40:1159 gfx::Rect playback_rect = raster_full_rect;
60 if (resource_has_previous_content) {
61 playback_rect.Intersect(raster_dirty_rect);
danakj05d69002015-06-02 01:42:2062 }
sunnyps5d6ff0d02016-06-28 00:40:1163 DCHECK(!playback_rect.IsEmpty())
64 << "Why are we rastering a tile that's not dirty?";
reveman47560ab2014-09-18 19:39:2165
ericrke4027312016-06-30 00:12:4266 // Log a histogram of the percentage of pixels that were saved due to
67 // partial raster.
ericrkc7c9e3f2016-07-01 17:30:1668 const char* client_name = GetClientNameForMetrics();
ericrke4027312016-06-30 00:12:4269 float full_rect_size = raster_full_rect.size().GetArea();
ericrkc7c9e3f2016-07-01 17:30:1670 if (full_rect_size > 0 && client_name) {
ericrke4027312016-06-30 00:12:4271 float fraction_partial_rastered =
72 static_cast<float>(playback_rect.size().GetArea()) / full_rect_size;
73 float fraction_saved = 1.0f - fraction_partial_rastered;
ericrkc7c9e3f2016-07-01 17:30:1674 UMA_HISTOGRAM_PERCENTAGE(
75 base::StringPrintf("Renderer4.%s.PartialRasterPercentageSaved.Gpu",
76 client_name),
77 100.0f * fraction_saved);
ericrke4027312016-06-30 00:12:4278 }
79
ccameron1f9a3662017-03-17 00:43:0680 raster_source->PlaybackToCanvas(
81 sk_surface->getCanvas(), resource_lock->color_space_for_raster(),
trchen178ac912017-04-04 10:11:1082 raster_full_rect, playback_rect, transform, playback_settings);
sunnyps5d6ff0d02016-06-28 00:40:1183}
reveman47560ab2014-09-18 19:39:2184
85} // namespace
sunnyps5d6ff0d02016-06-28 00:40:1186
87GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
88 GpuRasterBufferProvider* client,
89 ResourceProvider* resource_provider,
90 ResourceId resource_id,
91 bool async_worker_context_enabled,
92 bool resource_has_previous_content)
93 : client_(client),
94 lock_(resource_provider, resource_id, async_worker_context_enabled),
95 resource_has_previous_content_(resource_has_previous_content) {
96 client_->pending_raster_buffers_.insert(this);
97}
98
99GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
100 client_->pending_raster_buffers_.erase(this);
101}
102
103void GpuRasterBufferProvider::RasterBufferImpl::Playback(
104 const RasterSource* raster_source,
105 const gfx::Rect& raster_full_rect,
106 const gfx::Rect& raster_dirty_rect,
107 uint64_t new_content_id,
trchen178ac912017-04-04 10:11:10108 const gfx::AxisTransform2d& transform,
sunnyps5d6ff0d02016-06-28 00:40:11109 const RasterSource::PlaybackSettings& playback_settings) {
110 TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
111 client_->PlaybackOnWorkerThread(&lock_, sync_token_,
112 resource_has_previous_content_, raster_source,
113 raster_full_rect, raster_dirty_rect,
trchen178ac912017-04-04 10:11:10114 new_content_id, transform, playback_settings);
sunnyps5d6ff0d02016-06-28 00:40:11115}
vmiura78b69282015-02-14 00:01:17116
prashant.nb4d4f492016-04-29 12:51:28117GpuRasterBufferProvider::GpuRasterBufferProvider(
danakj0de0c95a2016-05-25 01:42:49118 ContextProvider* compositor_context_provider,
119 ContextProvider* worker_context_provider,
hendrikw59d449482015-04-04 00:44:32120 ResourceProvider* resource_provider,
121 bool use_distance_field_text,
sunnyps5d6ff0d02016-06-28 00:40:11122 int gpu_rasterization_msaa_sample_count,
ericrkd03c005d2017-03-24 18:48:52123 ResourceFormat preferred_tile_format,
sunnyps5d6ff0d02016-06-28 00:40:11124 bool async_worker_context_enabled)
danakj0de0c95a2016-05-25 01:42:49125 : compositor_context_provider_(compositor_context_provider),
sunnyps5d6ff0d02016-06-28 00:40:11126 worker_context_provider_(worker_context_provider),
127 resource_provider_(resource_provider),
128 use_distance_field_text_(use_distance_field_text),
129 msaa_sample_count_(gpu_rasterization_msaa_sample_count),
ericrkd03c005d2017-03-24 18:48:52130 preferred_tile_format_(preferred_tile_format),
sunnyps5d6ff0d02016-06-28 00:40:11131 async_worker_context_enabled_(async_worker_context_enabled) {
132 DCHECK(compositor_context_provider);
133 DCHECK(worker_context_provider);
danakj0de0c95a2016-05-25 01:42:49134}
reveman@chromium.orgb5641b92014-02-15 14:21:58135
sunnyps5d6ff0d02016-06-28 00:40:11136GpuRasterBufferProvider::~GpuRasterBufferProvider() {
137 DCHECK(pending_raster_buffers_.empty());
138}
reveman@chromium.orgec7541d2014-04-09 01:23:53139
prashant.nb4d4f492016-04-29 12:51:28140std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster(
danakje0b54782015-05-29 22:47:52141 const Resource* resource,
danakj510822aa2015-06-01 20:23:02142 uint64_t resource_content_id,
danakje0b54782015-05-29 22:47:52143 uint64_t previous_content_id) {
sunnyps5d6ff0d02016-06-28 00:40:11144 bool resource_has_previous_content =
145 resource_content_id && resource_content_id == previous_content_id;
riceada4bffb6e2016-08-22 05:28:17146 return base::MakeUnique<RasterBufferImpl>(
sunnyps5d6ff0d02016-06-28 00:40:11147 this, resource_provider_, resource->id(), async_worker_context_enabled_,
riceada4bffb6e2016-08-22 05:28:17148 resource_has_previous_content);
reveman@chromium.orgb5641b92014-02-15 14:21:58149}
150
prashant.nb4d4f492016-04-29 12:51:28151void GpuRasterBufferProvider::ReleaseBufferForRaster(
danakj60bc3bc2016-04-09 00:24:48152 std::unique_ptr<RasterBuffer> buffer) {
reveman47560ab2014-09-18 19:39:21153 // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
reveman@chromium.orgb5641b92014-02-15 14:21:58154}
155
sunnyps12074d3d2016-06-21 01:57:48156void GpuRasterBufferProvider::OrderingBarrier() {
prashant.nb4d4f492016-04-29 12:51:28157 TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier");
sunnyps5d6ff0d02016-06-28 00:40:11158
159 gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
160 if (async_worker_context_enabled_) {
161 GLuint64 fence = gl->InsertFenceSyncCHROMIUM();
162 gl->OrderingBarrierCHROMIUM();
163
164 gpu::SyncToken sync_token;
165 gl->GenUnverifiedSyncTokenCHROMIUM(fence, sync_token.GetData());
166
167 DCHECK(sync_token.HasData() ||
168 gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
169
170 for (RasterBufferImpl* buffer : pending_raster_buffers_)
171 buffer->set_sync_token(sync_token);
172 } else {
173 gl->OrderingBarrierCHROMIUM();
174 }
175 pending_raster_buffers_.clear();
prashant.nb4d4f492016-04-29 12:51:28176}
177
178ResourceFormat GpuRasterBufferProvider::GetResourceFormat(
179 bool must_support_alpha) const {
ericrkd03c005d2017-03-24 18:48:52180 if (resource_provider_->IsRenderBufferFormatSupported(
181 preferred_tile_format_) &&
182 (DoesResourceFormatSupportAlpha(preferred_tile_format_) ||
183 !must_support_alpha)) {
184 return preferred_tile_format_;
185 }
186
sunnyps5d6ff0d02016-06-28 00:40:11187 return resource_provider_->best_render_buffer_format();
prashant.nb4d4f492016-04-29 12:51:28188}
189
ericrkeeda58992016-07-07 02:34:27190bool GpuRasterBufferProvider::IsResourceSwizzleRequired(
prashant.nb4d4f492016-04-29 12:51:28191 bool must_support_alpha) const {
192 // This doesn't require a swizzle because we rasterize to the correct format.
193 return false;
194}
195
ericrk5ac42f322016-07-14 01:06:51196bool GpuRasterBufferProvider::CanPartialRasterIntoProvidedResource() const {
ericrkc9ed0832016-07-20 19:42:50197 // Partial raster doesn't support MSAA, as the MSAA resolve is unaware of clip
198 // rects.
199 // TODO(crbug.com/629683): See if we can work around this limitation.
200 return msaa_sample_count_ == 0;
ericrkeeda58992016-07-07 02:34:27201}
202
ericrk7f6a27f2017-01-31 22:34:32203bool GpuRasterBufferProvider::IsResourceReadyToDraw(
204 ResourceId resource_id) const {
205 if (!async_worker_context_enabled_)
206 return true;
207
ericrk7f6a27f2017-01-31 22:34:32208 gpu::SyncToken sync_token =
ericrk6d7564a2017-02-02 23:55:58209 resource_provider_->GetSyncTokenForResources({resource_id});
ericrk7f6a27f2017-01-31 22:34:32210 if (!sync_token.HasData())
211 return true;
212
sunnyps74996292017-03-15 02:35:48213 // IsSyncTokenSignaled is thread-safe, no need for worker context lock.
214 return worker_context_provider_->ContextSupport()->IsSyncTokenSignaled(
ericrk7f6a27f2017-01-31 22:34:32215 sync_token);
216}
217
218uint64_t GpuRasterBufferProvider::SetReadyToDrawCallback(
219 const ResourceProvider::ResourceIdArray& resource_ids,
220 const base::Closure& callback,
221 uint64_t pending_callback_id) const {
222 if (!async_worker_context_enabled_)
223 return 0;
224
225 gpu::SyncToken sync_token =
226 resource_provider_->GetSyncTokenForResources(resource_ids);
227 uint64_t callback_id = sync_token.release_count();
228 DCHECK_NE(callback_id, 0u);
229
230 // If the callback is different from the one the caller is already waiting on,
sunnyps31c92fe2017-02-10 23:46:55231 // pass the callback through to SignalSyncToken. Otherwise the request is
ericrk7f6a27f2017-01-31 22:34:32232 // redundant.
233 if (callback_id != pending_callback_id) {
sunnyps31c92fe2017-02-10 23:46:55234 // Use the compositor context because we want this callback on the impl
235 // thread.
236 compositor_context_provider_->ContextSupport()->SignalSyncToken(sync_token,
237 callback);
ericrk7f6a27f2017-01-31 22:34:32238 }
239
240 return callback_id;
241}
242
sunnyps5d6ff0d02016-06-28 00:40:11243void GpuRasterBufferProvider::Shutdown() {
244 pending_raster_buffers_.clear();
245}
246
247void GpuRasterBufferProvider::PlaybackOnWorkerThread(
248 ResourceProvider::ScopedWriteLockGL* resource_lock,
249 const gpu::SyncToken& sync_token,
250 bool resource_has_previous_content,
251 const RasterSource* raster_source,
252 const gfx::Rect& raster_full_rect,
253 const gfx::Rect& raster_dirty_rect,
254 uint64_t new_content_id,
trchen178ac912017-04-04 10:11:10255 const gfx::AxisTransform2d& transform,
sunnyps5d6ff0d02016-06-28 00:40:11256 const RasterSource::PlaybackSettings& playback_settings) {
257 ContextProvider::ScopedContextLock scoped_context(worker_context_provider_);
258 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
259 DCHECK(gl);
260
261 if (async_worker_context_enabled_) {
262 // Early out if sync token is invalid. This happens if the compositor
263 // context was lost before ScheduleTasks was called.
264 if (!sync_token.HasData())
265 return;
266 // Synchronize with compositor.
267 gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
268 }
269
vmiuraf7c765c2016-12-03 21:02:32270 RasterizeSource(raster_source, resource_has_previous_content,
271 resource_lock->size(), raster_full_rect, raster_dirty_rect,
trchen178ac912017-04-04 10:11:10272 transform, playback_settings, worker_context_provider_,
vmiuraf7c765c2016-12-03 21:02:32273 resource_lock, async_worker_context_enabled_,
ericrkb04a4a62017-01-03 20:48:08274 use_distance_field_text_, msaa_sample_count_);
sunnyps5d6ff0d02016-06-28 00:40:11275
276 const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
277
278 // Barrier to sync worker context output to cc context.
279 gl->OrderingBarrierCHROMIUM();
280
281 // Generate sync token after the barrier for cross context synchronization.
282 gpu::SyncToken resource_sync_token;
283 gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, resource_sync_token.GetData());
284 resource_lock->set_sync_token(resource_sync_token);
285 resource_lock->set_synchronized(!async_worker_context_enabled_);
286}
prashant.nb4d4f492016-04-29 12:51:28287
reveman@chromium.orgb5641b92014-02-15 14:21:58288} // namespace cc