Commit 49fc8a9c authored by Khushal's avatar Khushal Committed by Commit Bot

blink: Set up a cc::SoftwareImageDecodeCache for canvas image decodes.

Add an instance of SoftwareImageDecodeCache for image decoding for
non-accelerated canvas. This can potentially be used for any other
use-case requiring image decoding on the main thread in blink.

R=chrishtr@chromium.org

Bug: 791828
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I1df793ea00e8e5df26878d6ca8e0769a9ca0c500
Reviewed-on: https://chromium-review.googlesource.com/858570
Commit-Queue: Khushal <khushalsagar@chromium.org>
Reviewed-by: default avatarJustin Novosad <junov@chromium.org>
Reviewed-by: default avatarccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#555318}
parent 21ac0c57
...@@ -34,8 +34,7 @@ async_test(function(t) { ...@@ -34,8 +34,7 @@ async_test(function(t) {
var height = 100; var height = 100;
var ctx1 = createNewCanvas(width, height); var ctx1 = createNewCanvas(width, height);
var ctx2 = createNewCanvas(width, height); var ctx2 = createNewCanvas(width, height);
ctx1.imageSmoothingEnabled = true; ctx1.imageSmoothingEnabled = false;
ctx1.imageSmoothingQuality = 'low';
ctx2.imageSmoothingEnabled = true; ctx2.imageSmoothingEnabled = true;
ctx2.imageSmoothingQuality = 'high'; ctx2.imageSmoothingQuality = 'high';
ctx1.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, width, height); ctx1.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, width, height);
...@@ -43,5 +42,5 @@ async_test(function(t) { ...@@ -43,5 +42,5 @@ async_test(function(t) {
compareTwoCanvases(ctx1, ctx2, width, height); compareTwoCanvases(ctx1, ctx2, width, height);
}); });
video.src = "../../compositing/resources/video.ogv"; video.src = "../../compositing/resources/video.ogv";
}, 'drawImage from a video should look differently with different imageSmoothingQuality'); }, 'drawImage from a video should look differently with imageSmoothing enabled');
</script> </script>
...@@ -71,26 +71,17 @@ test(function(t) { ...@@ -71,26 +71,17 @@ test(function(t) {
lowContext.imageSmoothingEnabled = false; lowContext.imageSmoothingEnabled = false;
var noFilterData = scaleImageData(lowCanvas, lowCanvas.imageSmoothingQuality); var noFilterData = scaleImageData(lowCanvas, lowCanvas.imageSmoothingQuality);
assert_false(lowData === mediumData); // No filtering uses kNone quality, while with imageSmoothingEnabled we use the
// Skia uses mipmaps when downscaling, for both high and medium quality // same quality.
assert_equals(mediumData, highData); assert_false(noFilterData === mediumData);
assert_false(lowData === highData); assert_true(mediumData === highData);
assert_equals(sampleAlpha(noFilterData), sampleAlpha(lowData));
assert_true(sampleAlpha(lowData) > sampleAlpha(mediumData));
// Skia uses mipmaps when downscaling, for both high and medium quality
assert_equals(sampleAlpha(mediumData), sampleAlpha(highData));
// On setting, it must be set to the new value. // On setting, it must be set to the new value.
highContext.imageSmoothingQuality = 'medium'; highContext.imageSmoothingQuality = 'medium';
assert_equals(highContext.imageSmoothingQuality, 'medium'); assert_equals(highContext.imageSmoothingQuality, 'medium');
assert_equals(scaleImageData(highCanvas, highCanvas.imageSmoothingQuality),
mediumData);
highContext.imageSmoothingQuality = 'high'; highContext.imageSmoothingQuality = 'high';
assert_equals(highContext.imageSmoothingQuality, 'high'); assert_equals(highContext.imageSmoothingQuality, 'high');
assert_equals(scaleImageData(highCanvas, highCanvas.imageSmoothingQuality),
highData);
// When the CanvasRenderingContext2D object is created, the attribute must be set to 'low'. // When the CanvasRenderingContext2D object is created, the attribute must be set to 'low'.
assert_equals(document.getElementById("default").getContext("2d").imageSmoothingQuality, 'low'); assert_equals(document.getElementById("default").getContext("2d").imageSmoothingQuality, 'low');
......
...@@ -1076,16 +1076,6 @@ bool BaseRenderingContext2D::ShouldDrawImageAntialiased( ...@@ -1076,16 +1076,6 @@ bool BaseRenderingContext2D::ShouldDrawImageAntialiased(
dest_rect.Height() * fabs(height_expansion) < 1; dest_rect.Height() * fabs(height_expansion) < 1;
} }
static bool IsDrawScalingDown(const FloatRect& src_rect,
const FloatRect& dst_rect,
float x_scale_squared,
float y_scale_squared) {
return dst_rect.Width() * dst_rect.Width() * x_scale_squared <
src_rect.Width() * src_rect.Width() &&
dst_rect.Height() * dst_rect.Height() * y_scale_squared <
src_rect.Height() * src_rect.Height();
}
void BaseRenderingContext2D::DrawImageInternal(PaintCanvas* c, void BaseRenderingContext2D::DrawImageInternal(PaintCanvas* c,
CanvasImageSource* image_source, CanvasImageSource* image_source,
Image* image, Image* image,
...@@ -1119,12 +1109,6 @@ void BaseRenderingContext2D::DrawImageInternal(PaintCanvas* c, ...@@ -1119,12 +1109,6 @@ void BaseRenderingContext2D::DrawImageInternal(PaintCanvas* c,
image_flags.setImageFilter(nullptr); image_flags.setImageFilter(nullptr);
} }
if (!imageSmoothingEnabled() &&
IsDrawScalingDown(src_rect, dst_rect,
GetState().Transform().XScaleSquared(),
GetState().Transform().YScaleSquared()))
image_flags.setFilterQuality(kLow_SkFilterQuality);
if (!image_source->IsVideoElement()) { if (!image_source->IsVideoElement()) {
image_flags.setAntiAlias(ShouldDrawImageAntialiased(dst_rect)); image_flags.setAntiAlias(ShouldDrawImageAntialiased(dst_rect));
image->Draw(c, image_flags, dst_rect, src_rect, image->Draw(c, image_flags, dst_rect, src_rect,
......
...@@ -1298,13 +1298,14 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) { ...@@ -1298,13 +1298,14 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) {
Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>( Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration, IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
color_params)); color_params));
gfx::ColorSpace expected_color_space = gfx::ColorSpace::CreateSRGB();
std::vector<cc::DrawImage> images = { std::vector<cc::DrawImage> images = {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)), cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
SkIRect::MakeWH(10, 10), kNone_SkFilterQuality, SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace()), SkMatrix::I(), 0u, expected_color_space),
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)), cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(20, 20)),
SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(), SkIRect::MakeWH(5, 5), kNone_SkFilterQuality, SkMatrix::I(),
0u, color_params.GetStorageGfxColorSpace())}; 0u, expected_color_space)};
bridge->Canvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr); bridge->Canvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
bridge->Canvas()->drawImageRect( bridge->Canvas()->drawImageRect(
......
...@@ -382,12 +382,13 @@ PaintCanvas* CanvasResourceProvider::Canvas() { ...@@ -382,12 +382,13 @@ PaintCanvas* CanvasResourceProvider::Canvas() {
if (!canvas_) { if (!canvas_) {
DCHECK(!canvas_image_provider_); DCHECK(!canvas_image_provider_);
cc::ImageProvider* image_provider = nullptr; gfx::ColorSpace target_color_space =
if (ImageDecodeCache()) { ColorParams().NeedsSkColorSpaceXformCanvas()
canvas_image_provider_.emplace(ImageDecodeCache(), ? ColorParams().GetStorageGfxColorSpace()
ColorParams().GetStorageGfxColorSpace()); : gfx::ColorSpace::CreateSRGB();
image_provider = &*canvas_image_provider_;
} canvas_image_provider_.emplace(ImageDecodeCache(), target_color_space);
cc::ImageProvider* image_provider = &*canvas_image_provider_;
cc::SkiaPaintCanvas::ContextFlushes context_flushes; cc::SkiaPaintCanvas::ContextFlushes context_flushes;
if (IsAccelerated()) { if (IsAccelerated()) {
...@@ -399,11 +400,10 @@ PaintCanvas* CanvasResourceProvider::Canvas() { ...@@ -399,11 +400,10 @@ PaintCanvas* CanvasResourceProvider::Canvas() {
if (ColorParams().NeedsSkColorSpaceXformCanvas()) { if (ColorParams().NeedsSkColorSpaceXformCanvas()) {
canvas_ = std::make_unique<cc::SkiaPaintCanvas>( canvas_ = std::make_unique<cc::SkiaPaintCanvas>(
GetSkSurface()->getCanvas(), ColorParams().GetSkColorSpace(), GetSkSurface()->getCanvas(), ColorParams().GetSkColorSpace(),
std::move(image_provider), context_flushes); image_provider, context_flushes);
} else { } else {
canvas_ = std::make_unique<cc::SkiaPaintCanvas>( canvas_ = std::make_unique<cc::SkiaPaintCanvas>(
GetSkSurface()->getCanvas(), std::move(image_provider), GetSkSurface()->getCanvas(), image_provider, context_flushes);
context_flushes);
} }
} }
...@@ -542,10 +542,9 @@ scoped_refptr<CanvasResource> CanvasResourceProvider::CreateResource() { ...@@ -542,10 +542,9 @@ scoped_refptr<CanvasResource> CanvasResourceProvider::CreateResource() {
} }
cc::ImageDecodeCache* CanvasResourceProvider::ImageDecodeCache() { cc::ImageDecodeCache* CanvasResourceProvider::ImageDecodeCache() {
// TODO(khushalsagar): Hook up a software cache. if (context_provider_wrapper_)
if (!context_provider_wrapper_) return context_provider_wrapper_->ContextProvider()->ImageDecodeCache();
return nullptr; return &Image::SharedCCDecodeCache();
return context_provider_wrapper_->ContextProvider()->ImageDecodeCache();
} }
} // namespace blink } // namespace blink
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_DRAWING_BUFFER_TEST_HELPERS_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_DRAWING_BUFFER_TEST_HELPERS_H_
#include "build/build_config.h" #include "build/build_config.h"
#include "cc/test/stub_decode_cache.h"
#include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/capabilities.h"
#include "gpu/config/gpu_feature_info.h" #include "gpu/config/gpu_feature_info.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
...@@ -53,9 +54,12 @@ class WebGraphicsContext3DProviderForTests ...@@ -53,9 +54,12 @@ class WebGraphicsContext3DProviderForTests
void SetErrorMessageCallback( void SetErrorMessageCallback(
base::RepeatingCallback<void(const char*, int32_t id)>) override {} base::RepeatingCallback<void(const char*, int32_t id)>) override {}
void SignalQuery(uint32_t, base::OnceClosure) override {} void SignalQuery(uint32_t, base::OnceClosure) override {}
cc::ImageDecodeCache* ImageDecodeCache() override { return nullptr; } cc::ImageDecodeCache* ImageDecodeCache() override {
return &image_decode_cache_;
}
private: private:
cc::StubDecodeCache image_decode_cache_;
std::unique_ptr<gpu::gles2::GLES2Interface> gl_; std::unique_ptr<gpu::gles2::GLES2Interface> gl_;
gpu::Capabilities capabilities_; gpu::Capabilities capabilities_;
gpu::GpuFeatureInfo gpu_feature_info_; gpu::GpuFeatureInfo gpu_feature_info_;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/platform/graphics/image.h" #include "third_party/blink/renderer/platform/graphics/image.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "cc/tiles/software_image_decode_cache.h"
#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h" #include "third_party/blink/renderer/platform/geometry/float_point.h"
...@@ -91,6 +92,18 @@ Image* Image::NullImage() { ...@@ -91,6 +92,18 @@ Image* Image::NullImage() {
return null_image; return null_image;
} }
// static
cc::ImageDecodeCache& Image::SharedCCDecodeCache() {
// 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.
static const size_t kLockedMemoryLimitBytes = 64 * 1024 * 1024;
DEFINE_THREAD_SAFE_STATIC_LOCAL(cc::SoftwareImageDecodeCache,
image_decode_cache,
(kN32_SkColorType, kLockedMemoryLimitBytes));
return image_decode_cache;
}
scoped_refptr<Image> Image::LoadPlatformResource(const char* name) { scoped_refptr<Image> Image::LoadPlatformResource(const char* name) {
const WebData& resource = Platform::Current()->GetDataResource(name); const WebData& resource = Platform::Current()->GetDataResource(name);
if (resource.IsEmpty()) if (resource.IsEmpty())
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
class SkMatrix; class SkMatrix;
namespace cc { namespace cc {
class ImageDecodeCache;
class PaintCanvas; class PaintCanvas;
class PaintFlags; class PaintFlags;
} // namespace cc } // namespace cc
...@@ -75,6 +76,8 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> { ...@@ -75,6 +76,8 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
public: public:
virtual ~Image(); virtual ~Image();
static cc::ImageDecodeCache& SharedCCDecodeCache();
static scoped_refptr<Image> LoadPlatformResource(const char* name); static scoped_refptr<Image> LoadPlatformResource(const char* name);
static bool SupportsType(const String&); static bool SupportsType(const String&);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEST_FAKE_WEB_GRAPHICS_CONTEXT_3D_PROVIDER_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEST_FAKE_WEB_GRAPHICS_CONTEXT_3D_PROVIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEST_FAKE_WEB_GRAPHICS_CONTEXT_3D_PROVIDER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEST_FAKE_WEB_GRAPHICS_CONTEXT_3D_PROVIDER_H_
#include "cc/test/stub_decode_cache.h"
#include "cc/tiles/image_decode_cache.h" #include "cc/tiles/image_decode_cache.h"
#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/capabilities.h"
...@@ -20,7 +21,8 @@ class FakeWebGraphicsContext3DProvider : public WebGraphicsContext3DProvider { ...@@ -20,7 +21,8 @@ class FakeWebGraphicsContext3DProvider : public WebGraphicsContext3DProvider {
public: public:
FakeWebGraphicsContext3DProvider(gpu::gles2::GLES2Interface* gl, FakeWebGraphicsContext3DProvider(gpu::gles2::GLES2Interface* gl,
cc::ImageDecodeCache* cache = nullptr) cc::ImageDecodeCache* cache = nullptr)
: gl_(gl), image_decode_cache_(cache) { : gl_(gl),
image_decode_cache_(cache ? cache : &stub_image_decode_cache_) {
sk_sp<const GrGLInterface> gl_interface(GrGLCreateNullInterface()); sk_sp<const GrGLInterface> gl_interface(GrGLCreateNullInterface());
gr_context_ = GrContext::MakeGL(std::move(gl_interface)); gr_context_ = GrContext::MakeGL(std::move(gl_interface));
} }
...@@ -52,6 +54,8 @@ class FakeWebGraphicsContext3DProvider : public WebGraphicsContext3DProvider { ...@@ -52,6 +54,8 @@ class FakeWebGraphicsContext3DProvider : public WebGraphicsContext3DProvider {
} }
private: private:
cc::StubDecodeCache stub_image_decode_cache_;
gpu::gles2::GLES2Interface* gl_; gpu::gles2::GLES2Interface* gl_;
sk_sp<GrContext> gr_context_; sk_sp<GrContext> gr_context_;
gpu::Capabilities capabilities_; gpu::Capabilities capabilities_;
......
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