Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1015)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp

Issue 2493673002: Synchronize OffscreenCanvas content with the placeholder canvas (Closed)
Patch Set: fix printing Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform/graphics/OffscreenCanvasFrameDispatcherImpl.h" 5 #include "platform/graphics/OffscreenCanvasFrameDispatcherImpl.h"
6 6
7 #include "cc/output/compositor_frame.h" 7 #include "cc/output/compositor_frame.h"
8 #include "cc/quads/texture_draw_quad.h" 8 #include "cc/quads/texture_draw_quad.h"
9 #include "gpu/command_buffer/client/gles2_interface.h" 9 #include "gpu/command_buffer/client/gles2_interface.h"
10 #include "platform/CrossThreadFunctional.h"
10 #include "platform/Histogram.h" 11 #include "platform/Histogram.h"
12 #include "platform/WebTaskRunner.h"
13 #include "platform/graphics/OffscreenCanvasPlaceholder.h"
11 #include "platform/graphics/gpu/SharedGpuContext.h" 14 #include "platform/graphics/gpu/SharedGpuContext.h"
12 #include "public/platform/InterfaceProvider.h" 15 #include "public/platform/InterfaceProvider.h"
13 #include "public/platform/Platform.h" 16 #include "public/platform/Platform.h"
14 #include "public/platform/WebGraphicsContext3DProvider.h" 17 #include "public/platform/WebGraphicsContext3DProvider.h"
15 #include "public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom -blink.h" 18 #include "public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom -blink.h"
16 #include "third_party/khronos/GLES2/gl2.h" 19 #include "third_party/khronos/GLES2/gl2.h"
17 #include "third_party/khronos/GLES2/gl2ext.h" 20 #include "third_party/khronos/GLES2/gl2ext.h"
18 #include "third_party/skia/include/core/SkColor.h" 21 #include "third_party/skia/include/core/SkColor.h"
19 #include "third_party/skia/include/core/SkImage.h" 22 #include "third_party/skia/include/core/SkImage.h"
20 #include "ui/gfx/geometry/rect.h" 23 #include "ui/gfx/geometry/rect.h"
21 #include "ui/gfx/transform.h" 24 #include "ui/gfx/transform.h"
22 #include "wtf/typed_arrays/ArrayBuffer.h" 25 #include "wtf/typed_arrays/ArrayBuffer.h"
23 #include "wtf/typed_arrays/Uint8Array.h" 26 #include "wtf/typed_arrays/Uint8Array.h"
24 27
25 namespace blink { 28 namespace blink {
26 29
27 OffscreenCanvasFrameDispatcherImpl::OffscreenCanvasFrameDispatcherImpl( 30 OffscreenCanvasFrameDispatcherImpl::OffscreenCanvasFrameDispatcherImpl(
28 uint32_t clientId, 31 uint32_t clientId,
29 uint32_t sinkId, 32 uint32_t sinkId,
30 uint32_t localId, 33 uint32_t localId,
31 uint64_t nonce, 34 uint64_t nonce,
35 int canvasId,
32 int width, 36 int width,
33 int height) 37 int height)
34 : m_surfaceId(cc::FrameSinkId(clientId, sinkId), 38 : m_surfaceId(cc::FrameSinkId(clientId, sinkId),
35 cc::LocalFrameId(localId, nonce)), 39 cc::LocalFrameId(localId, nonce)),
36 m_width(width), 40 m_width(width),
37 m_height(height), 41 m_height(height),
38 m_nextResourceId(1u), 42 m_nextResourceId(1u),
39 m_binding(this) { 43 m_binding(this),
44 m_placeholderCanvasId(canvasId) {
40 DCHECK(!m_sink.is_bound()); 45 DCHECK(!m_sink.is_bound());
41 mojom::blink::OffscreenCanvasCompositorFrameSinkProviderPtr provider; 46 mojom::blink::OffscreenCanvasCompositorFrameSinkProviderPtr provider;
42 Platform::current()->interfaceProvider()->getInterface( 47 Platform::current()->interfaceProvider()->getInterface(
43 mojo::GetProxy(&provider)); 48 mojo::GetProxy(&provider));
44 provider->CreateCompositorFrameSink(m_surfaceId, 49 provider->CreateCompositorFrameSink(m_surfaceId,
45 m_binding.CreateInterfacePtrAndBind(), 50 m_binding.CreateInterfacePtrAndBind(),
46 mojo::GetProxy(&m_sink)); 51 mojo::GetProxy(&m_sink));
47 } 52 }
48 53
49 void OffscreenCanvasFrameDispatcherImpl::setTransferableResourceToSharedBitmap( 54 void OffscreenCanvasFrameDispatcherImpl::setTransferableResourceToSharedBitmap(
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 resource.mailbox_holder = 144 resource.mailbox_holder =
140 gpu::MailboxHolder(image->mailbox(), image->syncToken(), GL_TEXTURE_2D); 145 gpu::MailboxHolder(image->mailbox(), image->syncToken(), GL_TEXTURE_2D);
141 resource.read_lock_fences_enabled = false; 146 resource.read_lock_fences_enabled = false;
142 resource.is_software = false; 147 resource.is_software = false;
143 148
144 // Hold ref to |image|, to keep it alive until the browser ReclaimResources. 149 // Hold ref to |image|, to keep it alive until the browser ReclaimResources.
145 // It guarantees that the resource is not re-used or deleted. 150 // It guarantees that the resource is not re-used or deleted.
146 m_cachedImages.add(m_nextResourceId, std::move(image)); 151 m_cachedImages.add(m_nextResourceId, std::move(image));
147 } 152 }
148 153
154 namespace {
155
156 void updatePlaceholderImage(WeakPtr<OffscreenCanvasFrameDispatcher> dispatcher,
157 std::unique_ptr<WebTaskRunner> taskRunner,
158 int placeholderCanvasId,
159 RefPtr<blink::Image> image,
160 unsigned resourceId) {
161 DCHECK(isMainThread());
162 OffscreenCanvasPlaceholder* placeholderCanvas =
163 OffscreenCanvasPlaceholder::getPlaceholderById(placeholderCanvasId);
164 if (placeholderCanvas) {
165 placeholderCanvas->setPlaceholderFrame(std::move(image),
166 std::move(dispatcher),
167 std::move(taskRunner), resourceId);
168 }
169 }
170
171 } // namespace
172
149 void OffscreenCanvasFrameDispatcherImpl::dispatchFrame( 173 void OffscreenCanvasFrameDispatcherImpl::dispatchFrame(
150 RefPtr<StaticBitmapImage> image, 174 RefPtr<StaticBitmapImage> image,
151 double commitStartTime, 175 double commitStartTime,
152 bool isWebGLSoftwareRendering /* This flag is true when WebGL's commit is 176 bool isWebGLSoftwareRendering /* This flag is true when WebGL's commit is
153 called on SwiftShader. */) { 177 called on SwiftShader. */) {
154 if (!image) 178 if (!image)
155 return; 179 return;
156 if (!verifyImageSize(image->size())) 180 if (!verifyImageSize(image->size()))
157 return; 181 return;
158 cc::CompositorFrame frame; 182 cc::CompositorFrame frame;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 !isWebGLSoftwareRendering) { 228 !isWebGLSoftwareRendering) {
205 // Case 3: canvas is not gpu-accelerated, but compositor is 229 // Case 3: canvas is not gpu-accelerated, but compositor is
206 commitType = CommitSoftwareCanvasGPUCompositing; 230 commitType = CommitSoftwareCanvasGPUCompositing;
207 setTransferableResourceToSharedGPUContext(resource, image); 231 setTransferableResourceToSharedGPUContext(resource, image);
208 } else { 232 } else {
209 // Case 4: both canvas and compositor are not gpu accelerated. 233 // Case 4: both canvas and compositor are not gpu accelerated.
210 commitType = CommitSoftwareCanvasSoftwareCompositing; 234 commitType = CommitSoftwareCanvasSoftwareCompositing;
211 setTransferableResourceToSharedBitmap(resource, image); 235 setTransferableResourceToSharedBitmap(resource, image);
212 } 236 }
213 } 237 }
238
239 // After this point, |image| can only be used on the main thread, until
240 // it is returned.
241 image->transfer();
xlai (Olivia) 2016/11/11 16:28:33 In the case of gpu-accelerated offscreencanvas, th
Justin Novosad 2016/11/11 22:09:00 The idea is that We don't need to use this snapsho
242 std::unique_ptr<WebTaskRunner> dispatcherTaskRunner =
243 Platform::current()->currentThread()->getWebTaskRunner()->clone();
244
245 Platform::current()->mainThread()->getWebTaskRunner()->postTask(
xlai (Olivia) 2016/11/11 16:28:33 This dispatchFrame() is invoked in every commit().
Justin Novosad 2016/11/11 22:09:00 I tried that and it is actually more complicated w
246 BLINK_FROM_HERE,
247 crossThreadBind(updatePlaceholderImage, this->createWeakPtr(),
248 passed(std::move(dispatcherTaskRunner)),
249 m_placeholderCanvasId, std::move(image), resource.id));
250 m_spareResourceLocks.add(m_nextResourceId);
251
214 commitTypeHistogram.count(commitType); 252 commitTypeHistogram.count(commitType);
215 253
216 m_nextResourceId++; 254 m_nextResourceId++;
217 frame.resource_list.push_back(std::move(resource)); 255 frame.resource_list.push_back(std::move(resource));
218 256
219 cc::TextureDrawQuad* quad = 257 cc::TextureDrawQuad* quad =
220 pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>(); 258 pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>();
221 gfx::Size rectSize(m_width, m_height); 259 gfx::Size rectSize(m_width, m_height);
222 260
223 const bool needsBlending = true; 261 const bool needsBlending = true;
224 // TOOD(crbug.com/645993): this should be inherited from WebGL context's 262 // TOOD(crbug.com/645993): this should be inherited from WebGL context's
225 // creation settings. 263 // creation settings.
226 const bool premultipliedAlpha = true; 264 const bool premultipliedAlpha = true;
227 const gfx::PointF uvTopLeft(0.f, 0.f); 265 const gfx::PointF uvTopLeft(0.f, 0.f);
228 const gfx::PointF uvBottomRight(1.f, 1.f); 266 const gfx::PointF uvBottomRight(1.f, 1.f);
229 float vertexOpacity[4] = {1.f, 1.f, 1.f, 1.f}; 267 float vertexOpacity[4] = {1.f, 1.f, 1.f, 1.f};
230 // TODO(crbug.com/645994): this should be true when using style 268 // TODO(crbug.com/645994): this should be true when using style
231 // "image-rendering: pixelated". 269 // "image-rendering: pixelated".
232 const bool nearestNeighbor = false; 270 const bool nearestNeighbor = false;
233 quad->SetAll(sqs, bounds, bounds, bounds, needsBlending, resource.id, 271 quad->SetAll(sqs, bounds, bounds, bounds, needsBlending, resource.id,
234 gfx::Size(), premultipliedAlpha, uvTopLeft, uvBottomRight, 272 gfx::Size(), premultipliedAlpha, uvTopLeft, uvBottomRight,
235 SK_ColorTRANSPARENT, vertexOpacity, yflipped, nearestNeighbor, 273 SK_ColorTRANSPARENT, vertexOpacity, yflipped, nearestNeighbor,
236 false); 274 false);
237 275
238 frame.render_pass_list.push_back(std::move(pass)); 276 frame.render_pass_list.push_back(std::move(pass));
239 277
240 double elapsedTime = WTF::monotonicallyIncreasingTime() - commitStartTime; 278 double elapsedTime = WTF::monotonicallyIncreasingTime() - commitStartTime;
279
280 // TODO(crbug.com/663916): The off-main-thread metrics are commented-out
281 // because they cause thread check errors (static variable accessed in many
282 // threads)
241 switch (commitType) { 283 switch (commitType) {
242 case CommitGPUCanvasGPUCompositing: 284 case CommitGPUCanvasGPUCompositing:
243 if (isMainThread()) { 285 if (isMainThread()) {
244 DEFINE_STATIC_LOCAL( 286 DEFINE_STATIC_LOCAL(
245 CustomCountHistogram, commitGPUCanvasGPUCompositingMainTimer, 287 CustomCountHistogram, commitGPUCanvasGPUCompositingMainTimer,
246 ("Blink.Canvas.OffscreenCommit.GPUCanvasGPUCompositingMain", 0, 288 ("Blink.Canvas.OffscreenCommit.GPUCanvasGPUCompositingMain", 0,
247 10000000, 50)); 289 10000000, 50));
248 commitGPUCanvasGPUCompositingMainTimer.count(elapsedTime * 1000000.0); 290 commitGPUCanvasGPUCompositingMainTimer.count(elapsedTime * 1000000.0);
249 } else { 291 } /* else {
250 DEFINE_STATIC_LOCAL( 292 DEFINE_STATIC_LOCAL(
251 CustomCountHistogram, commitGPUCanvasGPUCompositingWorkerTimer, 293 CustomCountHistogram, commitGPUCanvasGPUCompositingWorkerTimer,
252 ("Blink.Canvas.OffscreenCommit.GPUCanvasGPUCompositingWorker", 0, 294 ("Blink.Canvas.OffscreenCommit.GPUCanvasGPUCompositingWorker", 0,
253 10000000, 50)); 295 10000000, 50));
254 commitGPUCanvasGPUCompositingWorkerTimer.count(elapsedTime * 1000000.0); 296 commitGPUCanvasGPUCompositingWorkerTimer.count(elapsedTime * 1000000.0);
255 } 297 } */
256 break; 298 break;
257 case CommitGPUCanvasSoftwareCompositing: 299 case CommitGPUCanvasSoftwareCompositing:
258 if (isMainThread()) { 300 if (isMainThread()) {
259 DEFINE_STATIC_LOCAL( 301 DEFINE_STATIC_LOCAL(
260 CustomCountHistogram, commitGPUCanvasSoftwareCompositingMainTimer, 302 CustomCountHistogram, commitGPUCanvasSoftwareCompositingMainTimer,
261 ("Blink.Canvas.OffscreenCommit.GPUCanvasSoftwareCompositingMain", 0, 303 ("Blink.Canvas.OffscreenCommit.GPUCanvasSoftwareCompositingMain", 0,
262 10000000, 50)); 304 10000000, 50));
263 commitGPUCanvasSoftwareCompositingMainTimer.count(elapsedTime * 305 commitGPUCanvasSoftwareCompositingMainTimer.count(elapsedTime *
264 1000000.0); 306 1000000.0);
265 } else { 307 } /* else {
266 DEFINE_STATIC_LOCAL( 308 DEFINE_STATIC_LOCAL(
267 CustomCountHistogram, commitGPUCanvasSoftwareCompositingWorkerTimer, 309 CustomCountHistogram, commitGPUCanvasSoftwareCompositingWorkerTimer,
268 ("Blink.Canvas.OffscreenCommit.GPUCanvasSoftwareCompositingWorker", 310 ("Blink.Canvas.OffscreenCommit.GPUCanvasSoftwareCompositingWorker",
269 0, 10000000, 50)); 311 0, 10000000, 50));
270 commitGPUCanvasSoftwareCompositingWorkerTimer.count(elapsedTime * 312 commitGPUCanvasSoftwareCompositingWorkerTimer.count(elapsedTime *
271 1000000.0); 313 1000000.0);
272 } 314 } */
273 break; 315 break;
274 case CommitSoftwareCanvasGPUCompositing: 316 case CommitSoftwareCanvasGPUCompositing:
275 if (isMainThread()) { 317 if (isMainThread()) {
276 DEFINE_STATIC_LOCAL( 318 DEFINE_STATIC_LOCAL(
277 CustomCountHistogram, commitSoftwareCanvasGPUCompositingMainTimer, 319 CustomCountHistogram, commitSoftwareCanvasGPUCompositingMainTimer,
278 ("Blink.Canvas.OffscreenCommit.SoftwareCanvasGPUCompositingMain", 0, 320 ("Blink.Canvas.OffscreenCommit.SoftwareCanvasGPUCompositingMain", 0,
279 10000000, 50)); 321 10000000, 50));
280 commitSoftwareCanvasGPUCompositingMainTimer.count(elapsedTime * 322 commitSoftwareCanvasGPUCompositingMainTimer.count(elapsedTime *
281 1000000.0); 323 1000000.0);
282 } else { 324 } /* else {
283 DEFINE_STATIC_LOCAL( 325 DEFINE_STATIC_LOCAL(
284 CustomCountHistogram, commitSoftwareCanvasGPUCompositingWorkerTimer, 326 CustomCountHistogram, commitSoftwareCanvasGPUCompositingWorkerTimer,
285 ("Blink.Canvas.OffscreenCommit.SoftwareCanvasGPUCompositingWorker", 327 ("Blink.Canvas.OffscreenCommit.SoftwareCanvasGPUCompositingWorker",
286 0, 10000000, 50)); 328 0, 10000000, 50));
287 commitSoftwareCanvasGPUCompositingWorkerTimer.count(elapsedTime * 329 commitSoftwareCanvasGPUCompositingWorkerTimer.count(elapsedTime *
288 1000000.0); 330 1000000.0);
289 } 331 } */
290 break; 332 break;
291 case CommitSoftwareCanvasSoftwareCompositing: 333 case CommitSoftwareCanvasSoftwareCompositing:
292 if (isMainThread()) { 334 if (isMainThread()) {
293 DEFINE_STATIC_LOCAL(CustomCountHistogram, 335 DEFINE_STATIC_LOCAL(CustomCountHistogram,
294 commitSoftwareCanvasSoftwareCompositingMainTimer, 336 commitSoftwareCanvasSoftwareCompositingMainTimer,
295 ("Blink.Canvas.OffscreenCommit." 337 ("Blink.Canvas.OffscreenCommit."
296 "SoftwareCanvasSoftwareCompositingMain", 338 "SoftwareCanvasSoftwareCompositingMain",
297 0, 10000000, 50)); 339 0, 10000000, 50));
298 commitSoftwareCanvasSoftwareCompositingMainTimer.count(elapsedTime * 340 commitSoftwareCanvasSoftwareCompositingMainTimer.count(elapsedTime *
299 1000000.0); 341 1000000.0);
300 } else { 342 } /* else {
301 DEFINE_STATIC_LOCAL(CustomCountHistogram, 343 DEFINE_STATIC_LOCAL(CustomCountHistogram,
302 commitSoftwareCanvasSoftwareCompositingWorkerTimer, 344 commitSoftwareCanvasSoftwareCompositingWorkerTimer,
303 ("Blink.Canvas.OffscreenCommit." 345 ("Blink.Canvas.OffscreenCommit."
304 "SoftwareCanvasSoftwareCompositingWorker", 346 "SoftwareCanvasSoftwareCompositingWorker",
305 0, 10000000, 50)); 347 0, 10000000, 50));
306 commitSoftwareCanvasSoftwareCompositingWorkerTimer.count(elapsedTime * 348 commitSoftwareCanvasSoftwareCompositingWorkerTimer.count(elapsedTime *
307 1000000.0); 349 1000000.0);
308 } 350 } */
309 break; 351 break;
310 case OffscreenCanvasCommitTypeCount: 352 case OffscreenCanvasCommitTypeCount:
311 NOTREACHED(); 353 NOTREACHED();
312 } 354 }
313 355
314 m_sink->SubmitCompositorFrame(std::move(frame)); 356 m_sink->SubmitCompositorFrame(std::move(frame));
315 } 357 }
316 358
317 void OffscreenCanvasFrameDispatcherImpl::DidReceiveCompositorFrameAck() { 359 void OffscreenCanvasFrameDispatcherImpl::DidReceiveCompositorFrameAck() {
318 // TODO(fsamuel): Implement this. 360 // TODO(fsamuel): Implement this.
319 } 361 }
320 362
321 void OffscreenCanvasFrameDispatcherImpl::OnBeginFrame( 363 void OffscreenCanvasFrameDispatcherImpl::OnBeginFrame(
322 const cc::BeginFrameArgs& beginFrameArgs) {} 364 const cc::BeginFrameArgs& beginFrameArgs) {}
323 365
324 void OffscreenCanvasFrameDispatcherImpl::ReclaimResources( 366 void OffscreenCanvasFrameDispatcherImpl::ReclaimResources(
325 const cc::ReturnedResourceArray& resources) { 367 const cc::ReturnedResourceArray& resources) {
326 for (const auto& resource : resources) { 368 for (const auto& resource : resources) {
327 RefPtr<StaticBitmapImage> image = m_cachedImages.get(resource.id); 369 RefPtr<StaticBitmapImage> image = m_cachedImages.get(resource.id);
328 if (image) 370 if (image)
329 image->updateSyncToken(resource.sync_token); 371 image->updateSyncToken(resource.sync_token);
330 m_cachedImages.remove(resource.id); 372 reclaimResource(resource.id);
331 m_sharedBitmaps.remove(resource.id);
332 m_cachedTextureIds.remove(resource.id);
333 } 373 }
334 } 374 }
335 375
376 void OffscreenCanvasFrameDispatcherImpl::reclaimResource(unsigned resourceId) {
377 // An image resource needs to be returned by both the
378 // CompositorFrameSink and the HTMLCanvasElement. These
379 // events can happen in any order. The first of the two
380 // to return a given resource will result in the spare
381 // resource lock being lifted, and the second will delete
382 // the resource for real.
383 if (m_spareResourceLocks.contains(resourceId)) {
384 m_spareResourceLocks.remove(resourceId);
385 return;
386 }
387 m_cachedImages.remove(resourceId);
388 m_sharedBitmaps.remove(resourceId);
389 m_cachedTextureIds.remove(resourceId);
390 }
391
336 bool OffscreenCanvasFrameDispatcherImpl::verifyImageSize( 392 bool OffscreenCanvasFrameDispatcherImpl::verifyImageSize(
337 const IntSize imageSize) { 393 const IntSize imageSize) {
338 if (imageSize.width() == m_width && imageSize.height() == m_height) 394 if (imageSize.width() == m_width && imageSize.height() == m_height)
339 return true; 395 return true;
340 return false; 396 return false;
341 } 397 }
342 398
343 } // namespace blink 399 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698