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

Side by Side Diff: cc/tiles/gpu_image_decode_controller.cc

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

Powered by Google App Engine
This is Rietveld 408576698