Commit e0c4b6ad authored by Adrienne Walker's avatar Adrienne Walker Committed by Commit Bot

Create per color space canvas image decode cache

Currently, cc image decode caches support multiple color spaces in the
same decode cache.  However, during rasterization there is only one
color space.  Additionally, each canvas that uses an image decode cache
in Blink also has only one color space (and there is only one canvas
active at once).

This patch is in support of that goal, by refactoring the canvas image
provider to use one image decode cache per color space (split in two
places because of provider dependency issues for gpu).  Once this is
done, then color space can be moved from cc::DrawImage to the image
decode cache.

Although there are now multiple active image decode caches, after
the use of each one they clean up and unlock all decodes via the
CanvasResourceProvider::CleanupLockedImages function.  This is posted
as a task, so it's possible that if there are multiple canvases
being rastered to with multiple color spaces that there may be a
higher watermark of memory usage before the cleanup tasks run.
This patch punts on this possibility for now.

Bug: 902022
Change-Id: I2a079c4ae9383986dffd6939f7ab31a5a45ed196
Reviewed-on: https://chromium-review.googlesource.com/c/1315962
Commit-Queue: enne <enne@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarKhushal <khushalsagar@chromium.org>
Reviewed-by: default avatarFernando Serboncini <fserb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#605557}
parent 5c390b84
......@@ -77,9 +77,14 @@ void WebGraphicsContext3DProviderImpl::OnContextLost() {
}
cc::ImageDecodeCache* WebGraphicsContext3DProviderImpl::ImageDecodeCache(
SkColorType color_type) {
blink::CanvasColorSpace color_space,
blink::CanvasPixelFormat pixel_format) {
SkColorType color_type =
blink::CanvasColorParams::PixelFormatToSkColorType(pixel_format);
DCHECK(GetGrContext()->colorTypeSupportedAsImage(color_type));
auto cache_iterator = image_decode_cache_map_.find(color_type);
auto key = std::make_pair(color_space, pixel_format);
auto cache_iterator = image_decode_cache_map_.find(key);
if (cache_iterator != image_decode_cache_map_.end())
return cache_iterator->second.get();
......@@ -91,13 +96,12 @@ cc::ImageDecodeCache* WebGraphicsContext3DProviderImpl::ImageDecodeCache(
// TransferCache is used only with OOP raster.
const bool use_transfer_cache = false;
auto insertion_result = image_decode_cache_map_.insert(
std::pair<SkColorType, std::unique_ptr<cc::ImageDecodeCache>>(
color_type, std::make_unique<cc::GpuImageDecodeCache>(
provider_.get(), use_transfer_cache, color_type,
kMaxWorkingSetBytes,
provider_->ContextCapabilities().max_texture_size,
cc::PaintImage::kDefaultGeneratorClientId)));
auto insertion_result = image_decode_cache_map_.emplace(
key,
std::make_unique<cc::GpuImageDecodeCache>(
provider_.get(), use_transfer_cache, color_type, kMaxWorkingSetBytes,
provider_->ContextCapabilities().max_texture_size,
cc::PaintImage::kDefaultGeneratorClientId));
DCHECK(insertion_result.second);
cache_iterator = insertion_result.first;
return cache_iterator->second.get();
......
......@@ -51,7 +51,9 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
void SetLostContextCallback(base::RepeatingClosure) override;
void SetErrorMessageCallback(
base::RepeatingCallback<void(const char*, int32_t)>) override;
cc::ImageDecodeCache* ImageDecodeCache(SkColorType) override;
cc::ImageDecodeCache* ImageDecodeCache(
blink::CanvasColorSpace color_space,
blink::CanvasPixelFormat pixel_format) override;
ws::ContextProviderCommandBuffer* context_provider() const {
return provider_.get();
......@@ -64,7 +66,8 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
scoped_refptr<ws::ContextProviderCommandBuffer> provider_;
std::unique_ptr<viz::GLHelper> gl_helper_;
base::RepeatingClosure context_lost_callback_;
base::flat_map<SkColorType, std::unique_ptr<cc::ImageDecodeCache>>
base::flat_map<std::pair<blink::CanvasColorSpace, blink::CanvasPixelFormat>,
std::unique_ptr<cc::ImageDecodeCache>>
image_decode_cache_map_;
DISALLOW_COPY_AND_ASSIGN(WebGraphicsContext3DProviderImpl);
......
......@@ -33,6 +33,7 @@
#include <cstdint>
#include "base/callback_forward.h"
#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
#include "third_party/skia/include/core/SkImageInfo.h"
class GrContext;
......@@ -77,7 +78,11 @@ class WebGraphicsContext3DProvider {
virtual void SetLostContextCallback(base::RepeatingClosure) = 0;
virtual void SetErrorMessageCallback(
base::RepeatingCallback<void(const char* msg, int32_t id)>) = 0;
virtual cc::ImageDecodeCache* ImageDecodeCache(SkColorType) = 0;
// Return a static software image decode cache that matches this color
// space and pixel format.
virtual cc::ImageDecodeCache* ImageDecodeCache(
CanvasColorSpace color_space,
CanvasPixelFormat pixel_format) = 0;
};
} // namespace blink
......
......@@ -121,8 +121,19 @@ bool CanvasColorParams::NeedsColorConversion(
}
SkColorType CanvasColorParams::GetSkColorType() const {
if (pixel_format_ == kF16CanvasPixelFormat)
return kRGBA_F16_SkColorType;
return PixelFormatToSkColorType(pixel_format_);
}
// static
SkColorType CanvasColorParams::PixelFormatToSkColorType(
CanvasPixelFormat pixel_format) {
switch (pixel_format) {
case kF16CanvasPixelFormat:
return kRGBA_F16_SkColorType;
case kRGBA8CanvasPixelFormat:
return kN32_SkColorType;
}
NOTREACHED();
return kN32_SkColorType;
}
......
......@@ -29,11 +29,13 @@ enum CanvasColorSpace {
kLinearRGBCanvasColorSpace,
kRec2020CanvasColorSpace,
kP3CanvasColorSpace,
kMaxCanvasColorSpace = kP3CanvasColorSpace
};
enum CanvasPixelFormat {
kRGBA8CanvasPixelFormat,
kF16CanvasPixelFormat,
kMaxCanvasPixelFormat = kF16CanvasPixelFormat
};
class PLATFORM_EXPORT CanvasColorParams {
......@@ -72,6 +74,7 @@ class PLATFORM_EXPORT CanvasColorParams {
// The pixel format to use for allocating SkSurfaces.
SkColorType GetSkColorType() const;
static SkColorType PixelFormatToSkColorType(CanvasPixelFormat pixel_format);
uint8_t BytesPerPixel() const;
// The color space in which pixels read from the canvas via a shader will be
......
......@@ -627,9 +627,9 @@ cc::PaintCanvas* CanvasResourceProvider::Canvas() {
// Create an ImageDecodeCache for half float images only if the canvas is
// using half float back storage.
cc::ImageDecodeCache* cache_f16 = nullptr;
if (ColorParams().GetSkColorType() == kRGBA_F16_SkColorType)
if (ColorParams().PixelFormat() == kF16CanvasPixelFormat)
cache_f16 = ImageDecodeCacheF16();
canvas_image_provider_.emplace(ImageDecodeCache(), cache_f16,
canvas_image_provider_.emplace(ImageDecodeCacheRGBA8(), cache_f16,
target_color_space,
color_params_.GetSkColorType());
cc::ImageProvider* image_provider = &*canvas_image_provider_;
......@@ -767,20 +767,22 @@ scoped_refptr<CanvasResource> CanvasResourceProvider::CreateResource() {
return nullptr;
}
cc::ImageDecodeCache* CanvasResourceProvider::ImageDecodeCache() {
cc::ImageDecodeCache* CanvasResourceProvider::ImageDecodeCacheRGBA8() {
if (IsAccelerated() && context_provider_wrapper_) {
return context_provider_wrapper_->ContextProvider()->ImageDecodeCache(
kN32_SkColorType);
ColorParams().ColorSpace(), kRGBA8CanvasPixelFormat);
}
return &Image::SharedCCDecodeCache(kN32_SkColorType);
return Image::SharedCCDecodeCache(ColorParams().ColorSpace(),
kRGBA8CanvasPixelFormat);
}
cc::ImageDecodeCache* CanvasResourceProvider::ImageDecodeCacheF16() {
if (IsAccelerated() && context_provider_wrapper_) {
return context_provider_wrapper_->ContextProvider()->ImageDecodeCache(
kRGBA_F16_SkColorType);
ColorParams().ColorSpace(), kF16CanvasPixelFormat);
}
return &Image::SharedCCDecodeCache(kRGBA_F16_SkColorType);
return Image::SharedCCDecodeCache(ColorParams().ColorSpace(),
kF16CanvasPixelFormat);
}
void CanvasResourceProvider::RecycleResource(
......
......@@ -208,7 +208,7 @@ class PLATFORM_EXPORT CanvasResourceProvider
virtual sk_sp<SkSurface> CreateSkSurface() const = 0;
virtual scoped_refptr<CanvasResource> CreateResource();
cc::ImageDecodeCache* ImageDecodeCache();
cc::ImageDecodeCache* ImageDecodeCacheRGBA8();
cc::ImageDecodeCache* ImageDecodeCacheF16();
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
......
......@@ -53,7 +53,8 @@ class WebGraphicsContext3DProviderForTests
void SetLostContextCallback(base::Closure) override {}
void SetErrorMessageCallback(
base::RepeatingCallback<void(const char*, int32_t id)>) override {}
cc::ImageDecodeCache* ImageDecodeCache(SkColorType) override {
cc::ImageDecodeCache* ImageDecodeCache(CanvasColorSpace,
CanvasPixelFormat) override {
return &image_decode_cache_;
}
......
......@@ -55,6 +55,33 @@
namespace blink {
class CombinedImageDecodeCache {
public:
CombinedImageDecodeCache(size_t locked_memory_limit_bytes)
: locked_memory_limit_bytes_(locked_memory_limit_bytes) {
constexpr int kMaxIndex =
(kMaxCanvasPixelFormat + 1) * (kMaxCanvasColorSpace + 1);
decode_caches_.resize(kMaxIndex);
}
cc::ImageDecodeCache* GetCache(CanvasColorSpace color_space,
CanvasPixelFormat pixel_format) {
base::AutoLock lock(lock_);
int index = (kMaxCanvasColorSpace + 1) * pixel_format + color_space;
if (!decode_caches_[index]) {
decode_caches_[index] = std::make_unique<cc::SoftwareImageDecodeCache>(
CanvasColorParams::PixelFormatToSkColorType(pixel_format),
locked_memory_limit_bytes_, PaintImage::kDefaultGeneratorClientId);
}
return decode_caches_[index].get();
}
private:
std::vector<std::unique_ptr<cc::SoftwareImageDecodeCache>> decode_caches_;
const size_t locked_memory_limit_bytes_;
base::Lock lock_;
};
Image::Image(ImageObserver* observer, bool is_multipart)
: image_observer_disabled_(false),
image_observer_(observer),
......@@ -72,24 +99,16 @@ Image* Image::NullImage() {
}
// static
cc::ImageDecodeCache& Image::SharedCCDecodeCache(SkColorType color_type) {
cc::ImageDecodeCache* Image::SharedCCDecodeCache(
CanvasColorSpace color_space,
CanvasPixelFormat pixel_format) {
// This denotes the allocated locked memory budget for the cache used for
// book-keeping. The cache indicates when the total memory locked exceeds this
// budget in cc::DecodedDrawImage.
DCHECK(color_type == kN32_SkColorType || color_type == kRGBA_F16_SkColorType);
static const size_t kLockedMemoryLimitBytes = 64 * 1024 * 1024;
if (color_type == kRGBA_F16_SkColorType) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
cc::SoftwareImageDecodeCache, image_decode_cache,
(kRGBA_F16_SkColorType, kLockedMemoryLimitBytes,
PaintImage::kDefaultGeneratorClientId));
return image_decode_cache;
}
DEFINE_THREAD_SAFE_STATIC_LOCAL(cc::SoftwareImageDecodeCache,
image_decode_cache,
(kN32_SkColorType, kLockedMemoryLimitBytes,
PaintImage::kDefaultGeneratorClientId));
return image_decode_cache;
DEFINE_THREAD_SAFE_STATIC_LOCAL(CombinedImageDecodeCache, combined_cache,
(kLockedMemoryLimitBytes));
return combined_cache.GetCache(color_space, pixel_format);
}
scoped_refptr<Image> Image::LoadPlatformResource(const char* name) {
......
......@@ -31,6 +31,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/image_animation_policy.h"
#include "third_party/blink/renderer/platform/graphics/image_observer.h"
......@@ -73,7 +74,9 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
public:
virtual ~Image();
static cc::ImageDecodeCache& SharedCCDecodeCache(SkColorType);
static cc::ImageDecodeCache* SharedCCDecodeCache(
CanvasColorSpace color_space,
CanvasPixelFormat pixel_format);
static scoped_refptr<Image> LoadPlatformResource(const char* name);
......
......@@ -52,7 +52,8 @@ class FakeWebGraphicsContext3DProvider : public WebGraphicsContext3DProvider {
void SetLostContextCallback(base::Closure) override {}
void SetErrorMessageCallback(
base::RepeatingCallback<void(const char*, int32_t id)>) override {}
cc::ImageDecodeCache* ImageDecodeCache(SkColorType) override {
cc::ImageDecodeCache* ImageDecodeCache(CanvasColorSpace,
CanvasPixelFormat) override {
return image_decode_cache_;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment