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) {
var height = 100;
var ctx1 = createNewCanvas(width, height);
var ctx2 = createNewCanvas(width, height);
ctx1.imageSmoothingEnabled = true;
ctx1.imageSmoothingQuality = 'low';
ctx1.imageSmoothingEnabled = false;
ctx2.imageSmoothingEnabled = true;
ctx2.imageSmoothingQuality = 'high';
ctx1.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, width, height);
......@@ -43,5 +42,5 @@ async_test(function(t) {
compareTwoCanvases(ctx1, ctx2, width, height);
});
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>
......@@ -71,26 +71,17 @@ test(function(t) {
lowContext.imageSmoothingEnabled = false;
var noFilterData = scaleImageData(lowCanvas, lowCanvas.imageSmoothingQuality);
assert_false(lowData === mediumData);
// Skia uses mipmaps when downscaling, for both high and medium quality
assert_equals(mediumData, highData);
assert_false(lowData === 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));
// No filtering uses kNone quality, while with imageSmoothingEnabled we use the
// same quality.
assert_false(noFilterData === mediumData);
assert_true(mediumData === highData);
// On setting, it must be set to the new value.
highContext.imageSmoothingQuality = 'medium';
assert_equals(highContext.imageSmoothingQuality, 'medium');
assert_equals(scaleImageData(highCanvas, highCanvas.imageSmoothingQuality),
mediumData);
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'.
assert_equals(document.getElementById("default").getContext("2d").imageSmoothingQuality, 'low');
......
......@@ -1076,16 +1076,6 @@ bool BaseRenderingContext2D::ShouldDrawImageAntialiased(
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,
CanvasImageSource* image_source,
Image* image,
......@@ -1119,12 +1109,6 @@ void BaseRenderingContext2D::DrawImageInternal(PaintCanvas* c,
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()) {
image_flags.setAntiAlias(ShouldDrawImageAntialiased(dst_rect));
image->Draw(c, image_flags, dst_rect, src_rect,
......
......@@ -1298,13 +1298,14 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) {
Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
color_params));
gfx::ColorSpace expected_color_space = gfx::ColorSpace::CreateSRGB();
std::vector<cc::DrawImage> images = {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
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)),
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()->drawImageRect(
......
......@@ -382,12 +382,13 @@ PaintCanvas* CanvasResourceProvider::Canvas() {
if (!canvas_) {
DCHECK(!canvas_image_provider_);
cc::ImageProvider* image_provider = nullptr;
if (ImageDecodeCache()) {
canvas_image_provider_.emplace(ImageDecodeCache(),
ColorParams().GetStorageGfxColorSpace());
image_provider = &*canvas_image_provider_;
}
gfx::ColorSpace target_color_space =
ColorParams().NeedsSkColorSpaceXformCanvas()
? ColorParams().GetStorageGfxColorSpace()
: gfx::ColorSpace::CreateSRGB();
canvas_image_provider_.emplace(ImageDecodeCache(), target_color_space);
cc::ImageProvider* image_provider = &*canvas_image_provider_;
cc::SkiaPaintCanvas::ContextFlushes context_flushes;
if (IsAccelerated()) {
......@@ -399,11 +400,10 @@ PaintCanvas* CanvasResourceProvider::Canvas() {
if (ColorParams().NeedsSkColorSpaceXformCanvas()) {
canvas_ = std::make_unique<cc::SkiaPaintCanvas>(
GetSkSurface()->getCanvas(), ColorParams().GetSkColorSpace(),
std::move(image_provider), context_flushes);
image_provider, context_flushes);
} else {
canvas_ = std::make_unique<cc::SkiaPaintCanvas>(
GetSkSurface()->getCanvas(), std::move(image_provider),
context_flushes);
GetSkSurface()->getCanvas(), image_provider, context_flushes);
}
}
......@@ -542,10 +542,9 @@ scoped_refptr<CanvasResource> CanvasResourceProvider::CreateResource() {
}
cc::ImageDecodeCache* CanvasResourceProvider::ImageDecodeCache() {
// TODO(khushalsagar): Hook up a software cache.
if (!context_provider_wrapper_)
return nullptr;
return context_provider_wrapper_->ContextProvider()->ImageDecodeCache();
if (context_provider_wrapper_)
return context_provider_wrapper_->ContextProvider()->ImageDecodeCache();
return &Image::SharedCCDecodeCache();
}
} // namespace blink
......@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_DRAWING_BUFFER_TEST_HELPERS_H_
#include "build/build_config.h"
#include "cc/test/stub_decode_cache.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/config/gpu_feature_info.h"
#include "testing/gmock/include/gmock/gmock.h"
......@@ -53,9 +54,12 @@ class WebGraphicsContext3DProviderForTests
void SetErrorMessageCallback(
base::RepeatingCallback<void(const char*, int32_t id)>) override {}
void SignalQuery(uint32_t, base::OnceClosure) override {}
cc::ImageDecodeCache* ImageDecodeCache() override { return nullptr; }
cc::ImageDecodeCache* ImageDecodeCache() override {
return &image_decode_cache_;
}
private:
cc::StubDecodeCache image_decode_cache_;
std::unique_ptr<gpu::gles2::GLES2Interface> gl_;
gpu::Capabilities capabilities_;
gpu::GpuFeatureInfo gpu_feature_info_;
......
......@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/platform/graphics/image.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/web_data.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
......@@ -91,6 +92,18 @@ Image* Image::NullImage() {
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) {
const WebData& resource = Platform::Current()->GetDataResource(name);
if (resource.IsEmpty())
......
......@@ -47,6 +47,7 @@
class SkMatrix;
namespace cc {
class ImageDecodeCache;
class PaintCanvas;
class PaintFlags;
} // namespace cc
......@@ -75,6 +76,8 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
public:
virtual ~Image();
static cc::ImageDecodeCache& SharedCCDecodeCache();
static scoped_refptr<Image> LoadPlatformResource(const char* name);
static bool SupportsType(const String&);
......
......@@ -5,6 +5,7 @@
#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_
#include "cc/test/stub_decode_cache.h"
#include "cc/tiles/image_decode_cache.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
......@@ -20,7 +21,8 @@ class FakeWebGraphicsContext3DProvider : public WebGraphicsContext3DProvider {
public:
FakeWebGraphicsContext3DProvider(gpu::gles2::GLES2Interface* gl,
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());
gr_context_ = GrContext::MakeGL(std::move(gl_interface));
}
......@@ -52,6 +54,8 @@ class FakeWebGraphicsContext3DProvider : public WebGraphicsContext3DProvider {
}
private:
cc::StubDecodeCache stub_image_decode_cache_;
gpu::gles2::GLES2Interface* gl_;
sk_sp<GrContext> gr_context_;
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