| 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 1c213d52faa49cff619ce8a9c54e347d42260f67..21c73e9d89b802bf2756a5259b84a192c9667ad1 100644
|
| --- a/cc/tiles/gpu_image_decode_controller.cc
|
| +++ b/cc/tiles/gpu_image_decode_controller.cc
|
| @@ -16,7 +16,6 @@
|
| #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"
|
| @@ -48,94 +47,16 @@
|
| return false;
|
| }
|
|
|
| -// Returns the filter quality to use for scaling the image to upload scale. For
|
| -// GPU raster, medium and high filter quality are identical for downscales.
|
| -// Upload scaling is always a downscale, so cap our filter quality to medium.
|
| -SkFilterQuality CalculateUploadScaleFilterQuality(const DrawImage& draw_image) {
|
| - return std::min(kMedium_SkFilterQuality, draw_image.filter_quality());
|
| -}
|
| -
|
| SkImage::DeferredTextureImageUsageParams ParamsFromDrawImage(
|
| - const DrawImage& draw_image,
|
| - int upload_scale_mip_level) {
|
| + const DrawImage& draw_image) {
|
| SkImage::DeferredTextureImageUsageParams params;
|
| params.fMatrix = draw_image.matrix();
|
| params.fQuality = draw_image.filter_quality();
|
| - params.fPreScaleMipLevel = upload_scale_mip_level;
|
|
|
| return params;
|
| }
|
|
|
| -// Calculate the mip level to upload-scale the image to before uploading. We use
|
| -// mip levels rather than exact scales to increase re-use of scaled images.
|
| -int CalculateUploadScaleMipLevel(const DrawImage& draw_image) {
|
| - // Images which are being clipped will have color-bleeding if scaled.
|
| - // TODO(ericrk): Investigate uploading clipped images to handle this case and
|
| - // provide further optimization. crbug.com/620899
|
| - if (draw_image.src_rect() != draw_image.image()->bounds())
|
| - return 0;
|
| -
|
| - 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. Take the abs of the scale, as mipmap functions don't handle
|
| - // (and aren't impacted by) negative image dimensions.
|
| - gfx::Size scaled_size =
|
| - gfx::ScaleToCeiledSize(base_size, std::abs(draw_image.scale().width()),
|
| - std::abs(draw_image.scale().height()));
|
| -
|
| - return MipMapUtil::GetLevelForSize(base_size, scaled_size);
|
| -}
|
| -
|
| -// Calculates the scale factor which can be used to scale an image to a given
|
| -// mip level.
|
| -SkSize CalculateScaleFactorForMipLevel(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);
|
| -}
|
| -
|
| -// Calculates the size of a given mip level.
|
| -gfx::Size CalculateSizeForMipLevel(const DrawImage& draw_image, int mip_level) {
|
| - gfx::Size base_size(draw_image.image()->width(),
|
| - draw_image.image()->height());
|
| - return MipMapUtil::GetSizeForLevel(base_size, mip_level);
|
| -}
|
| -
|
| -// Generates a uint64_t which uniquely identifies a DrawImage for the purposes
|
| -// of the |in_use_cache_|. The key is generated as follows:
|
| -// ╔══════════════════════╤═══════════╤═══════════╗
|
| -// ║ image_id │ mip_level │ quality ║
|
| -// ╚════════32═bits═══════╧══16═bits══╧══16═bits══╝
|
| -uint64_t GenerateInUseCacheKey(const DrawImage& draw_image) {
|
| - static_assert(
|
| - kLast_SkFilterQuality <= std::numeric_limits<uint16_t>::max(),
|
| - "InUseCacheKey depends on SkFilterQuality fitting in a uint16_t.");
|
| -
|
| - SkFilterQuality filter_quality =
|
| - CalculateUploadScaleFilterQuality(draw_image);
|
| - DCHECK_LE(filter_quality, kLast_SkFilterQuality);
|
| -
|
| - // An image has at most log_2(max(width, height)) mip levels, so given our
|
| - // usage of 32-bit sizes for images, key.mip_level is at most 31.
|
| - int32_t mip_level = CalculateUploadScaleMipLevel(draw_image);
|
| - DCHECK_LT(mip_level, 32);
|
| -
|
| - return (static_cast<uint64_t>(draw_image.image()->uniqueID()) << 32) |
|
| - (mip_level << 16) | filter_quality;
|
| -}
|
| -
|
| } // namespace
|
| -
|
| -GpuImageDecodeController::InUseCacheEntry::InUseCacheEntry(
|
| - scoped_refptr<ImageData> image_data)
|
| - : image_data(std::move(image_data)) {}
|
| -GpuImageDecodeController::InUseCacheEntry::InUseCacheEntry(
|
| - const InUseCacheEntry&) = default;
|
| -GpuImageDecodeController::InUseCacheEntry::InUseCacheEntry(InUseCacheEntry&&) =
|
| - default;
|
| -GpuImageDecodeController::InUseCacheEntry::~InUseCacheEntry() = 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.
|
| @@ -256,12 +177,12 @@
|
| }
|
|
|
| void GpuImageDecodeController::DecodedImageData::ReportUsageStats() const {
|
| - // lock_count │ used │ result state
|
| - // ═══════════╪═══════╪══════════════════
|
| - // 1 │ false │ WASTED_ONCE
|
| - // 1 │ true │ USED_ONCE
|
| - // >1 │ false │ WASTED_RELOCKED
|
| - // >1 │ true │ USED_RELOCKED
|
| + // lock_count | used | result state
|
| + // ===========+=======+==================
|
| + // 1 | false | WASTED_ONCE
|
| + // 1 | true | USED_ONCE
|
| + // >1 | false | WASTED_RELOCKED
|
| + // >1 | true | USED_RELOCKED
|
| // Note that it's important not to reorder the following enums, since the
|
| // numerical values are used in the histogram code.
|
| enum State : int {
|
| @@ -312,33 +233,18 @@
|
| usage_stats_.first_ref_wasted);
|
| }
|
|
|
| -GpuImageDecodeController::ImageData::ImageData(
|
| - DecodedDataMode mode,
|
| - size_t size,
|
| - int upload_scale_mip_level,
|
| - SkFilterQuality upload_scale_filter_quality)
|
| - : mode(mode),
|
| - size(size),
|
| - upload_scale_mip_level(upload_scale_mip_level),
|
| - upload_scale_filter_quality(upload_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::ImageData::ImageData(DecodedDataMode mode,
|
| + size_t size)
|
| + : mode(mode), size(size) {}
|
| +
|
| +GpuImageDecodeController::ImageData::~ImageData() = default;
|
|
|
| GpuImageDecodeController::GpuImageDecodeController(ContextProvider* context,
|
| ResourceFormat decode_format,
|
| size_t max_gpu_image_bytes)
|
| : format_(decode_format),
|
| context_(context),
|
| - persistent_cache_(PersistentCache::NO_AUTO_EVICT),
|
| + image_data_(ImageDataMRUCache::NO_AUTO_EVICT),
|
| cached_items_limit_(kMaxDiscardableItems),
|
| cached_bytes_limit_(max_gpu_image_bytes),
|
| bytes_used_(0),
|
| @@ -381,34 +287,54 @@
|
|
|
| base::AutoLock lock(lock_);
|
| const auto image_id = draw_image.image()->uniqueID();
|
| - ImageData* image_data = GetImageDataForDrawImage(draw_image);
|
| - scoped_refptr<ImageData> new_data;
|
| - if (!image_data) {
|
| - // We need an ImageData, create one now.
|
| - new_data = CreateImageData(draw_image);
|
| - image_data = new_data.get();
|
| - } else if (image_data->is_at_raster) {
|
| - // Image is at-raster, just return, this usage will be at-raster as well.
|
| - *task = nullptr;
|
| - return false;
|
| - } else if (image_data->decode.decode_failure) {
|
| - // We have already tried and failed to decode this image, so just return.
|
| - *task = nullptr;
|
| - return false;
|
| - } else if (image_data->upload.image()) {
|
| - // The image is already uploaded, ref and return.
|
| - RefImage(draw_image);
|
| - *task = nullptr;
|
| - return true;
|
| - } else if (image_data->upload.task) {
|
| +
|
| + auto found = image_data_.Get(image_id);
|
| + if (found != image_data_.end()) {
|
| + ImageData* image_data = found->second.get();
|
| + if (image_data->is_at_raster) {
|
| + // Image is at-raster, just return, this usage will be at-raster as well.
|
| + *task = nullptr;
|
| + return false;
|
| + }
|
| +
|
| + if (image_data->decode.decode_failure) {
|
| + // We have already tried and failed to decode this image, so just return.
|
| + *task = nullptr;
|
| + return false;
|
| + }
|
| +
|
| + if (image_data->upload.image()) {
|
| + // The image is already uploaded, ref and return.
|
| + RefImage(draw_image);
|
| + *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 = image_data->upload.task;
|
| + *task = existing_task;
|
| return true;
|
| }
|
|
|
| + // 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()) {
|
| + new_data = CreateImageData(draw_image);
|
| + data = new_data.get();
|
| + } else {
|
| + data = found->second.get();
|
| + }
|
| +
|
| // Ensure that the image we're about to decode/upload will fit in memory.
|
| - if (!EnsureCapacity(image_data->size)) {
|
| + if (!EnsureCapacity(data->size)) {
|
| // Image will not fit, do an at-raster decode.
|
| *task = nullptr;
|
| return false;
|
| @@ -417,19 +343,19 @@
|
| // If we had to create new image data, add it to our map now that we know it
|
| // will fit.
|
| if (new_data)
|
| - persistent_cache_.Put(image_id, std::move(new_data));
|
| + found = 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);
|
| - *task = make_scoped_refptr(new ImageUploadTaskImpl(
|
| + existing_task = make_scoped_refptr(new ImageUploadTaskImpl(
|
| this, draw_image, GetImageDecodeTaskAndRef(draw_image, tracing_info),
|
| tracing_info));
|
| - image_data->upload.task = *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;
|
| }
|
|
|
| @@ -440,8 +366,6 @@
|
|
|
| DecodedDrawImage GpuImageDecodeController::GetDecodedImageForDraw(
|
| const DrawImage& draw_image) {
|
| - TRACE_EVENT0("cc", "GpuImageDecodeController::GetDecodedImageForDraw");
|
| -
|
| // We are being called during raster. The context lock must already be
|
| // acquired by the caller.
|
| context_->GetLock()->AssertAcquired();
|
| @@ -449,14 +373,18 @@
|
| if (SkipImage(draw_image))
|
| return DecodedDrawImage(nullptr, draw_image.filter_quality());
|
|
|
| - base::AutoLock lock(lock_);
|
| - ImageData* image_data = GetImageDataForDrawImage(draw_image);
|
| - if (!image_data) {
|
| + 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()) {
|
| // We didn't find the image, create a new entry.
|
| auto data = CreateImageData(draw_image);
|
| - image_data = data.get();
|
| - persistent_cache_.Put(draw_image.image()->uniqueID(), std::move(data));
|
| - }
|
| + found = image_data_.Put(unique_id, 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.
|
| @@ -480,9 +408,7 @@
|
| image_data->upload.mark_used();
|
| DCHECK(image || image_data->decode.decode_failure);
|
|
|
| - SkSize scale_factor = CalculateScaleFactorForMipLevel(
|
| - draw_image, image_data->upload_scale_mip_level);
|
| - DecodedDrawImage decoded_draw_image(std::move(image), SkSize(), scale_factor,
|
| + DecodedDrawImage decoded_draw_image(std::move(image),
|
| draw_image.filter_quality());
|
| decoded_draw_image.set_at_raster_decode(image_data->is_at_raster);
|
| return decoded_draw_image;
|
| @@ -491,8 +417,6 @@
|
| void GpuImageDecodeController::DrawWithImageFinished(
|
| const DrawImage& draw_image,
|
| const DecodedDrawImage& decoded_draw_image) {
|
| - TRACE_EVENT0("cc", "GpuImageDecodeController::DrawWithImageFinished");
|
| -
|
| // We are being called during raster. The context lock must already be
|
| // acquired by the caller.
|
| context_->GetLock()->AssertAcquired();
|
| @@ -536,7 +460,7 @@
|
| bool GpuImageDecodeController::OnMemoryDump(
|
| const base::trace_event::MemoryDumpArgs& args,
|
| base::trace_event::ProcessMemoryDump* pmd) {
|
| - for (const auto& image_pair : persistent_cache_) {
|
| + for (const auto& image_pair : image_data_) {
|
| const ImageData* image_data = image_pair.second.get();
|
| const uint32_t image_id = image_pair.first;
|
|
|
| @@ -548,6 +472,7 @@
|
| base::trace_event::MemoryAllocatorDump* dump =
|
| image_data->decode.data()->CreateMemoryAllocatorDump(
|
| discardable_dump_name.c_str(), pmd);
|
| +
|
| // If our image is locked, dump the "locked_size" as an additional column.
|
| // This lets us see the amount of discardable which is contributing to
|
| // memory pressure.
|
| @@ -595,29 +520,26 @@
|
|
|
| void GpuImageDecodeController::DecodeImage(const DrawImage& draw_image) {
|
| base::AutoLock lock(lock_);
|
| - ImageData* image_data = GetImageDataForDrawImage(draw_image);
|
| - DCHECK(image_data);
|
| - DCHECK(!image_data->is_at_raster);
|
| - DecodeImageIfNecessary(draw_image, image_data);
|
| + 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());
|
| }
|
|
|
| void GpuImageDecodeController::UploadImage(const DrawImage& draw_image) {
|
| ContextProvider::ScopedContextLock context_lock(context_);
|
| base::AutoLock lock(lock_);
|
| - ImageData* image_data = GetImageDataForDrawImage(draw_image);
|
| - DCHECK(image_data);
|
| - DCHECK(!image_data->is_at_raster);
|
| - UploadImageIfNecessary(draw_image, image_data);
|
| + 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());
|
| }
|
|
|
| void GpuImageDecodeController::OnImageDecodeTaskCompleted(
|
| const DrawImage& draw_image) {
|
| base::AutoLock lock(lock_);
|
| - // Decode task is complete, remove our reference to it.
|
| - ImageData* image_data = GetImageDataForDrawImage(draw_image);
|
| - DCHECK(image_data);
|
| - DCHECK(image_data->decode.task);
|
| - image_data->decode.task = nullptr;
|
| + // Decode task is complete, remove it from our list of pending tasks.
|
| + pending_image_decode_tasks_.erase(draw_image.image()->uniqueID());
|
|
|
| // While the decode task is active, we keep a ref on the decoded data.
|
| // Release that ref now.
|
| @@ -627,11 +549,8 @@
|
| void GpuImageDecodeController::OnImageUploadTaskCompleted(
|
| const DrawImage& draw_image) {
|
| base::AutoLock lock(lock_);
|
| - // Upload task is complete, remove our reference to it.
|
| - ImageData* image_data = GetImageDataForDrawImage(draw_image);
|
| - DCHECK(image_data);
|
| - DCHECK(image_data->upload.task);
|
| - image_data->upload.task = nullptr;
|
| + // Upload task is complete, remove it from our list of pending tasks.
|
| + pending_image_upload_tasks_.erase(draw_image.image()->uniqueID());
|
|
|
| // 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
|
| @@ -647,22 +566,24 @@
|
| 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);
|
|
|
| - ImageData* image_data = GetImageDataForDrawImage(draw_image);
|
| - DCHECK(image_data);
|
| - if (image_data->decode.is_locked()) {
|
| + auto found = image_data_.Peek(image_id);
|
| + if (found != image_data_.end() && found->second->decode.is_locked()) {
|
| // We should never be creating a decode task for an at raster image.
|
| - DCHECK(!image_data->is_at_raster);
|
| + DCHECK(!found->second->is_at_raster);
|
| // We should never be creating a decode for an already-uploaded image.
|
| - DCHECK(!image_data->upload.image());
|
| + DCHECK(!found->second->upload.image());
|
| return nullptr;
|
| }
|
|
|
| // We didn't have an existing locked image, create a task to lock or decode.
|
| - scoped_refptr<TileTask>& existing_task = image_data->decode.task;
|
| + scoped_refptr<TileTask>& existing_task =
|
| + pending_image_decode_tasks_[image_id];
|
| if (!existing_task) {
|
| // Ref image decode and create a decode task. This ref will be released in
|
| // DecodeTaskCompleted.
|
| @@ -675,79 +596,47 @@
|
|
|
| void GpuImageDecodeController::RefImageDecode(const DrawImage& draw_image) {
|
| lock_.AssertAcquired();
|
| - auto found = in_use_cache_.find(GenerateInUseCacheKey(draw_image));
|
| - DCHECK(found != in_use_cache_.end());
|
| - ++found->second.ref_count;
|
| - ++found->second.image_data->decode.ref_count;
|
| - OwnershipChanged(found->second.image_data.get());
|
| + auto found = image_data_.Peek(draw_image.image()->uniqueID());
|
| + DCHECK(found != image_data_.end());
|
| + ++found->second->decode.ref_count;
|
| + RefCountChanged(found->second.get());
|
| }
|
|
|
| void GpuImageDecodeController::UnrefImageDecode(const DrawImage& draw_image) {
|
| lock_.AssertAcquired();
|
| - auto found = in_use_cache_.find(GenerateInUseCacheKey(draw_image));
|
| - DCHECK(found != in_use_cache_.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;
|
| - OwnershipChanged(found->second.image_data.get());
|
| - if (found->second.ref_count == 0u) {
|
| - in_use_cache_.erase(found);
|
| - }
|
| + 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());
|
| }
|
|
|
| void GpuImageDecodeController::RefImage(const DrawImage& draw_image) {
|
| lock_.AssertAcquired();
|
| - InUseCacheKey key = GenerateInUseCacheKey(draw_image);
|
| - auto found = in_use_cache_.find(key);
|
| -
|
| - // If no secondary cache entry was found for the given |draw_image|, then
|
| - // the draw_image only exists in the |persistent_cache_|. Create an in-use
|
| - // cache entry now.
|
| - if (found == in_use_cache_.end()) {
|
| - auto found_image = persistent_cache_.Peek(draw_image.image()->uniqueID());
|
| - DCHECK(found_image != persistent_cache_.end());
|
| - DCHECK(found_image->second->upload_scale_mip_level <=
|
| - CalculateUploadScaleMipLevel(draw_image));
|
| - found = in_use_cache_
|
| - .insert(InUseCache::value_type(
|
| - key, InUseCacheEntry(found_image->second)))
|
| - .first;
|
| - }
|
| -
|
| - DCHECK(found != in_use_cache_.end());
|
| - ++found->second.ref_count;
|
| - ++found->second.image_data->upload.ref_count;
|
| - OwnershipChanged(found->second.image_data.get());
|
| + auto found = image_data_.Peek(draw_image.image()->uniqueID());
|
| + DCHECK(found != image_data_.end());
|
| + ++found->second->upload.ref_count;
|
| + RefCountChanged(found->second.get());
|
| }
|
|
|
| void GpuImageDecodeController::UnrefImageInternal(const DrawImage& draw_image) {
|
| lock_.AssertAcquired();
|
| - auto found = in_use_cache_.find(GenerateInUseCacheKey(draw_image));
|
| - DCHECK(found != in_use_cache_.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;
|
| - OwnershipChanged(found->second.image_data.get());
|
| - if (found->second.ref_count == 0u) {
|
| - in_use_cache_.erase(found);
|
| - }
|
| + 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());
|
| }
|
|
|
| // Called any time an image or decode ref count changes. Takes care of any
|
| // necessary memory budget book-keeping and cleanup.
|
| -void GpuImageDecodeController::OwnershipChanged(ImageData* image_data) {
|
| +void GpuImageDecodeController::RefCountChanged(ImageData* image_data) {
|
| lock_.AssertAcquired();
|
|
|
| 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
|
| @@ -834,7 +723,7 @@
|
| // things: 1) We can free the uploaded image, reducing the memory usage of
|
| // the cache and 2) we can remove the entry entirely, reducing the count of
|
| // elements in the cache.
|
| - for (auto it = persistent_cache_.rbegin(); it != persistent_cache_.rend();) {
|
| + for (auto it = image_data_.rbegin(); it != image_data_.rend();) {
|
| if (it->second->decode.ref_count != 0 ||
|
| it->second->upload.ref_count != 0) {
|
| ++it;
|
| @@ -860,7 +749,7 @@
|
|
|
| // Free the entire entry if necessary.
|
| if (ExceedsPreferredCount()) {
|
| - it = persistent_cache_.Erase(it);
|
| + it = image_data_.Erase(it);
|
| } else {
|
| ++it;
|
| }
|
| @@ -885,7 +774,7 @@
|
| bool GpuImageDecodeController::ExceedsPreferredCount() const {
|
| lock_.AssertAcquired();
|
|
|
| - return persistent_cache_.size() > cached_items_limit_;
|
| + return image_data_.size() > cached_items_limit_;
|
| }
|
|
|
| void GpuImageDecodeController::DecodeImageIfNecessary(
|
| @@ -922,18 +811,10 @@
|
| backing_memory =
|
| base::DiscardableMemoryAllocator::GetInstance()
|
| ->AllocateLockedDiscardableMemory(image_data->size);
|
| - SkImageInfo image_info = CreateImageInfoForDrawImage(
|
| - draw_image, image_data->upload_scale_mip_level);
|
| - // 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.
|
| - SkPixmap image_pixmap(image_info, backing_memory->data(),
|
| - image_info.minRowBytes());
|
| - // Note that scalePixels falls back to readPixels if the sale is 1x, so
|
| - // no need to special case that as an optimization.
|
| - if (!draw_image.image()->scalePixels(
|
| - image_pixmap, CalculateUploadScaleFilterQuality(draw_image),
|
| - SkImage::kDisallow_CachingHint)) {
|
| + SkImageInfo image_info = CreateImageInfoForDrawImage(draw_image);
|
| + if (!draw_image.image()->readPixels(image_info, backing_memory->data(),
|
| + image_info.minRowBytes(), 0, 0,
|
| + SkImage::kDisallow_CachingHint)) {
|
| backing_memory.reset();
|
| }
|
| break;
|
| @@ -942,8 +823,7 @@
|
| backing_memory =
|
| base::DiscardableMemoryAllocator::GetInstance()
|
| ->AllocateLockedDiscardableMemory(image_data->size);
|
| - auto params =
|
| - ParamsFromDrawImage(draw_image, image_data->upload_scale_mip_level);
|
| + auto params = ParamsFromDrawImage(draw_image);
|
| if (!draw_image.image()->getDeferredTextureImageData(
|
| *context_threadsafe_proxy_.get(), ¶ms, 1,
|
| backing_memory->data())) {
|
| @@ -999,8 +879,7 @@
|
| base::AutoUnlock unlock(lock_);
|
| switch (image_data->mode) {
|
| case DecodedDataMode::CPU: {
|
| - SkImageInfo image_info = CreateImageInfoForDrawImage(
|
| - draw_image, image_data->upload_scale_mip_level);
|
| + SkImageInfo image_info = CreateImageInfoForDrawImage(draw_image);
|
| SkPixmap pixmap(image_info, image_data->decode.data()->data(),
|
| image_info.minRowBytes());
|
| uploaded_image =
|
| @@ -1024,30 +903,26 @@
|
| image_data->upload.SetImage(std::move(uploaded_image));
|
| }
|
|
|
| -scoped_refptr<GpuImageDecodeController::ImageData>
|
| +std::unique_ptr<GpuImageDecodeController::ImageData>
|
| GpuImageDecodeController::CreateImageData(const DrawImage& draw_image) {
|
| lock_.AssertAcquired();
|
|
|
| DecodedDataMode mode;
|
| - int upload_scale_mip_level = CalculateUploadScaleMipLevel(draw_image);
|
| + SkImageInfo info = CreateImageInfoForDrawImage(draw_image);
|
| SkImage::DeferredTextureImageUsageParams params =
|
| - ParamsFromDrawImage(draw_image, upload_scale_mip_level);
|
| + ParamsFromDrawImage(draw_image);
|
| size_t data_size = draw_image.image()->getDeferredTextureImageData(
|
| *context_threadsafe_proxy_.get(), ¶ms, 1, nullptr);
|
|
|
| if (data_size == 0) {
|
| // Can't upload image, too large or other failure. Try to use SW fallback.
|
| - SkImageInfo image_info =
|
| - CreateImageInfoForDrawImage(draw_image, upload_scale_mip_level);
|
| - data_size = image_info.getSafeSize(image_info.minRowBytes());
|
| + data_size = info.getSafeSize(info.minRowBytes());
|
| mode = DecodedDataMode::CPU;
|
| } else {
|
| mode = DecodedDataMode::GPU;
|
| }
|
|
|
| - return make_scoped_refptr(
|
| - new ImageData(mode, data_size, upload_scale_mip_level,
|
| - CalculateUploadScaleFilterQuality(draw_image)));
|
| + return base::WrapUnique(new ImageData(mode, data_size));
|
| }
|
|
|
| void GpuImageDecodeController::DeletePendingImages() {
|
| @@ -1057,70 +932,17 @@
|
| }
|
|
|
| SkImageInfo GpuImageDecodeController::CreateImageInfoForDrawImage(
|
| - const DrawImage& draw_image,
|
| - int upload_scale_mip_level) const {
|
| - gfx::Size mip_size =
|
| - CalculateSizeForMipLevel(draw_image, upload_scale_mip_level);
|
| - return SkImageInfo::Make(mip_size.width(), mip_size.height(),
|
| - ResourceFormatToClosestSkColorType(format_),
|
| - kPremul_SkAlphaType);
|
| -}
|
| -
|
| -// Tries to find an ImageData that can be used to draw the provided
|
| -// |draw_image|. First looks for an exact entry in our |in_use_cache_|. If one
|
| -// cannot be found, it looks for a compatible entry in our |persistent_cache_|.
|
| -GpuImageDecodeController::ImageData*
|
| -GpuImageDecodeController::GetImageDataForDrawImage(
|
| - const DrawImage& draw_image) {
|
| - lock_.AssertAcquired();
|
| - auto found_in_use = in_use_cache_.find(GenerateInUseCacheKey(draw_image));
|
| - if (found_in_use != in_use_cache_.end())
|
| - return found_in_use->second.image_data.get();
|
| -
|
| - auto found_persistent = persistent_cache_.Get(draw_image.image()->uniqueID());
|
| - if (found_persistent != persistent_cache_.end()) {
|
| - ImageData* image_data = found_persistent->second.get();
|
| - if (IsCompatible(image_data, draw_image)) {
|
| - return image_data;
|
| - } else {
|
| - found_persistent->second->is_orphaned = true;
|
| - // Call OwnershipChanged before erasing the orphaned task from the
|
| - // persistent cache. This ensures that if the orphaned task has 0
|
| - // references, it is cleaned up safely before it is deleted.
|
| - OwnershipChanged(image_data);
|
| - persistent_cache_.Erase(found_persistent);
|
| - }
|
| - }
|
| -
|
| - return nullptr;
|
| -}
|
| -
|
| -// Determines if we can draw the provided |draw_image| using the provided
|
| -// |image_data|. This is true if the |image_data| is not scaled, or if it
|
| -// is scaled at an equal or larger scale and equal or larger quality to
|
| -// the provided |draw_image|.
|
| -bool GpuImageDecodeController::IsCompatible(const ImageData* image_data,
|
| - const DrawImage& draw_image) const {
|
| - bool is_scaled = image_data->upload_scale_mip_level != 0;
|
| - bool scale_is_compatible = CalculateUploadScaleMipLevel(draw_image) >=
|
| - image_data->upload_scale_mip_level;
|
| - bool quality_is_compatible = CalculateUploadScaleFilterQuality(draw_image) <=
|
| - image_data->upload_scale_filter_quality;
|
| - return !is_scaled || (scale_is_compatible && quality_is_compatible);
|
| -}
|
| -
|
| -size_t GpuImageDecodeController::GetDrawImageSizeForTesting(
|
| - const DrawImage& image) {
|
| - base::AutoLock lock(lock_);
|
| - scoped_refptr<ImageData> data = CreateImageData(image);
|
| - return data->size;
|
| + const DrawImage& draw_image) const {
|
| + return SkImageInfo::Make(
|
| + draw_image.image()->width(), draw_image.image()->height(),
|
| + ResourceFormatToClosestSkColorType(format_), kPremul_SkAlphaType);
|
| }
|
|
|
| void GpuImageDecodeController::SetImageDecodingFailedForTesting(
|
| const DrawImage& image) {
|
| base::AutoLock lock(lock_);
|
| - auto found = persistent_cache_.Peek(image.image()->uniqueID());
|
| - DCHECK(found != persistent_cache_.end());
|
| + auto found = image_data_.Peek(image.image()->uniqueID());
|
| + DCHECK(found != image_data_.end());
|
| ImageData* image_data = found->second.get();
|
| image_data->decode.decode_failure = true;
|
| }
|
| @@ -1128,8 +950,8 @@
|
| bool GpuImageDecodeController::DiscardableIsLockedForTesting(
|
| const DrawImage& image) {
|
| base::AutoLock lock(lock_);
|
| - auto found = persistent_cache_.Peek(image.image()->uniqueID());
|
| - DCHECK(found != persistent_cache_.end());
|
| + auto found = image_data_.Peek(image.image()->uniqueID());
|
| + DCHECK(found != image_data_.end());
|
| ImageData* image_data = found->second.get();
|
| return image_data->decode.is_locked();
|
| }
|
|
|