Chromium Code Reviews| Index: services/gfx/compositor/render/render_layer.cc |
| diff --git a/services/gfx/compositor/render/render_layer.cc b/services/gfx/compositor/render/render_layer.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2473eac3f81a3da792e5b0c41bdf82b0343032a8 |
| --- /dev/null |
| +++ b/services/gfx/compositor/render/render_layer.cc |
| @@ -0,0 +1,267 @@ |
| +// 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 "services/gfx/compositor/render/render_layer.h" |
| + |
| +#include "base/logging.h" |
| +#include "third_party/skia/include/core/SkCanvas.h" |
| +#include "third_party/skia/include/core/SkPicture.h" |
| +#include "third_party/skia/include/core/SkPictureRecorder.h" |
| + |
| +namespace compositor { |
| + |
| +class RenderCommand { |
| + public: |
| + RenderCommand() {} |
| + virtual ~RenderCommand() {} |
| + |
| + virtual void Paint(const PaintingScope& painting_scope, SkCanvas* canvas) = 0; |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(RenderCommand); |
| +}; |
| + |
| +class PushSceneCommand : public RenderCommand { |
| + public: |
| + PushSceneCommand(uint32_t scene_token, uint32_t version) |
| + : scene_token_(scene_token), version_(version) {} |
| + ~PushSceneCommand() override {} |
| + |
| + void Paint(const PaintingScope& painting_scope, SkCanvas* canvas) override {} |
| + |
| + private: |
| + uint32_t scene_token_; |
| + uint32_t version_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(PushSceneCommand); |
| +}; |
| + |
| +class PushNodeCommand : public RenderCommand { |
| + public: |
| + PushNodeCommand(uint32_t node_id, uint32_t hit_id) |
| + : node_id_(node_id), hit_id_(hit_id) {} |
| + ~PushNodeCommand() override {} |
| + |
| + void Paint(const PaintingScope& painting_scope, SkCanvas* canvas) override { |
| + canvas->save(); |
| + } |
| + |
| + private: |
| + uint32_t node_id_; |
| + uint32_t hit_id_; |
| + SkMatrix content_transform_; |
| + SkPath content_clip_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(PushNodeCommand); |
| +}; |
| + |
| +class PushComplexNodeCommand : public PushNodeCommand { |
| + public: |
| + PushComplexNodeCommand(uint32_t node_id, |
| + uint32_t hit_id, |
| + const SkMatrix& content_transform, |
| + const SkPath& content_clip) |
| + : PushNodeCommand(node_id, hit_id), |
| + content_transform_(content_transform), |
| + content_clip_(content_clip) {} |
| + ~PushComplexNodeCommand() override {} |
| + |
| + void Paint(const PaintingScope& painting_scope, SkCanvas* canvas) override { |
| + PushNodeCommand::Paint(painting_scope, canvas); |
| + if (!content_transform_.isIdentity()) |
| + canvas->concat(content_transform_); |
|
abarth
2016/01/10 22:55:36
In Flutter (and in Chrome) we optimize the case wh
jeffbrown
2016/01/16 03:28:32
Yeah, this is just to get us off the ground.
|
| + if (!content_clip_.isEmpty()) |
| + canvas->clipPath(content_clip_); |
|
abarth
2016/01/10 22:55:36
It's strange to group these two operations togethe
jeffbrown
2016/01/16 03:28:32
Eliminating rounded clips for now.
|
| + } |
| + |
| + private: |
| + SkMatrix content_transform_; |
| + SkPath content_clip_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(PushComplexNodeCommand); |
| +}; |
| + |
| +class PopNodeCommand : public RenderCommand { |
| + public: |
| + PopNodeCommand() {} |
| + ~PopNodeCommand() override {} |
| + |
| + void Paint(const PaintingScope& painting_scope, SkCanvas* canvas) override { |
| + canvas->restore(); |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(PopNodeCommand); |
| +}; |
| + |
| +class DrawRectCommand : public RenderCommand { |
| + public: |
| + DrawRectCommand(const SkRect& content_rect, const SkPaint& paint) |
| + : content_rect_(content_rect), paint_(paint) {} |
| + ~DrawRectCommand() override {} |
| + |
| + void Paint(const PaintingScope& painting_scope, SkCanvas* canvas) override { |
| + canvas->drawRect(content_rect_, paint_); |
| + } |
| + |
| + private: |
| + const SkRect content_rect_; |
| + const SkPaint paint_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(DrawRectCommand); |
| +}; |
| + |
| +class DrawImageCommand : public RenderCommand { |
| + public: |
| + DrawImageCommand(const std::shared_ptr<RenderImage>& image, |
| + const SkRect& content_rect, |
| + const SkRect& image_rect, |
| + const SkPaint& paint) |
| + : image_(image), |
| + content_rect_(content_rect), |
| + image_rect_(image_rect), |
| + paint_(paint) {} |
| + ~DrawImageCommand() override {} |
| + |
| + void Paint(const PaintingScope& painting_scope, SkCanvas* canvas) override { |
| + skia::RefPtr<SkImage> skia_image = |
| + painting_scope.painting_cache()->GetSkImage(painting_scope, image_); |
| + canvas->drawImageRect(skia_image.get(), image_rect_, content_rect_, |
| + &paint_); |
| + } |
| + |
| + private: |
| + const std::shared_ptr<RenderImage> image_; |
| + const SkRect content_rect_; |
| + const SkRect image_rect_; |
| + const SkPaint paint_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(DrawImageCommand); |
| +}; |
| + |
| +class DrawLayerCommand : public RenderCommand { |
| + public: |
| + explicit DrawLayerCommand(const std::shared_ptr<RenderLayer>& layer) |
| + : layer_(layer) {} |
| + ~DrawLayerCommand() override {} |
| + |
| + void Paint(const PaintingScope& painting_scope, SkCanvas* canvas) override { |
| + skia::RefPtr<SkPicture> skia_picture = |
| + painting_scope.painting_cache()->GetSkPicture(painting_scope, layer_); |
| + canvas->drawPicture(skia_picture.get()); |
| + } |
| + |
| + private: |
| + const std::shared_ptr<RenderLayer> layer_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(DrawLayerCommand); |
| +}; |
| + |
| +class DrawSavedLayerCommand : public DrawLayerCommand { |
| + public: |
| + DrawSavedLayerCommand(const std::shared_ptr<RenderLayer>& layer, |
| + const SkRect& content_rect, |
| + const SkPaint& paint) |
| + : DrawLayerCommand(layer), content_rect_(content_rect), paint_(paint) {} |
| + ~DrawSavedLayerCommand() override {} |
| + |
| + void Paint(const PaintingScope& painting_scope, SkCanvas* canvas) override { |
| + canvas->saveLayer(content_rect_, &paint_); |
| + DrawLayerCommand::Paint(painting_scope, canvas); |
| + canvas->restore(); |
| + } |
| + |
| + private: |
| + const SkRect content_rect_; |
| + const SkPaint paint_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(DrawSavedLayerCommand); |
| +}; |
| + |
| +RenderLayer::RenderLayer(const SkRect& cull_rect) : cull_rect_(cull_rect) {} |
| + |
| +RenderLayer::~RenderLayer() {} |
| + |
| +skia::RefPtr<SkPicture> RenderLayer::CreateSkPicture( |
| + const PaintingScope& painting_scope) const { |
| + SkPictureRecorder recorder; |
| + SkCanvas* canvas = recorder.beginRecording(cull_rect()); |
| + DCHECK(canvas); |
| + |
| + for (const auto& command : commands_) |
| + command->Paint(painting_scope, canvas); |
| + |
| + canvas->flush(); |
|
abarth
2016/01/10 22:55:36
No need for flush here. endRecordingAsPicture is
jeffbrown
2016/01/16 03:28:32
Done.
|
| + return skia::AdoptRef(recorder.endRecordingAsPicture()); |
| +} |
| + |
| +RenderLayerBuilder::RenderLayerBuilder() : RenderLayerBuilder(nullptr) {} |
| + |
| +RenderLayerBuilder::RenderLayerBuilder(const SkRect* cull_rect) |
| + : layer_(std::make_shared<RenderLayer>(cull_rect ? *cull_rect |
| + : SkRect::MakeLargest())) { |
| +} |
| + |
| +RenderLayerBuilder::~RenderLayerBuilder() {} |
| + |
| +void RenderLayerBuilder::PushScene(uint32_t scene_token, uint32_t version) { |
| + DCHECK(layer_); |
| + layer_->commands_.emplace_back(new PushSceneCommand(scene_token, version)); |
| +} |
| + |
| +void RenderLayerBuilder::PopScene() { |
| + DCHECK(layer_); |
| +} |
| + |
| +void RenderLayerBuilder::PushNode(uint32_t node_id, |
| + uint32_t hit_id, |
| + const SkMatrix& content_transform, |
| + const SkPath& content_clip) { |
| + DCHECK(layer_); |
| + if (content_transform.isIdentity() && content_clip.isEmpty()) |
| + layer_->commands_.emplace_back(new PushNodeCommand(node_id, hit_id)); |
|
abarth
2016/01/10 22:55:36
This seems like it will generate a lot of extra sa
jeffbrown
2016/01/16 03:28:32
Oh yeah, it's horrible. Not to mention all of the
|
| + else |
| + layer_->commands_.emplace_back(new PushComplexNodeCommand( |
| + node_id, hit_id, content_transform, content_clip)); |
| +} |
| + |
| +void RenderLayerBuilder::PopNode() { |
| + DCHECK(layer_); |
| + layer_->commands_.emplace_back(new PopNodeCommand()); |
|
abarth
2016/01/10 22:55:36
This file looks a bit like you're re-implementing
jeffbrown
2016/01/16 03:28:32
I didn't know about SkImageGenerator. So... next
|
| +} |
| + |
| +void RenderLayerBuilder::DrawRect(const SkRect& content_rect, |
| + const SkPaint& paint) { |
| + DCHECK(layer_); |
| + layer_->commands_.emplace_back(new DrawRectCommand(content_rect, paint)); |
| +} |
| + |
| +void RenderLayerBuilder::DrawImage(const std::shared_ptr<RenderImage>& image, |
| + const SkRect& content_rect, |
| + const SkRect& image_rect, |
| + const SkPaint& paint) { |
| + DCHECK(layer_); |
| + layer_->commands_.emplace_back( |
| + new DrawImageCommand(image, content_rect, image_rect, paint)); |
| +} |
| + |
| +void RenderLayerBuilder::DrawLayer(const std::shared_ptr<RenderLayer>& layer) { |
| + DCHECK(layer_); |
| + layer_->commands_.emplace_back(new DrawLayerCommand(layer)); |
| +} |
| + |
| +void RenderLayerBuilder::DrawSavedLayer( |
| + const std::shared_ptr<RenderLayer>& layer, |
| + const SkRect& content_rect, |
| + const SkPaint& paint) { |
| + DCHECK(layer_); |
| + layer_->commands_.emplace_back( |
| + new DrawSavedLayerCommand(layer, content_rect, paint)); |
| +} |
| + |
| +std::shared_ptr<RenderLayer> RenderLayerBuilder::Build() { |
| + return std::move(layer_); |
| +} |
| + |
| +} // namespace compositor |