[go: nahoru, domu]

blob: 12fb55a19ca3a7d6819a4a4d319e7de02609e43b [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"
ssid904ce3b2015-01-27 15:20:1613#include "base/trace_event/trace_event.h"
vmpstr41d68f82016-03-30 01:20:2314#include "cc/playback/raster_source.h"
danakj920156852015-05-18 20:22:2915#include "cc/raster/scoped_gpu_raster.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5816#include "cc/resources/resource.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5817#include "gpu/command_buffer/client/gles2_interface.h"
hendrikw04cea972014-09-23 20:50:5318#include "third_party/skia/include/core/SkMultiPictureDraw.h"
19#include "third_party/skia/include/core/SkPictureRecorder.h"
reveman47560ab2014-09-18 19:39:2120#include "third_party/skia/include/core/SkSurface.h"
reveman@chromium.orgb5641b92014-02-15 14:21:5821#include "third_party/skia/include/gpu/GrContext.h"
22
23namespace cc {
reveman47560ab2014-09-18 19:39:2124namespace {
25
sunnyps5d6ff0d02016-06-28 00:40:1126static sk_sp<SkPicture> PlaybackToPicture(
27 const RasterSource* raster_source,
28 bool resource_has_previous_content,
29 const gfx::Size& resource_size,
30 const gfx::Rect& raster_full_rect,
31 const gfx::Rect& raster_dirty_rect,
32 float scale,
33 const RasterSource::PlaybackSettings& playback_settings) {
34 // GPU raster doesn't do low res tiles, so should always include images.
35 DCHECK(!playback_settings.skip_images);
36
37 gfx::Rect playback_rect = raster_full_rect;
38 if (resource_has_previous_content) {
39 playback_rect.Intersect(raster_dirty_rect);
danakj05d69002015-06-02 01:42:2040 }
sunnyps5d6ff0d02016-06-28 00:40:1141 DCHECK(!playback_rect.IsEmpty())
42 << "Why are we rastering a tile that's not dirty?";
reveman47560ab2014-09-18 19:39:2143
sunnyps5d6ff0d02016-06-28 00:40:1144 // Play back raster_source into temp SkPicture.
45 SkPictureRecorder recorder;
46 const int flags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
47 sk_sp<SkCanvas> canvas = sk_ref_sp(recorder.beginRecording(
48 resource_size.width(), resource_size.height(), NULL, flags));
49 canvas->save();
50 raster_source->PlaybackToCanvas(canvas.get(), raster_full_rect, playback_rect,
51 scale, playback_settings);
52 canvas->restore();
53 return recorder.finishRecordingAsPicture();
54}
vmiura78b69282015-02-14 00:01:1755
sunnyps5d6ff0d02016-06-28 00:40:1156static void RasterizePicture(SkPicture* picture,
57 ContextProvider* context_provider,
58 ResourceProvider::ScopedWriteLockGL* resource_lock,
59 bool async_worker_context_enabled,
60 bool use_distance_field_text,
61 bool can_use_lcd_text,
62 int msaa_sample_count) {
63 ScopedGpuRaster gpu_raster(context_provider);
vmiura78b69282015-02-14 00:01:1764
sunnyps5d6ff0d02016-06-28 00:40:1165 ResourceProvider::ScopedSkSurfaceProvider scoped_surface(
66 context_provider, resource_lock, async_worker_context_enabled,
67 use_distance_field_text, can_use_lcd_text, msaa_sample_count);
68 SkSurface* sk_surface = scoped_surface.sk_surface();
69 // Allocating an SkSurface will fail after a lost context. Pretend we
70 // rasterized, as the contents of the resource don't matter anymore.
71 if (!sk_surface)
72 return;
danakj05d69002015-06-02 01:42:2073
sunnyps5d6ff0d02016-06-28 00:40:1174 SkMultiPictureDraw multi_picture_draw;
75 multi_picture_draw.add(sk_surface->getCanvas(), picture);
76 multi_picture_draw.draw(false);
77}
reveman47560ab2014-09-18 19:39:2178
79} // namespace
sunnyps5d6ff0d02016-06-28 00:40:1180
81GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl(
82 GpuRasterBufferProvider* client,
83 ResourceProvider* resource_provider,
84 ResourceId resource_id,
85 bool async_worker_context_enabled,
86 bool resource_has_previous_content)
87 : client_(client),
88 lock_(resource_provider, resource_id, async_worker_context_enabled),
89 resource_has_previous_content_(resource_has_previous_content) {
90 client_->pending_raster_buffers_.insert(this);
91}
92
93GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() {
94 client_->pending_raster_buffers_.erase(this);
95}
96
97void GpuRasterBufferProvider::RasterBufferImpl::Playback(
98 const RasterSource* raster_source,
99 const gfx::Rect& raster_full_rect,
100 const gfx::Rect& raster_dirty_rect,
101 uint64_t new_content_id,
102 float scale,
103 const RasterSource::PlaybackSettings& playback_settings) {
104 TRACE_EVENT0("cc", "GpuRasterBuffer::Playback");
105 client_->PlaybackOnWorkerThread(&lock_, sync_token_,
106 resource_has_previous_content_, raster_source,
107 raster_full_rect, raster_dirty_rect,
108 new_content_id, scale, playback_settings);
109}
vmiura78b69282015-02-14 00:01:17110
prashant.nb4d4f492016-04-29 12:51:28111GpuRasterBufferProvider::GpuRasterBufferProvider(
danakj0de0c95a2016-05-25 01:42:49112 ContextProvider* compositor_context_provider,
113 ContextProvider* worker_context_provider,
hendrikw59d449482015-04-04 00:44:32114 ResourceProvider* resource_provider,
115 bool use_distance_field_text,
sunnyps5d6ff0d02016-06-28 00:40:11116 int gpu_rasterization_msaa_sample_count,
117 bool async_worker_context_enabled)
danakj0de0c95a2016-05-25 01:42:49118 : compositor_context_provider_(compositor_context_provider),
sunnyps5d6ff0d02016-06-28 00:40:11119 worker_context_provider_(worker_context_provider),
120 resource_provider_(resource_provider),
121 use_distance_field_text_(use_distance_field_text),
122 msaa_sample_count_(gpu_rasterization_msaa_sample_count),
123 async_worker_context_enabled_(async_worker_context_enabled) {
124 DCHECK(compositor_context_provider);
125 DCHECK(worker_context_provider);
danakj0de0c95a2016-05-25 01:42:49126}
reveman@chromium.orgb5641b92014-02-15 14:21:58127
sunnyps5d6ff0d02016-06-28 00:40:11128GpuRasterBufferProvider::~GpuRasterBufferProvider() {
129 DCHECK(pending_raster_buffers_.empty());
130}
reveman@chromium.orgec7541d2014-04-09 01:23:53131
prashant.nb4d4f492016-04-29 12:51:28132std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster(
danakje0b54782015-05-29 22:47:52133 const Resource* resource,
danakj510822aa2015-06-01 20:23:02134 uint64_t resource_content_id,
danakje0b54782015-05-29 22:47:52135 uint64_t previous_content_id) {
sunnyps5d6ff0d02016-06-28 00:40:11136 bool resource_has_previous_content =
137 resource_content_id && resource_content_id == previous_content_id;
138 return base::WrapUnique(new RasterBufferImpl(
139 this, resource_provider_, resource->id(), async_worker_context_enabled_,
140 resource_has_previous_content));
reveman@chromium.orgb5641b92014-02-15 14:21:58141}
142
prashant.nb4d4f492016-04-29 12:51:28143void GpuRasterBufferProvider::ReleaseBufferForRaster(
danakj60bc3bc2016-04-09 00:24:48144 std::unique_ptr<RasterBuffer> buffer) {
reveman47560ab2014-09-18 19:39:21145 // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
reveman@chromium.orgb5641b92014-02-15 14:21:58146}
147
sunnyps12074d3d2016-06-21 01:57:48148void GpuRasterBufferProvider::OrderingBarrier() {
prashant.nb4d4f492016-04-29 12:51:28149 TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier");
sunnyps5d6ff0d02016-06-28 00:40:11150
151 gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL();
152 if (async_worker_context_enabled_) {
153 GLuint64 fence = gl->InsertFenceSyncCHROMIUM();
154 gl->OrderingBarrierCHROMIUM();
155
156 gpu::SyncToken sync_token;
157 gl->GenUnverifiedSyncTokenCHROMIUM(fence, sync_token.GetData());
158
159 DCHECK(sync_token.HasData() ||
160 gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
161
162 for (RasterBufferImpl* buffer : pending_raster_buffers_)
163 buffer->set_sync_token(sync_token);
164 } else {
165 gl->OrderingBarrierCHROMIUM();
166 }
167 pending_raster_buffers_.clear();
prashant.nb4d4f492016-04-29 12:51:28168}
169
170ResourceFormat GpuRasterBufferProvider::GetResourceFormat(
171 bool must_support_alpha) const {
sunnyps5d6ff0d02016-06-28 00:40:11172 return resource_provider_->best_render_buffer_format();
prashant.nb4d4f492016-04-29 12:51:28173}
174
175bool GpuRasterBufferProvider::GetResourceRequiresSwizzle(
176 bool must_support_alpha) const {
177 // This doesn't require a swizzle because we rasterize to the correct format.
178 return false;
179}
180
sunnyps5d6ff0d02016-06-28 00:40:11181void GpuRasterBufferProvider::Shutdown() {
182 pending_raster_buffers_.clear();
183}
184
185void GpuRasterBufferProvider::PlaybackOnWorkerThread(
186 ResourceProvider::ScopedWriteLockGL* resource_lock,
187 const gpu::SyncToken& sync_token,
188 bool resource_has_previous_content,
189 const RasterSource* raster_source,
190 const gfx::Rect& raster_full_rect,
191 const gfx::Rect& raster_dirty_rect,
192 uint64_t new_content_id,
193 float scale,
194 const RasterSource::PlaybackSettings& playback_settings) {
195 ContextProvider::ScopedContextLock scoped_context(worker_context_provider_);
196 gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL();
197 DCHECK(gl);
198
199 if (async_worker_context_enabled_) {
200 // Early out if sync token is invalid. This happens if the compositor
201 // context was lost before ScheduleTasks was called.
202 if (!sync_token.HasData())
203 return;
204 // Synchronize with compositor.
205 gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
206 }
207
208 sk_sp<SkPicture> picture = PlaybackToPicture(
209 raster_source, resource_has_previous_content, resource_lock->size(),
210 raster_full_rect, raster_dirty_rect, scale, playback_settings);
211
212 // Turn on distance fields for layers that have ever animated.
213 bool use_distance_field_text =
214 use_distance_field_text_ ||
215 raster_source->ShouldAttemptToUseDistanceFieldText();
216
217 RasterizePicture(picture.get(), worker_context_provider_, resource_lock,
218 async_worker_context_enabled_, use_distance_field_text,
219 raster_source->CanUseLCDText(), msaa_sample_count_);
220
221 const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM();
222
223 // Barrier to sync worker context output to cc context.
224 gl->OrderingBarrierCHROMIUM();
225
226 // Generate sync token after the barrier for cross context synchronization.
227 gpu::SyncToken resource_sync_token;
228 gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, resource_sync_token.GetData());
229 resource_lock->set_sync_token(resource_sync_token);
230 resource_lock->set_synchronized(!async_worker_context_enabled_);
231}
prashant.nb4d4f492016-04-29 12:51:28232
reveman@chromium.orgb5641b92014-02-15 14:21:58233} // namespace cc