Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(431)

Unified Diff: third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp

Issue 2420203002: Implement convertToBlob() in OffscreenCanvas (Closed)
Patch Set: webgl layout test Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698