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

Side by Side Diff: cc/tiles/software_image_decode_controller.cc

Issue 1839833003: Add medium image quality to software predecode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moving CLZ to a separate CL. Making changes as per CR comments. Created 4 years, 8 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
« no previous file with comments | « cc/tiles/software_image_decode_controller.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "cc/tiles/software_image_decode_controller.h" 5 #include "cc/tiles/software_image_decode_controller.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <algorithm>
9 #include <functional> 10 #include <functional>
11 #include <limits>
10 12
11 #include "base/macros.h" 13 #include "base/macros.h"
12 #include "base/memory/discardable_memory.h" 14 #include "base/memory/discardable_memory.h"
13 #include "cc/debug/devtools_instrumentation.h" 15 #include "cc/debug/devtools_instrumentation.h"
14 #include "cc/raster/tile_task_runner.h" 16 #include "cc/raster/tile_task_runner.h"
15 #include "third_party/skia/include/core/SkCanvas.h" 17 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "third_party/skia/include/core/SkImage.h" 18 #include "third_party/skia/include/core/SkImage.h"
17 #include "ui/gfx/skia_util.h" 19 #include "ui/gfx/skia_util.h"
18 20
19 namespace cc { 21 namespace cc {
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", 169 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key",
168 key.ToString()); 170 key.ToString());
169 171
170 // If the target size is empty, we can skip this image during draw (and thus 172 // If the target size is empty, we can skip this image during draw (and thus
171 // we don't need to decode it or ref it). 173 // we don't need to decode it or ref it).
172 if (key.target_size().IsEmpty()) { 174 if (key.target_size().IsEmpty()) {
173 *task = nullptr; 175 *task = nullptr;
174 return false; 176 return false;
175 } 177 }
176 178
177 // If we're not going to do a scale, we will just create a task to preroll the
178 // image the first time we see it. This doesn't need to account for memory.
179 // TODO(vmpstr): We can also lock the original sized image, in which case it
180 // does require memory bookkeeping.
181 if (!CanHandleImage(key)) {
182 base::AutoLock lock(lock_);
183 if (prerolled_images_.count(key.image_id()) == 0) {
184 scoped_refptr<ImageDecodeTask>& existing_task = pending_image_tasks_[key];
185 if (!existing_task) {
186 existing_task = make_scoped_refptr(
187 new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id));
188 }
189 *task = existing_task;
190 } else {
191 *task = nullptr;
192 }
193 return false;
194 }
195
196 base::AutoLock lock(lock_); 179 base::AutoLock lock(lock_);
197 180
198 // If we already have the image in cache, then we can return it. 181 // If we already have the image in cache, then we can return it.
199 auto decoded_it = decoded_images_.Get(key); 182 auto decoded_it = decoded_images_.Get(key);
200 bool new_image_fits_in_memory = 183 bool new_image_fits_in_memory =
201 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes(); 184 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes();
202 if (decoded_it != decoded_images_.end()) { 185 if (decoded_it != decoded_images_.end()) {
203 if (decoded_it->second->is_locked() || 186 if (decoded_it->second->is_locked() ||
204 (new_image_fits_in_memory && decoded_it->second->Lock())) { 187 (new_image_fits_in_memory && decoded_it->second->Lock())) {
205 RefImage(key); 188 RefImage(key);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 } 240 }
258 241
259 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) { 242 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) {
260 // When we unref the image, there are several situations we need to consider: 243 // When we unref the image, there are several situations we need to consider:
261 // 1. The ref did not reach 0, which means we have to keep the image locked. 244 // 1. The ref did not reach 0, which means we have to keep the image locked.
262 // 2. The ref reached 0, we should unlock it. 245 // 2. The ref reached 0, we should unlock it.
263 // 2a. The image isn't in the locked cache because we didn't get to decode 246 // 2a. The image isn't in the locked cache because we didn't get to decode
264 // it yet (or failed to decode it). 247 // it yet (or failed to decode it).
265 // 2b. Unlock the image but keep it in list. 248 // 2b. Unlock the image but keep it in list.
266 const ImageKey& key = ImageKey::FromDrawImage(image); 249 const ImageKey& key = ImageKey::FromDrawImage(image);
267 DCHECK(CanHandleImage(key));
268 TRACE_EVENT1("disabled-by-default-cc.debug", 250 TRACE_EVENT1("disabled-by-default-cc.debug",
269 "SoftwareImageDecodeController::UnrefImage", "key", 251 "SoftwareImageDecodeController::UnrefImage", "key",
270 key.ToString()); 252 key.ToString());
271 253
272 base::AutoLock lock(lock_); 254 base::AutoLock lock(lock_);
273 auto ref_count_it = decoded_images_ref_counts_.find(key); 255 auto ref_count_it = decoded_images_ref_counts_.find(key);
274 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); 256 DCHECK(ref_count_it != decoded_images_ref_counts_.end());
275 257
276 --ref_count_it->second; 258 --ref_count_it->second;
277 if (ref_count_it->second == 0) { 259 if (ref_count_it->second == 0) {
(...skipping 10 matching lines...) Expand all
288 DCHECK(decoded_image_it->second->is_locked()); 270 DCHECK(decoded_image_it->second->is_locked());
289 decoded_image_it->second->Unlock(); 271 decoded_image_it->second->Unlock();
290 } 272 }
291 SanityCheckState(__LINE__, true); 273 SanityCheckState(__LINE__, true);
292 } 274 }
293 275
294 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key, 276 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key,
295 const DrawImage& image) { 277 const DrawImage& image) {
296 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key", 278 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key",
297 key.ToString()); 279 key.ToString());
298 if (!CanHandleImage(key)) {
299 image.image()->preroll();
300
301 base::AutoLock lock(lock_);
302 prerolled_images_.insert(key.image_id());
303 // Erase the pending task from the queue, since the task won't be doing
304 // anything useful after this function terminates. Since we don't preroll
305 // images twice, this is actually not necessary but it behaves similar to
306 // the other code path: when this function finishes, the task isn't in the
307 // pending_image_tasks_ list.
308 pending_image_tasks_.erase(key);
309 return;
310 }
311
312 base::AutoLock lock(lock_); 280 base::AutoLock lock(lock_);
313 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key); 281 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key);
314 282
315 // We could have finished all of the raster tasks (cancelled) while the task 283 // We could have finished all of the raster tasks (cancelled) while the task
316 // was just starting to run. Since this task already started running, it 284 // was just starting to run. Since this task already started running, it
317 // wasn't cancelled. So, if the ref count for the image is 0 then we can just 285 // wasn't cancelled. So, if the ref count for the image is 0 then we can just
318 // abort. 286 // abort.
319 if (decoded_images_ref_counts_.find(key) == 287 if (decoded_images_ref_counts_.find(key) ==
320 decoded_images_ref_counts_.end()) { 288 decoded_images_ref_counts_.end()) {
321 return; 289 return;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 if (decoded_images_ref_counts_.find(key) == 326 if (decoded_images_ref_counts_.find(key) ==
359 decoded_images_ref_counts_.end()) { 327 decoded_images_ref_counts_.end()) {
360 decoded_image->Unlock(); 328 decoded_image->Unlock();
361 } 329 }
362 330
363 decoded_images_.Put(key, std::move(decoded_image)); 331 decoded_images_.Put(key, std::move(decoded_image));
364 SanityCheckState(__LINE__, true); 332 SanityCheckState(__LINE__, true);
365 } 333 }
366 334
367 scoped_ptr<SoftwareImageDecodeController::DecodedImage> 335 scoped_ptr<SoftwareImageDecodeController::DecodedImage>
336 SoftwareImageDecodeController::DecodeImageMediumQuality(const ImageKey& key,
337 const SkImage& image) {
338 // We need an original decode to either do a scale or extract a subrect
339 // from the image.
340 auto decoded_image_result = DecodeImageOrUseCache(key, image);
341 if (!decoded_image_result.decoded_pixmap_.addr()) {
342 return nullptr;
343 }
344
345 // Generate a key and scaled image for each mipmap level.
346 gfx::Rect src_rect = key.src_rect();
347 int src_height = src_rect.height();
348 int src_width = src_rect.width();
349
350 std::unique_ptr<DecodedImage> last_mip_scaled_image;
351 std::unique_ptr<DecodedImage> target_mip_image;
352 for (int current_mip_level = 0;; current_mip_level++) {
353 int mip_height = std::max(1, src_height / (1 << current_mip_level));
354 int mip_width = std::max(1, src_width / (1 << current_mip_level));
355 SkScalar y_scale = static_cast<float>(mip_height) / src_height;
356 SkScalar x_scale = static_cast<float>(mip_width) / src_width;
357
358 // Generate an image and key to cache it
359 DrawImage mip_image(&image, gfx::RectToSkIRect(src_rect),
360 kMedium_SkFilterQuality,
vmpstr 2016/03/29 21:48:04 Passing medium here would make skia also generate
cblume 2016/03/30 00:31:08 Yeah. This is sort of a placeholder until we figur
361 SkMatrix::MakeScale(x_scale, y_scale));
362 auto mip_key = ImageKey::FromDrawImage(mip_image);
363 auto mip_scaled_image = ScaleImage(mip_key, decoded_image_result);
364
365 // Check if this is the first mipmap smaller than target.
366 // If so, use the mip level below on the mip stack.
367 // This effectively always uses the larger image and always scales down.
368 if (mip_height < key.target_size().height() ||
369 mip_width < key.target_size().width()) {
370 if (target_mip_image == nullptr) {
371 target_mip_image = std::move(last_mip_scaled_image);
vmpstr 2016/03/29 21:48:04 Should we just break here?
cblume 2016/03/30 00:31:08 If we are only generating one level (which I like)
372 }
373 }
374 last_mip_scaled_image =
375 std::unique_ptr<DecodedImage>(mip_scaled_image.release());
vmpstr 2016/03/29 21:48:04 is this just a std::move?
376
377 if (mip_height == 1 && mip_width == 1) {
378 // We have reached the final mip level
379 break;
380 }
381 }
382
383 return make_scoped_ptr<DecodedImage>(target_mip_image.release());
vmpstr 2016/03/29 21:48:04 just return target_mip_image;?
384 }
385
386 scoped_ptr<SoftwareImageDecodeController::DecodedImage>
387 SoftwareImageDecodeController::DecodeImageHighQuality(const ImageKey& key,
388 const SkImage& image) {
389 // We need an original decode to either do a scale or to extract a subrect
390 // from the image.
391 auto decoded_image_result = DecodeImageOrUseCache(key, image);
392 if (!decoded_image_result.decoded_pixmap_.addr()) {
393 return nullptr;
394 }
395
396
397 // Now we have a decoded_pixmap which represents the src_rect at the
398 // original scale. All we need to do is scale it.
399 return ScaleImage(key, decoded_image_result);
400 }
401
402 scoped_ptr<SoftwareImageDecodeController::DecodedImage>
368 SoftwareImageDecodeController::DecodeImageInternal( 403 SoftwareImageDecodeController::DecodeImageInternal(
369 const ImageKey& key, 404 const ImageKey& key,
370 const DrawImage& draw_image) { 405 const DrawImage& draw_image) {
371 TRACE_EVENT1("disabled-by-default-cc.debug", 406 TRACE_EVENT1("disabled-by-default-cc.debug",
372 "SoftwareImageDecodeController::DecodeImageInternal", "key", 407 "SoftwareImageDecodeController::DecodeImageInternal", "key",
373 key.ToString()); 408 key.ToString());
374 const SkImage* image = draw_image.image(); 409 const SkImage* image = draw_image.image();
375 410 if (!image) {
376 // If we can use the original decode, then we don't need to do scaling. We can
377 // just read pixels into the final memory.
378 if (key.can_use_original_decode()) {
379 SkImageInfo decoded_info =
380 CreateImageInfo(image->width(), image->height(), format_);
381 scoped_ptr<base::DiscardableMemory> decoded_pixels;
382 {
383 TRACE_EVENT0(
384 "disabled-by-default-cc.debug",
385 "SoftwareImageDecodeController::DecodeImageInternal - allocate "
386 "decoded pixels");
387 decoded_pixels =
388 base::DiscardableMemoryAllocator::GetInstance()
389 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() *
390 decoded_info.height());
391 }
392 {
393 TRACE_EVENT0(
394 "disabled-by-default-cc.debug",
395 "SoftwareImageDecodeController::DecodeImageInternal - read pixels");
396 bool result = image->readPixels(decoded_info, decoded_pixels->data(),
397 decoded_info.minRowBytes(), 0, 0,
398 SkImage::kDisallow_CachingHint);
399
400 if (!result) {
401 decoded_pixels->Unlock();
402 return nullptr;
403 }
404 }
405
406 return make_scoped_ptr(new DecodedImage(
407 decoded_info, std::move(decoded_pixels), SkSize::Make(0, 0)));
408 }
409
410 // If we get here, that means we couldn't use the original sized decode for
411 // whatever reason. However, in all cases we do need an original decode to
412 // either do a scale or to extract a subrect from the image. So, what we can
413 // do is construct a key that would require a full sized decode, then get that
414 // decode via GetDecodedImageForDrawInternal(), use it, and unref it. This
415 // ensures that if the original sized decode is already available in any of
416 // the caches, we reuse that. We also ensure that all the proper locking takes
417 // place. If, on the other hand, the decode was not available,
418 // GetDecodedImageForDrawInternal() would decode the image, and unreffing it
419 // later ensures that we will store the discardable memory unlocked in the
420 // cache to be used by future requests.
421 gfx::Rect full_image_rect(image->width(), image->height());
422 DrawImage original_size_draw_image(image, gfx::RectToSkIRect(full_image_rect),
423 kNone_SkFilterQuality, SkMatrix::I());
424 ImageKey original_size_key =
425 ImageKey::FromDrawImage(original_size_draw_image);
426 // Sanity checks.
427 DCHECK(original_size_key.can_use_original_decode());
428 DCHECK(full_image_rect.size() == original_size_key.target_size());
429
430 auto decoded_draw_image = GetDecodedImageForDrawInternal(
431 original_size_key, original_size_draw_image);
432 if (!decoded_draw_image.image()) {
433 DrawWithImageFinished(original_size_draw_image, decoded_draw_image);
434 return nullptr; 411 return nullptr;
435 } 412 }
436 413
437 SkPixmap decoded_pixmap; 414 switch (key.filter_quality()) {
438 bool result = decoded_draw_image.image()->peekPixels(&decoded_pixmap); 415 case kNone_SkFilterQuality:
439 DCHECK(result); 416 // fall through
440 if (key.src_rect() != full_image_rect) { 417 case kLow_SkFilterQuality:
441 result = decoded_pixmap.extractSubset(&decoded_pixmap, 418 DCHECK(key.can_use_original_decode());
442 gfx::RectToSkIRect(key.src_rect())); 419
443 DCHECK(result); 420 return AttemptToUseOriginalImage(key, *image);
421 case kMedium_SkFilterQuality:
422 return DecodeImageMediumQuality(key, *image);
423 case kHigh_SkFilterQuality:
424 return DecodeImageHighQuality(key, *image);
425 default:
426 NOTREACHED();
427 return nullptr;
444 } 428 }
445
446 // Now we have a decoded_pixmap which represents the src_rect at the
447 // original scale. All we need to do is scale it.
448 DCHECK(!key.target_size().IsEmpty());
449 SkImageInfo scaled_info = CreateImageInfo(
450 key.target_size().width(), key.target_size().height(), format_);
451 scoped_ptr<base::DiscardableMemory> scaled_pixels;
452 {
453 TRACE_EVENT0(
454 "disabled-by-default-cc.debug",
455 "SoftwareImageDecodeController::DecodeImageInternal - allocate "
456 "scaled pixels");
457 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance()
458 ->AllocateLockedDiscardableMemory(
459 scaled_info.minRowBytes() * scaled_info.height());
460 }
461 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(),
462 scaled_info.minRowBytes());
463 // TODO(vmpstr): Start handling more than just high filter quality.
464 DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality());
465 {
466 TRACE_EVENT0(
467 "disabled-by-default-cc.debug",
468 "SoftwareImageDecodeController::DecodeImageInternal - scale pixels");
469 bool result =
470 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality());
471 DCHECK(result);
472 }
473
474 // Release the original sized decode. Any other intermediate result to release
475 // would be the subrect memory. However, that's in a scoped_ptr and will be
476 // deleted automatically when we return.
477 DrawWithImageFinished(original_size_draw_image, decoded_draw_image);
478
479 return make_scoped_ptr(
480 new DecodedImage(scaled_info, std::move(scaled_pixels),
481 SkSize::Make(-key.src_rect().x(), -key.src_rect().y())));
482 } 429 }
483 430
484 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( 431 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw(
485 const DrawImage& draw_image) { 432 const DrawImage& draw_image) {
486 ImageKey key = ImageKey::FromDrawImage(draw_image); 433 ImageKey key = ImageKey::FromDrawImage(draw_image);
487 TRACE_EVENT1("disabled-by-default-cc.debug", 434 TRACE_EVENT1("disabled-by-default-cc.debug",
488 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", 435 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key",
489 key.ToString()); 436 key.ToString());
490 // If the target size is empty, we can skip this image draw. 437 // If the target size is empty, we can skip this image draw.
491 if (key.target_size().IsEmpty()) 438 if (key.target_size().IsEmpty())
492 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); 439 return DecodedDrawImage(nullptr, kNone_SkFilterQuality);
493 440
494 if (!CanHandleImage(key))
495 return DecodedDrawImage(draw_image.image(), draw_image.filter_quality());
496
497 return GetDecodedImageForDrawInternal(key, draw_image); 441 return GetDecodedImageForDrawInternal(key, draw_image);
498 } 442 }
499 443
500 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( 444 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal(
501 const ImageKey& key, 445 const ImageKey& key,
502 const DrawImage& draw_image) { 446 const DrawImage& draw_image) {
503 TRACE_EVENT1("disabled-by-default-cc.debug", 447 TRACE_EVENT1("disabled-by-default-cc.debug",
504 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", 448 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal",
505 "key", key.ToString()); 449 "key", key.ToString());
506 base::AutoLock lock(lock_); 450 base::AutoLock lock(lock_);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 // Now we know that we don't have a locked image, and we seem to be the first 486 // Now we know that we don't have a locked image, and we seem to be the first
543 // thread encountering this image (that might not be true, since other threads 487 // thread encountering this image (that might not be true, since other threads
544 // might be decoding it already). This means that we need to decode the image 488 // might be decoding it already). This means that we need to decode the image
545 // assuming we can't lock the one we found in the cache. 489 // assuming we can't lock the one we found in the cache.
546 bool check_at_raster_cache = false; 490 bool check_at_raster_cache = false;
547 if (!decoded_image || !decoded_image->Lock()) { 491 if (!decoded_image || !decoded_image->Lock()) {
548 // Note that we have to release the lock, since this lock is also accessed 492 // Note that we have to release the lock, since this lock is also accessed
549 // on the compositor thread. This means holding on to the lock might stall 493 // on the compositor thread. This means holding on to the lock might stall
550 // the compositor thread for the duration of the decode! 494 // the compositor thread for the duration of the decode!
551 base::AutoUnlock unlock(lock_); 495 base::AutoUnlock unlock(lock_);
552 scoped_decoded_image = DecodeImageInternal(key, draw_image); 496 const SkImage* image = draw_image.image();
497 if (!image) {
498 return DecodedDrawImage(nullptr, kNone_SkFilterQuality);
499 }
500 scoped_decoded_image = AttemptToUseOriginalImage(key, *image);
553 decoded_image = scoped_decoded_image.get(); 501 decoded_image = scoped_decoded_image.get();
554 502
555 // Skip the image if we couldn't decode it. 503 // Skip the image if we couldn't decode it.
556 if (!decoded_image) 504 if (!decoded_image)
557 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); 505 return DecodedDrawImage(nullptr, kNone_SkFilterQuality);
558 check_at_raster_cache = true; 506 check_at_raster_cache = true;
559 } 507 }
560 508
561 DCHECK(decoded_image == scoped_decoded_image.get()); 509 DCHECK(decoded_image == scoped_decoded_image.get());
562 510
(...skipping 20 matching lines...) Expand all
583 DCHECK(decoded_image->is_locked()); 531 DCHECK(decoded_image->is_locked());
584 RefAtRasterImage(key); 532 RefAtRasterImage(key);
585 SanityCheckState(__LINE__, true); 533 SanityCheckState(__LINE__, true);
586 auto decoded_draw_image = 534 auto decoded_draw_image =
587 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), 535 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(),
588 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); 536 GetScaleAdjustment(key), GetDecodedFilterQuality(key));
589 decoded_draw_image.set_at_raster_decode(true); 537 decoded_draw_image.set_at_raster_decode(true);
590 return decoded_draw_image; 538 return decoded_draw_image;
591 } 539 }
592 540
541 SoftwareImageDecodeController::DecodedImageResult::DecodedImageResult(
542 SkPixmap decoded_pixmap,
543 DrawImage original_size_draw_image,
544 DecodedDrawImage decoded_draw_image)
545 : decoded_pixmap_(decoded_pixmap),
546 original_size_draw_image_(original_size_draw_image),
547 decoded_draw_image_(decoded_draw_image) {}
548
549 scoped_ptr<SoftwareImageDecodeController::DecodedImage>
550 SoftwareImageDecodeController::AttemptToUseOriginalImage(const ImageKey& key,
551 const SkImage& image) {
552 TRACE_EVENT1("disabled-by-default-cc.debug",
553 "SoftwareImageDecodeController::AttemptToUseOriginalImage",
554 "key", key.ToString());
555 if (!key.can_use_original_decode()) {
556 return nullptr;
557 } else {
558 SkImageInfo decoded_info =
559 CreateImageInfo(image.width(), image.height(), format_);
560 scoped_ptr<base::DiscardableMemory> decoded_pixels;
561 {
562 TRACE_EVENT0("disabled-by-default-cc.debug",
563 "SoftwareImageDecodeController::AttemptToUseOriginalImage - "
564 "allocate decoded pixels");
565 decoded_pixels =
566 base::DiscardableMemoryAllocator::GetInstance()
567 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() *
568 decoded_info.height());
569 }
570 {
571 TRACE_EVENT0("disabled-by-default-cc.debug",
572 "SoftwareImageDecodeController::AttemptToUseOriginalImage - "
573 "read pixels");
574 bool result = image.readPixels(decoded_info, decoded_pixels->data(),
575 decoded_info.minRowBytes(), 0, 0,
576 SkImage::kDisallow_CachingHint);
577
578 if (!result) {
579 decoded_pixels->Unlock();
580 return nullptr;
581 }
582 }
583
584 return make_scoped_ptr(new DecodedImage(
585 decoded_info, std::move(decoded_pixels), SkSize::Make(0, 0)));
586 }
587 }
588
589 SoftwareImageDecodeController::DecodedImageResult
590 SoftwareImageDecodeController::DecodeImageOrUseCache(const ImageKey& key,
591 const SkImage& image) {
592 // Construct a key to use in GetDecodedImageForDrawInternal().
593 // This allows us to reuse an image in any cache if available.
594 gfx::Rect full_image_rect(image.width(), image.height());
595 DrawImage original_size_draw_image(&image,
596 gfx::RectToSkIRect(full_image_rect),
597 kNone_SkFilterQuality, SkMatrix::I());
598 ImageKey original_size_key =
599 ImageKey::FromDrawImage(original_size_draw_image);
600 // Sanity checks.
601 DCHECK(original_size_key.can_use_original_decode());
602 DCHECK(full_image_rect.size() == original_size_key.target_size());
603
604 auto decoded_draw_image = GetDecodedImageForDrawInternal(
605 original_size_key, original_size_draw_image);
606
607 if (!decoded_draw_image.image()) {
608 DrawWithImageFinished(original_size_draw_image, decoded_draw_image);
609 return DecodedImageResult(SkPixmap(), DrawImage(),
610 DecodedDrawImage(nullptr, kNone_SkFilterQuality));
611 }
612
613 SkPixmap decoded_pixmap;
614 bool result = decoded_draw_image.image()->peekPixels(&decoded_pixmap);
615 DCHECK(result);
616 if (key.src_rect() != full_image_rect) {
617 result = decoded_pixmap.extractSubset(&decoded_pixmap,
618 gfx::RectToSkIRect(key.src_rect()));
619 DCHECK(result);
620 }
621
622 return DecodedImageResult(decoded_pixmap, original_size_draw_image,
623 decoded_draw_image);
624 }
625
626 scoped_ptr<SoftwareImageDecodeController::DecodedImage>
627 SoftwareImageDecodeController::ScaleImage(
628 const ImageKey& key,
629 const DecodedImageResult& decoded_image_result) {
630 DCHECK(!key.target_size().IsEmpty());
631 SkImageInfo scaled_info = CreateImageInfo(
632 key.target_size().width(), key.target_size().height(), format_);
633 scoped_ptr<base::DiscardableMemory> scaled_pixels;
634 {
635 TRACE_EVENT0(
636 "disabled-by-default-cc.debug",
637 "SoftwareImageDecodeController::ScaleImage - allocate scaled pixels");
638 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance()
639 ->AllocateLockedDiscardableMemory(
640 scaled_info.minRowBytes() * scaled_info.height());
641 }
642 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(),
643 scaled_info.minRowBytes());
644 {
645 TRACE_EVENT0("disabled-by-default-cc.debug",
646 "SoftwareImageDecodeController::ScaleImage - scale pixels");
647 bool result = decoded_image_result.decoded_pixmap_.scalePixels(
648 scaled_pixmap, key.filter_quality());
649 DCHECK(result);
650 }
651
652 // Release the original sized decode. Any other intermediate result to release
653 // would be the subrect memory. However, that's in a scoped_ptr and will be
654 // deleted automatically when we return.
655 DrawWithImageFinished(decoded_image_result.original_size_draw_image_,
656 decoded_image_result.decoded_draw_image_);
657
658 return make_scoped_ptr(new SoftwareImageDecodeController::DecodedImage(
659 scaled_info, std::move(scaled_pixels),
660 SkSize::Make(-key.src_rect().x(), -key.src_rect().y())));
661 }
662
593 void SoftwareImageDecodeController::DrawWithImageFinished( 663 void SoftwareImageDecodeController::DrawWithImageFinished(
594 const DrawImage& image, 664 const DrawImage& image,
595 const DecodedDrawImage& decoded_image) { 665 const DecodedDrawImage& decoded_image) {
596 TRACE_EVENT1("disabled-by-default-cc.debug", 666 TRACE_EVENT1("disabled-by-default-cc.debug",
597 "SoftwareImageDecodeController::DrawWithImageFinished", "key", 667 "SoftwareImageDecodeController::DrawWithImageFinished", "key",
598 ImageKey::FromDrawImage(image).ToString()); 668 ImageKey::FromDrawImage(image).ToString());
599 ImageKey key = ImageKey::FromDrawImage(image); 669 ImageKey key = ImageKey::FromDrawImage(image);
600 if (!decoded_image.image() || !CanHandleImage(key)) 670 if (!decoded_image.image())
601 return; 671 return;
602 672
603 if (decoded_image.is_at_raster_decode()) 673 if (decoded_image.is_at_raster_decode())
604 UnrefAtRasterImage(key); 674 UnrefAtRasterImage(key);
605 else 675 else
606 UnrefImage(image); 676 UnrefImage(image);
607 SanityCheckState(__LINE__, false); 677 SanityCheckState(__LINE__, false);
608 } 678 }
609 679
610 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) { 680 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 DCHECK(decoded_images_ref_counts_.find(key) == 727 DCHECK(decoded_images_ref_counts_.find(key) ==
658 decoded_images_ref_counts_.end()); 728 decoded_images_ref_counts_.end());
659 at_raster_image_it->second->Unlock(); 729 at_raster_image_it->second->Unlock();
660 decoded_images_.Erase(image_it); 730 decoded_images_.Erase(image_it);
661 decoded_images_.Put(key, std::move(at_raster_image_it->second)); 731 decoded_images_.Put(key, std::move(at_raster_image_it->second));
662 } 732 }
663 at_raster_decoded_images_.Erase(at_raster_image_it); 733 at_raster_decoded_images_.Erase(at_raster_image_it);
664 } 734 }
665 } 735 }
666 736
667 bool SoftwareImageDecodeController::CanHandleImage(const ImageKey& key) {
668 // TODO(vmpstr): Start handling medium filter quality as well.
669 return key.filter_quality() != kMedium_SkFilterQuality;
670 }
671
672 void SoftwareImageDecodeController::ReduceCacheUsage() { 737 void SoftwareImageDecodeController::ReduceCacheUsage() {
673 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage"); 738 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage");
674 base::AutoLock lock(lock_); 739 base::AutoLock lock(lock_);
675 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache) 740 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache)
676 ? (decoded_images_.size() - kMaxItemsInCache) 741 ? (decoded_images_.size() - kMaxItemsInCache)
677 : 0; 742 : 0;
678 for (auto it = decoded_images_.rbegin(); 743 for (auto it = decoded_images_.rbegin();
679 num_to_remove != 0 && it != decoded_images_.rend();) { 744 num_to_remove != 0 && it != decoded_images_.rend();) {
680 if (it->second->is_locked()) { 745 if (it->second->is_locked()) {
681 ++it; 746 ++it;
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { 949 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() {
885 current_usage_bytes_ = 0; 950 current_usage_bytes_ = 0;
886 } 951 }
887 952
888 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() 953 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe()
889 const { 954 const {
890 return current_usage_bytes_.ValueOrDie(); 955 return current_usage_bytes_.ValueOrDie();
891 } 956 }
892 957
893 } // namespace cc 958 } // namespace cc
OLDNEW
« no previous file with comments | « cc/tiles/software_image_decode_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698