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