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

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

Issue 2644653003: Make OffscreenCanvas animation in sync with its placeholder canvas's parent frame rate (Closed)
Patch Set: rebase again Created 3 years, 10 months 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/CrossThreadFunctional.h"
11 #include "platform/Histogram.h" 11 #include "platform/Histogram.h"
12 #include "platform/WebTaskRunner.h" 12 #include "platform/WebTaskRunner.h"
13 #include "platform/graphics/OffscreenCanvasPlaceholder.h" 13 #include "platform/graphics/OffscreenCanvasPlaceholder.h"
14 #include "platform/graphics/gpu/SharedGpuContext.h" 14 #include "platform/graphics/gpu/SharedGpuContext.h"
15 #include "public/platform/InterfaceProvider.h" 15 #include "public/platform/InterfaceProvider.h"
16 #include "public/platform/Platform.h" 16 #include "public/platform/Platform.h"
17 #include "public/platform/WebGraphicsContext3DProvider.h" 17 #include "public/platform/WebGraphicsContext3DProvider.h"
18 #include "public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom -blink.h" 18 #include "public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom -blink.h"
19 #include "third_party/khronos/GLES2/gl2.h" 19 #include "third_party/khronos/GLES2/gl2.h"
20 #include "third_party/khronos/GLES2/gl2ext.h" 20 #include "third_party/khronos/GLES2/gl2ext.h"
21 #include "third_party/skia/include/core/SkColor.h" 21 #include "third_party/skia/include/core/SkColor.h"
22 #include "third_party/skia/include/core/SkImage.h" 22 #include "third_party/skia/include/core/SkImage.h"
23 #include "ui/gfx/geometry/rect.h" 23 #include "ui/gfx/geometry/rect.h"
24 #include "ui/gfx/transform.h" 24 #include "ui/gfx/transform.h"
25 #include "wtf/typed_arrays/ArrayBuffer.h" 25 #include "wtf/typed_arrays/ArrayBuffer.h"
26 #include "wtf/typed_arrays/Uint8Array.h" 26 #include "wtf/typed_arrays/Uint8Array.h"
27 27
28 namespace blink { 28 namespace blink {
29 29
30 // This constant specifies the maximum number of pixel buffer that are allowed
31 // to co-exist at a given time. The minimum number is 2 (double buffered).
32 // larger numbers can help maintain a steadier frame rates, but they increase
33 // latency.
34 const int kMaximumOffscreenCanvasBufferCount = 3;
35
36 OffscreenCanvasFrameDispatcherImpl::OffscreenCanvasFrameDispatcherImpl( 30 OffscreenCanvasFrameDispatcherImpl::OffscreenCanvasFrameDispatcherImpl(
37 OffscreenCanvasFrameDispatcherClient* client, 31 OffscreenCanvasFrameDispatcherClient* client,
38 uint32_t clientId, 32 uint32_t clientId,
39 uint32_t sinkId, 33 uint32_t sinkId,
40 int canvasId, 34 int canvasId,
41 int width, 35 int width,
42 int height) 36 int height)
43 : OffscreenCanvasFrameDispatcher(client), 37 : OffscreenCanvasFrameDispatcher(client),
44 m_frameSinkId(cc::FrameSinkId(clientId, sinkId)), 38 m_frameSinkId(cc::FrameSinkId(clientId, sinkId)),
45 m_width(width), 39 m_width(width),
46 m_height(height), 40 m_height(height),
47 m_changeSizeForNextCommit(false), 41 m_changeSizeForNextCommit(false),
42 m_needsBeginFrame(false),
48 m_nextResourceId(1u), 43 m_nextResourceId(1u),
49 m_binding(this), 44 m_binding(this),
50 m_placeholderCanvasId(canvasId) { 45 m_placeholderCanvasId(canvasId) {
51 m_currentLocalSurfaceId = m_surfaceIdAllocator.GenerateId(); 46 if (m_frameSinkId.is_valid()) {
52 DCHECK(!m_sink.is_bound()); 47 // Only frameless canvas pass an invalid frame sink id; we don't create
53 mojom::blink::OffscreenCanvasCompositorFrameSinkProviderPtr provider; 48 // mojo channel for this special case.
54 Platform::current()->interfaceProvider()->getInterface( 49 m_currentLocalSurfaceId = m_surfaceIdAllocator.GenerateId();
55 mojo::MakeRequest(&provider)); 50 DCHECK(!m_sink.is_bound());
56 provider->CreateCompositorFrameSink(m_frameSinkId, 51 mojom::blink::OffscreenCanvasCompositorFrameSinkProviderPtr provider;
57 m_binding.CreateInterfacePtrAndBind(), 52 Platform::current()->interfaceProvider()->getInterface(
58 mojo::MakeRequest(&m_sink)); 53 mojo::MakeRequest(&provider));
54 provider->CreateCompositorFrameSink(m_frameSinkId,
55 m_binding.CreateInterfacePtrAndBind(),
56 mojo::MakeRequest(&m_sink));
57 }
59 } 58 }
60 59
61 OffscreenCanvasFrameDispatcherImpl::~OffscreenCanvasFrameDispatcherImpl() { 60 OffscreenCanvasFrameDispatcherImpl::~OffscreenCanvasFrameDispatcherImpl() {
62 m_syntheticBeginFrameTask.cancel();
63 } 61 }
64 62
65 void OffscreenCanvasFrameDispatcherImpl::setTransferableResourceToSharedBitmap( 63 void OffscreenCanvasFrameDispatcherImpl::setTransferableResourceToSharedBitmap(
66 cc::TransferableResource& resource, 64 cc::TransferableResource& resource,
67 RefPtr<StaticBitmapImage> image) { 65 RefPtr<StaticBitmapImage> image) {
68 std::unique_ptr<cc::SharedBitmap> bitmap = 66 std::unique_ptr<cc::SharedBitmap> bitmap =
69 Platform::current()->allocateSharedBitmap(IntSize(m_width, m_height)); 67 Platform::current()->allocateSharedBitmap(IntSize(m_width, m_height));
70 if (!bitmap) 68 if (!bitmap)
71 return; 69 return;
72 unsigned char* pixels = bitmap->pixels(); 70 unsigned char* pixels = bitmap->pixels();
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 OffscreenCanvasPlaceholder::getPlaceholderById(placeholderCanvasId); 176 OffscreenCanvasPlaceholder::getPlaceholderById(placeholderCanvasId);
179 if (placeholderCanvas) { 177 if (placeholderCanvas) {
180 placeholderCanvas->setPlaceholderFrame(std::move(image), 178 placeholderCanvas->setPlaceholderFrame(std::move(image),
181 std::move(dispatcher), 179 std::move(dispatcher),
182 std::move(taskRunner), resourceId); 180 std::move(taskRunner), resourceId);
183 } 181 }
184 } 182 }
185 183
186 } // namespace 184 } // namespace
187 185
186 void OffscreenCanvasFrameDispatcherImpl::postImageToPlaceholder(
187 RefPtr<StaticBitmapImage> image) {
188 // After this point, |image| can only be used on the main thread, until
189 // it is returned.
190 image->transfer();
191 RefPtr<WebTaskRunner> dispatcherTaskRunner =
192 Platform::current()->currentThread()->getWebTaskRunner();
193
194 Platform::current()->mainThread()->getWebTaskRunner()->postTask(
195 BLINK_FROM_HERE,
196 crossThreadBind(updatePlaceholderImage, this->createWeakPtr(),
197 WTF::passed(std::move(dispatcherTaskRunner)),
198 m_placeholderCanvasId, std::move(image),
199 m_nextResourceId));
200 m_spareResourceLocks.insert(m_nextResourceId);
201 }
202
188 void OffscreenCanvasFrameDispatcherImpl::dispatchFrame( 203 void OffscreenCanvasFrameDispatcherImpl::dispatchFrame(
189 RefPtr<StaticBitmapImage> image, 204 RefPtr<StaticBitmapImage> image,
190 double commitStartTime, 205 double commitStartTime,
191 bool isWebGLSoftwareRendering /* This flag is true when WebGL's commit is 206 bool isWebGLSoftwareRendering /* This flag is true when WebGL's commit is
192 called on SwiftShader. */) { 207 called on SwiftShader. */) {
193 if (!image || !verifyImageSize(image->size())) 208 if (!image || !verifyImageSize(image->size()))
194 return; 209 return;
210 if (!m_frameSinkId.is_valid()) {
211 postImageToPlaceholder(std::move(image));
212 return;
213 }
195 cc::CompositorFrame frame; 214 cc::CompositorFrame frame;
196 // TODO(crbug.com/652931): update the device_scale_factor 215 // TODO(crbug.com/652931): update the device_scale_factor
197 frame.metadata.device_scale_factor = 1.0f; 216 frame.metadata.device_scale_factor = 1.0f;
198 217
199 const gfx::Rect bounds(m_width, m_height); 218 const gfx::Rect bounds(m_width, m_height);
200 const int renderPassId = 1; 219 const int renderPassId = 1;
201 std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create(); 220 std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
202 pass->SetNew(renderPassId, bounds, bounds, gfx::Transform()); 221 pass->SetNew(renderPassId, bounds, bounds, gfx::Transform());
203 pass->has_transparent_background = false; 222 pass->has_transparent_background = false;
204 223
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 // Case 3: canvas is not gpu-accelerated, but compositor is 259 // Case 3: canvas is not gpu-accelerated, but compositor is
241 commitType = CommitSoftwareCanvasGPUCompositing; 260 commitType = CommitSoftwareCanvasGPUCompositing;
242 setTransferableResourceToSharedGPUContext(resource, image); 261 setTransferableResourceToSharedGPUContext(resource, image);
243 } else { 262 } else {
244 // Case 4: both canvas and compositor are not gpu accelerated. 263 // Case 4: both canvas and compositor are not gpu accelerated.
245 commitType = CommitSoftwareCanvasSoftwareCompositing; 264 commitType = CommitSoftwareCanvasSoftwareCompositing;
246 setTransferableResourceToSharedBitmap(resource, image); 265 setTransferableResourceToSharedBitmap(resource, image);
247 } 266 }
248 } 267 }
249 268
250 // After this point, |image| can only be used on the main thread, until 269 postImageToPlaceholder(std::move(image));
251 // it is returned.
252 image->transfer();
253 RefPtr<WebTaskRunner> dispatcherTaskRunner =
254 Platform::current()->currentThread()->getWebTaskRunner();
255
256 Platform::current()->mainThread()->getWebTaskRunner()->postTask(
257 BLINK_FROM_HERE,
258 crossThreadBind(updatePlaceholderImage, this->createWeakPtr(),
259 WTF::passed(std::move(dispatcherTaskRunner)),
260 m_placeholderCanvasId, std::move(image), resource.id));
261 m_spareResourceLocks.insert(m_nextResourceId);
262
263 commitTypeHistogram.count(commitType); 270 commitTypeHistogram.count(commitType);
264 271
265 m_nextResourceId++; 272 m_nextResourceId++;
266 frame.resource_list.push_back(std::move(resource)); 273 frame.resource_list.push_back(std::move(resource));
267 274
268 cc::TextureDrawQuad* quad = 275 cc::TextureDrawQuad* quad =
269 pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>(); 276 pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>();
270 gfx::Size rectSize(m_width, m_height); 277 gfx::Size rectSize(m_width, m_height);
271 278
272 const bool needsBlending = true; 279 const bool needsBlending = true;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 } 371 }
365 break; 372 break;
366 case OffscreenCanvasCommitTypeCount: 373 case OffscreenCanvasCommitTypeCount:
367 NOTREACHED(); 374 NOTREACHED();
368 } 375 }
369 376
370 if (m_changeSizeForNextCommit) { 377 if (m_changeSizeForNextCommit) {
371 m_currentLocalSurfaceId = m_surfaceIdAllocator.GenerateId(); 378 m_currentLocalSurfaceId = m_surfaceIdAllocator.GenerateId();
372 m_changeSizeForNextCommit = false; 379 m_changeSizeForNextCommit = false;
373 } 380 }
381
374 m_sink->SubmitCompositorFrame(m_currentLocalSurfaceId, std::move(frame)); 382 m_sink->SubmitCompositorFrame(m_currentLocalSurfaceId, std::move(frame));
375
376 // TODO(crbug.com/674744): Get BeginFrame to fire on its own.
377 scheduleSyntheticBeginFrame();
378 }
379
380 void OffscreenCanvasFrameDispatcherImpl::scheduleSyntheticBeginFrame() {
381 m_syntheticBeginFrameTask =
382 Platform::current()
383 ->currentThread()
384 ->getWebTaskRunner()
385 ->postDelayedCancellableTask(
386 BLINK_FROM_HERE,
387 WTF::bind(&OffscreenCanvasFrameDispatcherImpl::OnBeginFrame,
388 WTF::unretained(this), cc::BeginFrameArgs()),
389 16);
390 } 383 }
391 384
392 void OffscreenCanvasFrameDispatcherImpl::DidReceiveCompositorFrameAck() { 385 void OffscreenCanvasFrameDispatcherImpl::DidReceiveCompositorFrameAck() {
393 // TODO(fsamuel): Implement this. 386 // TODO(fsamuel): Implement this.
394 } 387 }
395 388
396 void OffscreenCanvasFrameDispatcherImpl::OnBeginFrame( 389 void OffscreenCanvasFrameDispatcherImpl::setNeedsBeginFrame(
397 const cc::BeginFrameArgs& beginFrameArgs) { 390 bool needsBeginFrame) {
398 if (!client()) 391 if (m_sink && needsBeginFrame != m_needsBeginFrame) {
399 return; 392 m_needsBeginFrame = needsBeginFrame;
400 unsigned framesInFlight = m_cachedImages.size() + m_sharedBitmaps.size() + 393 m_sink->SetNeedsBeginFrame(needsBeginFrame);
401 m_cachedTextureIds.size();
402
403 // Limit the rate of compositor commits.
404 if (framesInFlight < kMaximumOffscreenCanvasBufferCount) {
405 client()->beginFrame();
406 } else {
407 // TODO(crbug.com/674744): Get BeginFrame to fire on its own.
408 // The following call is to reschedule the frame in cases where we encounter
409 // a backlog.
410 scheduleSyntheticBeginFrame();
411 } 394 }
412 } 395 }
413 396
397 void OffscreenCanvasFrameDispatcherImpl::OnBeginFrame(
398 const cc::BeginFrameArgs& beginFrameArgs) {
399 DCHECK(client());
400 client()->beginFrame();
401 }
402
414 void OffscreenCanvasFrameDispatcherImpl::ReclaimResources( 403 void OffscreenCanvasFrameDispatcherImpl::ReclaimResources(
415 const cc::ReturnedResourceArray& resources) { 404 const cc::ReturnedResourceArray& resources) {
416 for (const auto& resource : resources) { 405 for (const auto& resource : resources) {
417 RefPtr<StaticBitmapImage> image = m_cachedImages.get(resource.id); 406 RefPtr<StaticBitmapImage> image = m_cachedImages.get(resource.id);
418 if (image) 407 if (image)
419 image->updateSyncToken(resource.sync_token); 408 image->updateSyncToken(resource.sync_token);
420 reclaimResource(resource.id); 409 reclaimResource(resource.id);
421 } 410 }
422 } 411 }
423 412
(...skipping 26 matching lines...) Expand all
450 439
451 void OffscreenCanvasFrameDispatcherImpl::reshape(int width, int height) { 440 void OffscreenCanvasFrameDispatcherImpl::reshape(int width, int height) {
452 if (m_width != width || m_height != height) { 441 if (m_width != width || m_height != height) {
453 m_width = width; 442 m_width = width;
454 m_height = height; 443 m_height = height;
455 m_changeSizeForNextCommit = true; 444 m_changeSizeForNextCommit = true;
456 } 445 }
457 } 446 }
458 447
459 } // namespace blink 448 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698