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

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: Generating mip levels on demand. 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>
10 11
11 #include "base/macros.h" 12 #include "base/macros.h"
12 #include "base/memory/discardable_memory.h" 13 #include "base/memory/discardable_memory.h"
13 #include "cc/debug/devtools_instrumentation.h" 14 #include "cc/debug/devtools_instrumentation.h"
14 #include "cc/raster/tile_task_runner.h" 15 #include "cc/raster/tile_task_runner.h"
15 #include "third_party/skia/include/core/SkCanvas.h" 16 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "third_party/skia/include/core/SkImage.h" 17 #include "third_party/skia/include/core/SkImage.h"
17 #include "ui/gfx/skia_util.h" 18 #include "ui/gfx/skia_util.h"
18 19
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", 168 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key",
168 key.ToString()); 169 key.ToString());
169 170
170 // If the target size is empty, we can skip this image during draw (and thus 171 // 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). 172 // we don't need to decode it or ref it).
172 if (key.target_size().IsEmpty()) { 173 if (key.target_size().IsEmpty()) {
173 *task = nullptr; 174 *task = nullptr;
174 return false; 175 return false;
175 } 176 }
176 177
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_); 178 base::AutoLock lock(lock_);
197 179
198 // If we already have the image in cache, then we can return it. 180 // If we already have the image in cache, then we can return it.
199 auto decoded_it = decoded_images_.Get(key); 181 auto decoded_it = decoded_images_.Get(key);
200 bool new_image_fits_in_memory = 182 bool new_image_fits_in_memory =
201 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes(); 183 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes();
202 if (decoded_it != decoded_images_.end()) { 184 if (decoded_it != decoded_images_.end()) {
203 if (decoded_it->second->is_locked() || 185 if (decoded_it->second->is_locked() ||
204 (new_image_fits_in_memory && decoded_it->second->Lock())) { 186 (new_image_fits_in_memory && decoded_it->second->Lock())) {
205 RefImage(key); 187 RefImage(key);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 } 239 }
258 240
259 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) { 241 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) {
260 // When we unref the image, there are several situations we need to consider: 242 // 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. 243 // 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. 244 // 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 245 // 2a. The image isn't in the locked cache because we didn't get to decode
264 // it yet (or failed to decode it). 246 // it yet (or failed to decode it).
265 // 2b. Unlock the image but keep it in list. 247 // 2b. Unlock the image but keep it in list.
266 const ImageKey& key = ImageKey::FromDrawImage(image); 248 const ImageKey& key = ImageKey::FromDrawImage(image);
267 DCHECK(CanHandleImage(key));
268 TRACE_EVENT1("disabled-by-default-cc.debug", 249 TRACE_EVENT1("disabled-by-default-cc.debug",
269 "SoftwareImageDecodeController::UnrefImage", "key", 250 "SoftwareImageDecodeController::UnrefImage", "key",
270 key.ToString()); 251 key.ToString());
271 252
272 base::AutoLock lock(lock_); 253 base::AutoLock lock(lock_);
273 auto ref_count_it = decoded_images_ref_counts_.find(key); 254 auto ref_count_it = decoded_images_ref_counts_.find(key);
274 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); 255 DCHECK(ref_count_it != decoded_images_ref_counts_.end());
275 256
276 --ref_count_it->second; 257 --ref_count_it->second;
277 if (ref_count_it->second == 0) { 258 if (ref_count_it->second == 0) {
(...skipping 10 matching lines...) Expand all
288 DCHECK(decoded_image_it->second->is_locked()); 269 DCHECK(decoded_image_it->second->is_locked());
289 decoded_image_it->second->Unlock(); 270 decoded_image_it->second->Unlock();
290 } 271 }
291 SanityCheckState(__LINE__, true); 272 SanityCheckState(__LINE__, true);
292 } 273 }
293 274
294 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key, 275 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key,
295 const DrawImage& image) { 276 const DrawImage& image) {
296 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key", 277 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key",
297 key.ToString()); 278 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_); 279 base::AutoLock lock(lock_);
313 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key); 280 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key);
314 281
315 // We could have finished all of the raster tasks (cancelled) while the task 282 // 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 283 // 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 284 // wasn't cancelled. So, if the ref count for the image is 0 then we can just
318 // abort. 285 // abort.
319 if (decoded_images_ref_counts_.find(key) == 286 if (decoded_images_ref_counts_.find(key) ==
320 decoded_images_ref_counts_.end()) { 287 decoded_images_ref_counts_.end()) {
321 return; 288 return;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 if (decoded_images_ref_counts_.find(key) == 325 if (decoded_images_ref_counts_.find(key) ==
359 decoded_images_ref_counts_.end()) { 326 decoded_images_ref_counts_.end()) {
360 decoded_image->Unlock(); 327 decoded_image->Unlock();
361 } 328 }
362 329
363 decoded_images_.Put(key, std::move(decoded_image)); 330 decoded_images_.Put(key, std::move(decoded_image));
364 SanityCheckState(__LINE__, true); 331 SanityCheckState(__LINE__, true);
365 } 332 }
366 333
367 scoped_ptr<SoftwareImageDecodeController::DecodedImage> 334 scoped_ptr<SoftwareImageDecodeController::DecodedImage>
335 SoftwareImageDecodeController::DecodeImageMediumQuality(const ImageKey& key,
336 const SkImage& image) {
337 // We need an original decode to either do a scale or extract a subrect
338 // from the image.
339 auto decoded_image_result = DecodeImageOrUseCache(key, image);
340 if (!decoded_image_result.decoded_pixmap_.addr()) {
341 return nullptr;
342 }
343
344 // Generate a key and scaled image for each mipmap level.
345 gfx::Rect src_rect = key.src_rect();
346 int src_height = src_rect.height();
347 int src_width = src_rect.width();
348
349 for (int current_mip_level = 0;; current_mip_level++) {
350 int mip_height = std::max(1, src_height / (1 << current_mip_level));
351 int mip_width = std::max(1, src_width / (1 << current_mip_level));
352
353 // Check if this is the first mipmap smaller than target.
354 // If so, use the mip level below on the mip stack.
355 // This effectively always uses the larger image and always scales down.
356 if (mip_height < key.target_size().height() ||
vmpstr 2016/03/30 18:58:07 If the target size is 1x1, then I think this funct
cblume 2016/04/13 20:54:15 Done.
357 mip_width < key.target_size().width()) {
358 SkScalar y_scale = 1.f;
359 SkScalar x_scale = 1.f;
360 if (current_mip_level != 0) {
361 int previous_mip_height =
362 std::max(1, src_height / (1 << (current_mip_level - 1)));
363 int previous_mip_width =
364 std::max(1, src_width / (1 << (current_mip_level - 1)));
365 y_scale = static_cast<float>(previous_mip_height) / src_height;
366 x_scale = static_cast<float>(previous_mip_width) / src_width;
367 }
368
369 DrawImage mip_image(&image, gfx::RectToSkIRect(src_rect),
370 kHigh_SkFilterQuality,
371 SkMatrix::MakeScale(x_scale, y_scale));
372 auto mip_key = ImageKey::FromDrawImage(mip_image);
373 return ScaleImage(mip_key, decoded_image_result);
374
375 if (mip_height == 1 && mip_width == 1) {
376 // We have reached the final mip level
377 break;
378 }
379 }
380 }
381
382 return nullptr;
383 }
384
385 scoped_ptr<SoftwareImageDecodeController::DecodedImage>
386 SoftwareImageDecodeController::DecodeImageHighQuality(const ImageKey& key,
387 const SkImage& image) {
388 // We need an original decode to either do a scale or to extract a subrect
389 // from the image.
390 auto decoded_image_result = DecodeImageOrUseCache(key, image);
391 if (!decoded_image_result.decoded_pixmap_.addr()) {
392 return nullptr;
393 }
394
395
396 // Now we have a decoded_pixmap which represents the src_rect at the
397 // original scale. All we need to do is scale it.
398 return ScaleImage(key, decoded_image_result);
399 }
400
401 scoped_ptr<SoftwareImageDecodeController::DecodedImage>
368 SoftwareImageDecodeController::DecodeImageInternal( 402 SoftwareImageDecodeController::DecodeImageInternal(
369 const ImageKey& key, 403 const ImageKey& key,
370 const DrawImage& draw_image) { 404 const DrawImage& draw_image) {
371 TRACE_EVENT1("disabled-by-default-cc.debug", 405 TRACE_EVENT1("disabled-by-default-cc.debug",
372 "SoftwareImageDecodeController::DecodeImageInternal", "key", 406 "SoftwareImageDecodeController::DecodeImageInternal", "key",
373 key.ToString()); 407 key.ToString());
374 const SkImage* image = draw_image.image(); 408 const SkImage* image = draw_image.image();
375 409 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; 410 return nullptr;
435 } 411 }
436 412
437 SkPixmap decoded_pixmap; 413 switch (key.filter_quality()) {
438 bool result = decoded_draw_image.image()->peekPixels(&decoded_pixmap); 414 case kNone_SkFilterQuality:
439 DCHECK(result); 415 // fall through
440 if (key.src_rect() != full_image_rect) { 416 case kLow_SkFilterQuality:
441 result = decoded_pixmap.extractSubset(&decoded_pixmap, 417 DCHECK(key.can_use_original_decode());
442 gfx::RectToSkIRect(key.src_rect())); 418
443 DCHECK(result); 419 return AttemptToUseOriginalImage(key, *image);
420 case kMedium_SkFilterQuality:
421 return DecodeImageMediumQuality(key, *image);
422 case kHigh_SkFilterQuality:
423 return DecodeImageHighQuality(key, *image);
424 default:
425 NOTREACHED();
426 return nullptr;
444 } 427 }
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 } 428 }
483 429
484 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( 430 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw(
485 const DrawImage& draw_image) { 431 const DrawImage& draw_image) {
486 ImageKey key = ImageKey::FromDrawImage(draw_image); 432 ImageKey key = ImageKey::FromDrawImage(draw_image);
487 TRACE_EVENT1("disabled-by-default-cc.debug", 433 TRACE_EVENT1("disabled-by-default-cc.debug",
488 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", 434 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key",
489 key.ToString()); 435 key.ToString());
490 // If the target size is empty, we can skip this image draw. 436 // If the target size is empty, we can skip this image draw.
491 if (key.target_size().IsEmpty()) 437 if (key.target_size().IsEmpty())
492 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); 438 return DecodedDrawImage(nullptr, kNone_SkFilterQuality);
493 439
494 if (!CanHandleImage(key))
495 return DecodedDrawImage(draw_image.image(), draw_image.filter_quality());
496
497 return GetDecodedImageForDrawInternal(key, draw_image); 440 return GetDecodedImageForDrawInternal(key, draw_image);
498 } 441 }
499 442
500 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( 443 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal(
501 const ImageKey& key, 444 const ImageKey& key,
502 const DrawImage& draw_image) { 445 const DrawImage& draw_image) {
503 TRACE_EVENT1("disabled-by-default-cc.debug", 446 TRACE_EVENT1("disabled-by-default-cc.debug",
504 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", 447 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal",
505 "key", key.ToString()); 448 "key", key.ToString());
506 base::AutoLock lock(lock_); 449 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 485 // 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 486 // 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 487 // 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. 488 // assuming we can't lock the one we found in the cache.
546 bool check_at_raster_cache = false; 489 bool check_at_raster_cache = false;
547 if (!decoded_image || !decoded_image->Lock()) { 490 if (!decoded_image || !decoded_image->Lock()) {
548 // Note that we have to release the lock, since this lock is also accessed 491 // 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 492 // on the compositor thread. This means holding on to the lock might stall
550 // the compositor thread for the duration of the decode! 493 // the compositor thread for the duration of the decode!
551 base::AutoUnlock unlock(lock_); 494 base::AutoUnlock unlock(lock_);
552 scoped_decoded_image = DecodeImageInternal(key, draw_image); 495 const SkImage* image = draw_image.image();
496 if (!image) {
497 return DecodedDrawImage(nullptr, kNone_SkFilterQuality);
498 }
499 scoped_decoded_image = AttemptToUseOriginalImage(key, *image);
553 decoded_image = scoped_decoded_image.get(); 500 decoded_image = scoped_decoded_image.get();
554 501
555 // Skip the image if we couldn't decode it. 502 // Skip the image if we couldn't decode it.
556 if (!decoded_image) 503 if (!decoded_image)
557 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); 504 return DecodedDrawImage(nullptr, kNone_SkFilterQuality);
558 check_at_raster_cache = true; 505 check_at_raster_cache = true;
559 } 506 }
560 507
561 DCHECK(decoded_image == scoped_decoded_image.get()); 508 DCHECK(decoded_image == scoped_decoded_image.get());
562 509
(...skipping 20 matching lines...) Expand all
583 DCHECK(decoded_image->is_locked()); 530 DCHECK(decoded_image->is_locked());
584 RefAtRasterImage(key); 531 RefAtRasterImage(key);
585 SanityCheckState(__LINE__, true); 532 SanityCheckState(__LINE__, true);
586 auto decoded_draw_image = 533 auto decoded_draw_image =
587 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), 534 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(),
588 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); 535 GetScaleAdjustment(key), GetDecodedFilterQuality(key));
589 decoded_draw_image.set_at_raster_decode(true); 536 decoded_draw_image.set_at_raster_decode(true);
590 return decoded_draw_image; 537 return decoded_draw_image;
591 } 538 }
592 539
540 SoftwareImageDecodeController::DecodedImageResult::DecodedImageResult(
541 SkPixmap decoded_pixmap,
542 DrawImage original_size_draw_image,
543 DecodedDrawImage decoded_draw_image)
544 : decoded_pixmap_(decoded_pixmap),
545 original_size_draw_image_(original_size_draw_image),
546 decoded_draw_image_(decoded_draw_image) {}
547
548 scoped_ptr<SoftwareImageDecodeController::DecodedImage>
549 SoftwareImageDecodeController::AttemptToUseOriginalImage(const ImageKey& key,
550 const SkImage& image) {
551 TRACE_EVENT1("disabled-by-default-cc.debug",
552 "SoftwareImageDecodeController::AttemptToUseOriginalImage",
553 "key", key.ToString());
554 if (!key.can_use_original_decode()) {
555 return nullptr;
556 } else {
557 SkImageInfo decoded_info =
558 CreateImageInfo(image.width(), image.height(), format_);
559 scoped_ptr<base::DiscardableMemory> decoded_pixels;
560 {
561 TRACE_EVENT0("disabled-by-default-cc.debug",
562 "SoftwareImageDecodeController::AttemptToUseOriginalImage - "
563 "allocate decoded pixels");
564 decoded_pixels =
565 base::DiscardableMemoryAllocator::GetInstance()
566 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() *
567 decoded_info.height());
568 }
569 {
570 TRACE_EVENT0("disabled-by-default-cc.debug",
571 "SoftwareImageDecodeController::AttemptToUseOriginalImage - "
572 "read pixels");
573 bool result = image.readPixels(decoded_info, decoded_pixels->data(),
574 decoded_info.minRowBytes(), 0, 0,
575 SkImage::kDisallow_CachingHint);
576
577 if (!result) {
578 decoded_pixels->Unlock();
579 return nullptr;
580 }
581 }
582
583 return make_scoped_ptr(new DecodedImage(
584 decoded_info, std::move(decoded_pixels), SkSize::Make(0, 0)));
585 }
586 }
587
588 SoftwareImageDecodeController::DecodedImageResult
589 SoftwareImageDecodeController::DecodeImageOrUseCache(const ImageKey& key,
590 const SkImage& image) {
591 // Construct a key to use in GetDecodedImageForDrawInternal().
592 // This allows us to reuse an image in any cache if available.
593 gfx::Rect full_image_rect(image.width(), image.height());
594 DrawImage original_size_draw_image(&image,
595 gfx::RectToSkIRect(full_image_rect),
596 kNone_SkFilterQuality, SkMatrix::I());
597 ImageKey original_size_key =
598 ImageKey::FromDrawImage(original_size_draw_image);
599 // Sanity checks.
600 DCHECK(original_size_key.can_use_original_decode());
601 DCHECK(full_image_rect.size() == original_size_key.target_size());
602
603 auto decoded_draw_image = GetDecodedImageForDrawInternal(
604 original_size_key, original_size_draw_image);
605
606 if (!decoded_draw_image.image()) {
607 DrawWithImageFinished(original_size_draw_image, decoded_draw_image);
608 return DecodedImageResult(SkPixmap(), DrawImage(),
609 DecodedDrawImage(nullptr, kNone_SkFilterQuality));
610 }
611
612 SkPixmap decoded_pixmap;
613 bool result = decoded_draw_image.image()->peekPixels(&decoded_pixmap);
614 DCHECK(result);
615 if (key.src_rect() != full_image_rect) {
616 result = decoded_pixmap.extractSubset(&decoded_pixmap,
617 gfx::RectToSkIRect(key.src_rect()));
618 DCHECK(result);
619 }
620
621 return DecodedImageResult(decoded_pixmap, original_size_draw_image,
622 decoded_draw_image);
623 }
624
625 scoped_ptr<SoftwareImageDecodeController::DecodedImage>
626 SoftwareImageDecodeController::ScaleImage(
627 const ImageKey& key,
628 const DecodedImageResult& decoded_image_result) {
629 DCHECK(!key.target_size().IsEmpty());
630 SkImageInfo scaled_info = CreateImageInfo(
631 key.target_size().width(), key.target_size().height(), format_);
632 scoped_ptr<base::DiscardableMemory> scaled_pixels;
633 {
634 TRACE_EVENT0(
635 "disabled-by-default-cc.debug",
636 "SoftwareImageDecodeController::ScaleImage - allocate scaled pixels");
637 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance()
638 ->AllocateLockedDiscardableMemory(
639 scaled_info.minRowBytes() * scaled_info.height());
640 }
641 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(),
642 scaled_info.minRowBytes());
643 {
644 TRACE_EVENT0("disabled-by-default-cc.debug",
645 "SoftwareImageDecodeController::ScaleImage - scale pixels");
646 bool result = decoded_image_result.decoded_pixmap_.scalePixels(
647 scaled_pixmap, key.filter_quality());
648 DCHECK(result);
649 }
650
651 // Release the original sized decode. Any other intermediate result to release
652 // would be the subrect memory. However, that's in a scoped_ptr and will be
653 // deleted automatically when we return.
654 DrawWithImageFinished(decoded_image_result.original_size_draw_image_,
655 decoded_image_result.decoded_draw_image_);
656
657 return make_scoped_ptr(new SoftwareImageDecodeController::DecodedImage(
658 scaled_info, std::move(scaled_pixels),
659 SkSize::Make(-key.src_rect().x(), -key.src_rect().y())));
660 }
661
593 void SoftwareImageDecodeController::DrawWithImageFinished( 662 void SoftwareImageDecodeController::DrawWithImageFinished(
594 const DrawImage& image, 663 const DrawImage& image,
595 const DecodedDrawImage& decoded_image) { 664 const DecodedDrawImage& decoded_image) {
596 TRACE_EVENT1("disabled-by-default-cc.debug", 665 TRACE_EVENT1("disabled-by-default-cc.debug",
597 "SoftwareImageDecodeController::DrawWithImageFinished", "key", 666 "SoftwareImageDecodeController::DrawWithImageFinished", "key",
598 ImageKey::FromDrawImage(image).ToString()); 667 ImageKey::FromDrawImage(image).ToString());
599 ImageKey key = ImageKey::FromDrawImage(image); 668 ImageKey key = ImageKey::FromDrawImage(image);
600 if (!decoded_image.image() || !CanHandleImage(key)) 669 if (!decoded_image.image())
601 return; 670 return;
602 671
603 if (decoded_image.is_at_raster_decode()) 672 if (decoded_image.is_at_raster_decode())
604 UnrefAtRasterImage(key); 673 UnrefAtRasterImage(key);
605 else 674 else
606 UnrefImage(image); 675 UnrefImage(image);
607 SanityCheckState(__LINE__, false); 676 SanityCheckState(__LINE__, false);
608 } 677 }
609 678
610 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) { 679 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) == 726 DCHECK(decoded_images_ref_counts_.find(key) ==
658 decoded_images_ref_counts_.end()); 727 decoded_images_ref_counts_.end());
659 at_raster_image_it->second->Unlock(); 728 at_raster_image_it->second->Unlock();
660 decoded_images_.Erase(image_it); 729 decoded_images_.Erase(image_it);
661 decoded_images_.Put(key, std::move(at_raster_image_it->second)); 730 decoded_images_.Put(key, std::move(at_raster_image_it->second));
662 } 731 }
663 at_raster_decoded_images_.Erase(at_raster_image_it); 732 at_raster_decoded_images_.Erase(at_raster_image_it);
664 } 733 }
665 } 734 }
666 735
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() { 736 void SoftwareImageDecodeController::ReduceCacheUsage() {
673 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage"); 737 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage");
674 base::AutoLock lock(lock_); 738 base::AutoLock lock(lock_);
675 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache) 739 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache)
676 ? (decoded_images_.size() - kMaxItemsInCache) 740 ? (decoded_images_.size() - kMaxItemsInCache)
677 : 0; 741 : 0;
678 for (auto it = decoded_images_.rbegin(); 742 for (auto it = decoded_images_.rbegin();
679 num_to_remove != 0 && it != decoded_images_.rend();) { 743 num_to_remove != 0 && it != decoded_images_.rend();) {
680 if (it->second->is_locked()) { 744 if (it->second->is_locked()) {
681 ++it; 745 ++it;
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { 948 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() {
885 current_usage_bytes_ = 0; 949 current_usage_bytes_ = 0;
886 } 950 }
887 951
888 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() 952 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe()
889 const { 953 const {
890 return current_usage_bytes_.ValueOrDie(); 954 return current_usage_bytes_.ValueOrDie();
891 } 955 }
892 956
893 } // namespace cc 957 } // 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