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/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 16 #include "base/thread_task_runner_handle.h" | 17 #include "base/thread_task_runner_handle.h" |
| 17 #include "base/trace_event/memory_dump_manager.h" | 18 #include "base/trace_event/memory_dump_manager.h" |
| 18 #include "cc/debug/devtools_instrumentation.h" | 19 #include "cc/debug/devtools_instrumentation.h" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 private: | 90 private: |
| 90 SoftwareImageDecodeController* controller_; | 91 SoftwareImageDecodeController* controller_; |
| 91 SoftwareImageDecodeController::ImageKey image_key_; | 92 SoftwareImageDecodeController::ImageKey image_key_; |
| 92 DrawImage image_; | 93 DrawImage image_; |
| 93 skia::RefPtr<const SkImage> image_ref_; | 94 skia::RefPtr<const SkImage> image_ref_; |
| 94 uint64_t source_prepare_tiles_id_; | 95 uint64_t source_prepare_tiles_id_; |
| 95 | 96 |
| 96 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); | 97 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); |
| 97 }; | 98 }; |
| 98 | 99 |
| 100 SkMatrix GetMipMapScale(const SoftwareImageDecodeController::ImageKey& key) { | |
|
vmpstr
2016/04/21 20:11:30
Can you add a comment here to describe what the fu
cblume
2016/04/22 01:40:14
Done.
| |
| 101 gfx::Rect src_rect = key.src_rect(); | |
| 102 int src_height = src_rect.height(); | |
| 103 int src_width = src_rect.width(); | |
| 104 | |
| 105 int next_mip_height = src_height; | |
| 106 int next_mip_width = src_width; | |
| 107 for (int current_mip_level = 0;; current_mip_level++) { | |
| 108 int mip_height = next_mip_height; | |
| 109 int mip_width = next_mip_width; | |
| 110 | |
| 111 next_mip_height = std::max(1, src_height / (1 << (current_mip_level + 1))); | |
| 112 next_mip_width = std::max(1, src_width / (1 << (current_mip_level + 1))); | |
| 113 | |
| 114 // Check if an axis on the next mip level would be smaller than the target. | |
| 115 // If so, use the current mip level. | |
| 116 // This effectively always uses the larger image and always scales down. | |
| 117 if (next_mip_height < key.target_size().height() || | |
| 118 next_mip_width < key.target_size().width()) { | |
| 119 SkScalar y_scale = 1.f; | |
| 120 SkScalar x_scale = 1.f; | |
| 121 if (current_mip_level != 0) { | |
| 122 y_scale = static_cast<float>(mip_height) / src_height; | |
| 123 x_scale = static_cast<float>(mip_width) / src_width; | |
| 124 } | |
| 125 | |
| 126 return SkMatrix::MakeScale(x_scale, y_scale); | |
| 127 } | |
| 128 | |
| 129 if (mip_height == 1 && mip_width == 1) { | |
| 130 // We have reached the final mip level | |
| 131 break; | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 return SkMatrix::MakeScale(0, 0); | |
| 136 } | |
| 137 | |
| 99 SkSize GetScaleAdjustment(const ImageDecodeControllerKey& key) { | 138 SkSize GetScaleAdjustment(const ImageDecodeControllerKey& key) { |
| 100 // If the requested filter quality did not require scale, then the adjustment | 139 // If the requested filter quality did not require scale, then the adjustment |
| 101 // is identity. | 140 // is identity. |
| 102 if (key.can_use_original_decode()) | 141 float x_scale = 1.f; |
|
vmpstr
2016/04/21 20:11:30
I'd kind of prefer if we keep this type of logic:
cblume
2016/04/22 01:40:14
Done.
| |
| 103 return SkSize::Make(1.f, 1.f); | 142 float y_scale = 1.f; |
| 104 | 143 |
| 105 float x_scale = | 144 if (!key.can_use_original_decode()) { |
| 106 key.target_size().width() / static_cast<float>(key.src_rect().width()); | 145 if (key.filter_quality() == kMedium_SkFilterQuality) { |
| 107 float y_scale = | 146 SkMatrix mipmap_scale = GetMipMapScale(key); |
| 108 key.target_size().height() / static_cast<float>(key.src_rect().height()); | 147 x_scale = mipmap_scale.getScaleX(); |
| 148 y_scale = mipmap_scale.getScaleY(); | |
| 149 } else { | |
| 150 x_scale = key.target_size().width() / | |
| 151 static_cast<float>(key.src_rect().width()); | |
| 152 y_scale = key.target_size().height() / | |
| 153 static_cast<float>(key.src_rect().height()); | |
| 154 } | |
| 155 } | |
| 109 return SkSize::Make(x_scale, y_scale); | 156 return SkSize::Make(x_scale, y_scale); |
| 110 } | 157 } |
| 111 | 158 |
| 112 SkFilterQuality GetDecodedFilterQuality(const ImageDecodeControllerKey& key) { | 159 SkFilterQuality GetDecodedFilterQuality(const ImageDecodeControllerKey& key) { |
| 113 return std::min(key.filter_quality(), kLow_SkFilterQuality); | 160 return std::min(key.filter_quality(), kLow_SkFilterQuality); |
| 114 } | 161 } |
| 115 | 162 |
| 116 SkImageInfo CreateImageInfo(size_t width, | 163 SkImageInfo CreateImageInfo(size_t width, |
| 117 size_t height, | 164 size_t height, |
| 118 ResourceFormat format) { | 165 ResourceFormat format) { |
| 119 return SkImageInfo::Make(width, height, | 166 return SkImageInfo::Make(width, height, |
| 120 ResourceFormatToClosestSkColorType(format), | 167 ResourceFormatToClosestSkColorType(format), |
| 121 kPremul_SkAlphaType); | 168 kPremul_SkAlphaType); |
| 122 } | 169 } |
| 123 | 170 |
| 124 } // namespace | 171 } // namespace |
| 125 | |
|
vmpstr
2016/04/21 20:11:31
keep whitespace
cblume
2016/04/22 01:40:14
Done.
| |
| 126 SoftwareImageDecodeController::SoftwareImageDecodeController( | 172 SoftwareImageDecodeController::SoftwareImageDecodeController( |
| 127 ResourceFormat format) | 173 ResourceFormat format) |
| 128 : decoded_images_(ImageMRUCache::NO_AUTO_EVICT), | 174 : decoded_images_(ImageMRUCache::NO_AUTO_EVICT), |
| 129 at_raster_decoded_images_(ImageMRUCache::NO_AUTO_EVICT), | 175 at_raster_decoded_images_(ImageMRUCache::NO_AUTO_EVICT), |
| 130 locked_images_budget_(kLockedMemoryLimitBytes), | 176 locked_images_budget_(kLockedMemoryLimitBytes), |
| 131 format_(format) { | 177 format_(format) { |
| 132 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). | 178 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). |
| 133 // Don't register a dump provider in these cases. | 179 // Don't register a dump provider in these cases. |
| 134 if (base::ThreadTaskRunnerHandle::IsSet()) { | 180 if (base::ThreadTaskRunnerHandle::IsSet()) { |
| 135 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | 181 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 166 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", | 212 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", |
| 167 key.ToString()); | 213 key.ToString()); |
| 168 | 214 |
| 169 // If the target size is empty, we can skip this image during draw (and thus | 215 // If the target size is empty, we can skip this image during draw (and thus |
| 170 // we don't need to decode it or ref it). | 216 // we don't need to decode it or ref it). |
| 171 if (key.target_size().IsEmpty()) { | 217 if (key.target_size().IsEmpty()) { |
| 172 *task = nullptr; | 218 *task = nullptr; |
| 173 return false; | 219 return false; |
| 174 } | 220 } |
| 175 | 221 |
| 176 // If we're not going to do a scale, we will just create a task to preroll the | |
| 177 // image the first time we see it. This doesn't need to account for memory. | |
| 178 // TODO(vmpstr): We can also lock the original sized image, in which case it | |
| 179 // does require memory bookkeeping. | |
| 180 if (!CanHandleImage(key)) { | |
| 181 base::AutoLock lock(lock_); | |
| 182 if (prerolled_images_.count(key.image_id()) == 0) { | |
| 183 scoped_refptr<TileTask>& existing_task = pending_image_tasks_[key]; | |
| 184 if (!existing_task) { | |
| 185 existing_task = make_scoped_refptr( | |
| 186 new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id)); | |
| 187 } | |
| 188 *task = existing_task; | |
| 189 } else { | |
| 190 *task = nullptr; | |
| 191 } | |
| 192 return false; | |
| 193 } | |
| 194 | |
| 195 base::AutoLock lock(lock_); | 222 base::AutoLock lock(lock_); |
| 196 | 223 |
| 197 // If we already have the image in cache, then we can return it. | 224 // If we already have the image in cache, then we can return it. |
| 198 auto decoded_it = decoded_images_.Get(key); | 225 auto decoded_it = decoded_images_.Get(key); |
| 199 bool new_image_fits_in_memory = | 226 bool new_image_fits_in_memory = |
| 200 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes(); | 227 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes(); |
| 201 if (decoded_it != decoded_images_.end()) { | 228 if (decoded_it != decoded_images_.end()) { |
| 202 if (decoded_it->second->is_locked() || | 229 if (decoded_it->second->is_locked() || |
| 203 (new_image_fits_in_memory && decoded_it->second->Lock())) { | 230 (new_image_fits_in_memory && decoded_it->second->Lock())) { |
| 204 RefImage(key); | 231 RefImage(key); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 } | 283 } |
| 257 | 284 |
| 258 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) { | 285 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) { |
| 259 // When we unref the image, there are several situations we need to consider: | 286 // When we unref the image, there are several situations we need to consider: |
| 260 // 1. The ref did not reach 0, which means we have to keep the image locked. | 287 // 1. The ref did not reach 0, which means we have to keep the image locked. |
| 261 // 2. The ref reached 0, we should unlock it. | 288 // 2. The ref reached 0, we should unlock it. |
| 262 // 2a. The image isn't in the locked cache because we didn't get to decode | 289 // 2a. The image isn't in the locked cache because we didn't get to decode |
| 263 // it yet (or failed to decode it). | 290 // it yet (or failed to decode it). |
| 264 // 2b. Unlock the image but keep it in list. | 291 // 2b. Unlock the image but keep it in list. |
| 265 const ImageKey& key = ImageKey::FromDrawImage(image); | 292 const ImageKey& key = ImageKey::FromDrawImage(image); |
| 266 DCHECK(CanHandleImage(key)) << key.ToString(); | |
| 267 TRACE_EVENT1("disabled-by-default-cc.debug", | 293 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 268 "SoftwareImageDecodeController::UnrefImage", "key", | 294 "SoftwareImageDecodeController::UnrefImage", "key", |
| 269 key.ToString()); | 295 key.ToString()); |
| 270 | 296 |
| 271 base::AutoLock lock(lock_); | 297 base::AutoLock lock(lock_); |
| 272 auto ref_count_it = decoded_images_ref_counts_.find(key); | 298 auto ref_count_it = decoded_images_ref_counts_.find(key); |
| 273 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); | 299 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); |
| 274 | 300 |
| 275 --ref_count_it->second; | 301 --ref_count_it->second; |
| 276 if (ref_count_it->second == 0) { | 302 if (ref_count_it->second == 0) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 287 DCHECK(decoded_image_it->second->is_locked()); | 313 DCHECK(decoded_image_it->second->is_locked()); |
| 288 decoded_image_it->second->Unlock(); | 314 decoded_image_it->second->Unlock(); |
| 289 } | 315 } |
| 290 SanityCheckState(__LINE__, true); | 316 SanityCheckState(__LINE__, true); |
| 291 } | 317 } |
| 292 | 318 |
| 293 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key, | 319 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key, |
| 294 const DrawImage& image) { | 320 const DrawImage& image) { |
| 295 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key", | 321 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key", |
| 296 key.ToString()); | 322 key.ToString()); |
| 297 if (!CanHandleImage(key)) { | |
| 298 image.image()->preroll(); | |
| 299 | |
| 300 base::AutoLock lock(lock_); | |
| 301 prerolled_images_.insert(key.image_id()); | |
| 302 // Erase the pending task from the queue, since the task won't be doing | |
| 303 // anything useful after this function terminates. Since we don't preroll | |
| 304 // images twice, this is actually not necessary but it behaves similar to | |
| 305 // the other code path: when this function finishes, the task isn't in the | |
| 306 // pending_image_tasks_ list. | |
| 307 pending_image_tasks_.erase(key); | |
| 308 return; | |
| 309 } | |
| 310 | |
| 311 base::AutoLock lock(lock_); | 323 base::AutoLock lock(lock_); |
| 312 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key); | 324 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key); |
| 313 | 325 |
| 314 // We could have finished all of the raster tasks (cancelled) while the task | 326 // We could have finished all of the raster tasks (cancelled) while the task |
| 315 // was just starting to run. Since this task already started running, it | 327 // was just starting to run. Since this task already started running, it |
| 316 // wasn't cancelled. So, if the ref count for the image is 0 then we can just | 328 // wasn't cancelled. So, if the ref count for the image is 0 then we can just |
| 317 // abort. | 329 // abort. |
| 318 if (decoded_images_ref_counts_.find(key) == | 330 if (decoded_images_ref_counts_.find(key) == |
| 319 decoded_images_ref_counts_.end()) { | 331 decoded_images_ref_counts_.end()) { |
| 320 return; | 332 return; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 if (decoded_images_ref_counts_.find(key) == | 369 if (decoded_images_ref_counts_.find(key) == |
| 358 decoded_images_ref_counts_.end()) { | 370 decoded_images_ref_counts_.end()) { |
| 359 decoded_image->Unlock(); | 371 decoded_image->Unlock(); |
| 360 } | 372 } |
| 361 | 373 |
| 362 decoded_images_.Put(key, std::move(decoded_image)); | 374 decoded_images_.Put(key, std::move(decoded_image)); |
| 363 SanityCheckState(__LINE__, true); | 375 SanityCheckState(__LINE__, true); |
| 364 } | 376 } |
| 365 | 377 |
| 366 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> | 378 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> |
| 379 SoftwareImageDecodeController::DecodeImageMediumQuality(const ImageKey& key, | |
| 380 const SkImage& image) { | |
| 381 SkMatrix mipmap_scale = GetMipMapScale(key); | |
| 382 if (mipmap_scale.getScaleX() == 0 || mipmap_scale.getScaleY() == 0) { | |
|
vmpstr
2016/04/21 20:11:30
This should be doing an epsilon comparison since i
cblume
2016/04/22 01:40:14
This started a good conversation in my cube.
Our c
| |
| 383 return nullptr; | |
| 384 } | |
| 385 | |
| 386 gfx::Rect src_rect = key.src_rect(); | |
| 387 DrawImage mip_image(&image, gfx::RectToSkIRect(src_rect), | |
|
vmpstr
2016/04/21 20:11:31
nit: key.src_rect() directly here
cblume
2016/04/22 01:40:14
Done.
| |
| 388 kMedium_SkFilterQuality, mipmap_scale); | |
| 389 auto mip_key = ImageKey::FromDrawImage(mip_image); | |
|
vmpstr
2016/04/21 20:11:30
Interesting, so you create a new DrawImage that is
cblume
2016/04/22 01:40:14
I asked the Skia team about if it runs a bilerp if
| |
| 390 return GetScaledImageDecode(mip_key, image); | |
| 391 } | |
| 392 | |
| 393 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> | |
| 367 SoftwareImageDecodeController::DecodeImageInternal( | 394 SoftwareImageDecodeController::DecodeImageInternal( |
| 368 const ImageKey& key, | 395 const ImageKey& key, |
| 369 const DrawImage& draw_image) { | 396 const DrawImage& draw_image) { |
| 370 TRACE_EVENT1("disabled-by-default-cc.debug", | 397 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 371 "SoftwareImageDecodeController::DecodeImageInternal", "key", | 398 "SoftwareImageDecodeController::DecodeImageInternal", "key", |
| 372 key.ToString()); | 399 key.ToString()); |
| 373 const SkImage* image = draw_image.image(); | 400 const SkImage* image = draw_image.image(); |
| 374 if (!image) | 401 if (!image) |
| 375 return nullptr; | 402 return nullptr; |
| 376 | 403 |
| 377 switch (key.filter_quality()) { | 404 switch (key.filter_quality()) { |
| 378 case kNone_SkFilterQuality: | 405 case kNone_SkFilterQuality: |
| 379 case kLow_SkFilterQuality: | 406 case kLow_SkFilterQuality: |
| 380 return GetOriginalImageDecode(key, *image); | 407 return GetOriginalImageDecode(key, *image); |
| 381 case kMedium_SkFilterQuality: | 408 case kMedium_SkFilterQuality: |
| 382 NOTIMPLEMENTED(); | 409 return DecodeImageMediumQuality(key, *image); |
|
vmpstr
2016/04/21 20:11:30
To be consistent, can you have this GetMediumQuali
cblume
2016/04/22 01:40:14
Done.
| |
| 383 return nullptr; | |
| 384 case kHigh_SkFilterQuality: | 410 case kHigh_SkFilterQuality: |
| 385 return GetScaledImageDecode(key, *image); | 411 return GetScaledImageDecode(key, *image); |
| 386 default: | 412 default: |
| 387 NOTREACHED(); | 413 NOTREACHED(); |
| 388 return nullptr; | 414 return nullptr; |
| 389 } | 415 } |
| 390 } | 416 } |
| 391 | 417 |
| 392 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( | 418 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( |
| 393 const DrawImage& draw_image) { | 419 const DrawImage& draw_image) { |
| 394 ImageKey key = ImageKey::FromDrawImage(draw_image); | 420 ImageKey key = ImageKey::FromDrawImage(draw_image); |
| 395 TRACE_EVENT1("disabled-by-default-cc.debug", | 421 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 396 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", | 422 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", |
| 397 key.ToString()); | 423 key.ToString()); |
| 398 // If the target size is empty, we can skip this image draw. | 424 // If the target size is empty, we can skip this image draw. |
| 399 if (key.target_size().IsEmpty()) | 425 if (key.target_size().IsEmpty()) |
| 400 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); | 426 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); |
| 401 | 427 |
| 402 if (!CanHandleImage(key)) | |
| 403 return DecodedDrawImage(draw_image.image(), draw_image.filter_quality()); | |
| 404 | |
| 405 return GetDecodedImageForDrawInternal(key, draw_image); | 428 return GetDecodedImageForDrawInternal(key, draw_image); |
| 406 } | 429 } |
| 407 | 430 |
| 408 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( | 431 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( |
| 409 const ImageKey& key, | 432 const ImageKey& key, |
| 410 const DrawImage& draw_image) { | 433 const DrawImage& draw_image) { |
| 411 TRACE_EVENT1("disabled-by-default-cc.debug", | 434 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 412 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", | 435 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", |
| 413 "key", key.ToString()); | 436 "key", key.ToString()); |
| 414 base::AutoLock lock(lock_); | 437 base::AutoLock lock(lock_); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 { | 593 { |
| 571 TRACE_EVENT0( | 594 TRACE_EVENT0( |
| 572 "disabled-by-default-cc.debug", | 595 "disabled-by-default-cc.debug", |
| 573 "SoftwareImageDecodeController::ScaleImage - allocate scaled pixels"); | 596 "SoftwareImageDecodeController::ScaleImage - allocate scaled pixels"); |
| 574 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() | 597 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() |
| 575 ->AllocateLockedDiscardableMemory( | 598 ->AllocateLockedDiscardableMemory( |
| 576 scaled_info.minRowBytes() * scaled_info.height()); | 599 scaled_info.minRowBytes() * scaled_info.height()); |
| 577 } | 600 } |
| 578 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), | 601 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), |
| 579 scaled_info.minRowBytes()); | 602 scaled_info.minRowBytes()); |
| 580 // TODO(vmpstr): Start handling more than just high filter quality. | |
| 581 DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality()); | |
|
vmpstr
2016/04/21 20:11:31
Can you add a
DCHECK(key.filter_quality() == kHig
cblume
2016/04/22 01:40:14
Done.
| |
| 582 { | 603 { |
| 583 TRACE_EVENT0("disabled-by-default-cc.debug", | 604 TRACE_EVENT0("disabled-by-default-cc.debug", |
| 584 "SoftwareImageDecodeController::ScaleImage - scale pixels"); | 605 "SoftwareImageDecodeController::ScaleImage - scale pixels"); |
| 585 bool result = | 606 bool result = |
| 586 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); | 607 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); |
| 587 DCHECK(result) << key.ToString(); | 608 DCHECK(result) << key.ToString(); |
| 588 } | 609 } |
| 589 | 610 |
| 590 // Release the original sized decode. Any other intermediate result to release | 611 // Release the original sized decode. Any other intermediate result to release |
| 591 // would be the subrect memory. However, that's in a scoped_ptr and will be | 612 // would be the subrect memory. However, that's in a scoped_ptr and will be |
| 592 // deleted automatically when we return. | 613 // deleted automatically when we return. |
| 593 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); | 614 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); |
| 594 | 615 |
| 595 return base::WrapUnique( | 616 return base::WrapUnique( |
| 596 new DecodedImage(scaled_info, std::move(scaled_pixels), | 617 new DecodedImage(scaled_info, std::move(scaled_pixels), |
| 597 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), | 618 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), |
| 598 next_tracing_id_.GetNext())); | 619 next_tracing_id_.GetNext())); |
| 599 } | 620 } |
| 600 | 621 |
| 601 void SoftwareImageDecodeController::DrawWithImageFinished( | 622 void SoftwareImageDecodeController::DrawWithImageFinished( |
| 602 const DrawImage& image, | 623 const DrawImage& image, |
| 603 const DecodedDrawImage& decoded_image) { | 624 const DecodedDrawImage& decoded_image) { |
| 604 TRACE_EVENT1("disabled-by-default-cc.debug", | 625 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 605 "SoftwareImageDecodeController::DrawWithImageFinished", "key", | 626 "SoftwareImageDecodeController::DrawWithImageFinished", "key", |
| 606 ImageKey::FromDrawImage(image).ToString()); | 627 ImageKey::FromDrawImage(image).ToString()); |
| 607 ImageKey key = ImageKey::FromDrawImage(image); | 628 ImageKey key = ImageKey::FromDrawImage(image); |
| 608 if (!decoded_image.image() || !CanHandleImage(key)) | 629 if (!decoded_image.image()) |
| 609 return; | 630 return; |
| 610 | 631 |
| 611 if (decoded_image.is_at_raster_decode()) | 632 if (decoded_image.is_at_raster_decode()) |
| 612 UnrefAtRasterImage(key); | 633 UnrefAtRasterImage(key); |
| 613 else | 634 else |
| 614 UnrefImage(image); | 635 UnrefImage(image); |
| 615 SanityCheckState(__LINE__, false); | 636 SanityCheckState(__LINE__, false); |
| 616 } | 637 } |
| 617 | 638 |
| 618 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) { | 639 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 665 DCHECK(decoded_images_ref_counts_.find(key) == | 686 DCHECK(decoded_images_ref_counts_.find(key) == |
| 666 decoded_images_ref_counts_.end()); | 687 decoded_images_ref_counts_.end()); |
| 667 at_raster_image_it->second->Unlock(); | 688 at_raster_image_it->second->Unlock(); |
| 668 decoded_images_.Erase(image_it); | 689 decoded_images_.Erase(image_it); |
| 669 decoded_images_.Put(key, std::move(at_raster_image_it->second)); | 690 decoded_images_.Put(key, std::move(at_raster_image_it->second)); |
| 670 } | 691 } |
| 671 at_raster_decoded_images_.Erase(at_raster_image_it); | 692 at_raster_decoded_images_.Erase(at_raster_image_it); |
| 672 } | 693 } |
| 673 } | 694 } |
| 674 | 695 |
| 675 bool SoftwareImageDecodeController::CanHandleImage(const ImageKey& key) { | |
| 676 // TODO(vmpstr): Start handling medium filter quality as well. | |
| 677 return key.filter_quality() != kMedium_SkFilterQuality; | |
| 678 } | |
| 679 | |
| 680 void SoftwareImageDecodeController::ReduceCacheUsage() { | 696 void SoftwareImageDecodeController::ReduceCacheUsage() { |
| 681 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage"); | 697 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage"); |
| 682 base::AutoLock lock(lock_); | 698 base::AutoLock lock(lock_); |
| 683 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache) | 699 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache) |
| 684 ? (decoded_images_.size() - kMaxItemsInCache) | 700 ? (decoded_images_.size() - kMaxItemsInCache) |
| 685 : 0; | 701 : 0; |
| 686 for (auto it = decoded_images_.rbegin(); | 702 for (auto it = decoded_images_.rbegin(); |
| 687 num_to_remove != 0 && it != decoded_images_.rend();) { | 703 num_to_remove != 0 && it != decoded_images_.rend();) { |
| 688 if (it->second->is_locked()) { | 704 if (it->second->is_locked()) { |
| 689 ++it; | 705 ++it; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 933 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { | 949 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { |
| 934 current_usage_bytes_ = 0; | 950 current_usage_bytes_ = 0; |
| 935 } | 951 } |
| 936 | 952 |
| 937 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() | 953 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() |
| 938 const { | 954 const { |
| 939 return current_usage_bytes_.ValueOrDie(); | 955 return current_usage_bytes_.ValueOrDie(); |
| 940 } | 956 } |
| 941 | 957 |
| 942 } // namespace cc | 958 } // namespace cc |
| OLD | NEW |