Commit 13778fbf authored by vmpstr's avatar vmpstr Committed by Commit bot

cc: Optimize ImageDecodeCacheKey::FromDrawImage.

This patch reduces the time spent in ::FromDrawImage call by 50%. Comes
with a corresponding perftest. This is a frequently used function
when it comes to dealing with software images, so any savings should
be good.

Perftest result without the sidc change (z620):
*RESULT software_image_decode_cache_fromdrawimage: result= 318435.53125 runs/s

With the change:
*RESULT software_image_decode_cache_fromdrawimage: result= 657221.0625 runs/s (+106%)

R=enne@chromium.org, ericrk@chromium.org
CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel

Review-Url: https://codereview.chromium.org/2669933002
Cr-Commit-Position: refs/heads/master@{#447882}
parent ff3e5ef9
......@@ -955,6 +955,7 @@ cc_test("cc_perftests") {
"surfaces/surface_aggregator_perftest.cc",
"test/cc_test_suite.cc",
"test/run_all_perftests.cc",
"tiles/software_image_decode_cache_perftest.cc",
"tiles/tile_manager_perftest.cc",
"trees/layer_tree_host_common_perftest.cc",
"trees/layer_tree_host_perftest.cc",
......
......@@ -29,7 +29,7 @@ class CC_EXPORT DrawImage {
const sk_sp<const SkImage>& image() const { return image_; }
const SkSize& scale() const { return scale_; }
const SkIRect src_rect() const { return src_rect_; }
const SkIRect& src_rect() const { return src_rect_; }
SkFilterQuality filter_quality() const { return filter_quality_; }
bool matrix_is_decomposable() const { return matrix_is_decomposable_; }
const SkMatrix& matrix() const { return matrix_; }
......
......@@ -51,7 +51,10 @@ const size_t kSuspendedMaxItemsInCache = 0;
// The second part that much be true is that we cache only the needed subrect if
// the total size needed for the subrect is at most kMemoryRatioToSubrect *
// (size needed for the full original image).
// Note that at least one of the dimensions has to be at least
// kMinDimensionToSubrect before an image can breach the threshold.
const size_t kMemoryThresholdToSubrect = 64 * 1024 * 1024;
const int kMinDimensionToSubrect = 4 * 1024;
const float kMemoryRatioToSubrect = 0.5f;
class AutoRemoveKeyFromTaskMap {
......@@ -176,6 +179,17 @@ void RecordLockExistingCachedImageHistogram(TilePriority::PriorityBin bin,
}
}
gfx::Rect GetSrcRect(const DrawImage& image) {
const SkIRect& src_rect = image.src_rect();
int x = std::max(0, src_rect.x());
int y = std::max(0, src_rect.y());
int right = std::min(image.image()->width(), src_rect.right());
int bottom = std::min(image.image()->height(), src_rect.bottom());
if (x >= right || y >= bottom)
return gfx::Rect();
return gfx::Rect(x, y, right - x, bottom - y);
}
} // namespace
SoftwareImageDecodeCache::SoftwareImageDecodeCache(
......@@ -898,10 +912,7 @@ ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) {
// otherwise we might end up with uninitialized memory in the decode process.
// Note that the scale is still unchanged and the target size is now a
// function of the new src_rect.
gfx::Rect src_rect = gfx::IntersectRects(
gfx::SkIRectToRect(image.src_rect()),
gfx::Rect(image.image()->width(), image.image()->height()));
const gfx::Rect& src_rect = GetSrcRect(image);
gfx::Size target_size(
SkScalarRoundToInt(std::abs(src_rect.width() * scale.width())),
SkScalarRoundToInt(std::abs(src_rect.height() * scale.height())));
......@@ -950,7 +961,9 @@ ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) {
bool can_use_original_decode =
quality == kLow_SkFilterQuality || quality == kNone_SkFilterQuality;
bool should_use_subrect = false;
if (can_use_original_decode) {
if (can_use_original_decode &&
(image.image()->width() >= kMinDimensionToSubrect ||
image.image()->height() >= kMinDimensionToSubrect)) {
base::CheckedNumeric<size_t> checked_original_size = 4u;
checked_original_size *= image.image()->width();
checked_original_size *= image.image()->height();
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <vector>
#include "cc/debug/lap_timer.h"
#include "cc/playback/draw_image.h"
#include "cc/raster/tile_task.h"
#include "cc/tiles/software_image_decode_cache.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
namespace cc {
namespace {
static const int kTimeLimitMillis = 2000;
static const int kWarmupRuns = 5;
static const int kTimeCheckInterval = 10;
sk_sp<SkImage> CreateImage(int width, int height) {
SkBitmap bitmap;
bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height));
return SkImage::MakeFromBitmap(bitmap);
}
SkMatrix CreateMatrix(const SkSize& scale) {
SkMatrix matrix;
matrix.setScale(scale.width(), scale.height());
return matrix;
}
class SoftwareImageDecodeCachePerfTest : public testing::Test {
public:
SoftwareImageDecodeCachePerfTest()
: timer_(kWarmupRuns,
base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
kTimeCheckInterval) {}
void RunFromImage() {
SkFilterQuality qualities[] = {kNone_SkFilterQuality, kLow_SkFilterQuality,
kMedium_SkFilterQuality,
kHigh_SkFilterQuality};
std::pair<SkIRect, SkIRect> image_rect_subrect[] = {
std::make_pair(SkIRect::MakeWH(100, 100), SkIRect::MakeWH(100, 100)),
std::make_pair(SkIRect::MakeWH(100, 100), SkIRect::MakeWH(50, 50)),
std::make_pair(SkIRect::MakeWH(100, 100), SkIRect::MakeWH(1000, 1000))};
std::pair<float, float> scales[] = {
std::make_pair(1.f, 1.f), std::make_pair(0.5f, 0.5f),
std::make_pair(2.f, 2.f), std::make_pair(0.5f, 1.5f)};
std::vector<DrawImage> images;
for (auto& quality : qualities) {
for (auto& rect_subrect : image_rect_subrect) {
auto& rect = rect_subrect.first;
auto& subrect = rect_subrect.second;
for (auto& scale : scales) {
images.emplace_back(
CreateImage(rect.width(), rect.height()), subrect, quality,
CreateMatrix(SkSize::Make(scale.first, scale.second)));
}
}
}
timer_.Reset();
do {
for (auto& image : images)
ImageDecodeCacheKey::FromDrawImage(image);
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
perf_test::PrintResult("software_image_decode_cache_fromdrawimage", "",
"result", timer_.LapsPerSecond(), "runs/s", true);
}
private:
LapTimer timer_;
};
TEST_F(SoftwareImageDecodeCachePerfTest, FromDrawImage) {
RunFromImage();
}
} // namespace
} // namespace cc
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