Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/gpu_image_decode_controller.h" | 5 #include "cc/tiles/gpu_image_decode_controller.h" |
| 6 | 6 |
| 7 #include "base/memory/discardable_memory_allocator.h" | 7 #include "base/memory/discardable_memory_allocator.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
| 10 #include "base/numerics/safe_math.h" | 10 #include "base/numerics/safe_math.h" |
| 11 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
| 12 #include "base/threading/thread_task_runner_handle.h" | 12 #include "base/threading/thread_task_runner_handle.h" |
| 13 #include "cc/debug/devtools_instrumentation.h" | 13 #include "cc/debug/devtools_instrumentation.h" |
| 14 #include "cc/output/context_provider.h" | 14 #include "cc/output/context_provider.h" |
| 15 #include "cc/raster/tile_task.h" | 15 #include "cc/raster/tile_task.h" |
| 16 #include "cc/resources/resource_format_utils.h" | 16 #include "cc/resources/resource_format_utils.h" |
| 17 #include "cc/tiles/mipmap_util.h" | |
| 17 #include "gpu/command_buffer/client/context_support.h" | 18 #include "gpu/command_buffer/client/context_support.h" |
| 18 #include "gpu/command_buffer/client/gles2_interface.h" | 19 #include "gpu/command_buffer/client/gles2_interface.h" |
| 19 #include "gpu_image_decode_controller.h" | 20 #include "gpu_image_decode_controller.h" |
| 20 #include "skia/ext/texture_handle.h" | 21 #include "skia/ext/texture_handle.h" |
| 21 #include "third_party/skia/include/core/SkCanvas.h" | 22 #include "third_party/skia/include/core/SkCanvas.h" |
| 22 #include "third_party/skia/include/core/SkRefCnt.h" | 23 #include "third_party/skia/include/core/SkRefCnt.h" |
| 23 #include "third_party/skia/include/core/SkSurface.h" | 24 #include "third_party/skia/include/core/SkSurface.h" |
| 24 #include "third_party/skia/include/gpu/GrContext.h" | 25 #include "third_party/skia/include/gpu/GrContext.h" |
| 25 #include "third_party/skia/include/gpu/GrTexture.h" | 26 #include "third_party/skia/include/gpu/GrTexture.h" |
| 26 #include "ui/gfx/skia_util.h" | 27 #include "ui/gfx/skia_util.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 39 if (std::abs(draw_image.scale().width()) < | 40 if (std::abs(draw_image.scale().width()) < |
| 40 std::numeric_limits<float>::epsilon() || | 41 std::numeric_limits<float>::epsilon() || |
| 41 std::abs(draw_image.scale().height()) < | 42 std::abs(draw_image.scale().height()) < |
| 42 std::numeric_limits<float>::epsilon()) { | 43 std::numeric_limits<float>::epsilon()) { |
| 43 return true; | 44 return true; |
| 44 } | 45 } |
| 45 return false; | 46 return false; |
| 46 } | 47 } |
| 47 | 48 |
| 48 SkImage::DeferredTextureImageUsageParams ParamsFromDrawImage( | 49 SkImage::DeferredTextureImageUsageParams ParamsFromDrawImage( |
| 49 const DrawImage& draw_image) { | 50 const DrawImage& draw_image, |
| 51 int pre_scale_mip_level) { | |
| 50 SkImage::DeferredTextureImageUsageParams params; | 52 SkImage::DeferredTextureImageUsageParams params; |
| 51 params.fMatrix = draw_image.matrix(); | 53 params.fMatrix = draw_image.matrix(); |
| 52 params.fQuality = draw_image.filter_quality(); | 54 params.fQuality = draw_image.filter_quality(); |
| 55 params.fPreScaleMipLevel = pre_scale_mip_level; | |
| 53 | 56 |
| 54 return params; | 57 return params; |
| 55 } | 58 } |
| 56 | 59 |
| 60 // Calculate the mp level to pre-scale the image to before uploading. We use mip | |
|
vmpstr
2016/06/21 20:07:08
s/mp/mip/
ericrk
2016/06/22 18:56:38
Done.
| |
| 61 // levels rather than exact scales to increase re-use of scaled images. | |
| 62 int CalculatePreScaleMipLevel(const DrawImage& draw_image) { | |
|
vmpstr
2016/06/21 20:07:08
Can we rename "Pre" to "Upload"
ericrk
2016/06/22 18:56:37
Done.
| |
| 63 if (draw_image.src_rect() != draw_image.image()->bounds()) { | |
| 64 // Images which are being clipped will have color-bleeding if scaled. | |
|
vmpstr
2016/06/21 20:07:07
Move the comment before the if, please
ericrk
2016/06/22 18:56:38
Done.
| |
| 65 // TODO(ericrk): Investigate uploading clipped images to handle this case | |
| 66 // and provide further optimization. crbug.com/620899 | |
| 67 return 0; | |
| 68 } | |
| 69 | |
| 70 gfx::Size base_size(draw_image.image()->width(), | |
| 71 draw_image.image()->height()); | |
| 72 // Ceil our scaled size so that the mip map generated is guaranteed to be | |
| 73 // larger. | |
| 74 gfx::Size scaled_size = gfx::ScaleToCeiledSize( | |
| 75 base_size, draw_image.scale().width(), draw_image.scale().height()); | |
| 76 | |
| 77 return MipMapUtil::GetLevelForSize(base_size, scaled_size); | |
| 78 } | |
| 79 | |
| 80 SkSize CalculatePreScaleFactor(const DrawImage& draw_image, int mip_level) { | |
|
vmpstr
2016/06/21 20:07:07
Put a comment before the function please
ericrk
2016/06/22 18:56:38
Done.
| |
| 81 gfx::Size base_size(draw_image.image()->width(), | |
| 82 draw_image.image()->height()); | |
| 83 return MipMapUtil::GetScaleAdjustmentForLevel(base_size, mip_level); | |
| 84 } | |
| 85 | |
| 86 // Generates a uint64_t which uniquely identifies a DrawImage for the purposes | |
| 87 // of the |in_use_cache_|. The key is generated as follows: | |
| 88 // ╔══════════════════════╤═══════════╤═══════════╗ | |
| 89 // ║ image_id │ mip_level │ quality ║ | |
| 90 // ╚════════32═bits═══════╧══16═bits══╧══16═bits══╝ | |
| 91 uint64_t GenerateInUseCacheKey(const DrawImage& draw_image) { | |
| 92 static_assert( | |
| 93 kLast_SkFilterQuality <= std::numeric_limits<uint16_t>::max(), | |
| 94 "InUseCacheKey depends on SkFilterQuality fitting in a uint16_t."); | |
| 95 | |
| 96 SkFilterQuality filter_quality = draw_image.filter_quality(); | |
| 97 DCHECK_LE(filter_quality, kLast_SkFilterQuality); | |
| 98 | |
| 99 // An image has at most log_2(max(width, height)) mip levels, so given our | |
| 100 // usage of 32-bit sizes for images, key.mip_level is at most 31. | |
| 101 int32_t mip_level = CalculatePreScaleMipLevel(draw_image); | |
| 102 DCHECK_LT(mip_level, 32); | |
| 103 | |
| 104 return (static_cast<uint64_t>(draw_image.image()->uniqueID()) << 32) | | |
| 105 (mip_level << 16) | draw_image.filter_quality(); | |
| 106 } | |
| 107 | |
| 57 } // namespace | 108 } // namespace |
| 58 | 109 |
| 110 GpuImageDecodeController::InUseCacheEntry::InUseCacheEntry( | |
| 111 scoped_refptr<ImageData> image_data) | |
| 112 : image_data(std::move(image_data)) {} | |
| 113 GpuImageDecodeController::InUseCacheEntry::InUseCacheEntry( | |
| 114 const InUseCacheEntry&) = default; | |
| 115 GpuImageDecodeController::InUseCacheEntry::InUseCacheEntry(InUseCacheEntry&&) = | |
| 116 default; | |
| 117 GpuImageDecodeController::InUseCacheEntry::~InUseCacheEntry() = default; | |
| 118 | |
| 59 // Task which decodes an image and stores the result in discardable memory. | 119 // Task which decodes an image and stores the result in discardable memory. |
| 60 // This task does not use GPU resources and can be run on any thread. | 120 // This task does not use GPU resources and can be run on any thread. |
| 61 class ImageDecodeTaskImpl : public TileTask { | 121 class ImageDecodeTaskImpl : public TileTask { |
| 62 public: | 122 public: |
| 63 ImageDecodeTaskImpl(GpuImageDecodeController* controller, | 123 ImageDecodeTaskImpl(GpuImageDecodeController* controller, |
| 64 const DrawImage& draw_image, | 124 const DrawImage& draw_image, |
| 65 const ImageDecodeController::TracingInfo& tracing_info) | 125 const ImageDecodeController::TracingInfo& tracing_info) |
| 66 : TileTask(true), | 126 : TileTask(true), |
| 67 controller_(controller), | 127 controller_(controller), |
| 68 image_(draw_image), | 128 image_(draw_image), |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 | 228 |
| 169 void GpuImageDecodeController::DecodedImageData::ResetData() { | 229 void GpuImageDecodeController::DecodedImageData::ResetData() { |
| 170 DCHECK(!is_locked_); | 230 DCHECK(!is_locked_); |
| 171 if (data_) | 231 if (data_) |
| 172 ReportUsageStats(); | 232 ReportUsageStats(); |
| 173 data_ = nullptr; | 233 data_ = nullptr; |
| 174 usage_stats_ = UsageStats(); | 234 usage_stats_ = UsageStats(); |
| 175 } | 235 } |
| 176 | 236 |
| 177 void GpuImageDecodeController::DecodedImageData::ReportUsageStats() const { | 237 void GpuImageDecodeController::DecodedImageData::ReportUsageStats() const { |
| 178 // lock_count | used | result state | 238 // lock_count │ used │ result state |
| 179 // ===========+=======+================== | 239 // ═══════════╪═══════╪══════════════════ |
|
vmpstr
2016/06/21 20:07:08
nice!
ericrk
2016/06/22 18:56:38
Done.
| |
| 180 // 1 | false | WASTED_ONCE | 240 // 1 │ false │ WASTED_ONCE |
| 181 // 1 | true | USED_ONCE | 241 // 1 │ true │ USED_ONCE |
| 182 // >1 | false | WASTED_RELOCKED | 242 // >1 │ false │ WASTED_RELOCKED |
| 183 // >1 | true | USED_RELOCKED | 243 // >1 │ true │ USED_RELOCKED |
| 184 // Note that it's important not to reorder the following enums, since the | 244 // Note that it's important not to reorder the following enums, since the |
| 185 // numerical values are used in the histogram code. | 245 // numerical values are used in the histogram code. |
| 186 enum State : int { | 246 enum State : int { |
| 187 DECODED_IMAGE_STATE_WASTED_ONCE, | 247 DECODED_IMAGE_STATE_WASTED_ONCE, |
| 188 DECODED_IMAGE_STATE_USED_ONCE, | 248 DECODED_IMAGE_STATE_USED_ONCE, |
| 189 DECODED_IMAGE_STATE_WASTED_RELOCKED, | 249 DECODED_IMAGE_STATE_WASTED_RELOCKED, |
| 190 DECODED_IMAGE_STATE_USED_RELOCKED, | 250 DECODED_IMAGE_STATE_USED_RELOCKED, |
| 191 DECODED_IMAGE_STATE_COUNT | 251 DECODED_IMAGE_STATE_COUNT |
| 192 } state = DECODED_IMAGE_STATE_WASTED_ONCE; | 252 } state = DECODED_IMAGE_STATE_WASTED_ONCE; |
| 193 | 253 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 224 image_ = std::move(image); | 284 image_ = std::move(image); |
| 225 } | 285 } |
| 226 | 286 |
| 227 void GpuImageDecodeController::UploadedImageData::ReportUsageStats() const { | 287 void GpuImageDecodeController::UploadedImageData::ReportUsageStats() const { |
| 228 UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuImageUploadState.Used", | 288 UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuImageUploadState.Used", |
| 229 usage_stats_.used); | 289 usage_stats_.used); |
| 230 UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuImageUploadState.FirstRefWasted", | 290 UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuImageUploadState.FirstRefWasted", |
| 231 usage_stats_.first_ref_wasted); | 291 usage_stats_.first_ref_wasted); |
| 232 } | 292 } |
| 233 | 293 |
| 234 GpuImageDecodeController::ImageData::ImageData(DecodedDataMode mode, | 294 GpuImageDecodeController::ImageData::ImageData( |
| 235 size_t size) | 295 DecodedDataMode mode, |
| 236 : mode(mode), size(size) {} | 296 size_t size, |
| 297 int pre_scale_mip_level, | |
| 298 SkFilterQuality pre_scale_filter_quality) | |
| 299 : mode(mode), | |
| 300 size(size), | |
| 301 pre_scale_mip_level(pre_scale_mip_level), | |
| 302 pre_scale_filter_quality(pre_scale_filter_quality) {} | |
| 237 | 303 |
| 238 GpuImageDecodeController::ImageData::~ImageData() = default; | 304 GpuImageDecodeController::ImageData::~ImageData() { |
| 305 // We should never delete ImageData while it is in use or before it has been | |
| 306 // cleaned up. | |
| 307 DCHECK_EQ(0u, upload.ref_count); | |
| 308 DCHECK_EQ(0u, decode.ref_count); | |
| 309 DCHECK_EQ(false, decode.is_locked()); | |
| 310 // This should always be cleaned up before deleting the image, as it needs to | |
| 311 // be freed with the GL context lock held. | |
| 312 DCHECK(!upload.image()); | |
| 313 } | |
| 239 | 314 |
| 240 GpuImageDecodeController::GpuImageDecodeController(ContextProvider* context, | 315 GpuImageDecodeController::GpuImageDecodeController(ContextProvider* context, |
| 241 ResourceFormat decode_format, | 316 ResourceFormat decode_format, |
| 242 size_t max_gpu_image_bytes) | 317 size_t max_gpu_image_bytes) |
| 243 : format_(decode_format), | 318 : format_(decode_format), |
| 244 context_(context), | 319 context_(context), |
| 245 image_data_(ImageDataMRUCache::NO_AUTO_EVICT), | 320 persistent_cache_(ImageDataMRUCache::NO_AUTO_EVICT), |
| 246 cached_items_limit_(kMaxDiscardableItems), | 321 cached_items_limit_(kMaxDiscardableItems), |
| 247 cached_bytes_limit_(max_gpu_image_bytes), | 322 cached_bytes_limit_(max_gpu_image_bytes), |
| 248 bytes_used_(0), | 323 bytes_used_(0), |
| 249 max_gpu_image_bytes_(max_gpu_image_bytes) { | 324 max_gpu_image_bytes_(max_gpu_image_bytes) { |
| 250 // Acquire the context_lock so that we can safely retrieve the | 325 // Acquire the context_lock so that we can safely retrieve the |
| 251 // GrContextThreadSafeProxy. This proxy can then be used with no lock held. | 326 // GrContextThreadSafeProxy. This proxy can then be used with no lock held. |
| 252 { | 327 { |
| 253 ContextProvider::ScopedContextLock context_lock(context_); | 328 ContextProvider::ScopedContextLock context_lock(context_); |
| 254 context_threadsafe_proxy_ = sk_sp<GrContextThreadSafeProxy>( | 329 context_threadsafe_proxy_ = sk_sp<GrContextThreadSafeProxy>( |
| 255 context->GrContext()->threadSafeProxy()); | 330 context->GrContext()->threadSafeProxy()); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 278 const DrawImage& draw_image, | 353 const DrawImage& draw_image, |
| 279 const TracingInfo& tracing_info, | 354 const TracingInfo& tracing_info, |
| 280 scoped_refptr<TileTask>* task) { | 355 scoped_refptr<TileTask>* task) { |
| 281 if (SkipImage(draw_image)) { | 356 if (SkipImage(draw_image)) { |
| 282 *task = nullptr; | 357 *task = nullptr; |
| 283 return false; | 358 return false; |
| 284 } | 359 } |
| 285 | 360 |
| 286 base::AutoLock lock(lock_); | 361 base::AutoLock lock(lock_); |
| 287 const auto image_id = draw_image.image()->uniqueID(); | 362 const auto image_id = draw_image.image()->uniqueID(); |
| 288 | 363 ImageData* image_data = GetImageDataForDrawImage(draw_image); |
| 289 auto found = image_data_.Get(image_id); | 364 if (image_data) { |
| 290 if (found != image_data_.end()) { | |
| 291 ImageData* image_data = found->second.get(); | |
| 292 if (image_data->is_at_raster) { | 365 if (image_data->is_at_raster) { |
| 293 // Image is at-raster, just return, this usage will be at-raster as well. | 366 // Image is at-raster, just return, this usage will be at-raster as well. |
| 294 *task = nullptr; | 367 *task = nullptr; |
| 295 return false; | 368 return false; |
| 296 } | 369 } |
| 297 | 370 |
| 298 if (image_data->decode.decode_failure) { | 371 if (image_data->decode.decode_failure) { |
| 299 // We have already tried and failed to decode this image, so just return. | 372 // We have already tried and failed to decode this image, so just return. |
| 300 *task = nullptr; | 373 *task = nullptr; |
| 301 return false; | 374 return false; |
| 302 } | 375 } |
| 303 | 376 |
| 304 if (image_data->upload.image()) { | 377 if (image_data->upload.image()) { |
| 305 // The image is already uploaded, ref and return. | 378 // The image is already uploaded, ref and return. |
| 306 RefImage(draw_image); | 379 RefImage(draw_image); |
| 307 *task = nullptr; | 380 *task = nullptr; |
| 308 return true; | 381 return true; |
| 309 } | 382 } |
| 310 } | |
| 311 | 383 |
| 312 // We didn't have a pre-uploaded image, so we need an upload task. Try to find | 384 // We didn't have a pre-uploaded image, so we need an upload task. Try to |
| 313 // an existing one. | 385 // find an existing one. |
| 314 scoped_refptr<TileTask>& existing_task = | 386 if (image_data->upload.task) { |
| 315 pending_image_upload_tasks_[image_id]; | 387 // We had an existing upload task, ref the image and return the task. |
| 316 if (existing_task) { | 388 RefImage(draw_image); |
| 317 // We had an existing upload task, ref the image and return the task. | 389 *task = image_data->upload.task; |
| 318 RefImage(draw_image); | 390 return true; |
| 319 *task = existing_task; | 391 } else { |
| 320 return true; | 392 } |
| 321 } | 393 } |
| 322 | 394 |
| 323 // We will be creating a new upload task. If necessary, create a placeholder | 395 // We will be creating a new upload task. If necessary, create a placeholder |
| 324 // ImageData to hold the result. | 396 // ImageData to hold the result. |
| 325 std::unique_ptr<ImageData> new_data; | 397 scoped_refptr<ImageData> new_data; |
| 326 ImageData* data; | 398 if (!image_data) { |
| 327 if (found == image_data_.end()) { | |
| 328 new_data = CreateImageData(draw_image); | 399 new_data = CreateImageData(draw_image); |
| 329 data = new_data.get(); | 400 image_data = new_data.get(); |
| 330 } else { | |
| 331 data = found->second.get(); | |
| 332 } | 401 } |
| 333 | 402 |
| 334 // Ensure that the image we're about to decode/upload will fit in memory. | 403 // Ensure that the image we're about to decode/upload will fit in memory. |
| 335 if (!EnsureCapacity(data->size)) { | 404 if (!EnsureCapacity(image_data->size)) { |
| 336 // Image will not fit, do an at-raster decode. | 405 // Image will not fit, do an at-raster decode. |
| 337 *task = nullptr; | 406 *task = nullptr; |
| 338 return false; | 407 return false; |
| 339 } | 408 } |
| 340 | 409 |
| 341 // If we had to create new image data, add it to our map now that we know it | 410 // If we had to create new image data, add it to our map now that we know it |
| 342 // will fit. | 411 // will fit. |
| 343 if (new_data) | 412 if (new_data) |
| 344 found = image_data_.Put(image_id, std::move(new_data)); | 413 persistent_cache_.Put(image_id, std::move(new_data)); |
| 345 | 414 |
| 346 // Ref image and create a upload and decode tasks. We will release this ref | 415 // Ref image and create a upload and decode tasks. We will release this ref |
| 347 // in UploadTaskCompleted. | 416 // in UploadTaskCompleted. |
| 348 RefImage(draw_image); | 417 RefImage(draw_image); |
| 349 existing_task = make_scoped_refptr(new ImageUploadTaskImpl( | 418 *task = make_scoped_refptr(new ImageUploadTaskImpl( |
| 350 this, draw_image, GetImageDecodeTaskAndRef(draw_image, tracing_info), | 419 this, draw_image, GetImageDecodeTaskAndRef(draw_image, tracing_info), |
| 351 tracing_info)); | 420 tracing_info)); |
| 421 image_data->upload.task = *task; | |
| 352 | 422 |
| 353 // Ref the image again - this ref is owned by the caller, and it is their | 423 // Ref the image again - this ref is owned by the caller, and it is their |
| 354 // responsibility to release it by calling UnrefImage. | 424 // responsibility to release it by calling UnrefImage. |
| 355 RefImage(draw_image); | 425 RefImage(draw_image); |
| 356 *task = existing_task; | |
| 357 return true; | 426 return true; |
| 358 } | 427 } |
| 359 | 428 |
| 360 void GpuImageDecodeController::UnrefImage(const DrawImage& draw_image) { | 429 void GpuImageDecodeController::UnrefImage(const DrawImage& draw_image) { |
| 361 base::AutoLock lock(lock_); | 430 base::AutoLock lock(lock_); |
| 362 UnrefImageInternal(draw_image); | 431 UnrefImageInternal(draw_image); |
| 363 } | 432 } |
| 364 | 433 |
| 365 DecodedDrawImage GpuImageDecodeController::GetDecodedImageForDraw( | 434 DecodedDrawImage GpuImageDecodeController::GetDecodedImageForDraw( |
| 366 const DrawImage& draw_image) { | 435 const DrawImage& draw_image) { |
| 367 // We are being called during raster. The context lock must already be | 436 // We are being called during raster. The context lock must already be |
| 368 // acquired by the caller. | 437 // acquired by the caller. |
| 369 context_->GetLock()->AssertAcquired(); | 438 context_->GetLock()->AssertAcquired(); |
| 370 | 439 |
| 371 if (SkipImage(draw_image)) | 440 if (SkipImage(draw_image)) |
| 372 return DecodedDrawImage(nullptr, draw_image.filter_quality()); | 441 return DecodedDrawImage(nullptr, draw_image.filter_quality()); |
| 373 | 442 |
| 374 TRACE_EVENT0("cc", "GpuImageDecodeController::GetDecodedImageForDraw"); | 443 TRACE_EVENT0("cc", "GpuImageDecodeController::GetDecodedImageForDraw"); |
| 375 | 444 |
| 376 base::AutoLock lock(lock_); | 445 base::AutoLock lock(lock_); |
| 377 const uint32_t unique_id = draw_image.image()->uniqueID(); | 446 ImageData* image_data = GetImageDataForDrawImage(draw_image); |
| 378 auto found = image_data_.Peek(unique_id); | 447 if (!image_data) { |
| 379 if (found == image_data_.end()) { | |
| 380 // We didn't find the image, create a new entry. | 448 // We didn't find the image, create a new entry. |
| 381 auto data = CreateImageData(draw_image); | 449 auto data = CreateImageData(draw_image); |
| 382 found = image_data_.Put(unique_id, std::move(data)); | 450 image_data = data.get(); |
| 451 persistent_cache_.Put(draw_image.image()->uniqueID(), std::move(data)); | |
| 383 } | 452 } |
| 384 | 453 |
| 385 ImageData* image_data = found->second.get(); | |
| 386 | |
| 387 if (!image_data->upload.budgeted) { | 454 if (!image_data->upload.budgeted) { |
| 388 // If image data is not budgeted by this point, it is at-raster. | 455 // If image data is not budgeted by this point, it is at-raster. |
| 389 image_data->is_at_raster = true; | 456 image_data->is_at_raster = true; |
| 390 } | 457 } |
| 391 | 458 |
| 392 // Ref the image and decode so that they stay alive while we are | 459 // Ref the image and decode so that they stay alive while we are |
| 393 // decoding/uploading. | 460 // decoding/uploading. |
| 394 RefImage(draw_image); | 461 RefImage(draw_image); |
| 395 RefImageDecode(draw_image); | 462 RefImageDecode(draw_image); |
| 396 | 463 |
| 397 // We may or may not need to decode and upload the image we've found, the | 464 // We may or may not need to decode and upload the image we've found, the |
| 398 // following functions early-out to if we already decoded. | 465 // following functions early-out to if we already decoded. |
| 399 DecodeImageIfNecessary(draw_image, image_data); | 466 DecodeImageIfNecessary(draw_image, image_data); |
| 400 UploadImageIfNecessary(draw_image, image_data); | 467 UploadImageIfNecessary(draw_image, image_data); |
| 401 // Unref the image decode, but not the image. The image ref will be released | 468 // Unref the image decode, but not the image. The image ref will be released |
| 402 // in DrawWithImageFinished. | 469 // in DrawWithImageFinished. |
| 403 UnrefImageDecode(draw_image); | 470 UnrefImageDecode(draw_image); |
| 404 | 471 |
| 405 sk_sp<SkImage> image = image_data->upload.image(); | 472 sk_sp<SkImage> image = image_data->upload.image(); |
| 406 image_data->upload.mark_used(); | 473 image_data->upload.mark_used(); |
| 407 DCHECK(image || image_data->decode.decode_failure); | 474 DCHECK(image || image_data->decode.decode_failure); |
| 408 | 475 |
| 409 DecodedDrawImage decoded_draw_image(std::move(image), | 476 SkSize scale_factor = |
| 477 CalculatePreScaleFactor(draw_image, image_data->pre_scale_mip_level); | |
| 478 DecodedDrawImage decoded_draw_image(std::move(image), SkSize(), scale_factor, | |
| 410 draw_image.filter_quality()); | 479 draw_image.filter_quality()); |
| 411 decoded_draw_image.set_at_raster_decode(image_data->is_at_raster); | 480 decoded_draw_image.set_at_raster_decode(image_data->is_at_raster); |
| 412 return decoded_draw_image; | 481 return decoded_draw_image; |
| 413 } | 482 } |
| 414 | 483 |
| 415 void GpuImageDecodeController::DrawWithImageFinished( | 484 void GpuImageDecodeController::DrawWithImageFinished( |
| 416 const DrawImage& draw_image, | 485 const DrawImage& draw_image, |
| 417 const DecodedDrawImage& decoded_draw_image) { | 486 const DecodedDrawImage& decoded_draw_image) { |
| 418 // We are being called during raster. The context lock must already be | 487 // We are being called during raster. The context lock must already be |
| 419 // acquired by the caller. | 488 // acquired by the caller. |
| 420 context_->GetLock()->AssertAcquired(); | 489 context_->GetLock()->AssertAcquired(); |
| 421 | 490 |
| 422 if (SkipImage(draw_image)) | 491 if (SkipImage(draw_image)) |
| 423 return; | 492 return; |
| 424 | 493 |
| 425 base::AutoLock lock(lock_); | 494 base::AutoLock lock(lock_); |
| 495 TRACE_EVENT0("cc", "GpuImageDecodeController::DrawWithImageFinished"); | |
| 426 UnrefImageInternal(draw_image); | 496 UnrefImageInternal(draw_image); |
| 427 | 497 |
| 428 // We are mid-draw and holding the context lock, ensure we clean up any | 498 // We are mid-draw and holding the context lock, ensure we clean up any |
| 429 // textures (especially at-raster), which may have just been marked for | 499 // textures (especially at-raster), which may have just been marked for |
| 430 // deletion by UnrefImage. | 500 // deletion by UnrefImage. |
| 431 DeletePendingImages(); | 501 DeletePendingImages(); |
| 432 } | 502 } |
| 433 | 503 |
| 434 void GpuImageDecodeController::ReduceCacheUsage() { | 504 void GpuImageDecodeController::ReduceCacheUsage() { |
| 435 base::AutoLock lock(lock_); | 505 base::AutoLock lock(lock_); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 451 DeletePendingImages(); | 521 DeletePendingImages(); |
| 452 } else { | 522 } else { |
| 453 base::AutoLock lock(lock_); | 523 base::AutoLock lock(lock_); |
| 454 cached_bytes_limit_ = max_gpu_image_bytes_; | 524 cached_bytes_limit_ = max_gpu_image_bytes_; |
| 455 } | 525 } |
| 456 } | 526 } |
| 457 | 527 |
| 458 bool GpuImageDecodeController::OnMemoryDump( | 528 bool GpuImageDecodeController::OnMemoryDump( |
| 459 const base::trace_event::MemoryDumpArgs& args, | 529 const base::trace_event::MemoryDumpArgs& args, |
| 460 base::trace_event::ProcessMemoryDump* pmd) { | 530 base::trace_event::ProcessMemoryDump* pmd) { |
| 461 for (const auto& image_pair : image_data_) { | 531 for (const auto& image_pair : persistent_cache_) { |
| 462 const ImageData* image_data = image_pair.second.get(); | 532 const ImageData* image_data = image_pair.second.get(); |
| 463 const uint32_t image_id = image_pair.first; | 533 const uint32_t image_id = image_pair.first; |
| 464 | 534 |
| 465 // If we have discardable decoded data, dump this here. | 535 // If we have discardable decoded data, dump this here. |
| 466 if (image_data->decode.data()) { | 536 if (image_data->decode.data()) { |
| 467 std::string discardable_dump_name = base::StringPrintf( | 537 std::string discardable_dump_name = base::StringPrintf( |
| 468 "cc/image_memory/controller_%p/discardable/image_%d", this, image_id); | 538 "cc/image_memory/controller_%p/discardable/image_%d", this, image_id); |
| 469 base::trace_event::MemoryAllocatorDump* dump = | 539 base::trace_event::MemoryAllocatorDump* dump = |
| 470 image_data->decode.data()->CreateMemoryAllocatorDump( | 540 image_data->decode.data()->CreateMemoryAllocatorDump( |
| 471 discardable_dump_name.c_str(), pmd); | 541 discardable_dump_name.c_str(), pmd); |
| 472 | |
| 473 // If our image is locked, dump the "locked_size" as an additional column. | 542 // If our image is locked, dump the "locked_size" as an additional column. |
| 474 // This lets us see the amount of discardable which is contributing to | 543 // This lets us see the amount of discardable which is contributing to |
| 475 // memory pressure. | 544 // memory pressure. |
| 476 if (image_data->decode.is_locked()) { | 545 if (image_data->decode.is_locked()) { |
| 477 dump->AddScalar("locked_size", | 546 dump->AddScalar("locked_size", |
| 478 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | 547 base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| 479 image_data->size); | 548 image_data->size); |
| 480 } | 549 } |
| 481 } | 550 } |
| 482 | 551 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 509 pmd->CreateSharedGlobalAllocatorDump(guid); | 578 pmd->CreateSharedGlobalAllocatorDump(guid); |
| 510 pmd->AddOwnershipEdge(dump->guid(), guid, kImportance); | 579 pmd->AddOwnershipEdge(dump->guid(), guid, kImportance); |
| 511 } | 580 } |
| 512 } | 581 } |
| 513 | 582 |
| 514 return true; | 583 return true; |
| 515 } | 584 } |
| 516 | 585 |
| 517 void GpuImageDecodeController::DecodeImage(const DrawImage& draw_image) { | 586 void GpuImageDecodeController::DecodeImage(const DrawImage& draw_image) { |
| 518 base::AutoLock lock(lock_); | 587 base::AutoLock lock(lock_); |
| 519 auto found = image_data_.Peek(draw_image.image()->uniqueID()); | 588 ImageData* image_data = GetImageDataForDrawImage(draw_image); |
| 520 DCHECK(found != image_data_.end()); | 589 DCHECK(image_data); |
| 521 DCHECK(!found->second->is_at_raster); | 590 DCHECK(!image_data->is_at_raster); |
| 522 DecodeImageIfNecessary(draw_image, found->second.get()); | 591 DecodeImageIfNecessary(draw_image, image_data); |
| 523 } | 592 } |
| 524 | 593 |
| 525 void GpuImageDecodeController::UploadImage(const DrawImage& draw_image) { | 594 void GpuImageDecodeController::UploadImage(const DrawImage& draw_image) { |
| 526 ContextProvider::ScopedContextLock context_lock(context_); | 595 ContextProvider::ScopedContextLock context_lock(context_); |
| 527 base::AutoLock lock(lock_); | 596 base::AutoLock lock(lock_); |
| 528 auto found = image_data_.Peek(draw_image.image()->uniqueID()); | 597 ImageData* image_data = GetImageDataForDrawImage(draw_image); |
| 529 DCHECK(found != image_data_.end()); | 598 DCHECK(image_data); |
| 530 DCHECK(!found->second->is_at_raster); | 599 DCHECK(!image_data->is_at_raster); |
| 531 UploadImageIfNecessary(draw_image, found->second.get()); | 600 UploadImageIfNecessary(draw_image, image_data); |
| 532 } | 601 } |
| 533 | 602 |
| 534 void GpuImageDecodeController::OnImageDecodeTaskCompleted( | 603 void GpuImageDecodeController::OnImageDecodeTaskCompleted( |
| 535 const DrawImage& draw_image) { | 604 const DrawImage& draw_image) { |
| 536 base::AutoLock lock(lock_); | 605 base::AutoLock lock(lock_); |
| 537 // Decode task is complete, remove it from our list of pending tasks. | 606 // Decode task is complete, remove our reference to it. |
| 538 pending_image_decode_tasks_.erase(draw_image.image()->uniqueID()); | 607 ImageData* image_data = GetImageDataForDrawImage(draw_image); |
| 608 DCHECK(image_data); | |
| 609 DCHECK(image_data->decode.task); | |
| 610 image_data->decode.task = nullptr; | |
| 539 | 611 |
| 540 // While the decode task is active, we keep a ref on the decoded data. | 612 // While the decode task is active, we keep a ref on the decoded data. |
| 541 // Release that ref now. | 613 // Release that ref now. |
| 542 UnrefImageDecode(draw_image); | 614 UnrefImageDecode(draw_image); |
| 543 } | 615 } |
| 544 | 616 |
| 545 void GpuImageDecodeController::OnImageUploadTaskCompleted( | 617 void GpuImageDecodeController::OnImageUploadTaskCompleted( |
| 546 const DrawImage& draw_image) { | 618 const DrawImage& draw_image) { |
| 547 base::AutoLock lock(lock_); | 619 base::AutoLock lock(lock_); |
| 548 // Upload task is complete, remove it from our list of pending tasks. | 620 // Upload task is complete, remove our referene to it. |
|
vmpstr
2016/06/21 20:07:08
s/ne/nce/
ericrk
2016/06/22 18:56:37
Done.
| |
| 549 pending_image_upload_tasks_.erase(draw_image.image()->uniqueID()); | 621 ImageData* image_data = GetImageDataForDrawImage(draw_image); |
| 622 DCHECK(image_data); | |
| 623 DCHECK(image_data->upload.task); | |
| 624 image_data->upload.task = nullptr; | |
| 550 | 625 |
| 551 // While the upload task is active, we keep a ref on both the image it will be | 626 // While the upload task is active, we keep a ref on both the image it will be |
| 552 // populating, as well as the decode it needs to populate it. Release these | 627 // populating, as well as the decode it needs to populate it. Release these |
| 553 // refs now. | 628 // refs now. |
| 554 UnrefImageDecode(draw_image); | 629 UnrefImageDecode(draw_image); |
| 555 UnrefImageInternal(draw_image); | 630 UnrefImageInternal(draw_image); |
| 556 } | 631 } |
| 557 | 632 |
| 558 // Checks if an existing image decode exists. If not, returns a task to produce | 633 // Checks if an existing image decode exists. If not, returns a task to produce |
| 559 // the requested decode. | 634 // the requested decode. |
| 560 scoped_refptr<TileTask> GpuImageDecodeController::GetImageDecodeTaskAndRef( | 635 scoped_refptr<TileTask> GpuImageDecodeController::GetImageDecodeTaskAndRef( |
| 561 const DrawImage& draw_image, | 636 const DrawImage& draw_image, |
| 562 const TracingInfo& tracing_info) { | 637 const TracingInfo& tracing_info) { |
| 563 lock_.AssertAcquired(); | 638 lock_.AssertAcquired(); |
| 564 | 639 |
| 565 const uint32_t image_id = draw_image.image()->uniqueID(); | |
| 566 | |
| 567 // This ref is kept alive while an upload task may need this decode. We | 640 // This ref is kept alive while an upload task may need this decode. We |
| 568 // release this ref in UploadTaskCompleted. | 641 // release this ref in UploadTaskCompleted. |
| 569 RefImageDecode(draw_image); | 642 RefImageDecode(draw_image); |
| 570 | 643 |
| 571 auto found = image_data_.Peek(image_id); | 644 ImageData* image_data = GetImageDataForDrawImage(draw_image); |
| 572 if (found != image_data_.end() && found->second->decode.is_locked()) { | 645 DCHECK(image_data); |
| 646 if (image_data->decode.is_locked()) { | |
| 573 // We should never be creating a decode task for an at raster image. | 647 // We should never be creating a decode task for an at raster image. |
| 574 DCHECK(!found->second->is_at_raster); | 648 DCHECK(!image_data->is_at_raster); |
| 575 // We should never be creating a decode for an already-uploaded image. | 649 // We should never be creating a decode for an already-uploaded image. |
| 576 DCHECK(!found->second->upload.image()); | 650 DCHECK(!image_data->upload.image()); |
| 577 return nullptr; | 651 return nullptr; |
| 578 } | 652 } |
| 579 | 653 |
| 580 // We didn't have an existing locked image, create a task to lock or decode. | 654 // We didn't have an existing locked image, create a task to lock or decode. |
| 581 scoped_refptr<TileTask>& existing_task = | 655 scoped_refptr<TileTask>& existing_task = image_data->decode.task; |
| 582 pending_image_decode_tasks_[image_id]; | |
| 583 if (!existing_task) { | 656 if (!existing_task) { |
| 584 // Ref image decode and create a decode task. This ref will be released in | 657 // Ref image decode and create a decode task. This ref will be released in |
| 585 // DecodeTaskCompleted. | 658 // DecodeTaskCompleted. |
| 586 RefImageDecode(draw_image); | 659 RefImageDecode(draw_image); |
| 587 existing_task = make_scoped_refptr( | 660 existing_task = make_scoped_refptr( |
| 588 new ImageDecodeTaskImpl(this, draw_image, tracing_info)); | 661 new ImageDecodeTaskImpl(this, draw_image, tracing_info)); |
| 589 } | 662 } |
| 590 return existing_task; | 663 return existing_task; |
| 591 } | 664 } |
| 592 | 665 |
| 593 void GpuImageDecodeController::RefImageDecode(const DrawImage& draw_image) { | 666 void GpuImageDecodeController::RefImageDecode(const DrawImage& draw_image) { |
| 594 lock_.AssertAcquired(); | 667 lock_.AssertAcquired(); |
| 595 auto found = image_data_.Peek(draw_image.image()->uniqueID()); | 668 auto found = in_use_cache_.find(GenerateInUseCacheKey(draw_image)); |
| 596 DCHECK(found != image_data_.end()); | 669 DCHECK(found != in_use_cache_.end()); |
| 597 ++found->second->decode.ref_count; | 670 ++found->second.ref_count; |
| 598 RefCountChanged(found->second.get()); | 671 ++found->second.image_data->decode.ref_count; |
| 672 RefCountChanged(found->second.image_data.get()); | |
| 599 } | 673 } |
| 600 | 674 |
| 601 void GpuImageDecodeController::UnrefImageDecode(const DrawImage& draw_image) { | 675 void GpuImageDecodeController::UnrefImageDecode(const DrawImage& draw_image) { |
| 602 lock_.AssertAcquired(); | 676 lock_.AssertAcquired(); |
| 603 auto found = image_data_.Peek(draw_image.image()->uniqueID()); | 677 auto found = in_use_cache_.find(GenerateInUseCacheKey(draw_image)); |
| 604 DCHECK(found != image_data_.end()); | 678 DCHECK(found != in_use_cache_.end()); |
| 605 DCHECK_GT(found->second->decode.ref_count, 0u); | 679 DCHECK_GT(found->second.image_data->decode.ref_count, 0u); |
| 606 --found->second->decode.ref_count; | 680 DCHECK_GT(found->second.ref_count, 0u); |
| 607 RefCountChanged(found->second.get()); | 681 --found->second.ref_count; |
| 682 --found->second.image_data->decode.ref_count; | |
| 683 RefCountChanged(found->second.image_data.get()); | |
| 684 if (found->second.ref_count == 0u) { | |
| 685 in_use_cache_.erase(found); | |
| 686 } | |
| 608 } | 687 } |
| 609 | 688 |
| 610 void GpuImageDecodeController::RefImage(const DrawImage& draw_image) { | 689 void GpuImageDecodeController::RefImage(const DrawImage& draw_image) { |
| 611 lock_.AssertAcquired(); | 690 lock_.AssertAcquired(); |
| 612 auto found = image_data_.Peek(draw_image.image()->uniqueID()); | 691 InUseCacheKey key = GenerateInUseCacheKey(draw_image); |
| 613 DCHECK(found != image_data_.end()); | 692 auto found = in_use_cache_.find(key); |
| 614 ++found->second->upload.ref_count; | 693 |
| 615 RefCountChanged(found->second.get()); | 694 // If no secondary cache entry was found for the given |draw_image|, then |
| 695 // the draw_image only exists in the |persistent_cache_|. Create an in-use | |
| 696 // cache entry now. | |
| 697 if (found == in_use_cache_.end()) { | |
| 698 auto found_image = persistent_cache_.Peek(draw_image.image()->uniqueID()); | |
| 699 DCHECK(found_image != persistent_cache_.end()); | |
| 700 DCHECK(found_image->second->pre_scale_mip_level <= | |
| 701 CalculatePreScaleMipLevel(draw_image)); | |
| 702 found = | |
| 703 in_use_cache_ | |
| 704 .insert(std::make_pair(key, InUseCacheEntry(found_image->second))) | |
|
vmpstr
2016/06/21 20:07:08
make_pair here will make a std::pair<InUseCacheKey
ericrk
2016/06/22 18:56:37
Emplace works on windows - will update this again
| |
| 705 .first; | |
| 706 } | |
| 707 | |
| 708 DCHECK(found != in_use_cache_.end()); | |
| 709 ++found->second.ref_count; | |
| 710 ++found->second.image_data->upload.ref_count; | |
| 711 RefCountChanged(found->second.image_data.get()); | |
| 616 } | 712 } |
| 617 | 713 |
| 618 void GpuImageDecodeController::UnrefImageInternal(const DrawImage& draw_image) { | 714 void GpuImageDecodeController::UnrefImageInternal(const DrawImage& draw_image) { |
| 619 lock_.AssertAcquired(); | 715 lock_.AssertAcquired(); |
| 620 auto found = image_data_.Peek(draw_image.image()->uniqueID()); | 716 auto found = in_use_cache_.find(GenerateInUseCacheKey(draw_image)); |
| 621 DCHECK(found != image_data_.end()); | 717 DCHECK(found != in_use_cache_.end()); |
| 622 DCHECK_GT(found->second->upload.ref_count, 0u); | 718 DCHECK_GT(found->second.image_data->upload.ref_count, 0u); |
| 623 --found->second->upload.ref_count; | 719 DCHECK_GT(found->second.ref_count, 0u); |
| 624 if (found->second->upload.ref_count == 0) | 720 --found->second.ref_count; |
| 625 found->second->upload.notify_ref_reached_zero(); | 721 --found->second.image_data->upload.ref_count; |
| 626 RefCountChanged(found->second.get()); | 722 RefCountChanged(found->second.image_data.get()); |
| 723 if (found->second.ref_count == 0u) { | |
| 724 in_use_cache_.erase(found); | |
| 725 } | |
| 627 } | 726 } |
| 628 | 727 |
| 629 // Called any time an image or decode ref count changes. Takes care of any | 728 // Called any time an image or decode ref count changes. Takes care of any |
| 630 // necessary memory budget book-keeping and cleanup. | 729 // necessary memory budget book-keeping and cleanup. |
| 631 void GpuImageDecodeController::RefCountChanged(ImageData* image_data) { | 730 void GpuImageDecodeController::RefCountChanged(ImageData* image_data) { |
| 632 lock_.AssertAcquired(); | 731 lock_.AssertAcquired(); |
| 633 | 732 |
| 634 bool has_any_refs = | 733 bool has_any_refs = |
| 635 image_data->upload.ref_count > 0 || image_data->decode.ref_count > 0; | 734 image_data->upload.ref_count > 0 || image_data->decode.ref_count > 0; |
| 636 | 735 |
| 736 // Don't keep around orphaned images. | |
| 737 if (image_data->is_orphaned && !has_any_refs) { | |
| 738 images_pending_deletion_.push_back(std::move(image_data->upload.image())); | |
| 739 image_data->upload.SetImage(nullptr); | |
| 740 } | |
| 741 | |
| 637 // Don't keep CPU images if they are unused, these images can be recreated by | 742 // Don't keep CPU images if they are unused, these images can be recreated by |
| 638 // re-locking discardable (rather than requiring a full upload like GPU | 743 // re-locking discardable (rather than requiring a full upload like GPU |
| 639 // images). | 744 // images). |
| 640 if (image_data->mode == DecodedDataMode::CPU && !has_any_refs) { | 745 if (image_data->mode == DecodedDataMode::CPU && !has_any_refs) { |
| 641 images_pending_deletion_.push_back(image_data->upload.image()); | 746 images_pending_deletion_.push_back(image_data->upload.image()); |
| 642 image_data->upload.SetImage(nullptr); | 747 image_data->upload.SetImage(nullptr); |
| 643 } | 748 } |
| 644 | 749 |
| 645 if (image_data->is_at_raster && !has_any_refs) { | 750 if (image_data->is_at_raster && !has_any_refs) { |
| 646 // We have an at-raster image which has reached zero refs. If it won't fit | 751 // We have an at-raster image which has reached zero refs. If it won't fit |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 712 lock_.AssertAcquired(); | 817 lock_.AssertAcquired(); |
| 713 | 818 |
| 714 if (CanFitSize(required_size) && !ExceedsPreferredCount()) | 819 if (CanFitSize(required_size) && !ExceedsPreferredCount()) |
| 715 return true; | 820 return true; |
| 716 | 821 |
| 717 // While we are over memory or preferred item capacity, we iterate through | 822 // While we are over memory or preferred item capacity, we iterate through |
| 718 // our set of cached image data in LRU order. For each image, we can do two | 823 // our set of cached image data in LRU order. For each image, we can do two |
| 719 // things: 1) We can free the uploaded image, reducing the memory usage of | 824 // things: 1) We can free the uploaded image, reducing the memory usage of |
| 720 // the cache and 2) we can remove the entry entirely, reducing the count of | 825 // the cache and 2) we can remove the entry entirely, reducing the count of |
| 721 // elements in the cache. | 826 // elements in the cache. |
| 722 for (auto it = image_data_.rbegin(); it != image_data_.rend();) { | 827 for (auto it = persistent_cache_.rbegin(); it != persistent_cache_.rend();) { |
| 723 if (it->second->decode.ref_count != 0 || | 828 if (it->second->decode.ref_count != 0 || |
| 724 it->second->upload.ref_count != 0) { | 829 it->second->upload.ref_count != 0) { |
| 725 ++it; | 830 ++it; |
| 726 continue; | 831 continue; |
| 727 } | 832 } |
| 728 | 833 |
| 729 // Current entry has no refs. Ensure it is not locked. | 834 // Current entry has no refs. Ensure it is not locked. |
| 730 DCHECK(!it->second->decode.is_locked()); | 835 DCHECK(!it->second->decode.is_locked()); |
| 731 | 836 |
| 732 // If an image without refs is budgeted, it must have an associated image | 837 // If an image without refs is budgeted, it must have an associated image |
| 733 // upload. | 838 // upload. |
| 734 DCHECK(!it->second->upload.budgeted || it->second->upload.image()); | 839 DCHECK(!it->second->upload.budgeted || it->second->upload.image()); |
| 735 | 840 |
| 736 // Free the uploaded image if possible. | 841 // Free the uploaded image if possible. |
| 737 if (it->second->upload.image()) { | 842 if (it->second->upload.image()) { |
| 738 DCHECK(it->second->upload.budgeted); | 843 DCHECK(it->second->upload.budgeted); |
| 739 DCHECK_GE(bytes_used_, it->second->size); | 844 DCHECK_GE(bytes_used_, it->second->size); |
| 740 bytes_used_ -= it->second->size; | 845 bytes_used_ -= it->second->size; |
| 741 images_pending_deletion_.push_back(it->second->upload.image()); | 846 images_pending_deletion_.push_back(it->second->upload.image()); |
| 742 it->second->upload.SetImage(nullptr); | 847 it->second->upload.SetImage(nullptr); |
| 743 it->second->upload.budgeted = false; | 848 it->second->upload.budgeted = false; |
| 744 } | 849 } |
| 745 | 850 |
| 746 // Free the entire entry if necessary. | 851 // Free the entire entry if necessary. |
| 747 if (ExceedsPreferredCount()) { | 852 if (ExceedsPreferredCount()) { |
| 748 it = image_data_.Erase(it); | 853 it = persistent_cache_.Erase(it); |
| 749 } else { | 854 } else { |
| 750 ++it; | 855 ++it; |
| 751 } | 856 } |
| 752 | 857 |
| 753 if (CanFitSize(required_size) && !ExceedsPreferredCount()) | 858 if (CanFitSize(required_size) && !ExceedsPreferredCount()) |
| 754 return true; | 859 return true; |
| 755 } | 860 } |
| 756 | 861 |
| 757 // Preferred count is only used as a guideline when triming the cache. Allow | 862 // Preferred count is only used as a guideline when triming the cache. Allow |
| 758 // new elements to be added as long as we are below our size limit. | 863 // new elements to be added as long as we are below our size limit. |
| 759 return CanFitSize(required_size); | 864 return CanFitSize(required_size); |
| 760 } | 865 } |
| 761 | 866 |
| 762 bool GpuImageDecodeController::CanFitSize(size_t size) const { | 867 bool GpuImageDecodeController::CanFitSize(size_t size) const { |
| 763 lock_.AssertAcquired(); | 868 lock_.AssertAcquired(); |
| 764 | 869 |
| 765 base::CheckedNumeric<uint32_t> new_size(bytes_used_); | 870 base::CheckedNumeric<uint32_t> new_size(bytes_used_); |
| 766 new_size += size; | 871 new_size += size; |
| 767 return new_size.IsValid() && new_size.ValueOrDie() <= cached_bytes_limit_; | 872 return new_size.IsValid() && new_size.ValueOrDie() <= cached_bytes_limit_; |
| 768 } | 873 } |
| 769 | 874 |
| 770 bool GpuImageDecodeController::ExceedsPreferredCount() const { | 875 bool GpuImageDecodeController::ExceedsPreferredCount() const { |
| 771 lock_.AssertAcquired(); | 876 lock_.AssertAcquired(); |
| 772 | 877 |
| 773 return image_data_.size() > cached_items_limit_; | 878 return persistent_cache_.size() > cached_items_limit_; |
| 774 } | 879 } |
| 775 | 880 |
| 776 void GpuImageDecodeController::DecodeImageIfNecessary( | 881 void GpuImageDecodeController::DecodeImageIfNecessary( |
| 777 const DrawImage& draw_image, | 882 const DrawImage& draw_image, |
| 778 ImageData* image_data) { | 883 ImageData* image_data) { |
| 779 lock_.AssertAcquired(); | 884 lock_.AssertAcquired(); |
| 780 | 885 |
| 781 DCHECK_GT(image_data->decode.ref_count, 0u); | 886 DCHECK_GT(image_data->decode.ref_count, 0u); |
| 782 | 887 |
| 783 if (image_data->decode.decode_failure) { | 888 if (image_data->decode.decode_failure) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 800 | 905 |
| 801 image_data->decode.ResetData(); | 906 image_data->decode.ResetData(); |
| 802 std::unique_ptr<base::DiscardableMemory> backing_memory; | 907 std::unique_ptr<base::DiscardableMemory> backing_memory; |
| 803 { | 908 { |
| 804 base::AutoUnlock unlock(lock_); | 909 base::AutoUnlock unlock(lock_); |
| 805 switch (image_data->mode) { | 910 switch (image_data->mode) { |
| 806 case DecodedDataMode::CPU: { | 911 case DecodedDataMode::CPU: { |
| 807 backing_memory = | 912 backing_memory = |
| 808 base::DiscardableMemoryAllocator::GetInstance() | 913 base::DiscardableMemoryAllocator::GetInstance() |
| 809 ->AllocateLockedDiscardableMemory(image_data->size); | 914 ->AllocateLockedDiscardableMemory(image_data->size); |
| 810 SkImageInfo image_info = CreateImageInfoForDrawImage(draw_image); | 915 SkImageInfo image_info = CreateImageInfoForDrawImage( |
| 811 if (!draw_image.image()->readPixels(image_info, backing_memory->data(), | 916 draw_image, image_data->pre_scale_mip_level); |
| 812 image_info.minRowBytes(), 0, 0, | 917 // In order to match GPU scaling quality (which uses mip-maps at high |
| 813 SkImage::kDisallow_CachingHint)) { | 918 // quality), we want to use at most medium filter quality for the |
| 919 // scale. | |
| 920 SkFilterQuality scale_quality = | |
| 921 std::max(kMedium_SkFilterQuality, draw_image.filter_quality()); | |
| 922 SkPixmap image_pixmap(image_info, backing_memory->data(), | |
| 923 image_info.minRowBytes()); | |
| 924 // Note that scalePixels falls back to readPixels if the sale is 1x, so | |
| 925 // no need to special case that as an optimization. | |
| 926 if (!draw_image.image()->scalePixels(image_pixmap, scale_quality, | |
| 927 SkImage::kDisallow_CachingHint)) { | |
| 814 backing_memory.reset(); | 928 backing_memory.reset(); |
| 815 } | 929 } |
| 816 break; | 930 break; |
| 817 } | 931 } |
| 818 case DecodedDataMode::GPU: { | 932 case DecodedDataMode::GPU: { |
| 819 backing_memory = | 933 backing_memory = |
| 820 base::DiscardableMemoryAllocator::GetInstance() | 934 base::DiscardableMemoryAllocator::GetInstance() |
| 821 ->AllocateLockedDiscardableMemory(image_data->size); | 935 ->AllocateLockedDiscardableMemory(image_data->size); |
| 822 auto params = ParamsFromDrawImage(draw_image); | 936 auto params = |
| 937 ParamsFromDrawImage(draw_image, image_data->pre_scale_mip_level); | |
| 823 if (!draw_image.image()->getDeferredTextureImageData( | 938 if (!draw_image.image()->getDeferredTextureImageData( |
| 824 *context_threadsafe_proxy_.get(), ¶ms, 1, | 939 *context_threadsafe_proxy_.get(), ¶ms, 1, |
| 825 backing_memory->data())) { | 940 backing_memory->data())) { |
| 826 backing_memory.reset(); | 941 backing_memory.reset(); |
| 827 } | 942 } |
| 828 break; | 943 break; |
| 829 } | 944 } |
| 830 } | 945 } |
| 831 } | 946 } |
| 832 | 947 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 868 // We are about to upload a new image and are holding the context lock. | 983 // We are about to upload a new image and are holding the context lock. |
| 869 // Ensure that any images which have been marked for deletion are actually | 984 // Ensure that any images which have been marked for deletion are actually |
| 870 // cleaned up so we don't exceed our memory limit during this upload. | 985 // cleaned up so we don't exceed our memory limit during this upload. |
| 871 DeletePendingImages(); | 986 DeletePendingImages(); |
| 872 | 987 |
| 873 sk_sp<SkImage> uploaded_image; | 988 sk_sp<SkImage> uploaded_image; |
| 874 { | 989 { |
| 875 base::AutoUnlock unlock(lock_); | 990 base::AutoUnlock unlock(lock_); |
| 876 switch (image_data->mode) { | 991 switch (image_data->mode) { |
| 877 case DecodedDataMode::CPU: { | 992 case DecodedDataMode::CPU: { |
| 878 SkImageInfo image_info = CreateImageInfoForDrawImage(draw_image); | 993 SkImageInfo image_info = CreateImageInfoForDrawImage( |
| 994 draw_image, image_data->pre_scale_mip_level); | |
| 879 SkPixmap pixmap(image_info, image_data->decode.data()->data(), | 995 SkPixmap pixmap(image_info, image_data->decode.data()->data(), |
| 880 image_info.minRowBytes()); | 996 image_info.minRowBytes()); |
| 881 uploaded_image = | 997 uploaded_image = |
| 882 SkImage::MakeFromRaster(pixmap, [](const void*, void*) {}, nullptr); | 998 SkImage::MakeFromRaster(pixmap, [](const void*, void*) {}, nullptr); |
| 883 break; | 999 break; |
| 884 } | 1000 } |
| 885 case DecodedDataMode::GPU: { | 1001 case DecodedDataMode::GPU: { |
| 886 uploaded_image = SkImage::MakeFromDeferredTextureImageData( | 1002 uploaded_image = SkImage::MakeFromDeferredTextureImageData( |
| 887 context_->GrContext(), image_data->decode.data()->data(), | 1003 context_->GrContext(), image_data->decode.data()->data(), |
| 888 SkBudgeted::kNo); | 1004 SkBudgeted::kNo); |
| 889 break; | 1005 break; |
| 890 } | 1006 } |
| 891 } | 1007 } |
| 892 } | 1008 } |
| 893 image_data->decode.mark_used(); | 1009 image_data->decode.mark_used(); |
| 894 DCHECK(uploaded_image); | 1010 DCHECK(uploaded_image); |
| 895 | 1011 |
| 896 // At-raster may have decoded this while we were unlocked. If so, ignore our | 1012 // At-raster may have decoded this while we were unlocked. If so, ignore our |
| 897 // result. | 1013 // result. |
| 898 if (!image_data->upload.image()) | 1014 if (!image_data->upload.image()) |
| 899 image_data->upload.SetImage(std::move(uploaded_image)); | 1015 image_data->upload.SetImage(std::move(uploaded_image)); |
| 900 } | 1016 } |
| 901 | 1017 |
| 902 std::unique_ptr<GpuImageDecodeController::ImageData> | 1018 scoped_refptr<GpuImageDecodeController::ImageData> |
| 903 GpuImageDecodeController::CreateImageData(const DrawImage& draw_image) { | 1019 GpuImageDecodeController::CreateImageData(const DrawImage& draw_image) { |
| 904 lock_.AssertAcquired(); | 1020 lock_.AssertAcquired(); |
| 905 | 1021 |
| 906 DecodedDataMode mode; | 1022 DecodedDataMode mode; |
| 907 SkImageInfo info = CreateImageInfoForDrawImage(draw_image); | 1023 int pre_scale_mip_level = CalculatePreScaleMipLevel(draw_image); |
| 908 SkImage::DeferredTextureImageUsageParams params = | 1024 SkImage::DeferredTextureImageUsageParams params = |
| 909 ParamsFromDrawImage(draw_image); | 1025 ParamsFromDrawImage(draw_image, pre_scale_mip_level); |
| 910 size_t data_size = draw_image.image()->getDeferredTextureImageData( | 1026 size_t data_size = draw_image.image()->getDeferredTextureImageData( |
| 911 *context_threadsafe_proxy_.get(), ¶ms, 1, nullptr); | 1027 *context_threadsafe_proxy_.get(), ¶ms, 1, nullptr); |
| 912 | 1028 |
| 913 if (data_size == 0) { | 1029 if (data_size == 0) { |
| 914 // Can't upload image, too large or other failure. Try to use SW fallback. | 1030 // Can't upload image, too large or other failure. Try to use SW fallback. |
| 915 data_size = info.getSafeSize(info.minRowBytes()); | 1031 SkImageInfo image_info = |
| 1032 CreateImageInfoForDrawImage(draw_image, pre_scale_mip_level); | |
| 1033 data_size = image_info.getSafeSize(image_info.minRowBytes()); | |
| 916 mode = DecodedDataMode::CPU; | 1034 mode = DecodedDataMode::CPU; |
| 917 } else { | 1035 } else { |
| 918 mode = DecodedDataMode::GPU; | 1036 mode = DecodedDataMode::GPU; |
| 919 } | 1037 } |
| 920 | 1038 |
| 921 return base::WrapUnique(new ImageData(mode, data_size)); | 1039 return make_scoped_refptr(new ImageData(mode, data_size, pre_scale_mip_level, |
| 1040 draw_image.filter_quality())); | |
| 922 } | 1041 } |
| 923 | 1042 |
| 924 void GpuImageDecodeController::DeletePendingImages() { | 1043 void GpuImageDecodeController::DeletePendingImages() { |
| 925 context_->GetLock()->AssertAcquired(); | 1044 context_->GetLock()->AssertAcquired(); |
| 926 lock_.AssertAcquired(); | 1045 lock_.AssertAcquired(); |
| 927 images_pending_deletion_.clear(); | 1046 images_pending_deletion_.clear(); |
| 928 } | 1047 } |
| 929 | 1048 |
| 930 SkImageInfo GpuImageDecodeController::CreateImageInfoForDrawImage( | 1049 SkImageInfo GpuImageDecodeController::CreateImageInfoForDrawImage( |
| 1050 const DrawImage& draw_image, | |
| 1051 int pre_scale_mip_level) const { | |
| 1052 DrawImage scaled_draw_image = draw_image.ApplyScale( | |
| 1053 CalculatePreScaleFactor(draw_image, pre_scale_mip_level)); | |
| 1054 return SkImageInfo::Make( | |
| 1055 scaled_draw_image.image()->width() * scaled_draw_image.scale().width(), | |
| 1056 scaled_draw_image.image()->height() * scaled_draw_image.scale().height(), | |
| 1057 ResourceFormatToClosestSkColorType(format_), kPremul_SkAlphaType); | |
| 1058 } | |
| 1059 | |
| 1060 // Tries to find an ImageData that can be used to draw the provided | |
| 1061 // |draw_image|. First looks for an exact entry in our |in_use_cache_|. If one | |
| 1062 // cannot be found, it looks for a compatible entry in our |persistent_cache_|. | |
| 1063 GpuImageDecodeController::ImageData* | |
| 1064 GpuImageDecodeController::GetImageDataForDrawImage( | |
| 1065 const DrawImage& draw_image) { | |
| 1066 lock_.AssertAcquired(); | |
| 1067 { | |
| 1068 auto found = in_use_cache_.find(GenerateInUseCacheKey(draw_image)); | |
|
vmpstr
2016/06/21 20:07:08
I prefer if you just name a variable a different t
ericrk
2016/06/22 18:56:37
Done.
| |
| 1069 if (found != in_use_cache_.end()) { | |
|
vmpstr
2016/06/21 20:07:08
no braces
ericrk
2016/06/22 18:56:38
Done.
| |
| 1070 return found->second.image_data.get(); | |
| 1071 } | |
| 1072 } | |
| 1073 { | |
| 1074 auto found = persistent_cache_.Get(draw_image.image()->uniqueID()); | |
| 1075 if (found != persistent_cache_.end()) { | |
| 1076 if (IsCompatibleWithDrawImage(found->second.get(), draw_image)) { | |
| 1077 return found->second.get(); | |
| 1078 } else { | |
| 1079 found->second->is_orphaned = true; | |
| 1080 // Call RefCountChanged before erasing the orphaned task to ensure | |
| 1081 // that we clean up any SkImage safely. | |
| 1082 RefCountChanged(found->second.get()); | |
|
vmpstr
2016/06/21 20:07:07
Where did we change the ref count? Can this be cur
ericrk
2016/06/22 18:56:37
RefCountChanged really now means "ownership change
| |
| 1083 persistent_cache_.Erase(found); | |
| 1084 } | |
| 1085 } | |
| 1086 } | |
| 1087 | |
| 1088 return nullptr; | |
| 1089 } | |
| 1090 | |
| 1091 // Determines if we can draw the provided |draw_image| using the provided | |
| 1092 // |image_data|. This is true if the |image_data| is not scaled, or if it | |
| 1093 // is scaled at an equal or larger scale and equal or larger quality to | |
| 1094 // the provided |draw_image|. | |
| 1095 bool GpuImageDecodeController::IsCompatibleWithDrawImage( | |
| 1096 const ImageData* image_data, | |
| 931 const DrawImage& draw_image) const { | 1097 const DrawImage& draw_image) const { |
| 932 return SkImageInfo::Make( | 1098 bool not_scaled = image_data->pre_scale_mip_level == 0; |
|
vmpstr
2016/06/21 20:07:08
can you name bools in the positive? ie "is_scaled"
ericrk
2016/06/22 18:56:38
Done.
| |
| 933 draw_image.image()->width(), draw_image.image()->height(), | 1099 bool scale_is_compatible = |
| 934 ResourceFormatToClosestSkColorType(format_), kPremul_SkAlphaType); | 1100 CalculatePreScaleMipLevel(draw_image) >= image_data->pre_scale_mip_level; |
| 1101 bool quality_is_compatible = | |
| 1102 draw_image.filter_quality() <= image_data->pre_scale_filter_quality; | |
| 1103 return not_scaled || (scale_is_compatible && quality_is_compatible); | |
| 1104 } | |
| 1105 | |
| 1106 size_t GpuImageDecodeController::GetDrawImageSizeForTesting( | |
| 1107 const DrawImage& image) { | |
| 1108 base::AutoLock lock(lock_); | |
| 1109 scoped_refptr<ImageData> data = CreateImageData(image); | |
| 1110 return data->size; | |
| 935 } | 1111 } |
| 936 | 1112 |
| 937 void GpuImageDecodeController::SetImageDecodingFailedForTesting( | 1113 void GpuImageDecodeController::SetImageDecodingFailedForTesting( |
| 938 const DrawImage& image) { | 1114 const DrawImage& image) { |
| 939 base::AutoLock lock(lock_); | 1115 base::AutoLock lock(lock_); |
| 940 auto found = image_data_.Peek(image.image()->uniqueID()); | 1116 auto found = persistent_cache_.Peek(image.image()->uniqueID()); |
| 941 DCHECK(found != image_data_.end()); | 1117 DCHECK(found != persistent_cache_.end()); |
| 942 ImageData* image_data = found->second.get(); | 1118 ImageData* image_data = found->second.get(); |
| 943 image_data->decode.decode_failure = true; | 1119 image_data->decode.decode_failure = true; |
| 944 } | 1120 } |
| 945 | 1121 |
| 946 bool GpuImageDecodeController::DiscardableIsLockedForTesting( | 1122 bool GpuImageDecodeController::DiscardableIsLockedForTesting( |
| 947 const DrawImage& image) { | 1123 const DrawImage& image) { |
| 948 base::AutoLock lock(lock_); | 1124 base::AutoLock lock(lock_); |
| 949 auto found = image_data_.Peek(image.image()->uniqueID()); | 1125 auto found = persistent_cache_.Peek(image.image()->uniqueID()); |
| 950 DCHECK(found != image_data_.end()); | 1126 DCHECK(found != persistent_cache_.end()); |
| 951 ImageData* image_data = found->second.get(); | 1127 ImageData* image_data = found->second.get(); |
| 952 return image_data->decode.is_locked(); | 1128 return image_data->decode.is_locked(); |
| 953 } | 1129 } |
| 954 | 1130 |
| 955 } // namespace cc | 1131 } // namespace cc |
| OLD | NEW |