diff --git a/sky/compositor/BUILD.gn b/sky/compositor/BUILD.gn new file mode 100644 index 000000000..ffce6c03f --- /dev/null +++ b/sky/compositor/BUILD.gn @@ -0,0 +1,16 @@ +# 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. + +source_set("compositor") { + sources = [ + "layer.cc", + "layer.h", + ] + + deps = [ + "//base", + "//skia", + "//sky/engine/wtf", + ] +} diff --git a/sky/compositor/layer.cc b/sky/compositor/layer.cc new file mode 100644 index 000000000..d43bbcd2e --- /dev/null +++ b/sky/compositor/layer.cc @@ -0,0 +1,130 @@ +// 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/layer.h" + +#include "third_party/skia/include/core/SkColorFilter.h" + +namespace sky { + +Layer::Layer() { +} + +Layer::~Layer() { +} + +PictureLayer::PictureLayer() { +} + +PictureLayer::~PictureLayer() { +} + +void PictureLayer::Paint(SkCanvas* canvas) { + canvas->save(); + canvas->translate(offset_.x(), offset_.y()); + canvas->drawPicture(picture_.get()); + canvas->restore(); +} + +ContainerLayer::ContainerLayer() { +} + +ContainerLayer::~ContainerLayer() { +} + +void ContainerLayer::Add(std::unique_ptr layer) { + layer->set_parent(this); + layers_.push_back(std::move(layer)); +} + +void ContainerLayer::PaintChildren(SkCanvas* canvas) { + for (auto& layer : layers_) + layer->Paint(canvas); +} + +TransformLayer::TransformLayer() { +} + +TransformLayer::~TransformLayer() { +} + +void TransformLayer::Paint(SkCanvas* canvas) { + canvas->save(); + canvas->concat(transform_); + PaintChildren(canvas); + canvas->restore(); +} + +ClipRectLayer::ClipRectLayer() { +} + +ClipRectLayer::~ClipRectLayer() { +} + +void ClipRectLayer::Paint(SkCanvas* canvas) { + canvas->save(); + canvas->clipRect(clip_rect_); + PaintChildren(canvas); + canvas->restore(); +} + +ClipRRectLayer::ClipRRectLayer() { +} + +ClipRRectLayer::~ClipRRectLayer() { +} + +void ClipRRectLayer::Paint(SkCanvas* canvas) { + canvas->saveLayer(&clip_rrect_.getBounds(), nullptr); + canvas->clipRRect(clip_rrect_); + PaintChildren(canvas); + canvas->restore(); +} + +ClipPathLayer::ClipPathLayer() { +} + +ClipPathLayer::~ClipPathLayer() { +} + +void ClipPathLayer::Paint(SkCanvas* canvas) { + canvas->saveLayer(&clip_path_.getBounds(), nullptr); + canvas->clipPath(clip_path_); + PaintChildren(canvas); + canvas->restore(); +} + +OpacityLayer::OpacityLayer() { +} + +OpacityLayer::~OpacityLayer() { +} + +void OpacityLayer::Paint(SkCanvas* canvas) { + SkColor color = SkColorSetARGB(alpha_, 0, 0, 0); + RefPtr colorFilter = adoptRef(SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode)); + SkPaint paint; + paint.setColorFilter(colorFilter.get()); + canvas->saveLayer(&paint_bounds(), &paint); + PaintChildren(canvas); + canvas->restore(); +} + +ColorFilterLayer::ColorFilterLayer() { +} + +ColorFilterLayer::~ColorFilterLayer() { +} + +void ColorFilterLayer::Paint(SkCanvas* canvas) { + RefPtr color_filter = + adoptRef(SkColorFilter::CreateModeFilter(color_, transfer_mode_)); + SkPaint paint; + paint.setColorFilter(color_filter.get()); + canvas->saveLayer(&paint_bounds(), &paint); + PaintChildren(canvas); + canvas->restore(); +} + +} // namespace sky diff --git a/sky/compositor/layer.h b/sky/compositor/layer.h new file mode 100644 index 000000000..6dcd36e2b --- /dev/null +++ b/sky/compositor/layer.h @@ -0,0 +1,173 @@ +// 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_H_ +#define SKY_COMPOSITOR_H_ + +#include +#include + +#include "base/macros.h" +#include "sky/engine/wtf/PassRefPtr.h" +#include "sky/engine/wtf/RefPtr.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkColorFilter.h" +#include "third_party/skia/include/core/SkMatrix.h" +#include "third_party/skia/include/core/SkPath.h" +#include "third_party/skia/include/core/SkPicture.h" +#include "third_party/skia/include/core/SkRect.h" +#include "third_party/skia/include/core/SkRRect.h" +#include "third_party/skia/include/core/SkXfermode.h" + +namespace sky { +class ContainerLayer; + +class Layer { + public: + Layer(); + virtual ~Layer(); + + virtual void Paint(SkCanvas* canvas) = 0; + + ContainerLayer* parent() const { return parent_; } + void set_parent(ContainerLayer* parent) { parent_ = parent; } + + const SkRect& paint_bounds() const { return paint_bounds_; } + void set_paint_bounds(const SkRect& paint_bounds) { paint_bounds_ = paint_bounds; } + + private: + ContainerLayer* parent_; + SkRect paint_bounds_; + + DISALLOW_COPY_AND_ASSIGN(Layer); +}; + +class PictureLayer : public Layer { + public: + PictureLayer(); + ~PictureLayer() override; + + void Paint(SkCanvas* canvas) override; + + void set_offset(const SkPoint& offset) { offset_ = offset; } + void set_picture(PassRefPtr picture) { picture_ = picture; } + + private: + SkPoint offset_; + RefPtr picture_; + + DISALLOW_COPY_AND_ASSIGN(PictureLayer); +}; + +class ContainerLayer : public Layer { + public: + ContainerLayer(); + ~ContainerLayer() override; + + void Add(std::unique_ptr layer); + + void PaintChildren(SkCanvas* canvas); + + private: + std::vector> layers_; + + DISALLOW_COPY_AND_ASSIGN(ContainerLayer); +}; + +class TransformLayer : public ContainerLayer { + public: + TransformLayer(); + ~TransformLayer() override; + + void Paint(SkCanvas* canvas) override; + + void set_transform(const SkMatrix& transform) { transform_ = transform; } + + private: + SkMatrix transform_; + + DISALLOW_COPY_AND_ASSIGN(TransformLayer); +}; + +class ClipRectLayer : public ContainerLayer { + public: + ClipRectLayer(); + ~ClipRectLayer() override; + + void Paint(SkCanvas* canvas) override; + + void set_clip_rect(const SkRect& clip_rect) { clip_rect_ = clip_rect; } + + private: + SkRect clip_rect_; + + DISALLOW_COPY_AND_ASSIGN(ClipRectLayer); +}; + +class ClipRRectLayer : public ContainerLayer { + public: + ClipRRectLayer(); + ~ClipRRectLayer() override; + + void Paint(SkCanvas* canvas) override; + + void set_clip_rrect(const SkRRect& clip_rrect) { clip_rrect_ = clip_rrect; } + + private: + SkRRect clip_rrect_; + + DISALLOW_COPY_AND_ASSIGN(ClipRRectLayer); +}; + +class ClipPathLayer : public ContainerLayer { + public: + ClipPathLayer(); + ~ClipPathLayer() override; + + void Paint(SkCanvas* canvas) override; + + void set_clip_path(const SkPath& clip_path) { clip_path_ = clip_path; } + + private: + SkPath clip_path_; + + DISALLOW_COPY_AND_ASSIGN(ClipPathLayer); +}; + +class OpacityLayer : public ContainerLayer { + public: + OpacityLayer(); + ~OpacityLayer() override; + + void Paint(SkCanvas* canvas) override; + + void set_alpha(int alpha) { alpha_ = alpha; } + + private: + int alpha_; + + DISALLOW_COPY_AND_ASSIGN(OpacityLayer); +}; + +class ColorFilterLayer : public ContainerLayer { + public: + ColorFilterLayer(); + ~ColorFilterLayer() override; + + void Paint(SkCanvas* canvas) override; + + void set_color(SkColor color) { color_ = color; } + void set_transfer_mode(SkXfermode::Mode transfer_mode) { transfer_mode_ = transfer_mode; } + + private: + SkColor color_; + SkXfermode::Mode transfer_mode_; + + DISALLOW_COPY_AND_ASSIGN(ColorFilterLayer); +}; + +} // namespace sky + +#endif // SKY_COMPOSITOR_H_ diff --git a/sky/engine/core/BUILD.gn b/sky/engine/core/BUILD.gn index 45103f2ef..7922cb18f 100644 --- a/sky/engine/core/BUILD.gn +++ b/sky/engine/core/BUILD.gn @@ -21,6 +21,7 @@ source_set("libraries") { "//mojo/public/cpp/utility", "//mojo/public/interfaces/application", "//skia", + "//sky/compositor", "//sky/engine/tonic:tonic", "//sky/engine/wtf", "//third_party/iccjpeg", diff --git a/sky/engine/core/compositing/Scene.cpp b/sky/engine/core/compositing/Scene.cpp index 08458676c..d58883f98 100644 --- a/sky/engine/core/compositing/Scene.cpp +++ b/sky/engine/core/compositing/Scene.cpp @@ -4,16 +4,19 @@ #include "sky/engine/core/compositing/Scene.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" + namespace blink { -PassRefPtr Scene::create(PassRefPtr picture) +PassRefPtr Scene::create(std::unique_ptr rootLayer) { - ASSERT(picture); - return adoptRef(new Scene(picture)); + ASSERT(rootLayer); + return adoptRef(new Scene(std::move(rootLayer))); } -Scene::Scene(PassRefPtr picture) - : m_picture(picture) +Scene::Scene(std::unique_ptr rootLayer) + : m_rootLayer(std::move(rootLayer)) { } @@ -21,4 +24,14 @@ Scene::~Scene() { } +PassRefPtr Scene::createPicture() const +{ + SkRTreeFactory rtreeFactory; + SkPictureRecorder pictureRecorder; + SkCanvas* canvas = pictureRecorder.beginRecording(m_rootLayer->paint_bounds(), + &rtreeFactory, SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag); + m_rootLayer->Paint(canvas); + return adoptRef(pictureRecorder.endRecording()); +} + } // namespace blink diff --git a/sky/engine/core/compositing/Scene.h b/sky/engine/core/compositing/Scene.h index 8d3a5ac8c..af2347f1a 100644 --- a/sky/engine/core/compositing/Scene.h +++ b/sky/engine/core/compositing/Scene.h @@ -5,6 +5,9 @@ #ifndef SKY_ENGINE_CORE_COMPOSITING_SCENE_H_ #define SKY_ENGINE_CORE_COMPOSITING_SCENE_H_ +#include + +#include "sky/compositor/layer.h" #include "sky/engine/tonic/dart_wrappable.h" #include "sky/engine/wtf/PassRefPtr.h" #include "sky/engine/wtf/RefCounted.h" @@ -16,16 +19,16 @@ class Scene : public RefCounted, public DartWrappable { DEFINE_WRAPPERTYPEINFO(); public: ~Scene() override; - static PassRefPtr create(PassRefPtr skPicture); - - SkPicture* toSkia() const { return m_picture.get(); } - -private: - explicit Scene(PassRefPtr skPicture); + static PassRefPtr create(std::unique_ptr rootLayer); // While bootstraping the compositing system, we use an SkPicture instead // of a layer tree to back the scene. - RefPtr m_picture; + PassRefPtr createPicture() const; + +private: + explicit Scene(std::unique_ptr rootLayer); + + std::unique_ptr m_rootLayer; }; } // namespace blink diff --git a/sky/engine/core/compositing/SceneBuilder.cpp b/sky/engine/core/compositing/SceneBuilder.cpp index 7e10ca3d1..82def61dd 100644 --- a/sky/engine/core/compositing/SceneBuilder.cpp +++ b/sky/engine/core/compositing/SceneBuilder.cpp @@ -10,9 +10,9 @@ namespace blink { SceneBuilder::SceneBuilder(const Rect& bounds) + : m_rootPaintBounds(bounds.sk_rect) + , m_currentLayer(nullptr) { - m_canvas = m_pictureRecorder.beginRecording(bounds.sk_rect, - &m_rtreeFactory, SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag); } SceneBuilder::~SceneBuilder() @@ -24,77 +24,88 @@ void SceneBuilder::pushTransform(const Float32List& matrix4, ExceptionState& es) SkMatrix sk_matrix = toSkMatrix(matrix4, es); if (es.had_exception()) return; - m_canvas->save(); - m_canvas->concat(sk_matrix); + std::unique_ptr layer(new sky::TransformLayer()); + layer->set_transform(sk_matrix); + addLayer(std::move(layer)); } void SceneBuilder::pushClipRect(const Rect& rect) { - if (!m_canvas) - return; - m_canvas->save(); - m_canvas->clipRect(rect.sk_rect); + std::unique_ptr layer(new sky::ClipRectLayer()); + layer->set_clip_rect(rect.sk_rect); + addLayer(std::move(layer)); } void SceneBuilder::pushClipRRect(const RRect* rrect, const Rect& bounds) { - if (!m_canvas) - return; - m_canvas->saveLayer(&bounds.sk_rect, nullptr); - m_canvas->clipRRect(rrect->rrect()); + std::unique_ptr layer(new sky::ClipRRectLayer()); + layer->set_clip_rrect(rrect->rrect()); + addLayer(std::move(layer)); } void SceneBuilder::pushClipPath(const CanvasPath* path, const Rect& bounds) { - if (!m_canvas) - return; - m_canvas->saveLayer(&bounds.sk_rect, nullptr); - m_canvas->clipPath(path->path()); + std::unique_ptr layer(new sky::ClipPathLayer()); + layer->set_clip_path(path->path()); + addLayer(std::move(layer)); } void SceneBuilder::pushOpacity(int alpha, const Rect& bounds) { - if (!m_canvas) - return; - SkColor color = SkColorSetARGB(alpha, 0, 0, 0); - RefPtr colorFilter = adoptRef(SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode)); - SkPaint paint; - paint.setColorFilter(colorFilter.get()); - m_canvas->saveLayer(&bounds.sk_rect, &paint); + std::unique_ptr layer(new sky::OpacityLayer()); + layer->set_paint_bounds(bounds.sk_rect); + layer->set_alpha(alpha); + addLayer(std::move(layer)); } void SceneBuilder::pushColorFilter(SkColor color, SkXfermode::Mode transferMode, const Rect& bounds) { - if (!m_canvas) + std::unique_ptr layer(new sky::ColorFilterLayer()); + layer->set_paint_bounds(bounds.sk_rect); + layer->set_color(color); + layer->set_transfer_mode(transferMode); + addLayer(std::move(layer)); +} + +void SceneBuilder::addLayer(std::unique_ptr layer) +{ + DCHECK(layer); + if (!m_rootLayer) { + DCHECK(!m_currentLayer); + m_rootLayer = std::move(layer); + m_rootLayer->set_paint_bounds(m_rootPaintBounds); + m_currentLayer = m_rootLayer.get(); return; - RefPtr colorFilter = adoptRef(SkColorFilter::CreateModeFilter(color, transferMode)); - SkPaint paint; - paint.setColorFilter(colorFilter.get()); - m_canvas->saveLayer(&bounds.sk_rect, &paint); + } + if (!m_currentLayer) + return; + sky::ContainerLayer* newLayer = layer.get(); + m_currentLayer->Add(std::move(layer)); + m_currentLayer = newLayer; } void SceneBuilder::pop() { - if (!m_canvas) + if (!m_currentLayer) return; - m_canvas->restore(); + m_currentLayer = m_currentLayer->parent(); } void SceneBuilder::addPicture(const Offset& offset, Picture* picture, const Rect& paintBounds) { - if (!m_canvas) + if (!m_currentLayer) return; - m_canvas->save(); - m_canvas->translate(offset.sk_size.width(), offset.sk_size.height()); - m_canvas->drawPicture(picture->toSkia()); - m_canvas->restore(); + std::unique_ptr layer(new sky::PictureLayer()); + layer->set_offset(SkPoint::Make(offset.sk_size.width(), offset.sk_size.height())); + layer->set_picture(picture->toSkia()); + layer->set_paint_bounds(paintBounds.sk_rect); + m_currentLayer->Add(std::move(layer)); } PassRefPtr SceneBuilder::build() { - RefPtr scene = Scene::create(adoptRef(m_pictureRecorder.endRecording())); - m_canvas = nullptr; - return scene.release(); + m_currentLayer = nullptr; + return Scene::create(std::move(m_rootLayer)); } } // namespace blink diff --git a/sky/engine/core/compositing/SceneBuilder.h b/sky/engine/core/compositing/SceneBuilder.h index d8facf603..099d1f5b4 100644 --- a/sky/engine/core/compositing/SceneBuilder.h +++ b/sky/engine/core/compositing/SceneBuilder.h @@ -5,6 +5,9 @@ #ifndef SKY_ENGINE_CORE_COMPOSITING_SCENEBUILDER_H_ #define SKY_ENGINE_CORE_COMPOSITING_SCENEBUILDER_H_ +#include + +#include "sky/compositor/layer.h" #include "sky/engine/bindings/exception_state.h" #include "sky/engine/core/compositing/Scene.h" #include "sky/engine/core/painting/CanvasPath.h" @@ -19,8 +22,6 @@ #include "sky/engine/tonic/float32_list.h" #include "sky/engine/wtf/PassRefPtr.h" #include "sky/engine/wtf/RefCounted.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkPictureRecorder.h" namespace blink { @@ -47,9 +48,11 @@ public: private: explicit SceneBuilder(const Rect& bounds); - SkRTreeFactory m_rtreeFactory; - SkPictureRecorder m_pictureRecorder; - SkCanvas* m_canvas; + void addLayer(std::unique_ptr layer); + + SkRect m_rootPaintBounds; + std::unique_ptr m_rootLayer; + sky::ContainerLayer* m_currentLayer; }; } // namespace blink diff --git a/sky/engine/public/sky/sky_view.cc b/sky/engine/public/sky/sky_view.cc index 3122ce401..de5cc2df1 100644 --- a/sky/engine/public/sky/sky_view.cc +++ b/sky/engine/public/sky/sky_view.cc @@ -72,7 +72,7 @@ void SkyView::BeginFrame(base::TimeTicks frame_time) { PassRefPtr SkyView::Paint() { if (Scene* scene = view_->scene()) - return scene->toSkia(); + return scene->createPicture(); if (Picture* picture = view_->picture()) return picture->toSkia(); return nullptr;