提交 3de2e1cf 编写于 作者: A Adam Barth

Experiment with caching rasterized layers

This patch adds back (and tweaks) some code that we previously removed
for caching rasterized layers. Now that our layerization code in the
framework is more sophisticated, we should be able to get more value out
of this mechanism.
上级 e75a0cb4
......@@ -32,6 +32,8 @@ source_set("compositor") {
"picture_layer.h",
"picture_serializer.cc",
"picture_serializer.h",
"raster_cache.cc",
"raster_cache.h",
"statistics_layer.cc",
"statistics_layer.h",
"transform_layer.cc",
......
......@@ -27,12 +27,12 @@ static void DrawCheckerboard(SkCanvas* canvas,
canvas->drawPaint(paint);
}
void DrawCheckerboard(SkCanvas* canvas, int width, int height) {
SkRect rect = SkRect::MakeIWH(width, height);
void DrawCheckerboard(SkCanvas* canvas, const SkRect& rect) {
// Draw a checkerboard
canvas->save();
canvas->clipRect(rect);
DrawCheckerboard(canvas, 0x4400FF00, 0x00000000, 12);
canvas->restore();
// Stroke the drawn area
SkPaint debugPaint;
......
......@@ -10,7 +10,7 @@
namespace sky {
namespace compositor {
void DrawCheckerboard(SkCanvas* canvas, int width, int height);
void DrawCheckerboard(SkCanvas* canvas, const SkRect& rect);
} // namespace compositor
} // namespace sky
......
......@@ -22,6 +22,7 @@ void PaintContext::beginFrame(ScopedFrame& frame, bool enableInstrumentation) {
}
void PaintContext::endFrame(ScopedFrame& frame, bool enableInstrumentation) {
raster_cache_.SweepAfterFrame();
if (enableInstrumentation) {
frame_time_.stop();
}
......
......@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/logging.h"
#include "sky/compositor/instrumentation.h"
#include "sky/compositor/raster_cache.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "ui/gfx/geometry/size.h"
......@@ -56,6 +57,8 @@ class PaintContext {
ScopedFrame AcquireFrame(const std::string& trace_file_name,
gfx::Size frame_size);
RasterCache& raster_cache() { return raster_cache_; }
const instrumentation::Counter& frame_count() const { return frame_count_; }
const instrumentation::Stopwatch& frame_time() const { return frame_time_; }
......@@ -63,6 +66,8 @@ class PaintContext {
instrumentation::Stopwatch& engine_time() { return engine_time_; };
private:
RasterCache raster_cache_;
instrumentation::Counter frame_count_;
instrumentation::Stopwatch frame_time_;
instrumentation::Stopwatch engine_time_;
......
......@@ -3,11 +3,19 @@
// found in the LICENSE file.
#include "sky/compositor/picture_layer.h"
#include "base/logging.h"
#include "sky/compositor/checkerboard.h"
#include "sky/compositor/raster_cache.h"
#define ENABLE_RASTER_CACHE 0
namespace sky {
namespace compositor {
// TODO(abarth): Make this configurable by developers.
const bool kDebugCheckerboardRasterizedLayers = false;
PictureLayer::PictureLayer() {
}
......@@ -18,10 +26,30 @@ void PictureLayer::Paint(PaintContext::ScopedFrame& frame) {
DCHECK(picture_);
SkCanvas& canvas = frame.canvas();
canvas.save();
canvas.translate(offset_.x(), offset_.y());
canvas.drawPicture(picture_.get());
canvas.restore();
#if ENABLE_RASTER_CACHE
const SkMatrix& ctm = canvas.getTotalMatrix();
SkISize size = SkISize::Make(paint_bounds().width() * ctm.getScaleX(),
paint_bounds().height() * ctm.getScaleY());
RasterCache& cache = frame.context().raster_cache();
RefPtr<SkImage> image = cache.GetImage(picture_.get(), size);
#else
RefPtr<SkImage> image;
#endif
if (image) {
canvas.drawImage(image.get(), offset_.x(), offset_.y());
if (kDebugCheckerboardRasterizedLayers) {
SkRect rect = paint_bounds().makeOffset(offset_.x(), offset_.y());
DrawCheckerboard(&canvas, rect);
}
} else {
canvas.save();
canvas.translate(offset_.x(), offset_.y());
canvas.drawPicture(picture_.get());
canvas.restore();
}
}
} // namespace compositor
......
// Copyright 2016 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 "sky/compositor/raster_cache.h"
#include "sky/compositor/paint_context.h"
#include "base/logging.h"
#include "third_party/skia/include/core/SkImage.h"
namespace sky {
namespace compositor {
static const int kRasterThreshold = 3;
static bool isWorthRasterizing(SkPicture* picture) {
// TODO(abarth): We should find a better heuristic here that lets us avoid
// wasting memory on trivial layers that are easy to re-rasterize every frame.
return picture->approximateOpCount() > 10 || picture->hasText();
}
RasterCache::RasterCache() {
}
RasterCache::~RasterCache() {
}
RasterCache::Entry::Entry() {
physical_size.setEmpty();
}
RasterCache::Entry::~Entry() {
}
RefPtr<SkImage> RasterCache::GetImage(
SkPicture* picture, const SkISize& physical_size) {
if (physical_size.isEmpty())
return nullptr;
Entry& entry = cache_[picture->uniqueID()];
const bool size_matched = entry.physical_size == physical_size;
entry.used_this_frame = true;
entry.physical_size = physical_size;
if (!size_matched) {
entry.access_count = 1;
entry.image = nullptr;
return nullptr;
}
entry.access_count++;
if (entry.access_count >= kRasterThreshold) {
// Saturate at the threshhold.
entry.access_count = kRasterThreshold;
if (!entry.image && isWorthRasterizing(picture)) {
entry.image = adoptRef(SkImage::NewFromPicture(picture, physical_size,
nullptr, nullptr));
}
}
return entry.image;
}
void RasterCache::SweepAfterFrame() {
std::vector<Cache::iterator> dead;
for (auto it = cache_.begin(); it != cache_.end(); ++it) {
Entry& entry = it->second;
if (!entry.used_this_frame)
dead.push_back(it);
entry.used_this_frame = false;
}
for (auto it : dead)
cache_.erase(it);
}
} // namespace compositor
} // namespace sky
// Copyright 2016 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.
#ifndef SKY_COMPOSITOR_RASTER_CACHE_H_
#define SKY_COMPOSITOR_RASTER_CACHE_H_
#include <memory>
#include <unordered_map>
#include "base/macros.h"
#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/core/SkImage.h"
#include "sky/compositor/instrumentation.h"
#include "sky/engine/wtf/PassRefPtr.h"
#include "sky/engine/wtf/RefPtr.h"
namespace sky {
namespace compositor {
class RasterCache {
public:
RasterCache();
~RasterCache();
RefPtr<SkImage> GetImage(SkPicture* picture, const SkISize& physical_size);
void SweepAfterFrame();
private:
struct Entry {
Entry();
~Entry();
bool used_this_frame = false;
int access_count = 0;
SkISize physical_size;
RefPtr<SkImage> image;
};
using Cache = std::unordered_map<uint32_t, Entry>;
Cache cache_;
DISALLOW_COPY_AND_ASSIGN(RasterCache);
};
} // namespace compositor
} // namespace sky
#endif // SKY_COMPOSITOR_RASTER_CACHE_H_
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册