OLD | NEW |
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 |
30 OffscreenCanvasFrameDispatcherImpl::OffscreenCanvasFrameDispatcherImpl( | 36 OffscreenCanvasFrameDispatcherImpl::OffscreenCanvasFrameDispatcherImpl( |
| 37 OffscreenCanvasFrameDispatcherClient* client, |
31 uint32_t clientId, | 38 uint32_t clientId, |
32 uint32_t sinkId, | 39 uint32_t sinkId, |
33 int canvasId, | 40 int canvasId, |
34 int width, | 41 int width, |
35 int height) | 42 int height) |
36 : m_frameSinkId(cc::FrameSinkId(clientId, sinkId)), | 43 : OffscreenCanvasFrameDispatcher(client), |
| 44 m_frameSinkId(cc::FrameSinkId(clientId, sinkId)), |
37 m_width(width), | 45 m_width(width), |
38 m_height(height), | 46 m_height(height), |
39 m_nextResourceId(1u), | 47 m_nextResourceId(1u), |
40 m_binding(this), | 48 m_binding(this), |
41 m_placeholderCanvasId(canvasId) { | 49 m_placeholderCanvasId(canvasId) { |
42 m_currentLocalFrameId = m_surfaceIdAllocator.GenerateId(); | 50 m_currentLocalFrameId = m_surfaceIdAllocator.GenerateId(); |
43 DCHECK(!m_sink.is_bound()); | 51 DCHECK(!m_sink.is_bound()); |
44 mojom::blink::OffscreenCanvasCompositorFrameSinkProviderPtr provider; | 52 mojom::blink::OffscreenCanvasCompositorFrameSinkProviderPtr provider; |
45 Platform::current()->interfaceProvider()->getInterface( | 53 Platform::current()->interfaceProvider()->getInterface( |
46 mojo::MakeRequest(&provider)); | 54 mojo::MakeRequest(&provider)); |
47 provider->CreateCompositorFrameSink(m_frameSinkId, | 55 provider->CreateCompositorFrameSink(m_frameSinkId, |
48 m_binding.CreateInterfacePtrAndBind(), | 56 m_binding.CreateInterfacePtrAndBind(), |
49 mojo::MakeRequest(&m_sink)); | 57 mojo::MakeRequest(&m_sink)); |
50 } | 58 } |
51 | 59 |
| 60 OffscreenCanvasFrameDispatcherImpl::~OffscreenCanvasFrameDispatcherImpl() { |
| 61 m_syntheticBeginFrameTask.cancel(); |
| 62 } |
| 63 |
52 void OffscreenCanvasFrameDispatcherImpl::setTransferableResourceToSharedBitmap( | 64 void OffscreenCanvasFrameDispatcherImpl::setTransferableResourceToSharedBitmap( |
53 cc::TransferableResource& resource, | 65 cc::TransferableResource& resource, |
54 RefPtr<StaticBitmapImage> image) { | 66 RefPtr<StaticBitmapImage> image) { |
55 std::unique_ptr<cc::SharedBitmap> bitmap = | 67 std::unique_ptr<cc::SharedBitmap> bitmap = |
56 Platform::current()->allocateSharedBitmap(IntSize(m_width, m_height)); | 68 Platform::current()->allocateSharedBitmap(IntSize(m_width, m_height)); |
57 if (!bitmap) | 69 if (!bitmap) |
58 return; | 70 return; |
59 unsigned char* pixels = bitmap->pixels(); | 71 unsigned char* pixels = bitmap->pixels(); |
60 DCHECK(pixels); | 72 DCHECK(pixels); |
61 SkImageInfo imageInfo = SkImageInfo::Make( | 73 SkImageInfo imageInfo = SkImageInfo::Make( |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 182 } |
171 } | 183 } |
172 | 184 |
173 } // namespace | 185 } // namespace |
174 | 186 |
175 void OffscreenCanvasFrameDispatcherImpl::dispatchFrame( | 187 void OffscreenCanvasFrameDispatcherImpl::dispatchFrame( |
176 RefPtr<StaticBitmapImage> image, | 188 RefPtr<StaticBitmapImage> image, |
177 double commitStartTime, | 189 double commitStartTime, |
178 bool isWebGLSoftwareRendering /* This flag is true when WebGL's commit is | 190 bool isWebGLSoftwareRendering /* This flag is true when WebGL's commit is |
179 called on SwiftShader. */) { | 191 called on SwiftShader. */) { |
180 if (!image) | 192 if (!image || !verifyImageSize(image->size())) |
181 return; | |
182 if (!verifyImageSize(image->size())) | |
183 return; | 193 return; |
184 cc::CompositorFrame frame; | 194 cc::CompositorFrame frame; |
185 // TODO(crbug.com/652931): update the device_scale_factor | 195 // TODO(crbug.com/652931): update the device_scale_factor |
186 frame.metadata.device_scale_factor = 1.0f; | 196 frame.metadata.device_scale_factor = 1.0f; |
187 | 197 |
188 const gfx::Rect bounds(m_width, m_height); | 198 const gfx::Rect bounds(m_width, m_height); |
189 const int renderPassId = 1; | 199 const int renderPassId = 1; |
190 std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create(); | 200 std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create(); |
191 pass->SetNew(renderPassId, bounds, bounds, gfx::Transform()); | 201 pass->SetNew(renderPassId, bounds, bounds, gfx::Transform()); |
192 pass->has_transparent_background = false; | 202 pass->has_transparent_background = false; |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 0, 10000000, 50)); | 361 0, 10000000, 50)); |
352 commitSoftwareCanvasSoftwareCompositingWorkerTimer.count(elapsedTime * | 362 commitSoftwareCanvasSoftwareCompositingWorkerTimer.count(elapsedTime * |
353 1000000.0); | 363 1000000.0); |
354 } | 364 } |
355 break; | 365 break; |
356 case OffscreenCanvasCommitTypeCount: | 366 case OffscreenCanvasCommitTypeCount: |
357 NOTREACHED(); | 367 NOTREACHED(); |
358 } | 368 } |
359 | 369 |
360 m_sink->SubmitCompositorFrame(m_currentLocalFrameId, std::move(frame)); | 370 m_sink->SubmitCompositorFrame(m_currentLocalFrameId, std::move(frame)); |
| 371 |
| 372 // TODO(crbug.com/674744): Get BeginFrame to fire on its own. |
| 373 scheduleSyntheticBeginFrame(); |
| 374 } |
| 375 |
| 376 void OffscreenCanvasFrameDispatcherImpl::scheduleSyntheticBeginFrame() { |
| 377 m_syntheticBeginFrameTask = |
| 378 Platform::current() |
| 379 ->currentThread() |
| 380 ->getWebTaskRunner() |
| 381 ->postDelayedCancellableTask( |
| 382 BLINK_FROM_HERE, |
| 383 WTF::bind(&OffscreenCanvasFrameDispatcherImpl::OnBeginFrame, |
| 384 WTF::unretained(this), cc::BeginFrameArgs()), |
| 385 16); |
361 } | 386 } |
362 | 387 |
363 void OffscreenCanvasFrameDispatcherImpl::DidReceiveCompositorFrameAck() { | 388 void OffscreenCanvasFrameDispatcherImpl::DidReceiveCompositorFrameAck() { |
364 // TODO(fsamuel): Implement this. | 389 // TODO(fsamuel): Implement this. |
365 } | 390 } |
366 | 391 |
367 void OffscreenCanvasFrameDispatcherImpl::OnBeginFrame( | 392 void OffscreenCanvasFrameDispatcherImpl::OnBeginFrame( |
368 const cc::BeginFrameArgs& beginFrameArgs) {} | 393 const cc::BeginFrameArgs& beginFrameArgs) { |
| 394 if (!client()) |
| 395 return; |
| 396 unsigned framesInFlight = m_cachedImages.size() + m_sharedBitmaps.size() + |
| 397 m_cachedTextureIds.size(); |
| 398 |
| 399 // Limit the rate of compositor commits. |
| 400 if (framesInFlight < kMaximumOffscreenCanvasBufferCount) { |
| 401 client()->beginFrame(); |
| 402 } else { |
| 403 // TODO(crbug.com/674744): Get BeginFrame to fire on its own. |
| 404 // The following call is to reschedule the frame in cases where we encounter |
| 405 // a backlog. |
| 406 scheduleSyntheticBeginFrame(); |
| 407 } |
| 408 } |
369 | 409 |
370 void OffscreenCanvasFrameDispatcherImpl::ReclaimResources( | 410 void OffscreenCanvasFrameDispatcherImpl::ReclaimResources( |
371 const cc::ReturnedResourceArray& resources) { | 411 const cc::ReturnedResourceArray& resources) { |
372 for (const auto& resource : resources) { | 412 for (const auto& resource : resources) { |
373 RefPtr<StaticBitmapImage> image = m_cachedImages.get(resource.id); | 413 RefPtr<StaticBitmapImage> image = m_cachedImages.get(resource.id); |
374 if (image) | 414 if (image) |
375 image->updateSyncToken(resource.sync_token); | 415 image->updateSyncToken(resource.sync_token); |
376 reclaimResource(resource.id); | 416 reclaimResource(resource.id); |
377 } | 417 } |
378 } | 418 } |
379 | 419 |
380 void OffscreenCanvasFrameDispatcherImpl::WillDrawSurface() { | 420 void OffscreenCanvasFrameDispatcherImpl::WillDrawSurface() { |
381 // TODO(fsamuel, staraz): Implement this. | 421 // TODO(fsamuel, staraz): Implement this. |
382 NOTIMPLEMENTED(); | |
383 } | 422 } |
384 | 423 |
385 void OffscreenCanvasFrameDispatcherImpl::reclaimResource(unsigned resourceId) { | 424 void OffscreenCanvasFrameDispatcherImpl::reclaimResource(unsigned resourceId) { |
386 // An image resource needs to be returned by both the | 425 // An image resource needs to be returned by both the |
387 // CompositorFrameSink and the HTMLCanvasElement. These | 426 // CompositorFrameSink and the HTMLCanvasElement. These |
388 // events can happen in any order. The first of the two | 427 // events can happen in any order. The first of the two |
389 // to return a given resource will result in the spare | 428 // to return a given resource will result in the spare |
390 // resource lock being lifted, and the second will delete | 429 // resource lock being lifted, and the second will delete |
391 // the resource for real. | 430 // the resource for real. |
392 if (m_spareResourceLocks.contains(resourceId)) { | 431 if (m_spareResourceLocks.contains(resourceId)) { |
(...skipping 11 matching lines...) Expand all Loading... |
404 return true; | 443 return true; |
405 return false; | 444 return false; |
406 } | 445 } |
407 | 446 |
408 void OffscreenCanvasFrameDispatcherImpl::reshape(int width, int height) { | 447 void OffscreenCanvasFrameDispatcherImpl::reshape(int width, int height) { |
409 m_width = width; | 448 m_width = width; |
410 m_height = height; | 449 m_height = height; |
411 } | 450 } |
412 | 451 |
413 } // namespace blink | 452 } // namespace blink |
OLD | NEW |