Index: third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp |
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp |
index 58af50fe0faec277b63645d9c0f4022c0d274dc5..88ed5afaebefdc30ad5f3e93c854f07f8234f343 100644 |
--- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp |
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp |
@@ -86,7 +86,12 @@ CanvasAsyncBlobCreator::MimeType convertMimeTypeStringToEnum( |
} |
void recordIdleTaskStatusHistogram( |
+ CanvasAsyncBlobCreator::ToBlobFunctionType functionType, |
CanvasAsyncBlobCreator::IdleTaskStatus status) { |
+ // TODO: Add histograms for OffscreenCanvas.convertToBlob. |
+ // See crbug.com/653599. |
+ if (functionType == CanvasAsyncBlobCreator::OffscreenCanvasToBlobPromise) |
+ return; |
DEFINE_STATIC_LOCAL(EnumerationHistogram, toBlobIdleTaskStatus, |
("Blink.Canvas.ToBlob.IdleTaskStatus", |
CanvasAsyncBlobCreator::IdleTaskCount)); |
@@ -102,9 +107,16 @@ enum ElapsedTimeHistogramType { |
NumberOfElapsedTimeHistogramTypes |
}; |
-void recordElapsedTimeHistogram(ElapsedTimeHistogramType type, |
- CanvasAsyncBlobCreator::MimeType mimeType, |
- double elapsedTime) { |
+void recordElapsedTimeHistogram( |
+ CanvasAsyncBlobCreator::ToBlobFunctionType functionType, |
+ ElapsedTimeHistogramType type, |
+ CanvasAsyncBlobCreator::MimeType mimeType, |
+ double elapsedTime) { |
+ // TODO: Add histograms for OffscreenCanvas.convertToBlob. |
+ // See crbug.com/653599. |
+ if (functionType == CanvasAsyncBlobCreator::OffscreenCanvasToBlobPromise) |
+ return; |
+ |
if (type == InitiateEncodingDelay) { |
if (mimeType == CanvasAsyncBlobCreator::MimeTypePng) { |
DEFINE_STATIC_LOCAL( |
@@ -156,10 +168,11 @@ CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create( |
const IntSize& size, |
BlobCallback* callback, |
double startTime, |
- Document& document) { |
+ Document* document, |
+ ScriptPromiseResolver* resolver) { |
return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData, |
convertMimeTypeStringToEnum(mimeType), size, |
- callback, startTime, document); |
+ callback, startTime, document, resolver); |
} |
CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, |
@@ -167,21 +180,29 @@ CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, |
const IntSize& size, |
BlobCallback* callback, |
double startTime, |
- Document& document) |
+ Document* document, |
+ ScriptPromiseResolver* resolver) |
: m_data(data), |
- m_document(&document), |
+ m_document(document), |
m_size(size), |
m_mimeType(mimeType), |
- m_callback(callback), |
m_startTime(startTime), |
m_elapsedTime(0), |
- m_parentFrameTaskRunner( |
- ParentFrameTaskRunners::create(document.frame())) { |
- ASSERT(m_data->length() == (unsigned)(size.height() * size.width() * 4)); |
+ m_callback(callback), |
+ m_scriptPromiseResolver(resolver) { |
+ DCHECK(m_data->length() == (unsigned)(size.height() * size.width() * 4)); |
m_encodedImage = wrapUnique(new Vector<unsigned char>()); |
m_pixelRowStride = size.width() * NumChannelsPng; |
m_idleTaskStatus = IdleTaskNotSupported; |
m_numRowsCompleted = 0; |
+ if (document) { |
+ m_parentFrameTaskRunner = ParentFrameTaskRunners::create(document->frame()); |
+ } |
+ if (m_scriptPromiseResolver) { |
+ m_functionType = OffscreenCanvasToBlobPromise; |
+ } else { |
+ m_functionType = HTMLCanvasToBlobCallback; |
+ } |
} |
CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() {} |
@@ -194,12 +215,41 @@ void CanvasAsyncBlobCreator::dispose() { |
m_callback.clear(); |
} |
-void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation( |
- bool canUseIdlePeriodScheduling, |
- const double& quality) { |
- ASSERT(isMainThread()); |
xlai (Olivia)
2016/10/19 18:51:06
All these assertion of isMainThread() need to be r
|
+void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(const double& quality) { |
+ if (m_mimeType == MimeTypeWebp) { |
+ if (!isMainThread()) { |
+ DCHECK(m_functionType == OffscreenCanvasToBlobPromise); |
+ // When OffscreenCanvas.convertToBlob() occurs on worker thread, |
+ // we do not need to use background task runner to reduce load on main. |
+ // So we just directly encode images on the worker thread. |
+ if (!ImageDataBuffer(m_size, m_data->data()) |
+ .encodeImage("image/webp", quality, m_encodedImage.get())) { |
+ TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
+ ->postTask( |
+ BLINK_FROM_HERE, |
+ WTF::bind(&CanvasAsyncBlobCreator::createNullAndInvokeCallback, |
+ wrapPersistent(this))); |
- if (canUseIdlePeriodScheduling) { |
+ return; |
+ } |
+ TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
+ ->postTask( |
+ BLINK_FROM_HERE, |
+ WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, |
+ wrapPersistent(this))); |
+ |
+ } else { |
+ BackgroundTaskRunner::TaskSize taskSize = |
+ (m_size.height() * m_size.width() >= LongTaskImageSizeThreshold) |
+ ? BackgroundTaskRunner::TaskSizeLongRunningTask |
+ : BackgroundTaskRunner::TaskSizeShortRunningTask; |
+ BackgroundTaskRunner::postOnBackgroundThread( |
+ BLINK_FROM_HERE, |
+ crossThreadBind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, |
+ wrapCrossThreadPersistent(this), quality), |
+ taskSize); |
+ } |
+ } else { |
m_idleTaskStatus = IdleTaskNotStarted; |
if (m_mimeType == MimeTypePng) { |
this->scheduleInitiatePngEncoding(); |
@@ -211,47 +261,41 @@ void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation( |
// formats. |
// TODO(xlai): Progressive encoding on webp image formats |
// (crbug.com/571399) |
- ASSERT_NOT_REACHED(); |
+ NOTREACHED(); |
+ } |
+ |
+ // TODO: Enforce OffscreenCanvas.convertToBlob to finish within deadline. |
+ // See crbug.com/657102. |
+ if (m_functionType == HTMLCanvasToBlobCallback) { |
+ // We post the below task to check if the above idle task isn't late. |
+ // There's no risk of concurrency as both tasks are on main thread. |
+ this->postDelayedTaskToMainThread( |
+ BLINK_FROM_HERE, |
+ WTF::bind(&CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent, |
+ wrapPersistent(this), quality), |
+ IdleTaskStartTimeoutDelay); |
} |
- // We post the below task to check if the above idle task isn't late. |
- // There's no risk of concurrency as both tasks are on main thread. |
- this->postDelayedTaskToMainThread( |
- BLINK_FROM_HERE, |
- WTF::bind(&CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent, |
- wrapPersistent(this), quality), |
- IdleTaskStartTimeoutDelay); |
- } else if (m_mimeType == MimeTypeWebp) { |
- BackgroundTaskRunner::TaskSize taskSize = |
- (m_size.height() * m_size.width() >= LongTaskImageSizeThreshold) |
- ? BackgroundTaskRunner::TaskSizeLongRunningTask |
- : BackgroundTaskRunner::TaskSizeShortRunningTask; |
- BackgroundTaskRunner::postOnBackgroundThread( |
- BLINK_FROM_HERE, |
- crossThreadBind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, |
- wrapCrossThreadPersistent(this), quality), |
- taskSize); |
} |
} |
void CanvasAsyncBlobCreator::scheduleInitiateJpegEncoding( |
const double& quality) { |
m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime(); |
- Platform::current()->mainThread()->scheduler()->postIdleTask( |
+ Platform::current()->currentThread()->scheduler()->postIdleTask( |
BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::initiateJpegEncoding, |
wrapPersistent(this), quality)); |
} |
void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality, |
double deadlineSeconds) { |
- ASSERT(isMainThread()); |
recordElapsedTimeHistogram( |
- InitiateEncodingDelay, MimeTypeJpeg, |
+ m_functionType, InitiateEncodingDelay, MimeTypeJpeg, |
WTF::monotonicallyIncreasingTime() - m_scheduleInitiateStartTime); |
if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { |
return; |
} |
- ASSERT(m_idleTaskStatus == IdleTaskNotStarted); |
+ DCHECK(m_idleTaskStatus == IdleTaskNotStarted); |
m_idleTaskStatus = IdleTaskStarted; |
if (!initializeJpegStruct(quality)) { |
@@ -263,22 +307,20 @@ void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality, |
void CanvasAsyncBlobCreator::scheduleInitiatePngEncoding() { |
m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime(); |
- Platform::current()->mainThread()->scheduler()->postIdleTask( |
+ Platform::current()->currentThread()->scheduler()->postIdleTask( |
BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::initiatePngEncoding, |
wrapPersistent(this))); |
} |
void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) { |
- ASSERT(isMainThread()); |
recordElapsedTimeHistogram( |
- InitiateEncodingDelay, MimeTypePng, |
+ m_functionType, InitiateEncodingDelay, MimeTypePng, |
WTF::monotonicallyIncreasingTime() - m_scheduleInitiateStartTime); |
- |
if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { |
return; |
} |
- ASSERT(m_idleTaskStatus == IdleTaskNotStarted); |
+ DCHECK(m_idleTaskStatus == IdleTaskNotStarted); |
m_idleTaskStatus = IdleTaskStarted; |
if (!initializePngStruct()) { |
@@ -289,7 +331,6 @@ void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) { |
} |
void CanvasAsyncBlobCreator::idleEncodeRowsPng(double deadlineSeconds) { |
- ASSERT(isMainThread()); |
if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { |
return; |
} |
@@ -314,7 +355,8 @@ void CanvasAsyncBlobCreator::idleEncodeRowsPng(double deadlineSeconds) { |
m_idleTaskStatus = IdleTaskCompleted; |
m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime); |
- recordElapsedTimeHistogram(IdleEncodeDuration, MimeTypePng, m_elapsedTime); |
+ recordElapsedTimeHistogram(m_functionType, IdleEncodeDuration, MimeTypePng, |
+ m_elapsedTime); |
if (isDeadlineNearOrPassed(deadlineSeconds)) { |
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
->postTask( |
@@ -327,9 +369,10 @@ void CanvasAsyncBlobCreator::idleEncodeRowsPng(double deadlineSeconds) { |
} |
void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) { |
- ASSERT(isMainThread()); |
- if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { |
- return; |
+ if (m_callback) { |
+ if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { |
+ return; |
+ } |
} |
double startTime = WTF::monotonicallyIncreasingTime(); |
@@ -339,7 +382,8 @@ void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) { |
m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime); |
if (m_numRowsCompleted == m_size.height()) { |
m_idleTaskStatus = IdleTaskCompleted; |
- recordElapsedTimeHistogram(IdleEncodeDuration, MimeTypeJpeg, m_elapsedTime); |
+ recordElapsedTimeHistogram(m_functionType, IdleEncodeDuration, MimeTypeJpeg, |
+ m_elapsedTime); |
if (isDeadlineNearOrPassed(deadlineSeconds)) { |
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
@@ -361,7 +405,7 @@ void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) { |
} |
void CanvasAsyncBlobCreator::encodeRowsPngOnMainThread() { |
- ASSERT(m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask); |
+ DCHECK(m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask); |
// Continue encoding from the last completed row |
unsigned char* inputPixels = |
@@ -377,7 +421,7 @@ void CanvasAsyncBlobCreator::encodeRowsPngOnMainThread() { |
} |
void CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread() { |
- ASSERT(m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask); |
+ DCHECK(m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask); |
// Continue encoding from the last completed row |
if (JPEGImageEncoder::encodeWithPreInitializedState( |
@@ -391,36 +435,45 @@ void CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread() { |
} |
void CanvasAsyncBlobCreator::createBlobAndInvokeCallback() { |
- ASSERT(isMainThread()); |
- recordIdleTaskStatusHistogram(m_idleTaskStatus); |
- |
- recordElapsedTimeHistogram(ToBlobDuration, m_mimeType, |
+ recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus); |
+ recordElapsedTimeHistogram(m_functionType, ToBlobDuration, m_mimeType, |
WTF::monotonicallyIncreasingTime() - m_startTime); |
+ |
Blob* resultBlob = |
Blob::create(m_encodedImage->data(), m_encodedImage->size(), |
convertMimeTypeEnumToString(m_mimeType)); |
- TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
- ->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, |
- wrapPersistent(m_callback.get()), |
- wrapPersistent(resultBlob))); |
+ if (m_functionType == HTMLCanvasToBlobCallback) { |
+ TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
+ ->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, |
+ wrapPersistent(m_callback.get()), |
+ wrapPersistent(resultBlob))); |
+ } else { |
+ m_scriptPromiseResolver->resolve(resultBlob); |
+ } |
// Avoid unwanted retention, see dispose(). |
dispose(); |
} |
void CanvasAsyncBlobCreator::createNullAndInvokeCallback() { |
- ASSERT(isMainThread()); |
- recordIdleTaskStatusHistogram(m_idleTaskStatus); |
- TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
- ->postTask(BLINK_FROM_HERE, |
- WTF::bind(&BlobCallback::handleEvent, |
- wrapPersistent(m_callback.get()), nullptr)); |
+ recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus); |
+ if (m_functionType == HTMLCanvasToBlobCallback) { |
+ DCHECK(isMainThread()); |
+ recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus); |
+ TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
+ ->postTask(BLINK_FROM_HERE, |
+ WTF::bind(&BlobCallback::handleEvent, |
+ wrapPersistent(m_callback.get()), nullptr)); |
+ } else { |
+ Blob* blob = nullptr; |
+ m_scriptPromiseResolver->reject(blob); |
+ } |
// Avoid unwanted retention, see dispose(). |
dispose(); |
} |
void CanvasAsyncBlobCreator::encodeImageOnEncoderThread(double quality) { |
- ASSERT(!isMainThread()); |
- ASSERT(m_mimeType == MimeTypeWebp); |
+ DCHECK(!isMainThread()); |
+ DCHECK(m_mimeType == MimeTypeWebp); |
if (!ImageDataBuffer(m_size, m_data->data()) |
.encodeImage("image/webp", quality, m_encodedImage.get())) { |
@@ -486,7 +539,7 @@ void CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent(double quality) { |
this->signalAlternativeCodePathFinishedForTesting(); |
} |
} else { |
- ASSERT(m_mimeType == MimeTypeJpeg); |
+ DCHECK(m_mimeType == MimeTypeJpeg); |
if (initializeJpegStruct(quality)) { |
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
->postTask( |
@@ -499,14 +552,14 @@ void CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent(double quality) { |
} |
} |
} else { |
- ASSERT(m_idleTaskStatus == IdleTaskFailed || |
+ DCHECK(m_idleTaskStatus == IdleTaskFailed || |
m_idleTaskStatus == IdleTaskCompleted); |
this->signalAlternativeCodePathFinishedForTesting(); |
} |
} |
void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() { |
- ASSERT(m_idleTaskStatus != IdleTaskNotStarted); |
+ DCHECK(m_idleTaskStatus != IdleTaskNotStarted); |
if (m_idleTaskStatus == IdleTaskStarted) { |
// It has taken too long to complete for the idle task. |
@@ -520,7 +573,7 @@ void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() { |
WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread, |
wrapPersistent(this))); |
} else { |
- ASSERT(m_mimeType == MimeTypeJpeg); |
+ DCHECK(m_mimeType == MimeTypeJpeg); |
TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) |
->postTask( |
BLINK_FROM_HERE, |
@@ -528,7 +581,7 @@ void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() { |
wrapPersistent(this))); |
} |
} else { |
- ASSERT(m_idleTaskStatus == IdleTaskFailed || |
+ DCHECK(m_idleTaskStatus == IdleTaskFailed || |
m_idleTaskStatus == IdleTaskCompleted); |
this->signalAlternativeCodePathFinishedForTesting(); |
} |
@@ -548,6 +601,7 @@ DEFINE_TRACE(CanvasAsyncBlobCreator) { |
visitor->trace(m_data); |
visitor->trace(m_callback); |
visitor->trace(m_parentFrameTaskRunner); |
+ visitor->trace(m_scriptPromiseResolver); |
} |
} // namespace blink |