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

Unified 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: comments Created 4 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: cc/tiles/gpu_image_decode_controller.cc
diff --git a/cc/tiles/gpu_image_decode_controller.cc b/cc/tiles/gpu_image_decode_controller.cc
index 8a76daf9cd20278e89c9aed82e6aeb61f9fe6846..ada6a91e081e540ccdeea8d27bfdb13b027aab55 100644
--- a/cc/tiles/gpu_image_decode_controller.cc
+++ b/cc/tiles/gpu_image_decode_controller.cc
@@ -4,6 +4,7 @@
#include "cc/tiles/gpu_image_decode_controller.h"
+#include "base/debug/stack_trace.h"
#include "base/memory/discardable_memory_allocator.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
@@ -14,6 +15,7 @@
#include "cc/output/context_provider.h"
#include "cc/raster/tile_task.h"
#include "cc/resources/resource_format_utils.h"
+#include "cc/tiles/mipmap_util.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu_image_decode_controller.h"
@@ -46,16 +48,47 @@ bool SkipImage(const DrawImage& draw_image) {
}
SkImage::DeferredTextureImageUsageParams ParamsFromDrawImage(
- const DrawImage& draw_image) {
+ const DrawImage& draw_image,
+ int pre_scale_mip_level) {
SkImage::DeferredTextureImageUsageParams params;
params.fMatrix = draw_image.matrix();
params.fQuality = draw_image.filter_quality();
+ params.fPreScaleMipLevel = pre_scale_mip_level;
return params;
}
+// Calculate the mp level to pre-scale the image to before uploading. We use mip
+// levels rather than exact scales to increase re-use of scaled images.
+int CalculatePreScaleMipLevel(const DrawImage& draw_image) {
+ gfx::Size base_size(draw_image.image()->width(),
+ draw_image.image()->height());
+ // Ceil our scaled size so that the mip map generated is guaranteed to be
+ // larger.
+ gfx::Size scaled_size = gfx::ScaleToCeiledSize(
+ base_size, draw_image.scale().width(), draw_image.scale().height());
+
+ return MipMapUtil::GetLevelForSize(base_size, scaled_size);
+}
+
+SkSize CalculatePreScaleFactor(const DrawImage& draw_image, int mip_level) {
+ gfx::Size base_size(draw_image.image()->width(),
+ draw_image.image()->height());
+ return MipMapUtil::GetScaleAdjustmentForLevel(base_size, mip_level);
+}
+
} // namespace
+GpuImageDecodeController::ImageDataForDrawImageEntry::
+ ImageDataForDrawImageEntry(const scoped_refptr<ImageData>& image_data)
+ : image_data(image_data) {}
+GpuImageDecodeController::ImageDataForDrawImageEntry::
+ ImageDataForDrawImageEntry(const ImageDataForDrawImageEntry&) = default;
+GpuImageDecodeController::ImageDataForDrawImageEntry::
+ ImageDataForDrawImageEntry(ImageDataForDrawImageEntry&&) = default;
+GpuImageDecodeController::ImageDataForDrawImageEntry::
+ ~ImageDataForDrawImageEntry() = default;
+
// Task which decodes an image and stores the result in discardable memory.
// This task does not use GPU resources and can be run on any thread.
class ImageDecodeTaskImpl : public TileTask {
@@ -231,11 +264,26 @@ void GpuImageDecodeController::UploadedImageData::ReportUsageStats() const {
usage_stats_.first_ref_wasted);
}
-GpuImageDecodeController::ImageData::ImageData(DecodedDataMode mode,
- size_t size)
- : mode(mode), size(size) {}
-
-GpuImageDecodeController::ImageData::~ImageData() = default;
+GpuImageDecodeController::ImageData::ImageData(
+ DecodedDataMode mode,
+ size_t size,
+ int pre_scale_mip_level,
+ SkFilterQuality pre_scale_filter_quality)
+ : mode(mode),
+ size(size),
+ pre_scale_mip_level(pre_scale_mip_level),
+ pre_scale_filter_quality(pre_scale_filter_quality) {}
+
+GpuImageDecodeController::ImageData::~ImageData() {
+ // We should never delete ImageData while it is in use or before it has been
+ // cleaned up.
+ DCHECK_EQ(0u, upload.ref_count);
+ DCHECK_EQ(0u, decode.ref_count);
+ DCHECK_EQ(false, decode.is_locked());
+ // This should always be cleaned up before deleting the image, as it needs to
+ // be freed with the GL context lock held.
+ DCHECK(!upload.image());
+}
GpuImageDecodeController::GpuImageDecodeController(ContextProvider* context,
ResourceFormat decode_format,
@@ -285,10 +333,8 @@ bool GpuImageDecodeController::GetTaskForImageAndRef(
base::AutoLock lock(lock_);
const auto image_id = draw_image.image()->uniqueID();
-
- auto found = image_data_.Get(image_id);
- if (found != image_data_.end()) {
- ImageData* image_data = found->second.get();
+ ImageData* image_data = GetImageDataForDrawImage(draw_image);
+ if (image_data) {
if (image_data->is_at_raster) {
// Image is at-raster, just return, this usage will be at-raster as well.
*task = nullptr;
@@ -307,32 +353,30 @@ bool GpuImageDecodeController::GetTaskForImageAndRef(
*task = nullptr;
return true;
}
- }
- // We didn't have a pre-uploaded image, so we need an upload task. Try to find
- // an existing one.
- scoped_refptr<TileTask>& existing_task =
- pending_image_upload_tasks_[image_id];
- if (existing_task) {
- // We had an existing upload task, ref the image and return the task.
- RefImage(draw_image);
- *task = existing_task;
- return true;
+ // We didn't have a pre-uploaded image, so we need an upload task. Try to
+ // find an existing one.
+ auto existing_task = pending_image_upload_tasks_.find(
+ GenerateTaskKeyForDrawImage(draw_image));
+ if (existing_task != pending_image_upload_tasks_.end()) {
+ // We had an existing upload task, ref the image and return the task.
+ RefImage(draw_image);
+ *task = existing_task->second;
+ return true;
+ } else {
+ }
}
// We will be creating a new upload task. If necessary, create a placeholder
// ImageData to hold the result.
- std::unique_ptr<ImageData> new_data;
- ImageData* data;
- if (found == image_data_.end()) {
+ scoped_refptr<ImageData> new_data;
+ if (!image_data) {
new_data = CreateImageData(draw_image);
- data = new_data.get();
- } else {
- data = found->second.get();
+ image_data = new_data.get();
}
// Ensure that the image we're about to decode/upload will fit in memory.
- if (!EnsureCapacity(data->size)) {
+ if (!EnsureCapacity(image_data->size)) {
// Image will not fit, do an at-raster decode.
*task = nullptr;
return false;
@@ -341,19 +385,20 @@ bool GpuImageDecodeController::GetTaskForImageAndRef(
// If we had to create new image data, add it to our map now that we know it
// will fit.
if (new_data)
- found = image_data_.Put(image_id, std::move(new_data));
+ image_data_.Put(image_id, std::move(new_data));
// Ref image and create a upload and decode tasks. We will release this ref
// in UploadTaskCompleted.
RefImage(draw_image);
- existing_task = make_scoped_refptr(new ImageUploadTaskImpl(
+ *task = make_scoped_refptr(new ImageUploadTaskImpl(
this, draw_image, GetImageDecodeTaskAndRef(draw_image, tracing_info),
tracing_info));
+ pending_image_upload_tasks_.insert(
+ std::make_pair(GenerateTaskKeyForDrawImage(draw_image), *task));
// Ref the image again - this ref is owned by the caller, and it is their
// responsibility to release it by calling UnrefImage.
RefImage(draw_image);
- *task = existing_task;
return true;
}
@@ -374,16 +419,14 @@ DecodedDrawImage GpuImageDecodeController::GetDecodedImageForDraw(
TRACE_EVENT0("cc", "GpuImageDecodeController::GetDecodedImageForDraw");
base::AutoLock lock(lock_);
- const uint32_t unique_id = draw_image.image()->uniqueID();
- auto found = image_data_.Peek(unique_id);
- if (found == image_data_.end()) {
+ ImageData* image_data = GetImageDataForDrawImage(draw_image);
+ if (!image_data) {
// We didn't find the image, create a new entry.
auto data = CreateImageData(draw_image);
- found = image_data_.Put(unique_id, std::move(data));
+ image_data = data.get();
+ image_data_.Put(draw_image.image()->uniqueID(), std::move(data));
}
- ImageData* image_data = found->second.get();
-
if (!image_data->upload.budgeted) {
// If image data is not budgeted by this point, it is at-raster.
image_data->is_at_raster = true;
@@ -406,7 +449,9 @@ DecodedDrawImage GpuImageDecodeController::GetDecodedImageForDraw(
image_data->upload.mark_used();
DCHECK(image || image_data->decode.decode_failure);
- DecodedDrawImage decoded_draw_image(std::move(image),
+ SkSize scale_factor =
+ CalculatePreScaleFactor(draw_image, image_data->pre_scale_mip_level);
+ DecodedDrawImage decoded_draw_image(std::move(image), SkSize(), scale_factor,
draw_image.filter_quality());
decoded_draw_image.set_at_raster_decode(image_data->is_at_raster);
return decoded_draw_image;
@@ -423,6 +468,7 @@ void GpuImageDecodeController::DrawWithImageFinished(
return;
base::AutoLock lock(lock_);
+ TRACE_EVENT0("cc", "GpuImageDecodeController::DrawWithImageFinished");
UnrefImageInternal(draw_image);
// We are mid-draw and holding the context lock, ensure we clean up any
@@ -516,26 +562,26 @@ bool GpuImageDecodeController::OnMemoryDump(
void GpuImageDecodeController::DecodeImage(const DrawImage& draw_image) {
base::AutoLock lock(lock_);
- auto found = image_data_.Peek(draw_image.image()->uniqueID());
- DCHECK(found != image_data_.end());
- DCHECK(!found->second->is_at_raster);
- DecodeImageIfNecessary(draw_image, found->second.get());
+ ImageData* image_data = GetImageDataForDrawImage(draw_image);
+ DCHECK(image_data);
+ DCHECK(!image_data->is_at_raster);
+ DecodeImageIfNecessary(draw_image, image_data);
}
void GpuImageDecodeController::UploadImage(const DrawImage& draw_image) {
ContextProvider::ScopedContextLock context_lock(context_);
base::AutoLock lock(lock_);
- auto found = image_data_.Peek(draw_image.image()->uniqueID());
- DCHECK(found != image_data_.end());
- DCHECK(!found->second->is_at_raster);
- UploadImageIfNecessary(draw_image, found->second.get());
+ ImageData* image_data = GetImageDataForDrawImage(draw_image);
+ DCHECK(image_data);
+ DCHECK(!image_data->is_at_raster);
+ UploadImageIfNecessary(draw_image, image_data);
}
void GpuImageDecodeController::OnImageDecodeTaskCompleted(
const DrawImage& draw_image) {
base::AutoLock lock(lock_);
// Decode task is complete, remove it from our list of pending tasks.
- pending_image_decode_tasks_.erase(draw_image.image()->uniqueID());
+ pending_image_decode_tasks_.erase(GenerateTaskKeyForDrawImage(draw_image));
// While the decode task is active, we keep a ref on the decoded data.
// Release that ref now.
@@ -546,7 +592,7 @@ void GpuImageDecodeController::OnImageUploadTaskCompleted(
const DrawImage& draw_image) {
base::AutoLock lock(lock_);
// Upload task is complete, remove it from our list of pending tasks.
- pending_image_upload_tasks_.erase(draw_image.image()->uniqueID());
+ pending_image_upload_tasks_.erase(GenerateTaskKeyForDrawImage(draw_image));
// While the upload task is active, we keep a ref on both the image it will be
// populating, as well as the decode it needs to populate it. Release these
@@ -562,24 +608,22 @@ scoped_refptr<TileTask> GpuImageDecodeController::GetImageDecodeTaskAndRef(
const TracingInfo& tracing_info) {
lock_.AssertAcquired();
- const uint32_t image_id = draw_image.image()->uniqueID();
-
// This ref is kept alive while an upload task may need this decode. We
// release this ref in UploadTaskCompleted.
RefImageDecode(draw_image);
- auto found = image_data_.Peek(image_id);
- if (found != image_data_.end() && found->second->decode.is_locked()) {
+ ImageData* image_data = GetImageDataForDrawImage(draw_image);
+ if (image_data && image_data->decode.is_locked()) {
// We should never be creating a decode task for an at raster image.
- DCHECK(!found->second->is_at_raster);
+ DCHECK(!image_data->is_at_raster);
// We should never be creating a decode for an already-uploaded image.
- DCHECK(!found->second->upload.image());
+ DCHECK(!image_data->upload.image());
return nullptr;
}
// We didn't have an existing locked image, create a task to lock or decode.
scoped_refptr<TileTask>& existing_task =
- pending_image_decode_tasks_[image_id];
+ pending_image_decode_tasks_[GenerateTaskKeyForDrawImage(draw_image)];
if (!existing_task) {
// Ref image decode and create a decode task. This ref will be released in
// DecodeTaskCompleted.
@@ -592,38 +636,68 @@ scoped_refptr<TileTask> GpuImageDecodeController::GetImageDecodeTaskAndRef(
void GpuImageDecodeController::RefImageDecode(const DrawImage& draw_image) {
lock_.AssertAcquired();
- auto found = image_data_.Peek(draw_image.image()->uniqueID());
- DCHECK(found != image_data_.end());
- ++found->second->decode.ref_count;
- RefCountChanged(found->second.get());
+ auto found =
+ image_data_for_draw_image_.find(GenerateDrawImageKey(draw_image));
+ DCHECK(found != image_data_for_draw_image_.end());
+ ++found->second.ref_count;
+ ++found->second.image_data->decode.ref_count;
+ RefCountChanged(found->second.image_data.get());
}
void GpuImageDecodeController::UnrefImageDecode(const DrawImage& draw_image) {
lock_.AssertAcquired();
- auto found = image_data_.Peek(draw_image.image()->uniqueID());
- DCHECK(found != image_data_.end());
- DCHECK_GT(found->second->decode.ref_count, 0u);
- --found->second->decode.ref_count;
- RefCountChanged(found->second.get());
+ auto found =
+ image_data_for_draw_image_.find(GenerateDrawImageKey(draw_image));
+ DCHECK(found != image_data_for_draw_image_.end());
+ DCHECK_GT(found->second.image_data->decode.ref_count, 0u);
+ DCHECK_GT(found->second.ref_count, 0u);
+ --found->second.ref_count;
+ --found->second.image_data->decode.ref_count;
+ RefCountChanged(found->second.image_data.get());
+ if (found->second.ref_count == 0u) {
+ image_data_for_draw_image_.erase(found);
+ }
}
void GpuImageDecodeController::RefImage(const DrawImage& draw_image) {
lock_.AssertAcquired();
- auto found = image_data_.Peek(draw_image.image()->uniqueID());
- DCHECK(found != image_data_.end());
- ++found->second->upload.ref_count;
- RefCountChanged(found->second.get());
+ auto found =
+ image_data_for_draw_image_.find(GenerateDrawImageKey(draw_image));
+
+ // If no secondary cache entry was found for the given |draw_image|, then
+ // the draw_image only exists in the primary cache. Create a secondary
+ // cache entry now.
+ if (found == image_data_for_draw_image_.end()) {
+ auto found_image = image_data_.Peek(draw_image.image()->uniqueID());
+ DCHECK(found_image != image_data_.end());
+ DCHECK(found_image->second->pre_scale_mip_level <=
+ CalculatePreScaleMipLevel(draw_image));
+ found = image_data_for_draw_image_
+ .insert(std::make_pair(
+ GenerateDrawImageKey(draw_image),
+ ImageDataForDrawImageEntry(found_image->second)))
+ .first;
+ }
+
+ DCHECK(found != image_data_for_draw_image_.end());
+ ++found->second.ref_count;
+ ++found->second.image_data->upload.ref_count;
+ RefCountChanged(found->second.image_data.get());
}
void GpuImageDecodeController::UnrefImageInternal(const DrawImage& draw_image) {
lock_.AssertAcquired();
- auto found = image_data_.Peek(draw_image.image()->uniqueID());
- DCHECK(found != image_data_.end());
- DCHECK_GT(found->second->upload.ref_count, 0u);
- --found->second->upload.ref_count;
- if (found->second->upload.ref_count == 0)
- found->second->upload.notify_ref_reached_zero();
- RefCountChanged(found->second.get());
+ auto found =
+ image_data_for_draw_image_.find(GenerateDrawImageKey(draw_image));
+ DCHECK(found != image_data_for_draw_image_.end());
+ DCHECK_GT(found->second.image_data->upload.ref_count, 0u);
+ DCHECK_GT(found->second.ref_count, 0u);
+ --found->second.ref_count;
+ --found->second.image_data->upload.ref_count;
+ RefCountChanged(found->second.image_data.get());
+ if (found->second.ref_count == 0u) {
+ image_data_for_draw_image_.erase(found);
+ }
}
// Called any time an image or decode ref count changes. Takes care of any
@@ -634,6 +708,12 @@ void GpuImageDecodeController::RefCountChanged(ImageData* image_data) {
bool has_any_refs =
image_data->upload.ref_count > 0 || image_data->decode.ref_count > 0;
+ // Don't keep around orphaned images.
+ if (image_data->is_orphaned && !has_any_refs) {
+ images_pending_deletion_.push_back(std::move(image_data->upload.image()));
+ image_data->upload.SetImage(nullptr);
+ }
+
// Don't keep CPU images if they are unused, these images can be recreated by
// re-locking discardable (rather than requiring a full upload like GPU
// images).
@@ -807,10 +887,21 @@ void GpuImageDecodeController::DecodeImageIfNecessary(
backing_memory =
base::DiscardableMemoryAllocator::GetInstance()
->AllocateLockedDiscardableMemory(image_data->size);
- SkImageInfo image_info = CreateImageInfoForDrawImage(draw_image);
- if (!draw_image.image()->readPixels(image_info, backing_memory->data(),
- image_info.minRowBytes(), 0, 0,
- SkImage::kDisallow_CachingHint)) {
+ DrawImage scaled_draw_image =
+ draw_image.ApplyScale(CalculatePreScaleFactor(
+ draw_image, image_data->pre_scale_mip_level));
+ SkImageInfo scaled_image_info =
+ CreateImageInfoForDrawImage(scaled_draw_image);
+ // We are doing a software scale of the image before handing off to the
+ // GPU. In order to match GPU scaling quality (which uses mip-maps at
+ // high quality), we want to use at most medium filter quality for the
+ // scale.
+ SkFilterQuality scale_quality =
+ std::max(kMedium_SkFilterQuality, draw_image.filter_quality());
+ SkPixmap full_image_pixmap(scaled_image_info, backing_memory->data(),
+ scaled_image_info.minRowBytes());
+ if (!draw_image.image()->scalePixels(full_image_pixmap, scale_quality,
+ SkImage::kDisallow_CachingHint)) {
backing_memory.reset();
}
break;
@@ -819,7 +910,8 @@ void GpuImageDecodeController::DecodeImageIfNecessary(
backing_memory =
base::DiscardableMemoryAllocator::GetInstance()
->AllocateLockedDiscardableMemory(image_data->size);
- auto params = ParamsFromDrawImage(draw_image);
+ auto params =
+ ParamsFromDrawImage(draw_image, image_data->pre_scale_mip_level);
if (!draw_image.image()->getDeferredTextureImageData(
*context_threadsafe_proxy_.get(), &params, 1,
backing_memory->data())) {
@@ -875,9 +967,13 @@ void GpuImageDecodeController::UploadImageIfNecessary(
base::AutoUnlock unlock(lock_);
switch (image_data->mode) {
case DecodedDataMode::CPU: {
- SkImageInfo image_info = CreateImageInfoForDrawImage(draw_image);
- SkPixmap pixmap(image_info, image_data->decode.data()->data(),
- image_info.minRowBytes());
+ DrawImage scaled_draw_image =
+ draw_image.ApplyScale(CalculatePreScaleFactor(
+ draw_image, image_data->pre_scale_mip_level));
+ SkImageInfo scaled_image_info =
+ CreateImageInfoForDrawImage(scaled_draw_image);
+ SkPixmap pixmap(scaled_image_info, image_data->decode.data()->data(),
+ scaled_image_info.minRowBytes());
uploaded_image =
SkImage::MakeFromRaster(pixmap, [](const void*, void*) {}, nullptr);
break;
@@ -899,26 +995,31 @@ void GpuImageDecodeController::UploadImageIfNecessary(
image_data->upload.SetImage(std::move(uploaded_image));
}
-std::unique_ptr<GpuImageDecodeController::ImageData>
+scoped_refptr<GpuImageDecodeController::ImageData>
GpuImageDecodeController::CreateImageData(const DrawImage& draw_image) {
lock_.AssertAcquired();
DecodedDataMode mode;
- SkImageInfo info = CreateImageInfoForDrawImage(draw_image);
+ int pre_scale_mip_level = CalculatePreScaleMipLevel(draw_image);
SkImage::DeferredTextureImageUsageParams params =
- ParamsFromDrawImage(draw_image);
+ ParamsFromDrawImage(draw_image, pre_scale_mip_level);
size_t data_size = draw_image.image()->getDeferredTextureImageData(
*context_threadsafe_proxy_.get(), &params, 1, nullptr);
if (data_size == 0) {
// Can't upload image, too large or other failure. Try to use SW fallback.
- data_size = info.getSafeSize(info.minRowBytes());
+ DrawImage scaled_draw_image = draw_image.ApplyScale(
+ CalculatePreScaleFactor(draw_image, pre_scale_mip_level));
+ SkImageInfo scaled_image_info =
+ CreateImageInfoForDrawImage(scaled_draw_image);
+ data_size = scaled_image_info.getSafeSize(scaled_image_info.minRowBytes());
mode = DecodedDataMode::CPU;
} else {
mode = DecodedDataMode::GPU;
}
- return base::WrapUnique(new ImageData(mode, data_size));
+ return make_scoped_refptr(new ImageData(mode, data_size, pre_scale_mip_level,
+ draw_image.filter_quality()));
}
void GpuImageDecodeController::DeletePendingImages() {
@@ -930,10 +1031,81 @@ void GpuImageDecodeController::DeletePendingImages() {
SkImageInfo GpuImageDecodeController::CreateImageInfoForDrawImage(
const DrawImage& draw_image) const {
return SkImageInfo::Make(
- draw_image.image()->width(), draw_image.image()->height(),
+ draw_image.image()->width() * draw_image.scale().width(),
+ draw_image.image()->height() * draw_image.scale().height(),
ResourceFormatToClosestSkColorType(format_), kPremul_SkAlphaType);
}
+GpuImageDecodeController::ImageData*
+GpuImageDecodeController::GetImageDataForDrawImage(
+ const DrawImage& draw_image) {
+ lock_.AssertAcquired();
+ {
+ auto found =
+ image_data_for_draw_image_.find(GenerateDrawImageKey(draw_image));
+ if (found != image_data_for_draw_image_.end()) {
+ return found->second.image_data.get();
+ }
+ }
+ {
+ auto found = image_data_.Get(draw_image.image()->uniqueID());
+ if (found != image_data_.end()) {
+ if (IsCompatibleWithDrawImage(found->second.get(), draw_image)) {
+ return found->second.get();
+ } else {
+ found->second->is_orphaned = true;
+ // Call RefCountChanged before erasing the orphaned task to ensure
+ // that we clean up any SkImage safely.
+ RefCountChanged(found->second.get());
+ image_data_.Erase(found);
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+bool GpuImageDecodeController::IsCompatibleWithDrawImage(
+ const ImageData* image_data,
+ const DrawImage& draw_image) const {
+ bool not_scaled = image_data->pre_scale_mip_level == 0;
+ bool scale_is_compatible =
+ CalculatePreScaleMipLevel(draw_image) >=
+ image_data->pre_scale_mip_level &&
+ draw_image.filter_quality() <= image_data->pre_scale_filter_quality;
+ return not_scaled || scale_is_compatible;
+}
+
+GpuImageDecodeController::DrawImageKey
+GpuImageDecodeController::GenerateDrawImageKey(
+ const DrawImage& draw_image) const {
+ DrawImageKey key;
+ key.image_id = draw_image.image()->uniqueID();
+ key.mip_level = CalculatePreScaleMipLevel(draw_image);
+ key.quality = draw_image.filter_quality();
+ return key;
+}
+
+GpuImageDecodeController::DrawImageKey
+GpuImageDecodeController::GenerateTaskKeyForDrawImage(
+ const DrawImage& draw_image) {
+ lock_.AssertAcquired();
+ ImageData* image_data = GetImageDataForDrawImage(draw_image);
+ DDCHECK(image_data);
+ DrawImageKey key;
+ key.image_id = draw_image.image()->uniqueID();
+ key.mip_level = image_data->pre_scale_mip_level;
+ key.quality = image_data->pre_scale_filter_quality;
+ return key;
+}
+
+size_t GpuImageDecodeController::GetDrawImageSizeForTesting(
+ const DrawImage& image) {
+ base::AutoLock lock(lock_);
+ scoped_refptr<ImageData> data = CreateImageData(image);
+ return data->size;
+}
+
void GpuImageDecodeController::SetImageDecodingFailedForTesting(
const DrawImage& image) {
base::AutoLock lock(lock_);

Powered by Google App Engine
This is Rietveld 408576698