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

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: Rebasing. 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
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 <functional> 9 #include <functional>
10 10
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", 165 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key",
166 key.ToString()); 166 key.ToString());
167 167
168 // If the target size is empty, we can skip this image during draw (and thus 168 // If the target size is empty, we can skip this image during draw (and thus
169 // we don't need to decode it or ref it). 169 // we don't need to decode it or ref it).
170 if (key.target_size().IsEmpty()) { 170 if (key.target_size().IsEmpty()) {
171 *task = nullptr; 171 *task = nullptr;
172 return false; 172 return false;
173 } 173 }
174 174
175 // If we're not going to do a scale, we will just create a task to preroll the
176 // image the first time we see it. This doesn't need to account for memory.
177 // TODO(vmpstr): We can also lock the original sized image, in which case it
178 // does require memory bookkeeping.
179 if (!CanHandleImage(key)) {
180 base::AutoLock lock(lock_);
181 if (prerolled_images_.count(key.image_id()) == 0) {
182 scoped_refptr<ImageDecodeTask>& existing_task = pending_image_tasks_[key];
183 if (!existing_task) {
184 existing_task = make_scoped_refptr(
185 new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id));
186 }
187 *task = existing_task;
188 } else {
189 *task = nullptr;
190 }
191 return false;
192 }
193
194 base::AutoLock lock(lock_); 175 base::AutoLock lock(lock_);
195 176
196 // If we already have the image in cache, then we can return it. 177 // If we already have the image in cache, then we can return it.
197 auto decoded_it = decoded_images_.Get(key); 178 auto decoded_it = decoded_images_.Get(key);
198 bool new_image_fits_in_memory = 179 bool new_image_fits_in_memory =
199 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes(); 180 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes();
200 if (decoded_it != decoded_images_.end()) { 181 if (decoded_it != decoded_images_.end()) {
201 if (decoded_it->second->is_locked() || 182 if (decoded_it->second->is_locked() ||
202 (new_image_fits_in_memory && decoded_it->second->Lock())) { 183 (new_image_fits_in_memory && decoded_it->second->Lock())) {
203 RefImage(key); 184 RefImage(key);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 } 236 }
256 237
257 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) { 238 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) {
258 // When we unref the image, there are several situations we need to consider: 239 // When we unref the image, there are several situations we need to consider:
259 // 1. The ref did not reach 0, which means we have to keep the image locked. 240 // 1. The ref did not reach 0, which means we have to keep the image locked.
260 // 2. The ref reached 0, we should unlock it. 241 // 2. The ref reached 0, we should unlock it.
261 // 2a. The image isn't in the locked cache because we didn't get to decode 242 // 2a. The image isn't in the locked cache because we didn't get to decode
262 // it yet (or failed to decode it). 243 // it yet (or failed to decode it).
263 // 2b. Unlock the image but keep it in list. 244 // 2b. Unlock the image but keep it in list.
264 const ImageKey& key = ImageKey::FromDrawImage(image); 245 const ImageKey& key = ImageKey::FromDrawImage(image);
265 DCHECK(CanHandleImage(key)) << key.ToString();
266 TRACE_EVENT1("disabled-by-default-cc.debug", 246 TRACE_EVENT1("disabled-by-default-cc.debug",
267 "SoftwareImageDecodeController::UnrefImage", "key", 247 "SoftwareImageDecodeController::UnrefImage", "key",
268 key.ToString()); 248 key.ToString());
269 249
270 base::AutoLock lock(lock_); 250 base::AutoLock lock(lock_);
271 auto ref_count_it = decoded_images_ref_counts_.find(key); 251 auto ref_count_it = decoded_images_ref_counts_.find(key);
272 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); 252 DCHECK(ref_count_it != decoded_images_ref_counts_.end());
273 253
274 --ref_count_it->second; 254 --ref_count_it->second;
275 if (ref_count_it->second == 0) { 255 if (ref_count_it->second == 0) {
(...skipping 10 matching lines...) Expand all
286 DCHECK(decoded_image_it->second->is_locked()); 266 DCHECK(decoded_image_it->second->is_locked());
287 decoded_image_it->second->Unlock(); 267 decoded_image_it->second->Unlock();
288 } 268 }
289 SanityCheckState(__LINE__, true); 269 SanityCheckState(__LINE__, true);
290 } 270 }
291 271
292 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key, 272 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key,
293 const DrawImage& image) { 273 const DrawImage& image) {
294 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key", 274 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key",
295 key.ToString()); 275 key.ToString());
296 if (!CanHandleImage(key)) {
297 image.image()->preroll();
298
299 base::AutoLock lock(lock_);
300 prerolled_images_.insert(key.image_id());
301 // Erase the pending task from the queue, since the task won't be doing
302 // anything useful after this function terminates. Since we don't preroll
303 // images twice, this is actually not necessary but it behaves similar to
304 // the other code path: when this function finishes, the task isn't in the
305 // pending_image_tasks_ list.
306 pending_image_tasks_.erase(key);
307 return;
308 }
309
310 base::AutoLock lock(lock_); 276 base::AutoLock lock(lock_);
311 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key); 277 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key);
312 278
313 // We could have finished all of the raster tasks (cancelled) while the task 279 // We could have finished all of the raster tasks (cancelled) while the task
314 // was just starting to run. Since this task already started running, it 280 // was just starting to run. Since this task already started running, it
315 // wasn't cancelled. So, if the ref count for the image is 0 then we can just 281 // wasn't cancelled. So, if the ref count for the image is 0 then we can just
316 // abort. 282 // abort.
317 if (decoded_images_ref_counts_.find(key) == 283 if (decoded_images_ref_counts_.find(key) ==
318 decoded_images_ref_counts_.end()) { 284 decoded_images_ref_counts_.end()) {
319 return; 285 return;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 key.ToString()); 337 key.ToString());
372 const SkImage* image = draw_image.image(); 338 const SkImage* image = draw_image.image();
373 if (!image) 339 if (!image)
374 return nullptr; 340 return nullptr;
375 341
376 switch (key.filter_quality()) { 342 switch (key.filter_quality()) {
377 case kNone_SkFilterQuality: 343 case kNone_SkFilterQuality:
378 case kLow_SkFilterQuality: 344 case kLow_SkFilterQuality:
379 return GetOriginalImageDecode(key, *image); 345 return GetOriginalImageDecode(key, *image);
380 case kMedium_SkFilterQuality: 346 case kMedium_SkFilterQuality:
381 NOTIMPLEMENTED();
382 return nullptr;
383 case kHigh_SkFilterQuality: 347 case kHigh_SkFilterQuality:
384 return GetScaledImageDecode(key, *image); 348 return GetScaledImageDecode(key, *image);
385 default: 349 default:
386 NOTREACHED(); 350 NOTREACHED();
387 return nullptr; 351 return nullptr;
388 } 352 }
389 } 353 }
390 354
391 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( 355 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw(
392 const DrawImage& draw_image) { 356 const DrawImage& draw_image) {
393 ImageKey key = ImageKey::FromDrawImage(draw_image); 357 ImageKey key = ImageKey::FromDrawImage(draw_image);
394 TRACE_EVENT1("disabled-by-default-cc.debug", 358 TRACE_EVENT1("disabled-by-default-cc.debug",
395 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", 359 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key",
396 key.ToString()); 360 key.ToString());
397 // If the target size is empty, we can skip this image draw. 361 // If the target size is empty, we can skip this image draw.
398 if (key.target_size().IsEmpty()) 362 if (key.target_size().IsEmpty())
399 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); 363 return DecodedDrawImage(nullptr, kNone_SkFilterQuality);
400 364
401 if (!CanHandleImage(key))
402 return DecodedDrawImage(draw_image.image(), draw_image.filter_quality());
403
404 return GetDecodedImageForDrawInternal(key, draw_image); 365 return GetDecodedImageForDrawInternal(key, draw_image);
405 } 366 }
406 367
407 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( 368 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal(
408 const ImageKey& key, 369 const ImageKey& key,
409 const DrawImage& draw_image) { 370 const DrawImage& draw_image) {
410 TRACE_EVENT1("disabled-by-default-cc.debug", 371 TRACE_EVENT1("disabled-by-default-cc.debug",
411 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", 372 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal",
412 "key", key.ToString()); 373 "key", key.ToString());
413 base::AutoLock lock(lock_); 374 base::AutoLock lock(lock_);
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 { 530 {
570 TRACE_EVENT0( 531 TRACE_EVENT0(
571 "disabled-by-default-cc.debug", 532 "disabled-by-default-cc.debug",
572 "SoftwareImageDecodeController::ScaleImage - allocate scaled pixels"); 533 "SoftwareImageDecodeController::ScaleImage - allocate scaled pixels");
573 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() 534 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance()
574 ->AllocateLockedDiscardableMemory( 535 ->AllocateLockedDiscardableMemory(
575 scaled_info.minRowBytes() * scaled_info.height()); 536 scaled_info.minRowBytes() * scaled_info.height());
576 } 537 }
577 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), 538 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(),
578 scaled_info.minRowBytes()); 539 scaled_info.minRowBytes());
579 // TODO(vmpstr): Start handling more than just high filter quality.
580 DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality());
581 { 540 {
582 TRACE_EVENT0("disabled-by-default-cc.debug", 541 TRACE_EVENT0("disabled-by-default-cc.debug",
583 "SoftwareImageDecodeController::ScaleImage - scale pixels"); 542 "SoftwareImageDecodeController::ScaleImage - scale pixels");
584 bool result = 543 bool result =
585 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); 544 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality());
vmpstr 2016/04/19 23:04:57 So... we don't actually cache the mip level in thi
cblume 2016/04/21 19:28:11 Oh, I made a mistake here. Skia does mipmapping in
vmpstr 2016/04/21 20:11:30 Which 3 param version? I don't think SkPixmap has
cblume 2016/04/22 01:40:14 Oh sorry. I was looking at SkImage::scalePixels, w
586 DCHECK(result) << key.ToString(); 545 DCHECK(result) << key.ToString();
587 } 546 }
588 547
589 // Release the original sized decode. Any other intermediate result to release 548 // Release the original sized decode. Any other intermediate result to release
590 // would be the subrect memory. However, that's in a scoped_ptr and will be 549 // would be the subrect memory. However, that's in a scoped_ptr and will be
591 // deleted automatically when we return. 550 // deleted automatically when we return.
592 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); 551 DrawWithImageFinished(original_size_draw_image, decoded_draw_image);
593 552
594 return base::WrapUnique( 553 return base::WrapUnique(
595 new DecodedImage(scaled_info, std::move(scaled_pixels), 554 new DecodedImage(scaled_info, std::move(scaled_pixels),
596 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), 555 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()),
597 next_tracing_id_.GetNext())); 556 next_tracing_id_.GetNext()));
598 } 557 }
599 558
600 void SoftwareImageDecodeController::DrawWithImageFinished( 559 void SoftwareImageDecodeController::DrawWithImageFinished(
601 const DrawImage& image, 560 const DrawImage& image,
602 const DecodedDrawImage& decoded_image) { 561 const DecodedDrawImage& decoded_image) {
603 TRACE_EVENT1("disabled-by-default-cc.debug", 562 TRACE_EVENT1("disabled-by-default-cc.debug",
604 "SoftwareImageDecodeController::DrawWithImageFinished", "key", 563 "SoftwareImageDecodeController::DrawWithImageFinished", "key",
605 ImageKey::FromDrawImage(image).ToString()); 564 ImageKey::FromDrawImage(image).ToString());
606 ImageKey key = ImageKey::FromDrawImage(image); 565 ImageKey key = ImageKey::FromDrawImage(image);
607 if (!decoded_image.image() || !CanHandleImage(key)) 566 if (!decoded_image.image())
608 return; 567 return;
609 568
610 if (decoded_image.is_at_raster_decode()) 569 if (decoded_image.is_at_raster_decode())
611 UnrefAtRasterImage(key); 570 UnrefAtRasterImage(key);
612 else 571 else
613 UnrefImage(image); 572 UnrefImage(image);
614 SanityCheckState(__LINE__, false); 573 SanityCheckState(__LINE__, false);
615 } 574 }
616 575
617 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) { 576 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 DCHECK(decoded_images_ref_counts_.find(key) == 623 DCHECK(decoded_images_ref_counts_.find(key) ==
665 decoded_images_ref_counts_.end()); 624 decoded_images_ref_counts_.end());
666 at_raster_image_it->second->Unlock(); 625 at_raster_image_it->second->Unlock();
667 decoded_images_.Erase(image_it); 626 decoded_images_.Erase(image_it);
668 decoded_images_.Put(key, std::move(at_raster_image_it->second)); 627 decoded_images_.Put(key, std::move(at_raster_image_it->second));
669 } 628 }
670 at_raster_decoded_images_.Erase(at_raster_image_it); 629 at_raster_decoded_images_.Erase(at_raster_image_it);
671 } 630 }
672 } 631 }
673 632
674 bool SoftwareImageDecodeController::CanHandleImage(const ImageKey& key) {
675 // TODO(vmpstr): Start handling medium filter quality as well.
676 return key.filter_quality() != kMedium_SkFilterQuality;
677 }
678
679 void SoftwareImageDecodeController::ReduceCacheUsage() { 633 void SoftwareImageDecodeController::ReduceCacheUsage() {
680 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage"); 634 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage");
681 base::AutoLock lock(lock_); 635 base::AutoLock lock(lock_);
682 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache) 636 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache)
683 ? (decoded_images_.size() - kMaxItemsInCache) 637 ? (decoded_images_.size() - kMaxItemsInCache)
684 : 0; 638 : 0;
685 for (auto it = decoded_images_.rbegin(); 639 for (auto it = decoded_images_.rbegin();
686 num_to_remove != 0 && it != decoded_images_.rend();) { 640 num_to_remove != 0 && it != decoded_images_.rend();) {
687 if (it->second->is_locked()) { 641 if (it->second->is_locked()) {
688 ++it; 642 ++it;
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
932 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { 886 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() {
933 current_usage_bytes_ = 0; 887 current_usage_bytes_ = 0;
934 } 888 }
935 889
936 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() 890 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe()
937 const { 891 const {
938 return current_usage_bytes_.ValueOrDie(); 892 return current_usage_bytes_.ValueOrDie();
939 } 893 }
940 894
941 } // namespace cc 895 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698