[go: nahoru, domu]

blob: 0cd802b160842fc958740b63bd543099ca4cd084 [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"
vmpstr41d68f82016-03-30 01:20:2316#include "cc/playback/raster_source.h"
danakj920156852015-05-18 20:22:2917#include "cc/raster/scoped_gpu_raster.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5818#include "cc/resources/resource.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5819#include "gpu/command_buffer/client/gles2_interface.h"
hendrikw04cea972014-09-23 20:50:5320#include "third_party/skia/include/core/SkMultiPictureDraw.h"
21#include "third_party/skia/include/core/SkPictureRecorder.h"
reveman47560ab2014-09-18 19:39:2122#include "third_party/skia/include/core/SkSurface.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5823#include "third_party/skia/include/gpu/GrContext.h"
24
25namespace cc {
reveman47560ab2014-09-18 19:39:2126namespace {
27
sunnyps5d6ff0d02016-06-28 00:40:1128static sk_sp<SkPicture> PlaybackToPicture(
29 const RasterSource* raster_source,
30 bool resource_has_previous_content,
31 const gfx::Size& resource_size,
32 const gfx::Rect& raster_full_rect,
33 const gfx::Rect& raster_dirty_rect,
34 float scale,
35 const RasterSource::PlaybackSettings& playback_settings) {
36 // GPU raster doesn't do low res tiles, so should always include images.
37 DCHECK(!playback_settings.skip_images);
38
39 gfx::Rect playback_rect = raster_full_rect;
40 if (resource_has_previous_content) {
41 playback_rect.Intersect(raster_dirty_rect);
danakj05d69002015-06-02 01:42:2042 }
sunnyps5d6ff0d02016-06-28 00:40:1143 DCHECK(!playback_rect.IsEmpty())
44 << "Why are we rastering a tile that's not dirty?";
reveman47560ab2014-09-18 19:39:2145
ericrke4027312016-06-30 00:12:4246 // Log a histogram of the percentage of pixels that were saved due to
47 // partial raster.
ericrkc7c9e3f2016-07-01 17:30:1648 const char* client_name = GetClientNameForMetrics();
ericrke4027312016-06-30 00:12:4249 float full_rect_size = raster_full_rect.size().GetArea();
ericrkc7c9e3f2016-07-01 17:30:1650 if (full_rect_size > 0 && client_name) {
ericrke4027312016-06-30 00:12:4251 float fraction_partial_rastered =
52 static_cast<float>(playback_rect.size().GetArea()) / full_rect_size;
53 float fraction_saved = 1.0f - fraction_partial_rastered;
ericrkc7c9e3f2016-07-01 17:30:1654 UMA_HISTOGRAM_PERCENTAGE(
55 base::StringPrintf("Renderer4.%s.PartialRasterPercentageSaved.Gpu",
56 client_name),
57 100.0f * fraction_saved);
ericrke4027312016-06-30 00:12:4258 }
59
sunnyps5d6ff0d02016-06-28 00:40:1160 // Play back raster_source into temp SkPicture.
61 SkPictureRecorder recorder;
62 const int flags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
63 sk_sp<SkCanvas> canvas = sk_ref_sp(recorder.beginRecording(
64 resource_size.width(), resource_size.height(), NULL, flags));
65 canvas->save();
66 raster_source->PlaybackToCanvas(canvas.get(), raster_full_rect, playback_rect,
67 scale, playback_settings);
68 canvas->restore();
69 return recorder.finishRecordingAsPicture();
70}
vmiura78b69282015-02-14 00:01:1771
sunnyps5d6ff0d02016-06-28 00:40:1172static void RasterizePicture(SkPicture* picture,
73 ContextProvider* context_provider,
74 ResourceProvider::ScopedWriteLockGL* resource_lock,
75 bool async_worker_context_enabled,
76 bool use_distance_field_text,
77 bool can_use_lcd_text,
78 int msaa_sample_count) {
79 ScopedGpuRaster gpu_raster(context_provider);
vmiura78b69282015-02-14 00:01:1780
sunnyps5d6ff0d02016-06-28 00:40:1181 ResourceProvider::ScopedSkSurfaceProvider scoped_surface(
82 context_provider, resource_lock, async_worker_context_enabled,
83 use_distance_field_text, can_use_lcd_text, msaa_sample_count);
84 SkSurface* sk_surface = scoped_surface.sk_surface();
85 // Allocating an SkSurface will fail after a lost context. Pretend we
86 // rasterized, as the contents of the resource don't matter anymore.
87 if (!sk_surface)
88 return;
danakj05d69002015-06-02 01:42:2089
sunnyps5d6ff0d02016-06-28 00:40:1190 SkMultiPictureDraw multi_picture_draw;
91 multi_picture_draw.add(sk_surface->getCanvas(), picture);
92 multi_picture_draw.draw(false);
93}
reveman47560ab2014-09-18 19:39:2194
95} // namespace
sunnyps5d6ff0d02016-06-28 00:40:1196
97GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
98 GpuRasterBufferProvider* client,
99 ResourceProvider* resource_provider,
100 ResourceId resource_id,
101 bool async_worker_context_enabled,
102 bool resource_has_previous_content)
103 : client_(client),
104 lock_(resource_provider, resource_id, async_worker_context_enabled),
105 resource_has_previous_content_(resource_has_previous_content) {
106 client_->pending_raster_buffers_.insert(this);
107}
108
109GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
110 client_->pending_raster_buffers_.erase(this);
111}
112
113void GpuRasterBufferProvider::RasterBufferImpl::Playback(
114 const RasterSource* raster_source,
115 const gfx::Rect& raster_full_rect,
116 const gfx::Rect& raster_dirty_rect,
117 uint64_t new_content_id,
118 float scale,
119 const RasterSource::PlaybackSettings& playback_settings) {
120 TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
121 client_->PlaybackOnWorkerThread(&lock_, sync_token_,
122 resource_has_previous_content_, raster_source,
123 raster_full_rect, raster_dirty_rect,
124 new_content_id, scale, playback_settings);
125}
vmiura78b69282015-02-14 00:01:17126
prashant.nb4d4f492016-04-29 12:51:28127GpuRasterBufferProvider::GpuRasterBufferProvider(
danakj0de0c95a2016-05-25 01:42:49128 ContextProvider* compositor_context_provider,
129 ContextProvider* worker_context_provider,
hendrikw59d449482015-04-04 00:44:32130 ResourceProvider* resource_provider,
131 bool use_distance_field_text,
sunnyps5d6ff0d02016-06-28 00:40:11132 int gpu_rasterization_msaa_sample_count,
133 bool async_worker_context_enabled)
danakj0de0c95a2016-05-25 01:42:49134 : compositor_context_provider_(compositor_context_provider),
sunnyps5d6ff0d02016-06-28 00:40:11135 worker_context_provider_(worker_context_provider),
136 resource_provider_(resource_provider),
137 use_distance_field_text_(use_distance_field_text),
138 msaa_sample_count_(gpu_rasterization_msaa_sample_count),
139 async_worker_context_enabled_(async_worker_context_enabled) {
140 DCHECK(compositor_context_provider);
141 DCHECK(worker_context_provider);
danakj0de0c95a2016-05-25 01:42:49142}
reveman@chromium.orgb5641b92014-02-15 14:21:58143
sunnyps5d6ff0d02016-06-28 00:40:11144GpuRasterBufferProvider::~GpuRasterBufferProvider() {
145 DCHECK(pending_raster_buffers_.empty());
146}
reveman@chromium.orgec7541d2014-04-09 01:23:53147
prashant.nb4d4f492016-04-29 12:51:28148std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster(
danakje0b54782015-05-29 22:47:52149 const Resource* resource,
danakj510822aa2015-06-01 20:23:02150 uint64_t resource_content_id,
danakje0b54782015-05-29 22:47:52151 uint64_t previous_content_id) {
sunnyps5d6ff0d02016-06-28 00:40:11152 bool resource_has_previous_content =
153 resource_content_id && resource_content_id == previous_content_id;
154 return base::WrapUnique(new RasterBufferImpl(
155 this, resource_provider_, resource->id(), async_worker_context_enabled_,
156 resource_has_previous_content));
reveman@chromium.orgb5641b92014-02-15 14:21:58157}
158
prashant.nb4d4f492016-04-29 12:51:28159void GpuRasterBufferProvider::ReleaseBufferForRaster(
danakj60bc3bc2016-04-09 00:24:48160 std::unique_ptr<RasterBuffer> buffer) {
reveman47560ab2014-09-18 19:39:21161 // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
reveman@chromium.orgb5641b92014-02-15 14:21:58162}
163
sunnyps12074d3d2016-06-21 01:57:48164void GpuRasterBufferProvider::OrderingBarrier() {
prashant.nb4d4f492016-04-29 12:51:28165 TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier");
sunnyps5d6ff0d02016-06-28 00:40:11166
167 gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
168 if (async_worker_context_enabled_) {
169 GLuint64 fence = gl->InsertFenceSyncCHROMIUM();
170 gl->OrderingBarrierCHROMIUM();
171
172 gpu::SyncToken sync_token;
173 gl->GenUnverifiedSyncTokenCHROMIUM(fence, sync_token.GetData());
174
175 DCHECK(sync_token.HasData() ||
176 gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
177
178 for (RasterBufferImpl* buffer : pending_raster_buffers_)
179 buffer->set_sync_token(sync_token);
180 } else {
181 gl->OrderingBarrierCHROMIUM();
182 }
183 pending_raster_buffers_.clear();
prashant.nb4d4f492016-04-29 12:51:28184}
185
186ResourceFormat GpuRasterBufferProvider::GetResourceFormat(
187 bool must_support_alpha) const {
sunnyps5d6ff0d02016-06-28 00:40:11188 return resource_provider_->best_render_buffer_format();
prashant.nb4d4f492016-04-29 12:51:28189}
190
191bool GpuRasterBufferProvider::GetResourceRequiresSwizzle(
192 bool must_support_alpha) const {
193 // This doesn't require a swizzle because we rasterize to the correct format.
194 return false;
195}
196
sunnyps5d6ff0d02016-06-28 00:40:11197void GpuRasterBufferProvider::Shutdown() {
198 pending_raster_buffers_.clear();
199}
200
201void GpuRasterBufferProvider::PlaybackOnWorkerThread(
202 ResourceProvider::ScopedWriteLockGL* resource_lock,
203 const gpu::SyncToken& sync_token,
204 bool resource_has_previous_content,
205 const RasterSource* raster_source,
206 const gfx::Rect& raster_full_rect,
207 const gfx::Rect& raster_dirty_rect,
208 uint64_t new_content_id,
209 float scale,
210 const RasterSource::PlaybackSettings& playback_settings) {
211 ContextProvider::ScopedContextLock scoped_context(worker_context_provider_);
212 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
213 DCHECK(gl);
214
215 if (async_worker_context_enabled_) {
216 // Early out if sync token is invalid. This happens if the compositor
217 // context was lost before ScheduleTasks was called.
218 if (!sync_token.HasData())
219 return;
220 // Synchronize with compositor.
221 gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
222 }
223
224 sk_sp<SkPicture> picture = PlaybackToPicture(
225 raster_source, resource_has_previous_content, resource_lock->size(),
226 raster_full_rect, raster_dirty_rect, scale, playback_settings);
227
228 // Turn on distance fields for layers that have ever animated.
229 bool use_distance_field_text =
230 use_distance_field_text_ ||
231 raster_source->ShouldAttemptToUseDistanceFieldText();
232
233 RasterizePicture(picture.get(), worker_context_provider_, resource_lock,
234 async_worker_context_enabled_, use_distance_field_text,
235 raster_source->CanUseLCDText(), msaa_sample_count_);
236
237 const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
238
239 // Barrier to sync worker context output to cc context.
240 gl->OrderingBarrierCHROMIUM();
241
242 // Generate sync token after the barrier for cross context synchronization.
243 gpu::SyncToken resource_sync_token;
244 gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, resource_sync_token.GetData());
245 resource_lock->set_sync_token(resource_sync_token);
246 resource_lock->set_synchronized(!async_worker_context_enabled_);
247}
prashant.nb4d4f492016-04-29 12:51:28248
reveman@chromium.orgb5641b92014-02-15 14:21:58249} // namespace cc