提交 d0009550 编写于 作者: C Chinmay Garde

PictureRasterizer for caches pictures as images

上级 153a8005
......@@ -28,6 +28,7 @@
#include "services/sky/internals.h"
#include "services/sky/runtime_flags.h"
#include "skia/ext/refptr.h"
#include "sky/compositor/paint_context.h"
#include "sky/engine/public/platform/Platform.h"
#include "sky/engine/public/platform/WebInputEvent.h"
#include "sky/engine/public/web/Sky.h"
......@@ -222,8 +223,10 @@ void DocumentView::OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) {
}
void DocumentView::PaintContents(SkCanvas* canvas, const gfx::Rect& clip) {
if (current_layer_tree_)
current_layer_tree_->root_layer()->Paint(nullptr, canvas);
if (current_layer_tree_) {
compositor::PaintContext context(picture_rasterizer_, nullptr, canvas);
current_layer_tree_->root_layer()->Paint(context);
}
}
float DocumentView::GetDevicePixelRatio() const {
......
......@@ -23,6 +23,7 @@
#include "services/sky/compositor/layer_client.h"
#include "services/sky/compositor/layer_host_client.h"
#include "sky/compositor/layer_tree.h"
#include "sky/compositor/picture_rasterizer.h"
#include "sky/engine/public/platform/ServiceProvider.h"
#include "sky/engine/public/sky/sky_view.h"
#include "sky/engine/public/sky/sky_view_client.h"
......@@ -130,6 +131,7 @@ class DocumentView : public blink::ServiceProvider,
scoped_ptr<LayerHost> layer_host_;
scoped_refptr<TextureLayer> root_layer_;
std::unique_ptr<compositor::LayerTree> current_layer_tree_; // TODO(abarth): Integrate //sky/compositor and //services/sky/compositor.
compositor::PictureRasterzier picture_rasterizer_;
RasterizerBitmap* bitmap_rasterizer_; // Used for pixel tests.
mojo::ServiceRegistryPtr service_registry_;
scoped_ptr<mojo::StrongBinding<mojo::ServiceProvider>>
......
......@@ -20,8 +20,12 @@ source_set("compositor") {
"layer_tree.h",
"opacity_layer.cc",
"opacity_layer.h",
"paint_context.cc",
"paint_context.h",
"picture_layer.cc",
"picture_layer.h",
"picture_rasterizer.cc",
"picture_rasterizer.h",
"transform_layer.cc",
"transform_layer.h",
]
......
......@@ -13,10 +13,11 @@ ClipPathLayer::ClipPathLayer() {
ClipPathLayer::~ClipPathLayer() {
}
void ClipPathLayer::Paint(GrContext* context, SkCanvas* canvas) {
void ClipPathLayer::Paint(PaintContext& context) {
SkCanvas* canvas = context.canvas();
canvas->saveLayer(&clip_path_.getBounds(), nullptr);
canvas->clipPath(clip_path_);
PaintChildren(context, canvas);
PaintChildren(context);
canvas->restore();
}
......
......@@ -17,7 +17,7 @@ class ClipPathLayer : public ContainerLayer {
void set_clip_path(const SkPath& clip_path) { clip_path_ = clip_path; }
void Paint(GrContext* context, SkCanvas* canvas) override;
void Paint(PaintContext& context) override;
private:
SkPath clip_path_;
......
......@@ -13,10 +13,11 @@ ClipRectLayer::ClipRectLayer() {
ClipRectLayer::~ClipRectLayer() {
}
void ClipRectLayer::Paint(GrContext* context, SkCanvas* canvas) {
void ClipRectLayer::Paint(PaintContext& context) {
SkCanvas* canvas = context.canvas();
canvas->save();
canvas->clipRect(clip_rect_);
PaintChildren(context, canvas);
PaintChildren(context);
canvas->restore();
}
......
......@@ -17,7 +17,7 @@ class ClipRectLayer : public ContainerLayer {
void set_clip_rect(const SkRect& clip_rect) { clip_rect_ = clip_rect; }
void Paint(GrContext* context, SkCanvas* canvas) override;
void Paint(PaintContext& context) override;
private:
SkRect clip_rect_;
......
......@@ -13,10 +13,11 @@ ClipRRectLayer::ClipRRectLayer() {
ClipRRectLayer::~ClipRRectLayer() {
}
void ClipRRectLayer::Paint(GrContext* context, SkCanvas* canvas) {
void ClipRRectLayer::Paint(PaintContext& context) {
SkCanvas* canvas = context.canvas();
canvas->saveLayer(&clip_rrect_.getBounds(), nullptr);
canvas->clipRRect(clip_rrect_);
PaintChildren(context, canvas);
PaintChildren(context);
canvas->restore();
}
......
......@@ -17,7 +17,7 @@ class ClipRRectLayer : public ContainerLayer {
void set_clip_rrect(const SkRRect& clip_rrect) { clip_rrect_ = clip_rrect; }
void Paint(GrContext* context, SkCanvas* canvas) override;
void Paint(PaintContext& context) override;
private:
SkRRect clip_rrect_;
......
......@@ -13,13 +13,14 @@ ColorFilterLayer::ColorFilterLayer() {
ColorFilterLayer::~ColorFilterLayer() {
}
void ColorFilterLayer::Paint(GrContext* context, SkCanvas* canvas) {
void ColorFilterLayer::Paint(PaintContext& context) {
RefPtr<SkColorFilter> color_filter =
adoptRef(SkColorFilter::CreateModeFilter(color_, transfer_mode_));
SkPaint paint;
paint.setColorFilter(color_filter.get());
SkCanvas* canvas = context.canvas();
canvas->saveLayer(&paint_bounds(), &paint);
PaintChildren(context, canvas);
PaintChildren(context);
canvas->restore();
}
......
......@@ -21,7 +21,7 @@ class ColorFilterLayer : public ContainerLayer {
transfer_mode_ = transfer_mode;
}
void Paint(GrContext* context, SkCanvas* canvas) override;
void Paint(PaintContext& context) override;
private:
SkColor color_;
......
......@@ -18,9 +18,9 @@ void ContainerLayer::Add(std::unique_ptr<Layer> layer) {
layers_.push_back(std::move(layer));
}
void ContainerLayer::PaintChildren(GrContext* context, SkCanvas* canvas) const {
void ContainerLayer::PaintChildren(PaintContext& context) const {
for (auto& layer : layers_)
layer->Paint(context, canvas);
layer->Paint(context);
}
} // namespace compositor
......
......@@ -17,7 +17,7 @@ class ContainerLayer : public Layer {
void Add(std::unique_ptr<Layer> layer);
void PaintChildren(GrContext* context, SkCanvas* canvas) const;
void PaintChildren(PaintContext& context) const;
const std::vector<std::unique_ptr<Layer>>& layers() const { return layers_; }
......
......@@ -20,6 +20,8 @@
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkXfermode.h"
#include "sky/compositor/paint_context.h"
#include "sky/compositor/picture_rasterizer.h"
namespace sky {
namespace compositor {
......@@ -30,7 +32,7 @@ class Layer {
Layer();
virtual ~Layer();
virtual void Paint(GrContext* context, SkCanvas* canvas) = 0;
virtual void Paint(PaintContext& context) = 0;
virtual SkMatrix model_view_matrix(const SkMatrix& model_matrix) const;
......
......@@ -13,14 +13,15 @@ OpacityLayer::OpacityLayer() {
OpacityLayer::~OpacityLayer() {
}
void OpacityLayer::Paint(GrContext* context, SkCanvas* canvas) {
void OpacityLayer::Paint(PaintContext& context) {
SkColor color = SkColorSetARGB(alpha_, 0, 0, 0);
RefPtr<SkColorFilter> colorFilter = adoptRef(
SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode));
SkPaint paint;
paint.setColorFilter(colorFilter.get());
SkCanvas* canvas = context.canvas();
canvas->saveLayer(&paint_bounds(), &paint);
PaintChildren(context, canvas);
PaintChildren(context);
canvas->restore();
}
......
......@@ -17,7 +17,7 @@ class OpacityLayer : public ContainerLayer {
void set_alpha(int alpha) { alpha_ = alpha; }
void Paint(GrContext* context, SkCanvas* canvas) override;
void Paint(PaintContext& context) override;
private:
int alpha_;
......
// Copyright 2015 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/paint_context.h"
namespace sky {
namespace compositor {
PaintContext::PaintContext(PictureRasterzier& rasterizer,
GrContext* gr_context,
SkCanvas* canvas)
: rasterizer_(rasterizer), gr_context_(gr_context), canvas_(canvas) {
}
PaintContext::~PaintContext() {
rasterizer_.PurgeCache();
}
} // namespace compositor
} // namespace sky
// Copyright 2015 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_PAINT_CONTEXT_CC_
#define SKY_COMPOSITOR_PAINT_CONTEXT_CC_
#include "base/macros.h"
#include "sky/compositor/picture_rasterizer.h"
namespace sky {
namespace compositor {
class PaintContext {
public:
PaintContext(PictureRasterzier& rasterizer,
GrContext* gr_context,
SkCanvas* canvas);
~PaintContext();
PictureRasterzier& rasterizer() { return rasterizer_; }
GrContext* gr_context() { return gr_context_; }
SkCanvas* canvas() { return canvas_; }
private:
PictureRasterzier& rasterizer_;
GrContext* gr_context_;
SkCanvas* canvas_;
DISALLOW_COPY_AND_ASSIGN(PaintContext);
};
} // namespace compositor
} // namespace sky
#endif // SKY_COMPOSITOR_PAINT_CONTEXT_CC_
......@@ -4,13 +4,11 @@
#include "sky/compositor/picture_layer.h"
#include "base/logging.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace sky {
namespace compositor {
PictureLayer::PictureLayer() : last_picture_id_(UINT32_MAX) {
PictureLayer::PictureLayer() {
}
PictureLayer::~PictureLayer() {
......@@ -22,82 +20,18 @@ SkMatrix PictureLayer::model_view_matrix(const SkMatrix& model_matrix) const {
return modelView;
}
static void ImageReleaseProc(SkImage::ReleaseContext texture) {
DCHECK(texture);
reinterpret_cast<GrTexture*>(texture)->unref();
}
static RefPtr<SkImage> ImageFromPicture(GrContext* context,
SkPicture* picture,
const SkRect& paintBounds) {
// Step 1: Create a texture from the context's texture provider
GrSurfaceDesc desc;
desc.fWidth = paintBounds.width();
desc.fHeight = paintBounds.height();
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fConfig = kRGBA_8888_GrPixelConfig;
GrTexture* texture = context->textureProvider()->createTexture(desc, true);
if (!texture) {
// The texture provider could not allocate a texture backing. Render
// directly to the surface from the picture till the memory pressure
// subsides
return nullptr;
}
// Step 2: Create a backend render target description for the created texture
GrBackendTextureDesc backendDesc;
backendDesc.fConfig = desc.fConfig;
backendDesc.fWidth = desc.fWidth;
backendDesc.fHeight = desc.fHeight;
backendDesc.fSampleCnt = desc.fSampleCnt;
backendDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
backendDesc.fConfig = desc.fConfig;
backendDesc.fTextureHandle = texture->getTextureHandle();
// Step 3: Render the picture into the offscreen texture
GrRenderTarget* renderTarget = texture->asRenderTarget();
DCHECK(renderTarget);
PassRefPtr<SkSurface> surface =
adoptRef(SkSurface::NewRenderTargetDirect(renderTarget));
DCHECK(surface);
SkCanvas* canvas = surface->getCanvas();
DCHECK(canvas);
canvas->drawPicture(picture);
// Step 4: Create an image representation from the texture
RefPtr<SkImage> image = adoptRef(SkImage::NewFromTexture(
context, backendDesc, kPremul_SkAlphaType, &ImageReleaseProc, texture));
return image;
}
void PictureLayer::Paint(GrContext* context, SkCanvas* canvas) {
void PictureLayer::Paint(PaintContext& context) {
DCHECK(picture_);
if (last_picture_id_ == picture_->uniqueID()) {
// The last picture painted was the same as this one. Cache this into an
// offscreen surface and render that instead
if (!cached_image_ && context) {
// Generate the cached image
cached_image_ = ImageFromPicture(context, picture_.get(), paint_bounds());
}
} else {
// Release the cached image if one is present
cached_image_.release();
}
const SkRect& bounds = paint_bounds();
SkISize size = SkISize::Make(bounds.width(), bounds.height());
last_picture_id_ = picture_->uniqueID();
RefPtr<SkImage> image = context.rasterizer().GetCachedImageIfPresent(
context.gr_context(), picture_.get(), size);
SkCanvas* canvas = context.canvas();
if (cached_image_) {
canvas->drawImage(cached_image_.get(), offset_.x(), offset_.y());
if (image) {
canvas->drawImage(image.get(), offset_.x(), offset_.y());
} else {
canvas->save();
canvas->translate(offset_.x(), offset_.y());
......
......@@ -21,15 +21,13 @@ class PictureLayer : public Layer {
SkMatrix model_view_matrix(const SkMatrix& model_matrix) const override;
void Paint(GrContext* context, SkCanvas* canvas) override;
void Paint(PaintContext& context) override;
SkPicture* picture() const { return picture_.get(); }
private:
SkPoint offset_;
RefPtr<SkPicture> picture_;
RefPtr<SkImage> cached_image_;
uint32_t last_picture_id_;
DISALLOW_COPY_AND_ASSIGN(PictureLayer);
};
......
// Copyright 2015 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/picture_rasterizer.h"
#include "base/logging.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkCanvas.h"
namespace sky {
namespace compositor {
PictureRasterzier::PictureRasterzier() {
}
PictureRasterzier::~PictureRasterzier() {
}
static void ImageReleaseProc(SkImage::ReleaseContext texture) {
DCHECK(texture);
reinterpret_cast<GrTexture*>(texture)->unref();
}
PictureRasterzier::Key::Key(uint32_t ident, SkISize sz)
: pictureID(ident), size(sz){};
PictureRasterzier::Value::Value()
: access_count(kDeadAccessCount), image(nullptr) {
}
PictureRasterzier::Value::~Value() {
}
static RefPtr<SkImage> ImageFromPicture(GrContext* context,
SkPicture* picture,
const SkISize& size) {
// Step 1: Create a texture from the context's texture provider
GrSurfaceDesc desc;
desc.fWidth = size.width();
desc.fHeight = size.height();
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fConfig = kRGBA_8888_GrPixelConfig;
GrTexture* texture = context->textureProvider()->createTexture(desc, true);
if (!texture) {
// The texture provider could not allocate a texture backing. Render
// directly to the surface from the picture till the memory pressure
// subsides
return nullptr;
}
// Step 2: Create a backend render target description for the created texture
GrBackendTextureDesc backendDesc;
backendDesc.fConfig = desc.fConfig;
backendDesc.fWidth = desc.fWidth;
backendDesc.fHeight = desc.fHeight;
backendDesc.fSampleCnt = desc.fSampleCnt;
backendDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
backendDesc.fConfig = desc.fConfig;
backendDesc.fTextureHandle = texture->getTextureHandle();
// Step 3: Render the picture into the offscreen texture
GrRenderTarget* renderTarget = texture->asRenderTarget();
DCHECK(renderTarget);
PassRefPtr<SkSurface> surface =
adoptRef(SkSurface::NewRenderTargetDirect(renderTarget));
DCHECK(surface);
SkCanvas* canvas = surface->getCanvas();
DCHECK(canvas);
canvas->drawPicture(picture);
// Step 4: Create an image representation from the texture
RefPtr<SkImage> image = adoptRef(SkImage::NewFromTexture(
context, backendDesc, kPremul_SkAlphaType, &ImageReleaseProc, texture));
return image;
}
RefPtr<SkImage> PictureRasterzier::GetCachedImageIfPresent(GrContext* context,
SkPicture* picture,
SkISize size) {
if (size.isEmpty() || picture == nullptr || context == nullptr) {
return nullptr;
}
const Key key(picture->uniqueID(), size);
Value& value = cache_[key];
if (value.access_count == Value::kDeadAccessCount) {
value.access_count = 1;
return nullptr;
}
value.access_count++;
DCHECK(value.access_count == 1)
<< "Did you forget to call purge_cache between frames?";
if (!value.image) {
value.image = ImageFromPicture(context, picture, size);
}
return value.image;
}
void PictureRasterzier::PurgeCache() {
std::unordered_set<Key, KeyHash, KeyEqual> keys_to_purge;
for (auto& item : cache_) {
const auto count = --item.second.access_count;
if (count == Value::kDeadAccessCount) {
keys_to_purge.insert(item.first);
}
}
for (const auto& key : keys_to_purge) {
cache_.erase(key);
}
}
} // namespace compositor
} // namespace sky
// Copyright 2015 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_PICTURE_RASTERIZER_H_
#define SKY_COMPOSITOR_PICTURE_RASTERIZER_H_
#include "base/macros.h"
#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/core/SkImage.h"
#include "sky/engine/wtf/PassRefPtr.h"
#include "sky/engine/wtf/RefPtr.h"
#include <functional> // for std::hash
#include <unordered_map>
#include <unordered_set>
namespace sky {
namespace compositor {
class PictureRasterzier {
public:
PictureRasterzier();
~PictureRasterzier();
RefPtr<SkImage> GetCachedImageIfPresent(GrContext* context,
SkPicture* picture,
SkISize size);
void PurgeCache();
private:
struct Key {
uint32_t pictureID;
SkISize size;
explicit Key(uint32_t ident, SkISize sz);
};
struct KeyHash {
std::size_t operator()(const Key& key) const {
return std::hash<uint32_t>()(key.pictureID) ^
std::hash<int32_t>()(key.size.width()) ^
std::hash<int32_t>()(key.size.height());
}
};
struct KeyEqual {
bool operator()(const Key& lhs, const Key& rhs) const {
return lhs.pictureID == rhs.pictureID && lhs.size == rhs.size;
}
};
struct Value {
static const int8_t kDeadAccessCount = -1;
int8_t access_count;
RefPtr<SkImage> image;
Value();
~Value();
};
using Cache = std::unordered_map<Key, Value, KeyHash, KeyEqual>;
Cache cache_;
DISALLOW_COPY_AND_ASSIGN(PictureRasterzier);
};
} // namespace compositor
} // namespace sky
#endif // SKY_COMPOSITOR_PICTURE_RASTERIZER_H_
......@@ -19,10 +19,11 @@ SkMatrix TransformLayer::model_view_matrix(const SkMatrix& model_matrix) const {
return modelView;
}
void TransformLayer::Paint(GrContext* context, SkCanvas* canvas) {
void TransformLayer::Paint(PaintContext& context) {
SkCanvas* canvas = context.canvas();
canvas->save();
canvas->concat(transform_);
PaintChildren(context, canvas);
PaintChildren(context);
canvas->restore();
}
......
......@@ -19,7 +19,7 @@ class TransformLayer : public ContainerLayer {
SkMatrix model_view_matrix(const SkMatrix& model_matrix) const override;
void Paint(GrContext* context, SkCanvas* canvas) override;
void Paint(PaintContext& context) override;
private:
SkMatrix transform_;
......
......@@ -5,9 +5,10 @@
#include "sky/shell/gpu/rasterizer.h"
#include "base/trace_event/trace_event.h"
#include "sky/compositor/container_layer.h"
#include "sky/compositor/layer.h"
#include "sky/compositor/paint_context.h"
#include "sky/compositor/picture_layer.h"
#include "sky/compositor/container_layer.h"
#include "sky/shell/gpu/ganesh_context.h"
#include "sky/shell/gpu/ganesh_surface.h"
#include "sky/shell/gpu/picture_serializer.h"
......@@ -43,8 +44,8 @@ void SketchySerializeLayerTree(const char* path,
} // namespace
Rasterizer::Rasterizer()
: share_group_(new gfx::GLShareGroup()), weak_factory_(this) {
}
: share_group_(new gfx::GLShareGroup()),
weak_factory_(this) {}
Rasterizer::~Rasterizer() {
}
......@@ -77,7 +78,8 @@ void Rasterizer::Draw(scoped_ptr<compositor::LayerTree> layer_tree) {
SkCanvas* canvas = ganesh_surface_->canvas();
canvas->clear(SK_ColorBLACK);
layer_tree->root_layer()->Paint(ganesh_context_->gr(), canvas);
compositor::PaintContext context(rasterizer_, ganesh_context_->gr(), canvas);
layer_tree->root_layer()->Paint(context);
canvas->flush();
surface_->SwapBuffers();
......
......@@ -11,6 +11,7 @@
#include "sky/shell/gpu_delegate.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
#include "sky/compositor/picture_rasterizer.h"
class SkPicture;
......@@ -47,6 +48,8 @@ class Rasterizer : public GPUDelegate {
scoped_ptr<GaneshContext> ganesh_context_;
scoped_ptr<GaneshSurface> ganesh_surface_;
compositor::PictureRasterzier rasterizer_;
base::WeakPtrFactory<Rasterizer> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Rasterizer);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册