Chromium Code Reviews| 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 "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/format_macros.h" | 12 #include "base/format_macros.h" |
| 12 #include "base/macros.h" | 13 #include "base/macros.h" |
| 13 #include "base/memory/discardable_memory.h" | 14 #include "base/memory/discardable_memory.h" |
| 14 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 15 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 17 #include "base/thread_task_runner_handle.h" | 18 #include "base/thread_task_runner_handle.h" |
| 18 #include "base/trace_event/memory_dump_manager.h" | 19 #include "base/trace_event/memory_dump_manager.h" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 | 90 |
| 90 private: | 91 private: |
| 91 SoftwareImageDecodeController* controller_; | 92 SoftwareImageDecodeController* controller_; |
| 92 SoftwareImageDecodeController::ImageKey image_key_; | 93 SoftwareImageDecodeController::ImageKey image_key_; |
| 93 DrawImage image_; | 94 DrawImage image_; |
| 94 const ImageDecodeController::TracingInfo tracing_info_; | 95 const ImageDecodeController::TracingInfo tracing_info_; |
| 95 | 96 |
| 96 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); | 97 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); |
| 97 }; | 98 }; |
| 98 | 99 |
| 100 // Most images are scaled from the source image's size to the target size. | |
| 101 // But in the case of mipmaps, we are scaling from the mip level which is | |
| 102 // larger than we need. | |
| 103 // This function gets the scale of the mip level which will be used. | |
| 104 SkSize GetMipMapScaleAdjustment(const gfx::Size& src_size, | |
| 105 const gfx::Size& target_size) { | |
| 106 int src_height = src_size.height(); | |
| 107 int src_width = src_size.width(); | |
| 108 int target_height = target_size.height(); | |
| 109 int target_width = target_size.width(); | |
|
vmpstr
2016/05/02 19:58:26
nit: you can early out if target_width or target_h
cblume
2016/05/02 23:04:09
I had tried this but still needed a final return,
| |
| 110 | |
| 111 int next_mip_height = src_height; | |
| 112 int next_mip_width = src_width; | |
| 113 for (int current_mip_level = 0;; current_mip_level++) { | |
| 114 int mip_height = next_mip_height; | |
| 115 int mip_width = next_mip_width; | |
| 116 | |
| 117 next_mip_height = std::max(1, src_height / (1 << (current_mip_level + 1))); | |
| 118 next_mip_width = std::max(1, src_width / (1 << (current_mip_level + 1))); | |
| 119 | |
| 120 // Check if an axis on the next mip level would be smaller than the target. | |
| 121 // If so, use the current mip level. | |
| 122 // This effectively always uses the larger image and always scales down. | |
| 123 if (next_mip_height < target_height || next_mip_width < target_width) { | |
| 124 SkScalar y_scale = static_cast<float>(mip_height) / src_height; | |
| 125 SkScalar x_scale = static_cast<float>(mip_width) / src_width; | |
| 126 | |
| 127 return SkSize::Make(x_scale, y_scale); | |
| 128 } | |
| 129 | |
| 130 if (mip_height == 1 && mip_width == 1) { | |
| 131 // We have reached the final mip level | |
| 132 if (target_height == 1 && target_width == 1) { | |
|
vmpstr
2016/05/02 19:58:26
This is kind of meh... Do you still need this if y
cblume
2016/05/02 23:04:09
This is for the final mip level case (say 1x1), no
| |
| 133 SkScalar y_scale = static_cast<float>(mip_height) / src_height; | |
| 134 SkScalar x_scale = static_cast<float>(mip_width) / src_width; | |
| 135 | |
| 136 return SkSize::Make(x_scale, y_scale); | |
| 137 } | |
| 138 | |
| 139 break; | |
| 140 } | |
| 141 } | |
| 142 | |
| 143 return SkSize::Make(-1.f, -1.f); | |
| 144 } | |
| 145 | |
| 99 SkSize GetScaleAdjustment(const ImageDecodeControllerKey& key) { | 146 SkSize GetScaleAdjustment(const ImageDecodeControllerKey& key) { |
| 100 // If the requested filter quality did not require scale, then the adjustment | 147 // If the requested filter quality did not require scale, then the adjustment |
| 101 // is identity. | 148 // is identity. |
| 102 if (key.can_use_original_decode()) | 149 if (key.can_use_original_decode()) { |
| 103 return SkSize::Make(1.f, 1.f); | 150 return SkSize::Make(1.f, 1.f); |
| 104 | 151 } else if (key.filter_quality() == kMedium_SkFilterQuality) { |
| 105 float x_scale = | 152 return GetMipMapScaleAdjustment(key.src_rect().size(), key.target_size()); |
| 106 key.target_size().width() / static_cast<float>(key.src_rect().width()); | 153 } else { |
| 107 float y_scale = | 154 float x_scale = |
| 108 key.target_size().height() / static_cast<float>(key.src_rect().height()); | 155 key.target_size().width() / static_cast<float>(key.src_rect().width()); |
| 109 return SkSize::Make(x_scale, y_scale); | 156 float y_scale = key.target_size().height() / |
| 157 static_cast<float>(key.src_rect().height()); | |
| 158 return SkSize::Make(x_scale, y_scale); | |
| 159 } | |
| 110 } | 160 } |
| 111 | 161 |
| 112 SkFilterQuality GetDecodedFilterQuality(const ImageDecodeControllerKey& key) { | 162 SkFilterQuality GetDecodedFilterQuality(const ImageDecodeControllerKey& key) { |
| 113 return std::min(key.filter_quality(), kLow_SkFilterQuality); | 163 return std::min(key.filter_quality(), kLow_SkFilterQuality); |
| 114 } | 164 } |
| 115 | 165 |
| 116 SkImageInfo CreateImageInfo(size_t width, | 166 SkImageInfo CreateImageInfo(size_t width, |
| 117 size_t height, | 167 size_t height, |
| 118 ResourceFormat format) { | 168 ResourceFormat format) { |
| 119 return SkImageInfo::Make(width, height, | 169 return SkImageInfo::Make(width, height, |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", | 231 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", |
| 182 key.ToString()); | 232 key.ToString()); |
| 183 | 233 |
| 184 // If the target size is empty, we can skip this image during draw (and thus | 234 // If the target size is empty, we can skip this image during draw (and thus |
| 185 // we don't need to decode it or ref it). | 235 // we don't need to decode it or ref it). |
| 186 if (key.target_size().IsEmpty()) { | 236 if (key.target_size().IsEmpty()) { |
| 187 *task = nullptr; | 237 *task = nullptr; |
| 188 return false; | 238 return false; |
| 189 } | 239 } |
| 190 | 240 |
| 191 // If we're not going to do a scale, we will just create a task to preroll the | |
| 192 // image the first time we see it. This doesn't need to account for memory. | |
| 193 // TODO(vmpstr): We can also lock the original sized image, in which case it | |
| 194 // does require memory bookkeeping. | |
| 195 if (!CanHandleImage(key)) { | |
| 196 base::AutoLock lock(lock_); | |
| 197 if (prerolled_images_.count(key.image_id()) == 0) { | |
| 198 scoped_refptr<TileTask>& existing_task = pending_image_tasks_[key]; | |
| 199 if (!existing_task) { | |
| 200 existing_task = make_scoped_refptr( | |
| 201 new ImageDecodeTaskImpl(this, key, image, tracing_info)); | |
| 202 } | |
| 203 *task = existing_task; | |
| 204 } else { | |
| 205 *task = nullptr; | |
| 206 } | |
| 207 return false; | |
| 208 } | |
| 209 | |
| 210 base::AutoLock lock(lock_); | 241 base::AutoLock lock(lock_); |
| 211 | 242 |
| 212 // If we already have the image in cache, then we can return it. | 243 // If we already have the image in cache, then we can return it. |
| 213 auto decoded_it = decoded_images_.Get(key); | 244 auto decoded_it = decoded_images_.Get(key); |
| 214 bool new_image_fits_in_memory = | 245 bool new_image_fits_in_memory = |
| 215 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes(); | 246 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes(); |
| 216 if (decoded_it != decoded_images_.end()) { | 247 if (decoded_it != decoded_images_.end()) { |
| 217 bool image_was_locked = decoded_it->second->is_locked(); | 248 bool image_was_locked = decoded_it->second->is_locked(); |
| 218 if (image_was_locked || | 249 if (image_was_locked || |
| 219 (new_image_fits_in_memory && decoded_it->second->Lock())) { | 250 (new_image_fits_in_memory && decoded_it->second->Lock())) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 } | 313 } |
| 283 | 314 |
| 284 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) { | 315 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) { |
| 285 // When we unref the image, there are several situations we need to consider: | 316 // When we unref the image, there are several situations we need to consider: |
| 286 // 1. The ref did not reach 0, which means we have to keep the image locked. | 317 // 1. The ref did not reach 0, which means we have to keep the image locked. |
| 287 // 2. The ref reached 0, we should unlock it. | 318 // 2. The ref reached 0, we should unlock it. |
| 288 // 2a. The image isn't in the locked cache because we didn't get to decode | 319 // 2a. The image isn't in the locked cache because we didn't get to decode |
| 289 // it yet (or failed to decode it). | 320 // it yet (or failed to decode it). |
| 290 // 2b. Unlock the image but keep it in list. | 321 // 2b. Unlock the image but keep it in list. |
| 291 const ImageKey& key = ImageKey::FromDrawImage(image); | 322 const ImageKey& key = ImageKey::FromDrawImage(image); |
| 292 DCHECK(CanHandleImage(key)) << key.ToString(); | |
| 293 TRACE_EVENT1("disabled-by-default-cc.debug", | 323 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 294 "SoftwareImageDecodeController::UnrefImage", "key", | 324 "SoftwareImageDecodeController::UnrefImage", "key", |
| 295 key.ToString()); | 325 key.ToString()); |
| 296 | 326 |
| 297 base::AutoLock lock(lock_); | 327 base::AutoLock lock(lock_); |
| 298 auto ref_count_it = decoded_images_ref_counts_.find(key); | 328 auto ref_count_it = decoded_images_ref_counts_.find(key); |
| 299 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); | 329 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); |
| 300 | 330 |
| 301 --ref_count_it->second; | 331 --ref_count_it->second; |
| 302 if (ref_count_it->second == 0) { | 332 if (ref_count_it->second == 0) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 313 DCHECK(decoded_image_it->second->is_locked()); | 343 DCHECK(decoded_image_it->second->is_locked()); |
| 314 decoded_image_it->second->Unlock(); | 344 decoded_image_it->second->Unlock(); |
| 315 } | 345 } |
| 316 SanityCheckState(__LINE__, true); | 346 SanityCheckState(__LINE__, true); |
| 317 } | 347 } |
| 318 | 348 |
| 319 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key, | 349 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key, |
| 320 const DrawImage& image) { | 350 const DrawImage& image) { |
| 321 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key", | 351 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key", |
| 322 key.ToString()); | 352 key.ToString()); |
| 323 if (!CanHandleImage(key)) { | |
| 324 image.image()->preroll(); | |
| 325 | |
| 326 base::AutoLock lock(lock_); | |
| 327 prerolled_images_.insert(key.image_id()); | |
| 328 // Erase the pending task from the queue, since the task won't be doing | |
| 329 // anything useful after this function terminates. Since we don't preroll | |
| 330 // images twice, this is actually not necessary but it behaves similar to | |
| 331 // the other code path: when this function finishes, the task isn't in the | |
| 332 // pending_image_tasks_ list. | |
| 333 pending_image_tasks_.erase(key); | |
| 334 return; | |
| 335 } | |
| 336 | |
| 337 base::AutoLock lock(lock_); | 353 base::AutoLock lock(lock_); |
| 338 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key); | 354 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key); |
| 339 | 355 |
| 340 // We could have finished all of the raster tasks (cancelled) while the task | 356 // We could have finished all of the raster tasks (cancelled) while the task |
| 341 // was just starting to run. Since this task already started running, it | 357 // was just starting to run. Since this task already started running, it |
| 342 // wasn't cancelled. So, if the ref count for the image is 0 then we can just | 358 // wasn't cancelled. So, if the ref count for the image is 0 then we can just |
| 343 // abort. | 359 // abort. |
| 344 if (decoded_images_ref_counts_.find(key) == | 360 if (decoded_images_ref_counts_.find(key) == |
| 345 decoded_images_ref_counts_.end()) { | 361 decoded_images_ref_counts_.end()) { |
| 346 return; | 362 return; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 if (decoded_images_ref_counts_.find(key) == | 399 if (decoded_images_ref_counts_.find(key) == |
| 384 decoded_images_ref_counts_.end()) { | 400 decoded_images_ref_counts_.end()) { |
| 385 decoded_image->Unlock(); | 401 decoded_image->Unlock(); |
| 386 } | 402 } |
| 387 | 403 |
| 388 decoded_images_.Put(key, std::move(decoded_image)); | 404 decoded_images_.Put(key, std::move(decoded_image)); |
| 389 SanityCheckState(__LINE__, true); | 405 SanityCheckState(__LINE__, true); |
| 390 } | 406 } |
| 391 | 407 |
| 392 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> | 408 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> |
| 409 SoftwareImageDecodeController::GetMediumQualityImageDecode( | |
| 410 const ImageKey& key, | |
| 411 sk_sp<const SkImage> image) { | |
| 412 SkSize mipmap_scale = | |
| 413 GetMipMapScaleAdjustment(key.src_rect().size(), key.target_size()); | |
| 414 DCHECK(mipmap_scale.width() > 0.f && mipmap_scale.height() > 0.f); | |
| 415 | |
| 416 if (mipmap_scale.width() == 1.f && mipmap_scale.height() == 1.f) { | |
| 417 return GetOriginalImageDecode(key, std::move(image)); | |
| 418 } else { | |
| 419 DrawImage mip_image( | |
| 420 image, gfx::RectToSkIRect(key.src_rect()), kMedium_SkFilterQuality, | |
| 421 SkMatrix::MakeScale(mipmap_scale.width(), mipmap_scale.height())); | |
| 422 auto mip_key = ImageKey::FromDrawImage(mip_image); | |
|
vmpstr
2016/05/02 19:58:26
I'm a bit confused: wouldn't the passed key alread
cblume
2016/05/02 23:04:09
Good catch. After our change to ::FromDrawImage, t
| |
| 423 return GetScaledImageDecode(mip_key, std::move(image)); | |
| 424 } | |
| 425 } | |
| 426 | |
| 427 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> | |
| 393 SoftwareImageDecodeController::DecodeImageInternal( | 428 SoftwareImageDecodeController::DecodeImageInternal( |
| 394 const ImageKey& key, | 429 const ImageKey& key, |
| 395 const DrawImage& draw_image) { | 430 const DrawImage& draw_image) { |
| 396 TRACE_EVENT1("disabled-by-default-cc.debug", | 431 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 397 "SoftwareImageDecodeController::DecodeImageInternal", "key", | 432 "SoftwareImageDecodeController::DecodeImageInternal", "key", |
| 398 key.ToString()); | 433 key.ToString()); |
| 399 sk_sp<const SkImage> image = draw_image.image(); | 434 sk_sp<const SkImage> image = draw_image.image(); |
| 400 if (!image) | 435 if (!image) |
| 401 return nullptr; | 436 return nullptr; |
| 402 | 437 |
| 403 switch (key.filter_quality()) { | 438 switch (key.filter_quality()) { |
| 404 case kNone_SkFilterQuality: | 439 case kNone_SkFilterQuality: |
| 405 case kLow_SkFilterQuality: | 440 case kLow_SkFilterQuality: |
| 406 return GetOriginalImageDecode(key, std::move(image)); | 441 return GetOriginalImageDecode(key, std::move(image)); |
| 407 case kMedium_SkFilterQuality: | 442 case kMedium_SkFilterQuality: |
| 408 NOTIMPLEMENTED(); | 443 return GetMediumQualityImageDecode(key, std::move(image)); |
| 409 return nullptr; | |
| 410 case kHigh_SkFilterQuality: | 444 case kHigh_SkFilterQuality: |
| 411 return GetScaledImageDecode(key, std::move(image)); | 445 return GetScaledImageDecode(key, std::move(image)); |
| 412 default: | 446 default: |
| 413 NOTREACHED(); | 447 NOTREACHED(); |
| 414 return nullptr; | 448 return nullptr; |
| 415 } | 449 } |
| 416 } | 450 } |
| 417 | 451 |
| 418 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( | 452 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( |
| 419 const DrawImage& draw_image) { | 453 const DrawImage& draw_image) { |
| 420 ImageKey key = ImageKey::FromDrawImage(draw_image); | 454 ImageKey key = ImageKey::FromDrawImage(draw_image); |
| 421 TRACE_EVENT1("disabled-by-default-cc.debug", | 455 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 422 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", | 456 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", |
| 423 key.ToString()); | 457 key.ToString()); |
| 424 // If the target size is empty, we can skip this image draw. | 458 // If the target size is empty, we can skip this image draw. |
| 425 if (key.target_size().IsEmpty()) | 459 if (key.target_size().IsEmpty()) |
| 426 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); | 460 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); |
| 427 | 461 |
| 428 if (!CanHandleImage(key)) | |
| 429 return DecodedDrawImage(draw_image.image(), draw_image.filter_quality()); | |
| 430 | |
| 431 return GetDecodedImageForDrawInternal(key, draw_image); | 462 return GetDecodedImageForDrawInternal(key, draw_image); |
| 432 } | 463 } |
| 433 | 464 |
| 434 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( | 465 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( |
| 435 const ImageKey& key, | 466 const ImageKey& key, |
| 436 const DrawImage& draw_image) { | 467 const DrawImage& draw_image) { |
| 437 TRACE_EVENT1("disabled-by-default-cc.debug", | 468 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 438 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", | 469 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", |
| 439 "key", key.ToString()); | 470 "key", key.ToString()); |
| 440 base::AutoLock lock(lock_); | 471 base::AutoLock lock(lock_); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 598 { | 629 { |
| 599 TRACE_EVENT0( | 630 TRACE_EVENT0( |
| 600 "disabled-by-default-cc.debug", | 631 "disabled-by-default-cc.debug", |
| 601 "SoftwareImageDecodeController::ScaleImage - allocate scaled pixels"); | 632 "SoftwareImageDecodeController::ScaleImage - allocate scaled pixels"); |
| 602 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() | 633 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() |
| 603 ->AllocateLockedDiscardableMemory( | 634 ->AllocateLockedDiscardableMemory( |
| 604 scaled_info.minRowBytes() * scaled_info.height()); | 635 scaled_info.minRowBytes() * scaled_info.height()); |
| 605 } | 636 } |
| 606 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), | 637 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), |
| 607 scaled_info.minRowBytes()); | 638 scaled_info.minRowBytes()); |
| 608 // TODO(vmpstr): Start handling more than just high filter quality. | 639 DCHECK(key.filter_quality() == kHigh_SkFilterQuality || |
| 609 DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality()); | 640 key.filter_quality() == kMedium_SkFilterQuality); |
| 610 { | 641 { |
| 611 TRACE_EVENT0("disabled-by-default-cc.debug", | 642 TRACE_EVENT0("disabled-by-default-cc.debug", |
| 612 "SoftwareImageDecodeController::ScaleImage - scale pixels"); | 643 "SoftwareImageDecodeController::ScaleImage - scale pixels"); |
| 613 bool result = | 644 bool result = |
| 614 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); | 645 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); |
| 615 DCHECK(result) << key.ToString(); | 646 DCHECK(result) << key.ToString(); |
| 616 } | 647 } |
| 617 | 648 |
| 618 // Release the original sized decode. Any other intermediate result to release | 649 // Release the original sized decode. Any other intermediate result to release |
| 619 // would be the subrect memory. However, that's in a scoped_ptr and will be | 650 // would be the subrect memory. However, that's in a scoped_ptr and will be |
| 620 // deleted automatically when we return. | 651 // deleted automatically when we return. |
| 621 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); | 652 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); |
| 622 | 653 |
| 623 return base::WrapUnique( | 654 return base::WrapUnique( |
| 624 new DecodedImage(scaled_info, std::move(scaled_pixels), | 655 new DecodedImage(scaled_info, std::move(scaled_pixels), |
| 625 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), | 656 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), |
| 626 next_tracing_id_.GetNext())); | 657 next_tracing_id_.GetNext())); |
| 627 } | 658 } |
| 628 | 659 |
| 629 void SoftwareImageDecodeController::DrawWithImageFinished( | 660 void SoftwareImageDecodeController::DrawWithImageFinished( |
| 630 const DrawImage& image, | 661 const DrawImage& image, |
| 631 const DecodedDrawImage& decoded_image) { | 662 const DecodedDrawImage& decoded_image) { |
| 632 TRACE_EVENT1("disabled-by-default-cc.debug", | 663 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 633 "SoftwareImageDecodeController::DrawWithImageFinished", "key", | 664 "SoftwareImageDecodeController::DrawWithImageFinished", "key", |
| 634 ImageKey::FromDrawImage(image).ToString()); | 665 ImageKey::FromDrawImage(image).ToString()); |
| 635 ImageKey key = ImageKey::FromDrawImage(image); | 666 ImageKey key = ImageKey::FromDrawImage(image); |
| 636 if (!decoded_image.image() || !CanHandleImage(key)) | 667 if (!decoded_image.image()) |
| 637 return; | 668 return; |
| 638 | 669 |
| 639 if (decoded_image.is_at_raster_decode()) | 670 if (decoded_image.is_at_raster_decode()) |
| 640 UnrefAtRasterImage(key); | 671 UnrefAtRasterImage(key); |
| 641 else | 672 else |
| 642 UnrefImage(image); | 673 UnrefImage(image); |
| 643 SanityCheckState(__LINE__, false); | 674 SanityCheckState(__LINE__, false); |
| 644 } | 675 } |
| 645 | 676 |
| 646 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) { | 677 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 693 DCHECK(decoded_images_ref_counts_.find(key) == | 724 DCHECK(decoded_images_ref_counts_.find(key) == |
| 694 decoded_images_ref_counts_.end()); | 725 decoded_images_ref_counts_.end()); |
| 695 at_raster_image_it->second->Unlock(); | 726 at_raster_image_it->second->Unlock(); |
| 696 decoded_images_.Erase(image_it); | 727 decoded_images_.Erase(image_it); |
| 697 decoded_images_.Put(key, std::move(at_raster_image_it->second)); | 728 decoded_images_.Put(key, std::move(at_raster_image_it->second)); |
| 698 } | 729 } |
| 699 at_raster_decoded_images_.Erase(at_raster_image_it); | 730 at_raster_decoded_images_.Erase(at_raster_image_it); |
| 700 } | 731 } |
| 701 } | 732 } |
| 702 | 733 |
| 703 bool SoftwareImageDecodeController::CanHandleImage(const ImageKey& key) { | |
| 704 // TODO(vmpstr): Start handling medium filter quality as well. | |
| 705 return key.filter_quality() != kMedium_SkFilterQuality; | |
| 706 } | |
| 707 | |
| 708 void SoftwareImageDecodeController::ReduceCacheUsage() { | 734 void SoftwareImageDecodeController::ReduceCacheUsage() { |
| 709 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage"); | 735 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage"); |
| 710 base::AutoLock lock(lock_); | 736 base::AutoLock lock(lock_); |
| 711 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache) | 737 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache) |
| 712 ? (decoded_images_.size() - kMaxItemsInCache) | 738 ? (decoded_images_.size() - kMaxItemsInCache) |
| 713 : 0; | 739 : 0; |
| 714 for (auto it = decoded_images_.rbegin(); | 740 for (auto it = decoded_images_.rbegin(); |
| 715 num_to_remove != 0 && it != decoded_images_.rend();) { | 741 num_to_remove != 0 && it != decoded_images_.rend();) { |
| 716 if (it->second->is_locked()) { | 742 if (it->second->is_locked()) { |
| 717 ++it; | 743 ++it; |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 846 } | 872 } |
| 847 } | 873 } |
| 848 | 874 |
| 849 bool can_use_original_decode = | 875 bool can_use_original_decode = |
| 850 quality == kLow_SkFilterQuality || quality == kNone_SkFilterQuality; | 876 quality == kLow_SkFilterQuality || quality == kNone_SkFilterQuality; |
| 851 | 877 |
| 852 // If we're going to use the original decode, then the target size should be | 878 // If we're going to use the original decode, then the target size should be |
| 853 // the full image size, since that will allow for proper memory accounting. | 879 // the full image size, since that will allow for proper memory accounting. |
| 854 // Note we skip the decode if the target size is empty altogether, so don't | 880 // Note we skip the decode if the target size is empty altogether, so don't |
| 855 // update the target size in that case. | 881 // update the target size in that case. |
| 856 if (can_use_original_decode && !target_size.IsEmpty()) | 882 if (can_use_original_decode && !target_size.IsEmpty()) |
|
vmpstr
2016/05/02 19:58:26
Should the below condition also check if target_si
cblume
2016/05/02 23:04:09
Done.
| |
| 857 target_size = gfx::Size(image.image()->width(), image.image()->height()); | 883 target_size = gfx::Size(image.image()->width(), image.image()->height()); |
| 858 | 884 |
| 885 if (quality == kMedium_SkFilterQuality) { | |
| 886 SkSize mip_target_size = | |
| 887 GetMipMapScaleAdjustment(src_rect.size(), target_size); | |
| 888 target_size.set_width(src_rect.width() * mip_target_size.width()); | |
| 889 target_size.set_height(src_rect.height() * mip_target_size.height()); | |
| 890 } | |
| 891 | |
| 859 return ImageDecodeControllerKey(image.image()->uniqueID(), src_rect, | 892 return ImageDecodeControllerKey(image.image()->uniqueID(), src_rect, |
| 860 target_size, quality, | 893 target_size, quality, |
| 861 can_use_original_decode); | 894 can_use_original_decode); |
| 862 } | 895 } |
| 863 | 896 |
| 864 ImageDecodeControllerKey::ImageDecodeControllerKey( | 897 ImageDecodeControllerKey::ImageDecodeControllerKey( |
| 865 uint32_t image_id, | 898 uint32_t image_id, |
| 866 const gfx::Rect& src_rect, | 899 const gfx::Rect& src_rect, |
| 867 const gfx::Size& target_size, | 900 const gfx::Size& target_size, |
| 868 SkFilterQuality filter_quality, | 901 SkFilterQuality filter_quality, |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 961 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { | 994 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { |
| 962 current_usage_bytes_ = 0; | 995 current_usage_bytes_ = 0; |
| 963 } | 996 } |
| 964 | 997 |
| 965 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() | 998 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() |
| 966 const { | 999 const { |
| 967 return current_usage_bytes_.ValueOrDie(); | 1000 return current_usage_bytes_.ValueOrDie(); |
| 968 } | 1001 } |
| 969 | 1002 |
| 970 } // namespace cc | 1003 } // namespace cc |
| OLD | NEW |