| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "core/offscreencanvas/OffscreenCanvas.h" | 5 #include "core/offscreencanvas/OffscreenCanvas.h" |
| 6 | 6 |
| 7 #include <memory> |
| 7 #include "core/dom/ExceptionCode.h" | 8 #include "core/dom/ExceptionCode.h" |
| 8 #include "core/fileapi/Blob.h" | 9 #include "core/fileapi/Blob.h" |
| 9 #include "core/frame/ImageBitmap.h" | 10 #include "core/frame/ImageBitmap.h" |
| 10 #include "core/html/ImageData.h" | 11 #include "core/html/ImageData.h" |
| 11 #include "core/html/canvas/CanvasAsyncBlobCreator.h" | 12 #include "core/html/canvas/CanvasAsyncBlobCreator.h" |
| 12 #include "core/html/canvas/CanvasContextCreationAttributes.h" | 13 #include "core/html/canvas/CanvasContextCreationAttributes.h" |
| 13 #include "core/html/canvas/CanvasRenderingContext.h" | 14 #include "core/html/canvas/CanvasRenderingContext.h" |
| 14 #include "core/html/canvas/CanvasRenderingContextFactory.h" | 15 #include "core/html/canvas/CanvasRenderingContextFactory.h" |
| 15 #include "platform/graphics/Image.h" | 16 #include "platform/graphics/Image.h" |
| 16 #include "platform/graphics/ImageBuffer.h" | 17 #include "platform/graphics/ImageBuffer.h" |
| 17 #include "platform/graphics/OffscreenCanvasFrameDispatcherImpl.h" | 18 #include "platform/graphics/OffscreenCanvasFrameDispatcherImpl.h" |
| 18 #include "platform/graphics/StaticBitmapImage.h" | 19 #include "platform/graphics/StaticBitmapImage.h" |
| 19 #include "platform/image-encoders/ImageEncoderUtils.h" | 20 #include "platform/image-encoders/ImageEncoderUtils.h" |
| 21 #include "public/platform/Platform.h" |
| 20 #include "wtf/MathExtras.h" | 22 #include "wtf/MathExtras.h" |
| 21 #include <memory> | |
| 22 | 23 |
| 23 namespace blink { | 24 namespace blink { |
| 24 | 25 |
| 25 OffscreenCanvas::OffscreenCanvas(const IntSize& size) : m_size(size) {} | 26 OffscreenCanvas::OffscreenCanvas(const IntSize& size) : m_size(size) {} |
| 26 | 27 |
| 27 OffscreenCanvas* OffscreenCanvas::create(unsigned width, unsigned height) { | 28 OffscreenCanvas* OffscreenCanvas::create(unsigned width, unsigned height) { |
| 28 return new OffscreenCanvas( | 29 return new OffscreenCanvas( |
| 29 IntSize(clampTo<int>(width), clampTo<int>(height))); | 30 IntSize(clampTo<int>(width), clampTo<int>(height))); |
| 30 } | 31 } |
| 31 | 32 |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 this, m_clientId, m_sinkId, m_placeholderCanvasId, m_size.width(), | 231 this, m_clientId, m_sinkId, m_placeholderCanvasId, m_size.width(), |
| 231 m_size.height())); | 232 m_size.height())); |
| 232 } | 233 } |
| 233 return m_frameDispatcher.get(); | 234 return m_frameDispatcher.get(); |
| 234 } | 235 } |
| 235 | 236 |
| 236 ScriptPromise OffscreenCanvas::commit(RefPtr<StaticBitmapImage> image, | 237 ScriptPromise OffscreenCanvas::commit(RefPtr<StaticBitmapImage> image, |
| 237 bool isWebGLSoftwareRendering, | 238 bool isWebGLSoftwareRendering, |
| 238 ScriptState* scriptState) { | 239 ScriptState* scriptState) { |
| 239 getOrCreateFrameDispatcher()->setNeedsBeginFrame(true); | 240 getOrCreateFrameDispatcher()->setNeedsBeginFrame(true); |
| 240 if (m_commitPromiseResolver) { | 241 |
| 241 if (image) { | 242 if (!m_commitPromiseResolver) { |
| 242 m_overdrawFrame = std::move(image); | |
| 243 m_overdrawFrameIsWebGLSoftwareRendering = isWebGLSoftwareRendering; | |
| 244 } | |
| 245 } else { | |
| 246 m_overdrawFrame = nullptr; | |
| 247 m_commitPromiseResolver = ScriptPromiseResolver::create(scriptState); | 243 m_commitPromiseResolver = ScriptPromiseResolver::create(scriptState); |
| 248 m_commitPromiseResolver->keepAliveWhilePending(); | 244 m_commitPromiseResolver->keepAliveWhilePending(); |
| 249 // TODO(eseckler): OffscreenCanvas shouldn't dispatch CompositorFrames | 245 |
| 250 // without a prior BeginFrame. | 246 if (image) { |
| 251 doCommit(std::move(image), isWebGLSoftwareRendering); | 247 // We defer the submission of commit frames at the end of JS task |
| 248 m_currentFrame = std::move(image); |
| 249 m_currentFrameIsWebGLSoftwareRendering = isWebGLSoftwareRendering; |
| 250 m_context->needsFinalizeFrame(); |
| 251 } |
| 252 } else if (image) { |
| 253 // Two possible scenarios: |
| 254 // 1. An override of m_currentFrame can happen when there are multiple |
| 255 // frames committed before JS task finishes. (m_currentFrame!=nullptr) |
| 256 // 2. The current frame has been dispatched but the promise is not |
| 257 // resolved yet. (m_currentFrame==nullptr) |
| 258 m_currentFrame = std::move(image); |
| 259 m_currentFrameIsWebGLSoftwareRendering = isWebGLSoftwareRendering; |
| 252 } | 260 } |
| 261 |
| 253 return m_commitPromiseResolver->promise(); | 262 return m_commitPromiseResolver->promise(); |
| 254 } | 263 } |
| 255 | 264 |
| 265 void OffscreenCanvas::finalizeFrame() { |
| 266 if (m_currentFrame) { |
| 267 // TODO(eseckler): OffscreenCanvas shouldn't dispatch CompositorFrames |
| 268 // without a prior BeginFrame. |
| 269 doCommit(std::move(m_currentFrame), m_currentFrameIsWebGLSoftwareRendering); |
| 270 } |
| 271 } |
| 272 |
| 256 void OffscreenCanvas::doCommit(RefPtr<StaticBitmapImage> image, | 273 void OffscreenCanvas::doCommit(RefPtr<StaticBitmapImage> image, |
| 257 bool isWebGLSoftwareRendering) { | 274 bool isWebGLSoftwareRendering) { |
| 258 double commitStartTime = WTF::monotonicallyIncreasingTime(); | 275 double commitStartTime = WTF::monotonicallyIncreasingTime(); |
| 259 getOrCreateFrameDispatcher()->dispatchFrame(std::move(image), commitStartTime, | 276 getOrCreateFrameDispatcher()->dispatchFrame(std::move(image), commitStartTime, |
| 260 isWebGLSoftwareRendering); | 277 isWebGLSoftwareRendering); |
| 261 } | 278 } |
| 262 | 279 |
| 263 void OffscreenCanvas::beginFrame() { | 280 void OffscreenCanvas::beginFrame() { |
| 264 // TODO(eseckler): beginFrame() shouldn't be used as confirmation of | 281 if (m_currentFrame) { |
| 265 // CompositorFrame activation. | 282 // TODO(eseckler): beginFrame() shouldn't be used as confirmation of |
| 266 if (m_overdrawFrame) { | 283 // CompositorFrame activation. |
| 267 // if we have an overdraw backlog, push the frame from the backlog | 284 // If we have an overdraw backlog, push the frame from the backlog |
| 268 // first and save the promise resolution for later. | 285 // first and save the promise resolution for later. |
| 269 doCommit(std::move(m_overdrawFrame), | 286 // Then we need to wait for one more frame time to resolve the existing |
| 270 m_overdrawFrameIsWebGLSoftwareRendering); | 287 // promise. |
| 288 doCommit(std::move(m_currentFrame), m_currentFrameIsWebGLSoftwareRendering); |
| 271 } else if (m_commitPromiseResolver) { | 289 } else if (m_commitPromiseResolver) { |
| 272 m_commitPromiseResolver->resolve(); | 290 m_commitPromiseResolver->resolve(); |
| 273 m_commitPromiseResolver.clear(); | 291 m_commitPromiseResolver.clear(); |
| 274 // We need to tell parent frame to stop sending signals on begin frame to | 292 // We need to tell parent frame to stop sending signals on begin frame to |
| 275 // avoid overhead once we resolve the promise. | 293 // avoid overhead once we resolve the promise. |
| 276 // In the case of overdraw frame (if block), we still need to wait for one | |
| 277 // more frame time to resolve the existing promise. | |
| 278 getOrCreateFrameDispatcher()->setNeedsBeginFrame(false); | 294 getOrCreateFrameDispatcher()->setNeedsBeginFrame(false); |
| 279 } | 295 } |
| 280 } | 296 } |
| 281 | 297 |
| 282 ScriptPromise OffscreenCanvas::convertToBlob(ScriptState* scriptState, | 298 ScriptPromise OffscreenCanvas::convertToBlob(ScriptState* scriptState, |
| 283 const ImageEncodeOptions& options, | 299 const ImageEncodeOptions& options, |
| 284 ExceptionState& exceptionState) { | 300 ExceptionState& exceptionState) { |
| 285 if (this->isNeutered()) { | 301 if (this->isNeutered()) { |
| 286 exceptionState.throwDOMException(InvalidStateError, | 302 exceptionState.throwDOMException(InvalidStateError, |
| 287 "OffscreenCanvas object is detached."); | 303 "OffscreenCanvas object is detached."); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 } | 347 } |
| 332 | 348 |
| 333 DEFINE_TRACE(OffscreenCanvas) { | 349 DEFINE_TRACE(OffscreenCanvas) { |
| 334 visitor->trace(m_context); | 350 visitor->trace(m_context); |
| 335 visitor->trace(m_executionContext); | 351 visitor->trace(m_executionContext); |
| 336 visitor->trace(m_commitPromiseResolver); | 352 visitor->trace(m_commitPromiseResolver); |
| 337 EventTargetWithInlineData::trace(visitor); | 353 EventTargetWithInlineData::trace(visitor); |
| 338 } | 354 } |
| 339 | 355 |
| 340 } // namespace blink | 356 } // namespace blink |
| OLD | NEW |