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 |