mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Merge pull request #2225 from abarth/cache_layers
Experiment with caching rasterized layers
This commit is contained in:
commit
f4fc4e24a0
@ -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
|
||||
|
||||
83
sky/compositor/raster_cache.cc
Normal file
83
sky/compositor/raster_cache.cc
Normal file
@ -0,0 +1,83 @@
|
||||
// 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
|
||||
49
sky/compositor/raster_cache.h
Normal file
49
sky/compositor/raster_cache.h
Normal file
@ -0,0 +1,49 @@
|
||||
// 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_
|
||||
Loading…
x
Reference in New Issue
Block a user