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/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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |