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

Side by Side 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 unified diff | Download patch
OLDNEW
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/dom/Document.h" 7 #include "core/dom/Document.h"
8 #include "core/dom/TaskRunnerHelper.h" 8 #include "core/dom/TaskRunnerHelper.h"
9 #include "core/fileapi/Blob.h" 9 #include "core/fileapi/Blob.h"
10 #include "platform/CrossThreadFunctional.h" 10 #include "platform/CrossThreadFunctional.h"
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 mimeTypeEnum = CanvasAsyncBlobCreator::MimeTypeJpeg; 79 mimeTypeEnum = CanvasAsyncBlobCreator::MimeTypeJpeg;
80 } else if (mimeType == "image/webp") { 80 } else if (mimeType == "image/webp") {
81 mimeTypeEnum = CanvasAsyncBlobCreator::MimeTypeWebp; 81 mimeTypeEnum = CanvasAsyncBlobCreator::MimeTypeWebp;
82 } else { 82 } else {
83 mimeTypeEnum = CanvasAsyncBlobCreator::NumberOfMimeTypeSupported; 83 mimeTypeEnum = CanvasAsyncBlobCreator::NumberOfMimeTypeSupported;
84 } 84 }
85 return mimeTypeEnum; 85 return mimeTypeEnum;
86 } 86 }
87 87
88 void recordIdleTaskStatusHistogram( 88 void recordIdleTaskStatusHistogram(
89 CanvasAsyncBlobCreator::ToBlobFunctionType functionType,
89 CanvasAsyncBlobCreator::IdleTaskStatus status) { 90 CanvasAsyncBlobCreator::IdleTaskStatus status) {
91 // TODO: Add histograms for OffscreenCanvas.convertToBlob.
92 // See crbug.com/653599.
93 if (functionType == CanvasAsyncBlobCreator::OffscreenCanvasToBlobPromise)
94 return;
90 DEFINE_STATIC_LOCAL(EnumerationHistogram, toBlobIdleTaskStatus, 95 DEFINE_STATIC_LOCAL(EnumerationHistogram, toBlobIdleTaskStatus,
91 ("Blink.Canvas.ToBlob.IdleTaskStatus", 96 ("Blink.Canvas.ToBlob.IdleTaskStatus",
92 CanvasAsyncBlobCreator::IdleTaskCount)); 97 CanvasAsyncBlobCreator::IdleTaskCount));
93 toBlobIdleTaskStatus.count(status); 98 toBlobIdleTaskStatus.count(status);
94 } 99 }
95 100
96 // This enum is used in histogram and any more types should be appended at the 101 // This enum is used in histogram and any more types should be appended at the
97 // end of the list. 102 // end of the list.
98 enum ElapsedTimeHistogramType { 103 enum ElapsedTimeHistogramType {
99 InitiateEncodingDelay, 104 InitiateEncodingDelay,
100 IdleEncodeDuration, 105 IdleEncodeDuration,
101 ToBlobDuration, 106 ToBlobDuration,
102 NumberOfElapsedTimeHistogramTypes 107 NumberOfElapsedTimeHistogramTypes
103 }; 108 };
104 109
105 void recordElapsedTimeHistogram(ElapsedTimeHistogramType type, 110 void recordElapsedTimeHistogram(
106 CanvasAsyncBlobCreator::MimeType mimeType, 111 CanvasAsyncBlobCreator::ToBlobFunctionType functionType,
107 double elapsedTime) { 112 ElapsedTimeHistogramType type,
113 CanvasAsyncBlobCreator::MimeType mimeType,
114 double elapsedTime) {
115 // TODO: Add histograms for OffscreenCanvas.convertToBlob.
116 // See crbug.com/653599.
117 if (functionType == CanvasAsyncBlobCreator::OffscreenCanvasToBlobPromise)
118 return;
119
108 if (type == InitiateEncodingDelay) { 120 if (type == InitiateEncodingDelay) {
109 if (mimeType == CanvasAsyncBlobCreator::MimeTypePng) { 121 if (mimeType == CanvasAsyncBlobCreator::MimeTypePng) {
110 DEFINE_STATIC_LOCAL( 122 DEFINE_STATIC_LOCAL(
111 CustomCountHistogram, toBlobPNGInitiateEncodingCounter, 123 CustomCountHistogram, toBlobPNGInitiateEncodingCounter,
112 ("Blink.Canvas.ToBlob.InitiateEncodingDelay.PNG", 0, 10000000, 50)); 124 ("Blink.Canvas.ToBlob.InitiateEncodingDelay.PNG", 0, 10000000, 50));
113 toBlobPNGInitiateEncodingCounter.count(elapsedTime * 1000000.0); 125 toBlobPNGInitiateEncodingCounter.count(elapsedTime * 1000000.0);
114 } else if (mimeType == CanvasAsyncBlobCreator::MimeTypeJpeg) { 126 } else if (mimeType == CanvasAsyncBlobCreator::MimeTypeJpeg) {
115 DEFINE_STATIC_LOCAL( 127 DEFINE_STATIC_LOCAL(
116 CustomCountHistogram, toBlobJPEGInitiateEncodingCounter, 128 CustomCountHistogram, toBlobJPEGInitiateEncodingCounter,
117 ("Blink.Canvas.ToBlob.InitiateEncodingDelay.JPEG", 0, 10000000, 50)); 129 ("Blink.Canvas.ToBlob.InitiateEncodingDelay.JPEG", 0, 10000000, 50));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 } 161 }
150 162
151 } // anonymous namespace 163 } // anonymous namespace
152 164
153 CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create( 165 CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create(
154 DOMUint8ClampedArray* unpremultipliedRGBAImageData, 166 DOMUint8ClampedArray* unpremultipliedRGBAImageData,
155 const String& mimeType, 167 const String& mimeType,
156 const IntSize& size, 168 const IntSize& size,
157 BlobCallback* callback, 169 BlobCallback* callback,
158 double startTime, 170 double startTime,
159 Document& document) { 171 Document* document,
172 ScriptPromiseResolver* resolver) {
160 return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData, 173 return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData,
161 convertMimeTypeStringToEnum(mimeType), size, 174 convertMimeTypeStringToEnum(mimeType), size,
162 callback, startTime, document); 175 callback, startTime, document, resolver);
163 } 176 }
164 177
165 CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, 178 CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data,
166 MimeType mimeType, 179 MimeType mimeType,
167 const IntSize& size, 180 const IntSize& size,
168 BlobCallback* callback, 181 BlobCallback* callback,
169 double startTime, 182 double startTime,
170 Document& document) 183 Document* document,
184 ScriptPromiseResolver* resolver)
171 : m_data(data), 185 : m_data(data),
172 m_document(&document), 186 m_document(document),
173 m_size(size), 187 m_size(size),
174 m_mimeType(mimeType), 188 m_mimeType(mimeType),
175 m_callback(callback),
176 m_startTime(startTime), 189 m_startTime(startTime),
177 m_elapsedTime(0), 190 m_elapsedTime(0),
178 m_parentFrameTaskRunner( 191 m_callback(callback),
179 ParentFrameTaskRunners::create(document.frame())) { 192 m_scriptPromiseResolver(resolver) {
180 ASSERT(m_data->length() == (unsigned)(size.height() * size.width() * 4)); 193 DCHECK(m_data->length() == (unsigned)(size.height() * size.width() * 4));
181 m_encodedImage = wrapUnique(new Vector<unsigned char>()); 194 m_encodedImage = wrapUnique(new Vector<unsigned char>());
182 m_pixelRowStride = size.width() * NumChannelsPng; 195 m_pixelRowStride = size.width() * NumChannelsPng;
183 m_idleTaskStatus = IdleTaskNotSupported; 196 m_idleTaskStatus = IdleTaskNotSupported;
184 m_numRowsCompleted = 0; 197 m_numRowsCompleted = 0;
198 if (document) {
199 m_parentFrameTaskRunner = ParentFrameTaskRunners::create(document->frame());
200 }
201 if (m_scriptPromiseResolver) {
202 m_functionType = OffscreenCanvasToBlobPromise;
203 } else {
204 m_functionType = HTMLCanvasToBlobCallback;
205 }
185 } 206 }
186 207
187 CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() {} 208 CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() {}
188 209
189 void CanvasAsyncBlobCreator::dispose() { 210 void CanvasAsyncBlobCreator::dispose() {
190 // Eagerly let go of references to prevent retention of these 211 // Eagerly let go of references to prevent retention of these
191 // resources while any remaining posted tasks are queued. 212 // resources while any remaining posted tasks are queued.
192 m_data.clear(); 213 m_data.clear();
193 m_document.clear(); 214 m_document.clear();
194 m_callback.clear(); 215 m_callback.clear();
195 } 216 }
196 217
197 void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation( 218 void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(const double& quality) {
198 bool canUseIdlePeriodScheduling, 219 if (m_mimeType == MimeTypeWebp) {
199 const double& quality) { 220 if (!isMainThread()) {
200 ASSERT(isMainThread()); 221 DCHECK(m_functionType == OffscreenCanvasToBlobPromise);
xlai (Olivia) 2016/10/19 18:51:06 All these assertion of isMainThread() need to be r
222 // When OffscreenCanvas.convertToBlob() occurs on worker thread,
223 // we do not need to use background task runner to reduce load on main.
224 // So we just directly encode images on the worker thread.
225 if (!ImageDataBuffer(m_size, m_data->data())
226 .encodeImage("image/webp", quality, m_encodedImage.get())) {
227 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
228 ->postTask(
229 BLINK_FROM_HERE,
230 WTF::bind(&CanvasAsyncBlobCreator::createNullAndInvokeCallback,
231 wrapPersistent(this)));
201 232
202 if (canUseIdlePeriodScheduling) { 233 return;
234 }
235 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
236 ->postTask(
237 BLINK_FROM_HERE,
238 WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback,
239 wrapPersistent(this)));
240
241 } else {
242 BackgroundTaskRunner::TaskSize taskSize =
243 (m_size.height() * m_size.width() >= LongTaskImageSizeThreshold)
244 ? BackgroundTaskRunner::TaskSizeLongRunningTask
245 : BackgroundTaskRunner::TaskSizeShortRunningTask;
246 BackgroundTaskRunner::postOnBackgroundThread(
247 BLINK_FROM_HERE,
248 crossThreadBind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread,
249 wrapCrossThreadPersistent(this), quality),
250 taskSize);
251 }
252 } else {
203 m_idleTaskStatus = IdleTaskNotStarted; 253 m_idleTaskStatus = IdleTaskNotStarted;
204 if (m_mimeType == MimeTypePng) { 254 if (m_mimeType == MimeTypePng) {
205 this->scheduleInitiatePngEncoding(); 255 this->scheduleInitiatePngEncoding();
206 } else if (m_mimeType == MimeTypeJpeg) { 256 } else if (m_mimeType == MimeTypeJpeg) {
207 this->scheduleInitiateJpegEncoding(quality); 257 this->scheduleInitiateJpegEncoding(quality);
208 } else { 258 } else {
209 // Progressive encoding is only applicable to png and jpeg image format, 259 // Progressive encoding is only applicable to png and jpeg image format,
210 // and thus idle tasks scheduling can only be applied to these image 260 // and thus idle tasks scheduling can only be applied to these image
211 // formats. 261 // formats.
212 // TODO(xlai): Progressive encoding on webp image formats 262 // TODO(xlai): Progressive encoding on webp image formats
213 // (crbug.com/571399) 263 // (crbug.com/571399)
214 ASSERT_NOT_REACHED(); 264 NOTREACHED();
215 } 265 }
216 // We post the below task to check if the above idle task isn't late. 266
217 // There's no risk of concurrency as both tasks are on main thread. 267 // TODO: Enforce OffscreenCanvas.convertToBlob to finish within deadline.
218 this->postDelayedTaskToMainThread( 268 // See crbug.com/657102.
219 BLINK_FROM_HERE, 269 if (m_functionType == HTMLCanvasToBlobCallback) {
220 WTF::bind(&CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent, 270 // We post the below task to check if the above idle task isn't late.
221 wrapPersistent(this), quality), 271 // There's no risk of concurrency as both tasks are on main thread.
222 IdleTaskStartTimeoutDelay); 272 this->postDelayedTaskToMainThread(
223 } else if (m_mimeType == MimeTypeWebp) { 273 BLINK_FROM_HERE,
224 BackgroundTaskRunner::TaskSize taskSize = 274 WTF::bind(&CanvasAsyncBlobCreator::idleTaskStartTimeoutEvent,
225 (m_size.height() * m_size.width() >= LongTaskImageSizeThreshold) 275 wrapPersistent(this), quality),
226 ? BackgroundTaskRunner::TaskSizeLongRunningTask 276 IdleTaskStartTimeoutDelay);
227 : BackgroundTaskRunner::TaskSizeShortRunningTask; 277 }
228 BackgroundTaskRunner::postOnBackgroundThread(
229 BLINK_FROM_HERE,
230 crossThreadBind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread,
231 wrapCrossThreadPersistent(this), quality),
232 taskSize);
233 } 278 }
234 } 279 }
235 280
236 void CanvasAsyncBlobCreator::scheduleInitiateJpegEncoding( 281 void CanvasAsyncBlobCreator::scheduleInitiateJpegEncoding(
237 const double& quality) { 282 const double& quality) {
238 m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime(); 283 m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime();
239 Platform::current()->mainThread()->scheduler()->postIdleTask( 284 Platform::current()->currentThread()->scheduler()->postIdleTask(
240 BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::initiateJpegEncoding, 285 BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::initiateJpegEncoding,
241 wrapPersistent(this), quality)); 286 wrapPersistent(this), quality));
242 } 287 }
243 288
244 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality, 289 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality,
245 double deadlineSeconds) { 290 double deadlineSeconds) {
246 ASSERT(isMainThread());
247 recordElapsedTimeHistogram( 291 recordElapsedTimeHistogram(
248 InitiateEncodingDelay, MimeTypeJpeg, 292 m_functionType, InitiateEncodingDelay, MimeTypeJpeg,
249 WTF::monotonicallyIncreasingTime() - m_scheduleInitiateStartTime); 293 WTF::monotonicallyIncreasingTime() - m_scheduleInitiateStartTime);
250 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { 294 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
251 return; 295 return;
252 } 296 }
253 297
254 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); 298 DCHECK(m_idleTaskStatus == IdleTaskNotStarted);
255 m_idleTaskStatus = IdleTaskStarted; 299 m_idleTaskStatus = IdleTaskStarted;
256 300
257 if (!initializeJpegStruct(quality)) { 301 if (!initializeJpegStruct(quality)) {
258 m_idleTaskStatus = IdleTaskFailed; 302 m_idleTaskStatus = IdleTaskFailed;
259 return; 303 return;
260 } 304 }
261 this->idleEncodeRowsJpeg(deadlineSeconds); 305 this->idleEncodeRowsJpeg(deadlineSeconds);
262 } 306 }
263 307
264 void CanvasAsyncBlobCreator::scheduleInitiatePngEncoding() { 308 void CanvasAsyncBlobCreator::scheduleInitiatePngEncoding() {
265 m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime(); 309 m_scheduleInitiateStartTime = WTF::monotonicallyIncreasingTime();
266 Platform::current()->mainThread()->scheduler()->postIdleTask( 310 Platform::current()->currentThread()->scheduler()->postIdleTask(
267 BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::initiatePngEncoding, 311 BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::initiatePngEncoding,
268 wrapPersistent(this))); 312 wrapPersistent(this)));
269 } 313 }
270 314
271 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) { 315 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) {
272 ASSERT(isMainThread());
273 recordElapsedTimeHistogram( 316 recordElapsedTimeHistogram(
274 InitiateEncodingDelay, MimeTypePng, 317 m_functionType, InitiateEncodingDelay, MimeTypePng,
275 WTF::monotonicallyIncreasingTime() - m_scheduleInitiateStartTime); 318 WTF::monotonicallyIncreasingTime() - m_scheduleInitiateStartTime);
276
277 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { 319 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
278 return; 320 return;
279 } 321 }
280 322
281 ASSERT(m_idleTaskStatus == IdleTaskNotStarted); 323 DCHECK(m_idleTaskStatus == IdleTaskNotStarted);
282 m_idleTaskStatus = IdleTaskStarted; 324 m_idleTaskStatus = IdleTaskStarted;
283 325
284 if (!initializePngStruct()) { 326 if (!initializePngStruct()) {
285 m_idleTaskStatus = IdleTaskFailed; 327 m_idleTaskStatus = IdleTaskFailed;
286 return; 328 return;
287 } 329 }
288 this->idleEncodeRowsPng(deadlineSeconds); 330 this->idleEncodeRowsPng(deadlineSeconds);
289 } 331 }
290 332
291 void CanvasAsyncBlobCreator::idleEncodeRowsPng(double deadlineSeconds) { 333 void CanvasAsyncBlobCreator::idleEncodeRowsPng(double deadlineSeconds) {
292 ASSERT(isMainThread());
293 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { 334 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
294 return; 335 return;
295 } 336 }
296 337
297 double startTime = WTF::monotonicallyIncreasingTime(); 338 double startTime = WTF::monotonicallyIncreasingTime();
298 unsigned char* inputPixels = 339 unsigned char* inputPixels =
299 m_data->data() + m_pixelRowStride * m_numRowsCompleted; 340 m_data->data() + m_pixelRowStride * m_numRowsCompleted;
300 for (int y = m_numRowsCompleted; y < m_size.height(); ++y) { 341 for (int y = m_numRowsCompleted; y < m_size.height(); ++y) {
301 if (isDeadlineNearOrPassed(deadlineSeconds)) { 342 if (isDeadlineNearOrPassed(deadlineSeconds)) {
302 m_numRowsCompleted = y; 343 m_numRowsCompleted = y;
303 m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime); 344 m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime);
304 Platform::current()->currentThread()->scheduler()->postIdleTask( 345 Platform::current()->currentThread()->scheduler()->postIdleTask(
305 BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::idleEncodeRowsPng, 346 BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::idleEncodeRowsPng,
306 wrapPersistent(this))); 347 wrapPersistent(this)));
307 return; 348 return;
308 } 349 }
309 PNGImageEncoder::writeOneRowToPng(inputPixels, m_pngEncoderState.get()); 350 PNGImageEncoder::writeOneRowToPng(inputPixels, m_pngEncoderState.get());
310 inputPixels += m_pixelRowStride; 351 inputPixels += m_pixelRowStride;
311 } 352 }
312 m_numRowsCompleted = m_size.height(); 353 m_numRowsCompleted = m_size.height();
313 PNGImageEncoder::finalizePng(m_pngEncoderState.get()); 354 PNGImageEncoder::finalizePng(m_pngEncoderState.get());
314 355
315 m_idleTaskStatus = IdleTaskCompleted; 356 m_idleTaskStatus = IdleTaskCompleted;
316 m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime); 357 m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime);
317 recordElapsedTimeHistogram(IdleEncodeDuration, MimeTypePng, m_elapsedTime); 358 recordElapsedTimeHistogram(m_functionType, IdleEncodeDuration, MimeTypePng,
359 m_elapsedTime);
318 if (isDeadlineNearOrPassed(deadlineSeconds)) { 360 if (isDeadlineNearOrPassed(deadlineSeconds)) {
319 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) 361 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
320 ->postTask( 362 ->postTask(
321 BLINK_FROM_HERE, 363 BLINK_FROM_HERE,
322 WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, 364 WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback,
323 wrapPersistent(this))); 365 wrapPersistent(this)));
324 } else { 366 } else {
325 this->createBlobAndInvokeCallback(); 367 this->createBlobAndInvokeCallback();
326 } 368 }
327 } 369 }
328 370
329 void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) { 371 void CanvasAsyncBlobCreator::idleEncodeRowsJpeg(double deadlineSeconds) {
330 ASSERT(isMainThread()); 372 if (m_callback) {
331 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) { 373 if (m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask) {
332 return; 374 return;
375 }
333 } 376 }
334 377
335 double startTime = WTF::monotonicallyIncreasingTime(); 378 double startTime = WTF::monotonicallyIncreasingTime();
336 m_numRowsCompleted = JPEGImageEncoder::progressiveEncodeRowsJpegHelper( 379 m_numRowsCompleted = JPEGImageEncoder::progressiveEncodeRowsJpegHelper(
337 m_jpegEncoderState.get(), m_data->data(), m_numRowsCompleted, 380 m_jpegEncoderState.get(), m_data->data(), m_numRowsCompleted,
338 SlackBeforeDeadline, deadlineSeconds); 381 SlackBeforeDeadline, deadlineSeconds);
339 m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime); 382 m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime);
340 if (m_numRowsCompleted == m_size.height()) { 383 if (m_numRowsCompleted == m_size.height()) {
341 m_idleTaskStatus = IdleTaskCompleted; 384 m_idleTaskStatus = IdleTaskCompleted;
342 recordElapsedTimeHistogram(IdleEncodeDuration, MimeTypeJpeg, m_elapsedTime); 385 recordElapsedTimeHistogram(m_functionType, IdleEncodeDuration, MimeTypeJpeg,
386 m_elapsedTime);
343 387
344 if (isDeadlineNearOrPassed(deadlineSeconds)) { 388 if (isDeadlineNearOrPassed(deadlineSeconds)) {
345 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) 389 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
346 ->postTask( 390 ->postTask(
347 BLINK_FROM_HERE, 391 BLINK_FROM_HERE,
348 WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, 392 WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback,
349 wrapPersistent(this))); 393 wrapPersistent(this)));
350 } else { 394 } else {
351 this->createBlobAndInvokeCallback(); 395 this->createBlobAndInvokeCallback();
352 } 396 }
353 } else if (m_numRowsCompleted == JPEGImageEncoder::ProgressiveEncodeFailed) { 397 } else if (m_numRowsCompleted == JPEGImageEncoder::ProgressiveEncodeFailed) {
354 m_idleTaskStatus = IdleTaskFailed; 398 m_idleTaskStatus = IdleTaskFailed;
355 this->createNullAndInvokeCallback(); 399 this->createNullAndInvokeCallback();
356 } else { 400 } else {
357 Platform::current()->currentThread()->scheduler()->postIdleTask( 401 Platform::current()->currentThread()->scheduler()->postIdleTask(
358 BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::idleEncodeRowsJpeg, 402 BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::idleEncodeRowsJpeg,
359 wrapPersistent(this))); 403 wrapPersistent(this)));
360 } 404 }
361 } 405 }
362 406
363 void CanvasAsyncBlobCreator::encodeRowsPngOnMainThread() { 407 void CanvasAsyncBlobCreator::encodeRowsPngOnMainThread() {
364 ASSERT(m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask); 408 DCHECK(m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask);
365 409
366 // Continue encoding from the last completed row 410 // Continue encoding from the last completed row
367 unsigned char* inputPixels = 411 unsigned char* inputPixels =
368 m_data->data() + m_pixelRowStride * m_numRowsCompleted; 412 m_data->data() + m_pixelRowStride * m_numRowsCompleted;
369 for (int y = m_numRowsCompleted; y < m_size.height(); ++y) { 413 for (int y = m_numRowsCompleted; y < m_size.height(); ++y) {
370 PNGImageEncoder::writeOneRowToPng(inputPixels, m_pngEncoderState.get()); 414 PNGImageEncoder::writeOneRowToPng(inputPixels, m_pngEncoderState.get());
371 inputPixels += m_pixelRowStride; 415 inputPixels += m_pixelRowStride;
372 } 416 }
373 PNGImageEncoder::finalizePng(m_pngEncoderState.get()); 417 PNGImageEncoder::finalizePng(m_pngEncoderState.get());
374 this->createBlobAndInvokeCallback(); 418 this->createBlobAndInvokeCallback();
375 419
376 this->signalAlternativeCodePathFinishedForTesting(); 420 this->signalAlternativeCodePathFinishedForTesting();
377 } 421 }
378 422
379 void CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread() { 423 void CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread() {
380 ASSERT(m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask); 424 DCHECK(m_idleTaskStatus == IdleTaskSwitchedToMainThreadTask);
381 425
382 // Continue encoding from the last completed row 426 // Continue encoding from the last completed row
383 if (JPEGImageEncoder::encodeWithPreInitializedState( 427 if (JPEGImageEncoder::encodeWithPreInitializedState(
384 std::move(m_jpegEncoderState), m_data->data(), m_numRowsCompleted)) { 428 std::move(m_jpegEncoderState), m_data->data(), m_numRowsCompleted)) {
385 this->createBlobAndInvokeCallback(); 429 this->createBlobAndInvokeCallback();
386 } else { 430 } else {
387 this->createNullAndInvokeCallback(); 431 this->createNullAndInvokeCallback();
388 } 432 }
389 433
390 this->signalAlternativeCodePathFinishedForTesting(); 434 this->signalAlternativeCodePathFinishedForTesting();
391 } 435 }
392 436
393 void CanvasAsyncBlobCreator::createBlobAndInvokeCallback() { 437 void CanvasAsyncBlobCreator::createBlobAndInvokeCallback() {
394 ASSERT(isMainThread()); 438 recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus);
395 recordIdleTaskStatusHistogram(m_idleTaskStatus); 439 recordElapsedTimeHistogram(m_functionType, ToBlobDuration, m_mimeType,
440 WTF::monotonicallyIncreasingTime() - m_startTime);
396 441
397 recordElapsedTimeHistogram(ToBlobDuration, m_mimeType,
398 WTF::monotonicallyIncreasingTime() - m_startTime);
399 Blob* resultBlob = 442 Blob* resultBlob =
400 Blob::create(m_encodedImage->data(), m_encodedImage->size(), 443 Blob::create(m_encodedImage->data(), m_encodedImage->size(),
401 convertMimeTypeEnumToString(m_mimeType)); 444 convertMimeTypeEnumToString(m_mimeType));
402 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) 445 if (m_functionType == HTMLCanvasToBlobCallback) {
403 ->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, 446 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
404 wrapPersistent(m_callback.get()), 447 ->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent,
405 wrapPersistent(resultBlob))); 448 wrapPersistent(m_callback.get()),
449 wrapPersistent(resultBlob)));
450 } else {
451 m_scriptPromiseResolver->resolve(resultBlob);
452 }
406 // Avoid unwanted retention, see dispose(). 453 // Avoid unwanted retention, see dispose().
407 dispose(); 454 dispose();
408 } 455 }
409 456
410 void CanvasAsyncBlobCreator::createNullAndInvokeCallback() { 457 void CanvasAsyncBlobCreator::createNullAndInvokeCallback() {
411 ASSERT(isMainThread()); 458 recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus);
412 recordIdleTaskStatusHistogram(m_idleTaskStatus); 459 if (m_functionType == HTMLCanvasToBlobCallback) {
413 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) 460 DCHECK(isMainThread());
414 ->postTask(BLINK_FROM_HERE, 461 recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus);
415 WTF::bind(&BlobCallback::handleEvent, 462 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
416 wrapPersistent(m_callback.get()), nullptr)); 463 ->postTask(BLINK_FROM_HERE,
464 WTF::bind(&BlobCallback::handleEvent,
465 wrapPersistent(m_callback.get()), nullptr));
466 } else {
467 Blob* blob = nullptr;
468 m_scriptPromiseResolver->reject(blob);
469 }
417 // Avoid unwanted retention, see dispose(). 470 // Avoid unwanted retention, see dispose().
418 dispose(); 471 dispose();
419 } 472 }
420 473
421 void CanvasAsyncBlobCreator::encodeImageOnEncoderThread(double quality) { 474 void CanvasAsyncBlobCreator::encodeImageOnEncoderThread(double quality) {
422 ASSERT(!isMainThread()); 475 DCHECK(!isMainThread());
423 ASSERT(m_mimeType == MimeTypeWebp); 476 DCHECK(m_mimeType == MimeTypeWebp);
424 477
425 if (!ImageDataBuffer(m_size, m_data->data()) 478 if (!ImageDataBuffer(m_size, m_data->data())
426 .encodeImage("image/webp", quality, m_encodedImage.get())) { 479 .encodeImage("image/webp", quality, m_encodedImage.get())) {
427 m_parentFrameTaskRunner->get(TaskType::CanvasBlobSerialization) 480 m_parentFrameTaskRunner->get(TaskType::CanvasBlobSerialization)
428 ->postTask(BLINK_FROM_HERE, 481 ->postTask(BLINK_FROM_HERE,
429 crossThreadBind(&BlobCallback::handleEvent, 482 crossThreadBind(&BlobCallback::handleEvent,
430 wrapCrossThreadPersistent(m_callback.get()), 483 wrapCrossThreadPersistent(m_callback.get()),
431 nullptr)); 484 nullptr));
432 return; 485 return;
433 } 486 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) 532 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
480 ->postTask( 533 ->postTask(
481 BLINK_FROM_HERE, 534 BLINK_FROM_HERE,
482 WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread, 535 WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread,
483 wrapPersistent(this))); 536 wrapPersistent(this)));
484 } else { 537 } else {
485 // Failing in initialization of png struct 538 // Failing in initialization of png struct
486 this->signalAlternativeCodePathFinishedForTesting(); 539 this->signalAlternativeCodePathFinishedForTesting();
487 } 540 }
488 } else { 541 } else {
489 ASSERT(m_mimeType == MimeTypeJpeg); 542 DCHECK(m_mimeType == MimeTypeJpeg);
490 if (initializeJpegStruct(quality)) { 543 if (initializeJpegStruct(quality)) {
491 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) 544 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
492 ->postTask( 545 ->postTask(
493 BLINK_FROM_HERE, 546 BLINK_FROM_HERE,
494 WTF::bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, 547 WTF::bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread,
495 wrapPersistent(this))); 548 wrapPersistent(this)));
496 } else { 549 } else {
497 // Failing in initialization of jpeg struct 550 // Failing in initialization of jpeg struct
498 this->signalAlternativeCodePathFinishedForTesting(); 551 this->signalAlternativeCodePathFinishedForTesting();
499 } 552 }
500 } 553 }
501 } else { 554 } else {
502 ASSERT(m_idleTaskStatus == IdleTaskFailed || 555 DCHECK(m_idleTaskStatus == IdleTaskFailed ||
503 m_idleTaskStatus == IdleTaskCompleted); 556 m_idleTaskStatus == IdleTaskCompleted);
504 this->signalAlternativeCodePathFinishedForTesting(); 557 this->signalAlternativeCodePathFinishedForTesting();
505 } 558 }
506 } 559 }
507 560
508 void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() { 561 void CanvasAsyncBlobCreator::idleTaskCompleteTimeoutEvent() {
509 ASSERT(m_idleTaskStatus != IdleTaskNotStarted); 562 DCHECK(m_idleTaskStatus != IdleTaskNotStarted);
510 563
511 if (m_idleTaskStatus == IdleTaskStarted) { 564 if (m_idleTaskStatus == IdleTaskStarted) {
512 // It has taken too long to complete for the idle task. 565 // It has taken too long to complete for the idle task.
513 m_idleTaskStatus = IdleTaskSwitchedToMainThreadTask; 566 m_idleTaskStatus = IdleTaskSwitchedToMainThreadTask;
514 signalTaskSwitchInCompleteTimeoutEventForTesting(); 567 signalTaskSwitchInCompleteTimeoutEventForTesting();
515 568
516 if (m_mimeType == MimeTypePng) { 569 if (m_mimeType == MimeTypePng) {
517 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) 570 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
518 ->postTask( 571 ->postTask(
519 BLINK_FROM_HERE, 572 BLINK_FROM_HERE,
520 WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread, 573 WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread,
521 wrapPersistent(this))); 574 wrapPersistent(this)));
522 } else { 575 } else {
523 ASSERT(m_mimeType == MimeTypeJpeg); 576 DCHECK(m_mimeType == MimeTypeJpeg);
524 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) 577 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
525 ->postTask( 578 ->postTask(
526 BLINK_FROM_HERE, 579 BLINK_FROM_HERE,
527 WTF::bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, 580 WTF::bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread,
528 wrapPersistent(this))); 581 wrapPersistent(this)));
529 } 582 }
530 } else { 583 } else {
531 ASSERT(m_idleTaskStatus == IdleTaskFailed || 584 DCHECK(m_idleTaskStatus == IdleTaskFailed ||
532 m_idleTaskStatus == IdleTaskCompleted); 585 m_idleTaskStatus == IdleTaskCompleted);
533 this->signalAlternativeCodePathFinishedForTesting(); 586 this->signalAlternativeCodePathFinishedForTesting();
534 } 587 }
535 } 588 }
536 589
537 void CanvasAsyncBlobCreator::postDelayedTaskToMainThread( 590 void CanvasAsyncBlobCreator::postDelayedTaskToMainThread(
538 const WebTraceLocation& location, 591 const WebTraceLocation& location,
539 std::unique_ptr<WTF::Closure> task, 592 std::unique_ptr<WTF::Closure> task,
540 double delayMs) { 593 double delayMs) {
541 DCHECK(isMainThread()); 594 DCHECK(isMainThread());
542 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document) 595 TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
543 ->postDelayedTask(location, std::move(task), delayMs); 596 ->postDelayedTask(location, std::move(task), delayMs);
544 } 597 }
545 598
546 DEFINE_TRACE(CanvasAsyncBlobCreator) { 599 DEFINE_TRACE(CanvasAsyncBlobCreator) {
547 visitor->trace(m_document); 600 visitor->trace(m_document);
548 visitor->trace(m_data); 601 visitor->trace(m_data);
549 visitor->trace(m_callback); 602 visitor->trace(m_callback);
550 visitor->trace(m_parentFrameTaskRunner); 603 visitor->trace(m_parentFrameTaskRunner);
604 visitor->trace(m_scriptPromiseResolver);
551 } 605 }
552 606
553 } // namespace blink 607 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698