[go: nahoru, domu]

blob: 208068a8103ecc6d0c9e91e588501945aeb0b1da [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"
ericrk1259d6e72016-07-15 00:47:3217#include "cc/playback/image_hijack_canvas.h"
vmpstr41d68f82016-03-30 01:20:2318#include "cc/playback/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,
vmpstr69c12082017-01-13 01:52:4337 float scale,
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
vmiuraf7c765c2016-12-03 21:02:3280 raster_source->PlaybackToCanvas(sk_surface->getCanvas(), raster_full_rect,
vmpstr69c12082017-01-13 01:52:4381 playback_rect, scale, playback_settings);
sunnyps5d6ff0d02016-06-28 00:40:1182}
reveman47560ab2014-09-18 19:39:2183
84} // namespace
sunnyps5d6ff0d02016-06-28 00:40:1185
86GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
87 GpuRasterBufferProvider* client,
88 ResourceProvider* resource_provider,
89 ResourceId resource_id,
90 bool async_worker_context_enabled,
91 bool resource_has_previous_content)
92 : client_(client),
93 lock_(resource_provider, resource_id, async_worker_context_enabled),
94 resource_has_previous_content_(resource_has_previous_content) {
95 client_->pending_raster_buffers_.insert(this);
96}
97
98GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
99 client_->pending_raster_buffers_.erase(this);
100}
101
102void GpuRasterBufferProvider::RasterBufferImpl::Playback(
103 const RasterSource* raster_source,
104 const gfx::Rect& raster_full_rect,
105 const gfx::Rect& raster_dirty_rect,
106 uint64_t new_content_id,
vmpstr69c12082017-01-13 01:52:43107 float scale,
sunnyps5d6ff0d02016-06-28 00:40:11108 const RasterSource::PlaybackSettings& playback_settings) {
109 TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
110 client_->PlaybackOnWorkerThread(&lock_, sync_token_,
111 resource_has_previous_content_, raster_source,
112 raster_full_rect, raster_dirty_rect,
vmpstr69c12082017-01-13 01:52:43113 new_content_id, scale, playback_settings);
sunnyps5d6ff0d02016-06-28 00:40:11114}
vmiura78b69282015-02-14 00:01:17115
prashant.nb4d4f492016-04-29 12:51:28116GpuRasterBufferProvider::GpuRasterBufferProvider(
danakj0de0c95a2016-05-25 01:42:49117 ContextProvider* compositor_context_provider,
118 ContextProvider* worker_context_provider,
hendrikw59d449482015-04-04 00:44:32119 ResourceProvider* resource_provider,
120 bool use_distance_field_text,
sunnyps5d6ff0d02016-06-28 00:40:11121 int gpu_rasterization_msaa_sample_count,
122 bool async_worker_context_enabled)
danakj0de0c95a2016-05-25 01:42:49123 : compositor_context_provider_(compositor_context_provider),
sunnyps5d6ff0d02016-06-28 00:40:11124 worker_context_provider_(worker_context_provider),
125 resource_provider_(resource_provider),
126 use_distance_field_text_(use_distance_field_text),
127 msaa_sample_count_(gpu_rasterization_msaa_sample_count),
128 async_worker_context_enabled_(async_worker_context_enabled) {
129 DCHECK(compositor_context_provider);
130 DCHECK(worker_context_provider);
danakj0de0c95a2016-05-25 01:42:49131}
reveman@chromium.orgb5641b92014-02-15 14:21:58132
sunnyps5d6ff0d02016-06-28 00:40:11133GpuRasterBufferProvider::~GpuRasterBufferProvider() {
134 DCHECK(pending_raster_buffers_.empty());
135}
reveman@chromium.orgec7541d2014-04-09 01:23:53136
prashant.nb4d4f492016-04-29 12:51:28137std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster(
danakje0b54782015-05-29 22:47:52138 const Resource* resource,
danakj510822aa2015-06-01 20:23:02139 uint64_t resource_content_id,
danakje0b54782015-05-29 22:47:52140 uint64_t previous_content_id) {
sunnyps5d6ff0d02016-06-28 00:40:11141 bool resource_has_previous_content =
142 resource_content_id && resource_content_id == previous_content_id;
riceada4bffb6e2016-08-22 05:28:17143 return base::MakeUnique<RasterBufferImpl>(
sunnyps5d6ff0d02016-06-28 00:40:11144 this, resource_provider_, resource->id(), async_worker_context_enabled_,
riceada4bffb6e2016-08-22 05:28:17145 resource_has_previous_content);
reveman@chromium.orgb5641b92014-02-15 14:21:58146}
147
prashant.nb4d4f492016-04-29 12:51:28148void GpuRasterBufferProvider::ReleaseBufferForRaster(
danakj60bc3bc2016-04-09 00:24:48149 std::unique_ptr<RasterBuffer> buffer) {
reveman47560ab2014-09-18 19:39:21150 // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
reveman@chromium.orgb5641b92014-02-15 14:21:58151}
152
sunnyps12074d3d2016-06-21 01:57:48153void GpuRasterBufferProvider::OrderingBarrier() {
prashant.nb4d4f492016-04-29 12:51:28154 TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier");
sunnyps5d6ff0d02016-06-28 00:40:11155
156 gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
157 if (async_worker_context_enabled_) {
158 GLuint64 fence = gl->InsertFenceSyncCHROMIUM();
159 gl->OrderingBarrierCHROMIUM();
160
161 gpu::SyncToken sync_token;
162 gl->GenUnverifiedSyncTokenCHROMIUM(fence, sync_token.GetData());
163
164 DCHECK(sync_token.HasData() ||
165 gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
166
167 for (RasterBufferImpl* buffer : pending_raster_buffers_)
168 buffer->set_sync_token(sync_token);
169 } else {
170 gl->OrderingBarrierCHROMIUM();
171 }
172 pending_raster_buffers_.clear();
prashant.nb4d4f492016-04-29 12:51:28173}
174
175ResourceFormat GpuRasterBufferProvider::GetResourceFormat(
176 bool must_support_alpha) const {
sunnyps5d6ff0d02016-06-28 00:40:11177 return resource_provider_->best_render_buffer_format();
prashant.nb4d4f492016-04-29 12:51:28178}
179
ericrkeeda58992016-07-07 02:34:27180bool GpuRasterBufferProvider::IsResourceSwizzleRequired(
prashant.nb4d4f492016-04-29 12:51:28181 bool must_support_alpha) const {
182 // This doesn't require a swizzle because we rasterize to the correct format.
183 return false;
184}
185
ericrk5ac42f322016-07-14 01:06:51186bool GpuRasterBufferProvider::CanPartialRasterIntoProvidedResource() const {
ericrkc9ed0832016-07-20 19:42:50187 // Partial raster doesn't support MSAA, as the MSAA resolve is unaware of clip
188 // rects.
189 // TODO(crbug.com/629683): See if we can work around this limitation.
190 return msaa_sample_count_ == 0;
ericrkeeda58992016-07-07 02:34:27191}
192
ericrk7f6a27f2017-01-31 22:34:32193bool GpuRasterBufferProvider::IsResourceReadyToDraw(
194 ResourceId resource_id) const {
195 if (!async_worker_context_enabled_)
196 return true;
197
ericrk7f6a27f2017-01-31 22:34:32198 gpu::SyncToken sync_token =
ericrk6d7564a2017-02-02 23:55:58199 resource_provider_->GetSyncTokenForResources({resource_id});
ericrk7f6a27f2017-01-31 22:34:32200 if (!sync_token.HasData())
201 return true;
202
sunnyps74996292017-03-15 02:35:48203 // IsSyncTokenSignaled is thread-safe, no need for worker context lock.
204 return worker_context_provider_->ContextSupport()->IsSyncTokenSignaled(
ericrk7f6a27f2017-01-31 22:34:32205 sync_token);
206}
207
208uint64_t GpuRasterBufferProvider::SetReadyToDrawCallback(
209 const ResourceProvider::ResourceIdArray& resource_ids,
210 const base::Closure& callback,
211 uint64_t pending_callback_id) const {
212 if (!async_worker_context_enabled_)
213 return 0;
214
215 gpu::SyncToken sync_token =
216 resource_provider_->GetSyncTokenForResources(resource_ids);
217 uint64_t callback_id = sync_token.release_count();
218 DCHECK_NE(callback_id, 0u);
219
220 // If the callback is different from the one the caller is already waiting on,
sunnyps31c92fe2017-02-10 23:46:55221 // pass the callback through to SignalSyncToken. Otherwise the request is
ericrk7f6a27f2017-01-31 22:34:32222 // redundant.
223 if (callback_id != pending_callback_id) {
sunnyps31c92fe2017-02-10 23:46:55224 // Use the compositor context because we want this callback on the impl
225 // thread.
226 compositor_context_provider_->ContextSupport()->SignalSyncToken(sync_token,
227 callback);
ericrk7f6a27f2017-01-31 22:34:32228 }
229
230 return callback_id;
231}
232
sunnyps5d6ff0d02016-06-28 00:40:11233void GpuRasterBufferProvider::Shutdown() {
234 pending_raster_buffers_.clear();
235}
236
237void GpuRasterBufferProvider::PlaybackOnWorkerThread(
238 ResourceProvider::ScopedWriteLockGL* resource_lock,
239 const gpu::SyncToken& sync_token,
240 bool resource_has_previous_content,
241 const RasterSource* raster_source,
242 const gfx::Rect& raster_full_rect,
243 const gfx::Rect& raster_dirty_rect,
244 uint64_t new_content_id,
vmpstr69c12082017-01-13 01:52:43245 float scale,
sunnyps5d6ff0d02016-06-28 00:40:11246 const RasterSource::PlaybackSettings& playback_settings) {
247 ContextProvider::ScopedContextLock scoped_context(worker_context_provider_);
248 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
249 DCHECK(gl);
250
251 if (async_worker_context_enabled_) {
252 // Early out if sync token is invalid. This happens if the compositor
253 // context was lost before ScheduleTasks was called.
254 if (!sync_token.HasData())
255 return;
256 // Synchronize with compositor.
257 gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
258 }
259
vmiuraf7c765c2016-12-03 21:02:32260 RasterizeSource(raster_source, resource_has_previous_content,
261 resource_lock->size(), raster_full_rect, raster_dirty_rect,
vmpstr69c12082017-01-13 01:52:43262 scale, playback_settings, worker_context_provider_,
vmiuraf7c765c2016-12-03 21:02:32263 resource_lock, async_worker_context_enabled_,
ericrkb04a4a62017-01-03 20:48:08264 use_distance_field_text_, msaa_sample_count_);
sunnyps5d6ff0d02016-06-28 00:40:11265
266 const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
267
268 // Barrier to sync worker context output to cc context.
269 gl->OrderingBarrierCHROMIUM();
270
271 // Generate sync token after the barrier for cross context synchronization.
272 gpu::SyncToken resource_sync_token;
273 gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, resource_sync_token.GetData());
274 resource_lock->set_sync_token(resource_sync_token);
275 resource_lock->set_synchronized(!async_worker_context_enabled_);
276}
prashant.nb4d4f492016-04-29 12:51:28277
reveman@chromium.orgb5641b92014-02-15 14:21:58278} // namespace cc