Commit 75028fa6 authored by Khushal's avatar Khushal Committed by Commit Bot

cc/blink: Use same rounding for cc and ImageDecoder mip level sizes.

The JPEGDecoder ceils when rounding floats for mip level sizes while the
cc code floors. This results in 1 pixel differences in the scaled sizes
when using decode to scale. Avoid this by switching the cc mip size
calculations to match the decoder.

R=ericrk@chromium.org, chrishtr@chromium.org

Bug: 761565,558070
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I07069a4eff582ffbb621388ccae32b18aedebd3a
Reviewed-on: https://chromium-review.googlesource.com/1107049
Commit-Queue: Khushal <khushalsagar@chromium.org>
Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569626}
parent ae149e74
...@@ -4,13 +4,25 @@ ...@@ -4,13 +4,25 @@
#include "cc/tiles/mipmap_util.h" #include "cc/tiles/mipmap_util.h"
#include "base/numerics/safe_math.h"
namespace cc { namespace cc {
namespace { namespace {
// Calculates the size of |axis_base_size| at the given |mip_level| using // Calculates the size of |axis_base_size| at the given |mip_level|. Note that
// OpenGL rounding rules. // the calculation here rounds up for consistency with size calculations in the
// JPEG decoder. This allows us to decode images to the mip size directly.
int ScaleAxisToMipLevel(int axis_base_size, int mip_level) { int ScaleAxisToMipLevel(int axis_base_size, int mip_level) {
DCHECK_GE(mip_level, 0); DCHECK_GE(mip_level, 0);
DCHECK_LT(mip_level, 32); DCHECK_LT(mip_level, 32);
if (mip_level == 0)
return axis_base_size;
// Increment the size by (2^mip_level - 1) so we round on when dividing it
// below.
base::CheckedNumeric<int> base_size = axis_base_size;
base_size += (1 << mip_level) - 1;
axis_base_size = base_size.ValueOrDefault(std::numeric_limits<int>::max());
return std::max(1, axis_base_size >> mip_level); return std::max(1, axis_base_size >> mip_level);
} }
......
...@@ -85,8 +85,8 @@ TEST(MipMapUtilTest, NonSquare) { ...@@ -85,8 +85,8 @@ TEST(MipMapUtilTest, NonSquare) {
// Ensures that we handle rounding images correctly. // Ensures that we handle rounding images correctly.
TEST(MipMapUtilTest, Rounding) { TEST(MipMapUtilTest, Rounding) {
const gfx::Size src_size(49, 49); const gfx::Size src_size(49, 49);
const gfx::Size target_size_larger(25, 25); const gfx::Size target_size_larger(26, 26);
const gfx::Size target_size_smaller(24, 24); const gfx::Size target_size_smaller(25, 25);
const int target_level_larger = 0; const int target_level_larger = 0;
const int target_level_smaller = 1; const int target_level_smaller = 1;
const SkSize expected_scale_larger = SkSize::Make(1, 1); const SkSize expected_scale_larger = SkSize::Make(1, 1);
...@@ -116,5 +116,15 @@ TEST(MipMapUtilTest, Rounding) { ...@@ -116,5 +116,15 @@ TEST(MipMapUtilTest, Rounding) {
MipMapUtil::GetScaleAdjustmentForSize(src_size, target_size_smaller)); MipMapUtil::GetScaleAdjustmentForSize(src_size, target_size_smaller));
} }
// Ensures that we round up during mip calculation.
TEST(MipMapUtilTest, RoundUp) {
const gfx::Size src_sizes[] = {gfx::Size(3, 3), gfx::Size(5, 7),
gfx::Size(11, 14), gfx::Size(17, 31)};
for (int i = 0; i < 4; ++i) {
EXPECT_EQ(MipMapUtil::GetSizeForLevel(src_sizes[i], i + 1),
gfx::Size(2, 2));
}
}
} // namespace } // namespace
} // namespace cc } // namespace cc
...@@ -396,9 +396,9 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_1Scale) { ...@@ -396,9 +396,9 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_1Scale) {
draw_image, kN32_SkColorType); draw_image, kN32_SkColorType);
EXPECT_EQ(draw_image.frame_key(), key.frame_key()); EXPECT_EQ(draw_image.frame_key(), key.frame_key());
EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale); EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
EXPECT_EQ(62, key.target_size().width()); EXPECT_EQ(63, key.target_size().width());
EXPECT_EQ(25, key.target_size().height()); EXPECT_EQ(25, key.target_size().height());
EXPECT_EQ(62u * 25u * 4u, key.locked_bytes()); EXPECT_EQ(63u * 25u * 4u, key.locked_bytes());
} }
TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_01Scale) { TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_01Scale) {
...@@ -415,9 +415,9 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_01Scale) { ...@@ -415,9 +415,9 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_01Scale) {
draw_image, kN32_SkColorType); draw_image, kN32_SkColorType);
EXPECT_EQ(draw_image.frame_key(), key.frame_key()); EXPECT_EQ(draw_image.frame_key(), key.frame_key());
EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale); EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
EXPECT_EQ(7, key.target_size().width()); EXPECT_EQ(8, key.target_size().width());
EXPECT_EQ(3, key.target_size().height()); EXPECT_EQ(4, key.target_size().height());
EXPECT_EQ(7u * 3u * 4u, key.locked_bytes()); EXPECT_EQ(8u * 4u * 4u, key.locked_bytes());
} }
TEST(SoftwareImageDecodeCacheTest, TEST(SoftwareImageDecodeCacheTest,
...@@ -477,9 +477,9 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToMediumIfTooLarge) { ...@@ -477,9 +477,9 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToMediumIfTooLarge) {
draw_image, kN32_SkColorType); draw_image, kN32_SkColorType);
EXPECT_EQ(draw_image.frame_key(), key.frame_key()); EXPECT_EQ(draw_image.frame_key(), key.frame_key());
EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale); EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
EXPECT_EQ(2277, key.target_size().width()); EXPECT_EQ(2278, key.target_size().width());
EXPECT_EQ(1024, key.target_size().height()); EXPECT_EQ(1024, key.target_size().height());
EXPECT_EQ(2277u * 1024u * 4u, key.locked_bytes()); EXPECT_EQ(2278u * 1024u * 4u, key.locked_bytes());
} }
TEST(SoftwareImageDecodeCacheTest, TEST(SoftwareImageDecodeCacheTest,
...@@ -1445,7 +1445,7 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_1ScaleIsHandled) { ...@@ -1445,7 +1445,7 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_1ScaleIsHandled) {
// Decoded image should not be lazy generated. // Decoded image should not be lazy generated.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated()); EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality()); EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
EXPECT_EQ(62, decoded_draw_image.image()->width()); EXPECT_EQ(63, decoded_draw_image.image()->width());
EXPECT_EQ(25, decoded_draw_image.image()->height()); EXPECT_EQ(25, decoded_draw_image.image()->height());
cache.DrawWithImageFinished(draw_image, decoded_draw_image); cache.DrawWithImageFinished(draw_image, decoded_draw_image);
...@@ -1476,8 +1476,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_01ScaleIsHandled) { ...@@ -1476,8 +1476,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_01ScaleIsHandled) {
// Decoded image should not be lazy generated. // Decoded image should not be lazy generated.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated()); EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality()); EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
EXPECT_EQ(7, decoded_draw_image.image()->width()); EXPECT_EQ(8, decoded_draw_image.image()->width());
EXPECT_EQ(3, decoded_draw_image.image()->height()); EXPECT_EQ(4, decoded_draw_image.image()->height());
cache.DrawWithImageFinished(draw_image, decoded_draw_image); cache.DrawWithImageFinished(draw_image, decoded_draw_image);
cache.UnrefImage(draw_image); cache.UnrefImage(draw_image);
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "base/test/simple_test_tick_clock.h" #include "base/test/simple_test_tick_clock.h"
#include "cc/paint/skia_paint_canvas.h" #include "cc/paint/skia_paint_canvas.h"
#include "cc/tiles/mipmap_util.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h" #include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h" #include "third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h"
...@@ -504,6 +505,22 @@ TEST_F(BitmapImageTest, GIFRepetitionCount) { ...@@ -504,6 +505,22 @@ TEST_F(BitmapImageTest, GIFRepetitionCount) {
EXPECT_EQ(paint_image.FrameCount(), 3u); EXPECT_EQ(paint_image.FrameCount(), 3u);
} }
TEST_F(BitmapImageTest, DecoderAndCacheMipLevels) {
// Tests that the supported sizes from the decoder match the mip level sizes
// in cc.
LoadImage("/images/resources/cat.jpg");
auto paint_image = image_->PaintImageForCurrentFrame();
// Jpeg decoder supports upto 1/8 downscales, or mip level 3.
for (int mip_level = 0; mip_level < 4; ++mip_level) {
SCOPED_TRACE(mip_level);
SkISize scaled_size = gfx::SizeToSkISize(cc::MipMapUtil::GetSizeForLevel(
gfx::Size(paint_image.width(), paint_image.height()), mip_level));
SkISize supported_size = paint_image.GetSupportedDecodeSize(scaled_size);
EXPECT_EQ(gfx::SkISizeToSize(supported_size),
gfx::SkISizeToSize(scaled_size));
}
}
class BitmapImageTestWithMockDecoder : public BitmapImageTest, class BitmapImageTestWithMockDecoder : public BitmapImageTest,
public MockImageDecoderClient { public MockImageDecoderClient {
public: public:
......
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