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 |