| 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/html/canvas/CanvasAsyncBlobCreator.h" | 5 #include "core/html/canvas/CanvasAsyncBlobCreator.h" |
| 6 | 6 |
| 7 #include "core/fileapi/Blob.h" | 7 #include "core/fileapi/Blob.h" |
| 8 #include "platform/ThreadSafeFunctional.h" | 8 #include "platform/ThreadSafeFunctional.h" |
| 9 #include "platform/graphics/ImageBuffer.h" | 9 #include "platform/graphics/ImageBuffer.h" |
| 10 #include "platform/image-encoders/JPEGImageEncoder.h" | 10 #include "platform/image-encoders/JPEGImageEncoder.h" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 m_encodedImage = adoptPtr(new Vector<unsigned char>()); | 93 m_encodedImage = adoptPtr(new Vector<unsigned char>()); |
| 94 m_pixelRowStride = size.width() * NumChannelsPng; | 94 m_pixelRowStride = size.width() * NumChannelsPng; |
| 95 m_idleTaskStatus = IdleTaskNotSupported; | 95 m_idleTaskStatus = IdleTaskNotSupported; |
| 96 m_numRowsCompleted = 0; | 96 m_numRowsCompleted = 0; |
| 97 } | 97 } |
| 98 | 98 |
| 99 CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() | 99 CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() |
| 100 { | 100 { |
| 101 } | 101 } |
| 102 | 102 |
| 103 void CanvasAsyncBlobCreator::dispose() |
| 104 { |
| 105 // Eagerly let go of references to prevent retention of these |
| 106 // resources while any remaining posted tasks are queued. |
| 107 m_data.clear(); |
| 108 m_callback.clear(); |
| 109 } |
| 110 |
| 103 void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(bool canUseIdlePeriodSche
duling, const double& quality) | 111 void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(bool canUseIdlePeriodSche
duling, const double& quality) |
| 104 { | 112 { |
| 105 ASSERT(isMainThread()); | 113 ASSERT(isMainThread()); |
| 106 | 114 |
| 107 if (canUseIdlePeriodScheduling) { | 115 if (canUseIdlePeriodScheduling) { |
| 108 m_idleTaskStatus = IdleTaskNotStarted; | 116 m_idleTaskStatus = IdleTaskNotStarted; |
| 109 if (m_mimeType == MimeTypePng) { | 117 if (m_mimeType == MimeTypePng) { |
| 110 this->scheduleInitiatePngEncoding(); | 118 this->scheduleInitiatePngEncoding(); |
| 111 } else if (m_mimeType == MimeTypeJpeg) { | 119 } else if (m_mimeType == MimeTypeJpeg) { |
| 112 this->scheduleInitiateJpegEncoding(quality); | 120 this->scheduleInitiateJpegEncoding(quality); |
| 113 } else { | 121 } else { |
| 114 // Progressive encoding is only applicable to png and jpeg image for
mat, | 122 // Progressive encoding is only applicable to png and jpeg image for
mat, |
| 115 // and thus idle tasks scheduling can only be applied to these image
formats. | 123 // and thus idle tasks scheduling can only be applied to these image
formats. |
| 116 // TODO(xlai): Progressive encoding on webp image formats (crbug.com
/571399) | 124 // TODO(xlai): Progressive encoding on webp image formats (crbug.com
/571399) |
| 117 ASSERT_NOT_REACHED(); | 125 ASSERT_NOT_REACHED(); |
| 118 } | 126 } |
| 119 // We post the below task to check if the above idle task isn't late. | 127 // We post the below task to check if the above idle task isn't late. |
| 120 // There's no risk of concurrency as both tasks are on main thread. | 128 // There's no risk of concurrency as both tasks are on main thread. |
| 121 this->postDelayedTaskToMainThread(BLINK_FROM_HERE, bind(&CanvasAsyncBlob
Creator::idleTaskStartTimeoutEvent, this, quality), IdleTaskStartTimeoutDelay); | 129 this->postDelayedTaskToMainThread(BLINK_FROM_HERE, bind(&CanvasAsyncBlob
Creator::idleTaskStartTimeoutEvent, this, quality), IdleTaskStartTimeoutDelay); |
| 122 } else if (m_mimeType == MimeTypeWebp) { | 130 } else if (m_mimeType == MimeTypeWebp) { |
| 123 BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.widt
h() >= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTa
sk : BackgroundTaskRunner::TaskSizeShortRunningTask; | 131 BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.widt
h() >= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTa
sk : BackgroundTaskRunner::TaskSizeShortRunningTask; |
| 124 BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafe
Bind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, wrapCrossThreadPersist
ent(this), quality), taskSize); | 132 BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafe
Bind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, wrapCrossThreadPersist
ent(this), quality), taskSize); |
| 125 } | 133 } |
| 126 } | 134 } |
| 127 | 135 |
| 128 void CanvasAsyncBlobCreator::scheduleInitiateJpegEncoding(const double& quality) | 136 void CanvasAsyncBlobCreator::scheduleInitiateJpegEncoding(const double& quality) |
| 129 { | 137 { |
| 130 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE
, bind<double>(&CanvasAsyncBlobCreator::initiateJpegEncoding, WeakPersistentThis
Pointer<CanvasAsyncBlobCreator>(this), quality)); | 138 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE
, bind<double>(&CanvasAsyncBlobCreator::initiateJpegEncoding, this, quality)); |
| 131 } | 139 } |
| 132 | 140 |
| 133 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality, double
deadlineSeconds) | 141 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality, double
deadlineSeconds) |
| 134 { | 142 { |
| 135 ASSERT(isMainThread()); | 143 ASSERT(isMainThread()); |
| 136 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { | 144 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { |
| 137 return; | 145 return; |
| 138 } | 146 } |
| 139 | 147 |
| 140 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); | 148 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); |
| 141 m_idleTaskStatus = IdleTaskStarted; | 149 m_idleTaskStatus = IdleTaskStarted; |
| 142 | 150 |
| 143 if (!initializeJpegStruct(quality)) { | 151 if (!initializeJpegStruct(quality)) { |
| 144 m_idleTaskStatus = IdleTaskFailed; | 152 m_idleTaskStatus = IdleTaskFailed; |
| 145 return; | 153 return; |
| 146 } | 154 } |
| 147 this->idleEncodeRowsJpeg(deadlineSeconds); | 155 this->idleEncodeRowsJpeg(deadlineSeconds); |
| 148 } | 156 } |
| 149 | 157 |
| 150 void CanvasAsyncBlobCreator::scheduleInitiatePngEncoding() | 158 void CanvasAsyncBlobCreator::scheduleInitiatePngEncoding() |
| 151 { | 159 { |
| 152 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE
, bind<double>(&CanvasAsyncBlobCreator::initiatePngEncoding, WeakPersistentThisP
ointer<CanvasAsyncBlobCreator>(this))); | 160 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_HERE
, bind<double>(&CanvasAsyncBlobCreator::initiatePngEncoding, this)); |
| 153 } | 161 } |
| 154 | 162 |
| 155 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) | 163 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) |
| 156 { | 164 { |
| 157 ASSERT(isMainThread()); | 165 ASSERT(isMainThread()); |
| 158 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { | 166 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { |
| 159 return; | 167 return; |
| 160 } | 168 } |
| 161 | 169 |
| 162 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); | 170 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 } | 257 } |
| 250 | 258 |
| 251 this->signalAlternativeCodePathFinishedForTesting(); | 259 this->signalAlternativeCodePathFinishedForTesting(); |
| 252 } | 260 } |
| 253 | 261 |
| 254 void CanvasAsyncBlobCreator::createBlobAndInvokeCallback() | 262 void CanvasAsyncBlobCreator::createBlobAndInvokeCallback() |
| 255 { | 263 { |
| 256 ASSERT(isMainThread()); | 264 ASSERT(isMainThread()); |
| 257 Blob* resultBlob = Blob::create(m_encodedImage->data(), m_encodedImage->size
(), convertMimeTypeEnumToString(m_mimeType)); | 265 Blob* resultBlob = Blob::create(m_encodedImage->data(), m_encodedImage->size
(), convertMimeTypeEnumToString(m_mimeType)); |
| 258 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H
ERE, bind(&BlobCallback::handleEvent, m_callback, resultBlob)); | 266 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H
ERE, bind(&BlobCallback::handleEvent, m_callback, resultBlob)); |
| 267 // Avoid unwanted retention, see dispose(). |
| 268 dispose(); |
| 259 } | 269 } |
| 260 | 270 |
| 261 void CanvasAsyncBlobCreator::createNullAndInvokeCallback() | 271 void CanvasAsyncBlobCreator::createNullAndInvokeCallback() |
| 262 { | 272 { |
| 263 ASSERT(isMainThread()); | 273 ASSERT(isMainThread()); |
| 264 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H
ERE, bind(&BlobCallback::handleEvent, m_callback, nullptr)); | 274 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H
ERE, bind(&BlobCallback::handleEvent, m_callback, nullptr)); |
| 275 // Avoid unwanted retention, see dispose(). |
| 276 dispose(); |
| 265 } | 277 } |
| 266 | 278 |
| 267 void CanvasAsyncBlobCreator::encodeImageOnEncoderThread(double quality) | 279 void CanvasAsyncBlobCreator::encodeImageOnEncoderThread(double quality) |
| 268 { | 280 { |
| 269 ASSERT(!isMainThread()); | 281 ASSERT(!isMainThread()); |
| 270 ASSERT(m_mimeType == MimeTypeWebp); | 282 ASSERT(m_mimeType == MimeTypeWebp); |
| 271 | 283 |
| 272 if (!ImageDataBuffer(m_size, m_data->data()).encodeImage("image/webp", quali
ty, m_encodedImage.get())) { | 284 if (!ImageDataBuffer(m_size, m_data->data()).encodeImage("image/webp", quali
ty, m_encodedImage.get())) { |
| 273 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR
OM_HERE, threadSafeBind(&BlobCallback::handleEvent, wrapCrossThreadPersistent(m_
callback.get()), nullptr)); | 285 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR
OM_HERE, threadSafeBind(&BlobCallback::handleEvent, wrapCrossThreadPersistent(m_
callback.get()), nullptr)); |
| 274 return; | 286 return; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 } | 365 } |
| 354 } | 366 } |
| 355 | 367 |
| 356 void CanvasAsyncBlobCreator::postDelayedTaskToMainThread(const WebTraceLocation&
location, std::unique_ptr<SameThreadClosure> task, double delayMs) | 368 void CanvasAsyncBlobCreator::postDelayedTaskToMainThread(const WebTraceLocation&
location, std::unique_ptr<SameThreadClosure> task, double delayMs) |
| 357 { | 369 { |
| 358 DCHECK(isMainThread()); | 370 DCHECK(isMainThread()); |
| 359 Platform::current()->mainThread()->getWebTaskRunner()->postDelayedTask(locat
ion, std::move(task), delayMs); | 371 Platform::current()->mainThread()->getWebTaskRunner()->postDelayedTask(locat
ion, std::move(task), delayMs); |
| 360 } | 372 } |
| 361 | 373 |
| 362 } // namespace blink | 374 } // namespace blink |
| OLD | NEW |