diff options
Diffstat (limited to 'third_party/WebKit')
8 files changed, 77 insertions, 8 deletions
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites index 6c191d5..48c7271 100644 --- a/third_party/WebKit/LayoutTests/VirtualTestSuites +++ b/third_party/WebKit/LayoutTests/VirtualTestSuites @@ -12,6 +12,11 @@ }, { "prefix": "threaded", + "base": "fast/canvas/toBlob", + "args": ["--enable-threaded-compositing"] + }, + { + "prefix": "threaded", "base": "compositing/visibility", "args": ["--enable-threaded-compositing"] }, diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-toBlob-defaultpng-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/toBlob/canvas-toBlob-defaultpng-expected.txt index fed3498..fed3498 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-toBlob-defaultpng-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/canvas/toBlob/canvas-toBlob-defaultpng-expected.txt diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-toBlob-defaultpng.html b/third_party/WebKit/LayoutTests/fast/canvas/toBlob/canvas-toBlob-defaultpng.html index 14cab66..c68d3ea 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-toBlob-defaultpng.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/toBlob/canvas-toBlob-defaultpng.html @@ -1,4 +1,4 @@ -<script src = "../../resources/js-test.js"></script> +<script src = "../../../resources/js-test.js"></script> <script type = 'text/javascript'> jsTestIsAsync = true; description("Test that verifies whether the image data survives the toBlob process after async image encoding"); diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-png-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/toBlob/canvas-toBlob-toDataURL-race-imageEncoder-png-expected.txt index ac789eb..ac789eb 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-png-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/canvas/toBlob/canvas-toBlob-toDataURL-race-imageEncoder-png-expected.txt diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-png.html b/third_party/WebKit/LayoutTests/fast/canvas/toBlob/canvas-toBlob-toDataURL-race-imageEncoder-png.html index 3bbcaa7..806cc27 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-png.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/toBlob/canvas-toBlob-toDataURL-race-imageEncoder-png.html @@ -1,5 +1,5 @@ -<script src = "../../resources/js-test.js"></script> -<script src = "script-tests/canvas-toBlob-toDataURL-race.js"></script> +<script src = "../../../resources/js-test.js"></script> +<script src = "../script-tests/canvas-toBlob-toDataURL-race.js"></script> <script type = 'text/javascript'> description("Verifies if synchronous PNG image encoding (toDataURL) conflicts with asynchronous image encoding (toBlob)"); diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp index 6fa3c4b..2b554b5 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp @@ -611,7 +611,11 @@ void HTMLCanvasElement::toBlob(ScriptState* scriptState, BlobCallback* callback, RefPtr<CanvasAsyncBlobCreator> asyncCreatorRef = CanvasAsyncBlobCreator::create(imageDataRef.release(), encodingMimeType, imageData->size(), callback, scriptState->executionContext()); - asyncCreatorRef->scheduleAsyncBlobCreation(quality); + if (Platform::current()->isThreadedCompositingEnabled() && (encodingMimeType == DefaultMimeType)) { + asyncCreatorRef->scheduleAsyncBlobCreation(true); + } else { + asyncCreatorRef->scheduleAsyncBlobCreation(false, quality); + } } void HTMLCanvasElement::addListener(CanvasDrawListener* listener) diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp index d2fb12d..3f7d29e 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp +++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp @@ -13,15 +13,27 @@ #include "platform/image-encoders/skia/PNGImageEncoder.h" #include "platform/threading/BackgroundTaskRunner.h" #include "public/platform/Platform.h" +#include "public/platform/WebScheduler.h" +#include "public/platform/WebTaskRunner.h" #include "public/platform/WebThread.h" #include "public/platform/WebTraceLocation.h" #include "wtf/Functional.h" namespace blink { +namespace { + +const double SlackBeforeDeadline = 0.001; // a small slack period between deadline and current time for safety const int NumChannelsPng = 4; const int LongTaskImageSizeThreshold = 1000 * 1000; // The max image size we expect to encode in 14ms on Linux in PNG format +bool isDeadlineNearOrPassed(double deadlineSeconds) +{ + return (deadlineSeconds - SlackBeforeDeadline - Platform::current()->monotonicallyIncreasingTimeSeconds() <= 0); +} + +} // anonymous namespace + class CanvasAsyncBlobCreator::ContextObserver final : public NoBaseWillBeGarbageCollected<CanvasAsyncBlobCreator::ContextObserver>, public ContextLifecycleObserver { WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(CanvasAsyncBlobCreator::ContextObserver); public: @@ -88,7 +100,7 @@ DEFINE_TRACE(CanvasAsyncBlobCreator::ContextObserver) ContextLifecycleObserver::trace(visitor); } -void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(double quality) +void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(bool canUseIdlePeriodScheduling, double quality) { // TODO: async blob creation should be supported in worker_pool threads as well. but right now blink does not have that ASSERT(isMainThread()); @@ -96,8 +108,52 @@ void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(double quality) // Make self-reference to keep this object alive until the final task completes m_selfRef = this; - BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.width() >= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTask : BackgroundTaskRunner::TaskSizeShortRunningTask; - BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafeBind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, AllowCrossThreadAccess(this), quality), taskSize); + if (canUseIdlePeriodScheduling) { + ASSERT(m_mimeType == "image/png"); + Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE, WTF::bind<double>(&CanvasAsyncBlobCreator::initiatePngEncoding, this)); + } else { + BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.width() >= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTask : BackgroundTaskRunner::TaskSizeShortRunningTask; + BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafeBind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, AllowCrossThreadAccess(this), quality), taskSize); + } +} + +void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) +{ + m_encoderState = PNGImageEncoderState::create(m_size, m_encodedImage.get()); + if (!m_encoderState) { + Platform::current()->mainThread()->taskRunner()->postTask(BLINK_FROM_HERE, bind(&BlobCallback::handleEvent, m_callback, nullptr)); + m_selfRef.clear(); + return; + } + + CanvasAsyncBlobCreator::idleEncodeRowsPng(deadlineSeconds); +} + +void CanvasAsyncBlobCreator::scheduleIdleEncodeRowsPng() +{ + Platform::current()->currentThread()->scheduler()->postIdleTask(BLINK_FROM_HERE, WTF::bind<double>(&CanvasAsyncBlobCreator::idleEncodeRowsPng, this)); +} + +void CanvasAsyncBlobCreator::idleEncodeRowsPng(double deadlineSeconds) +{ + unsigned char* inputPixels = m_data->data() + m_pixelRowStride * m_numRowsCompleted; + for (int y = m_numRowsCompleted; y < m_size.height(); ++y) { + if (isDeadlineNearOrPassed(deadlineSeconds)) { + m_numRowsCompleted = y; + CanvasAsyncBlobCreator::scheduleIdleEncodeRowsPng(); + return; + } + PNGImageEncoder::writeOneRowToPng(inputPixels, m_encoderState.get()); + inputPixels += m_pixelRowStride; + } + m_numRowsCompleted = m_size.height(); + PNGImageEncoder::finalizePng(m_encoderState.get()); + + if (isDeadlineNearOrPassed(deadlineSeconds)) { + Platform::current()->mainThread()->taskRunner()->postTask(BLINK_FROM_HERE, bind(&CanvasAsyncBlobCreator::createBlobAndCall, this)); + } else { + this->createBlobAndCall(); + } } void CanvasAsyncBlobCreator::createBlobAndCall() diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h index ccda72a..d06a843 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h +++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h @@ -21,7 +21,7 @@ class CORE_EXPORT CanvasAsyncBlobCreator : public RefCounted<CanvasAsyncBlobCreator> { public: static PassRefPtr<CanvasAsyncBlobCreator> create(PassRefPtr<DOMUint8ClampedArray> unpremultipliedRGBAImageData, const String& mimeType, const IntSize&, BlobCallback*, ExecutionContext*); - void scheduleAsyncBlobCreation(double quality = 0.0); + void scheduleAsyncBlobCreation(bool canUseIdlePeriodScheduling, double quality = 0.0); virtual ~CanvasAsyncBlobCreator(); protected: @@ -47,6 +47,10 @@ private: RefPtr<CanvasAsyncBlobCreator> m_selfRef; void clearSelfReference(); + void initiatePngEncoding(double deadlineSeconds); + void scheduleIdleEncodeRowsPng(); + void idleEncodeRowsPng(double deadlineSeconds); + void createBlobAndCall(); void encodeImageOnEncoderThread(double quality); |