From f7d1856bd08ec9f24b74734bf147beacd0c2524f Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 8 Jan 2016 16:05:34 -0800 Subject: [PATCH] Compute paint bounds from cull rects Rather than relying upon the rects passed in from Dart, the compositor should compute the paint bounds of layers from the cull rects of the underlying SkPictures. This approach is better because it will handle effects like shadows that paint outside the incorrect paint bounds we use today (as well as shrinking around empty space). --- sky/compositor/color_filter_layer.cc | 7 ++++++- sky/compositor/color_filter_layer.h | 2 ++ sky/compositor/container_layer.cc | 16 ++++++++++------ sky/compositor/container_layer.h | 5 ++--- sky/compositor/layer.cc | 2 +- sky/compositor/layer.h | 8 ++++++-- sky/compositor/layer_tree.cc | 3 ++- sky/compositor/opacity_layer.cc | 7 ++++++- sky/compositor/opacity_layer.h | 1 + sky/compositor/picture_layer.cc | 14 +++++++------- sky/compositor/picture_layer.h | 3 +-- sky/compositor/transform_layer.cc | 6 +++--- sky/compositor/transform_layer.h | 3 +-- sky/engine/core/compositing/SceneBuilder.cpp | 10 +--------- sky/engine/core/compositing/SceneBuilder.h | 1 - 15 files changed, 49 insertions(+), 39 deletions(-) diff --git a/sky/compositor/color_filter_layer.cc b/sky/compositor/color_filter_layer.cc index e844db9f6..674022ec1 100644 --- a/sky/compositor/color_filter_layer.cc +++ b/sky/compositor/color_filter_layer.cc @@ -13,13 +13,18 @@ ColorFilterLayer::ColorFilterLayer() { ColorFilterLayer::~ColorFilterLayer() { } +void ColorFilterLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + ContainerLayer::Preroll(context, matrix); + set_paint_bounds(context->child_paint_bounds); +} + void ColorFilterLayer::Paint(PaintContext::ScopedFrame& frame) { RefPtr color_filter = adoptRef(SkColorFilter::CreateModeFilter(color_, transfer_mode_)); SkPaint paint; paint.setColorFilter(color_filter.get()); SkCanvas& canvas = frame.canvas(); - canvas.saveLayer(has_paint_bounds() ? &paint_bounds() : nullptr, &paint); + canvas.saveLayer(&paint_bounds(), &paint); PaintChildren(frame); canvas.restore(); } diff --git a/sky/compositor/color_filter_layer.h b/sky/compositor/color_filter_layer.h index db0832756..7633842c0 100644 --- a/sky/compositor/color_filter_layer.h +++ b/sky/compositor/color_filter_layer.h @@ -21,6 +21,8 @@ class ColorFilterLayer : public ContainerLayer { transfer_mode_ = transfer_mode; } + protected: + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext::ScopedFrame& frame) override; private: diff --git a/sky/compositor/container_layer.cc b/sky/compositor/container_layer.cc index 28c71d945..985baef35 100644 --- a/sky/compositor/container_layer.cc +++ b/sky/compositor/container_layer.cc @@ -18,15 +18,19 @@ void ContainerLayer::Add(std::unique_ptr layer) { layers_.push_back(std::move(layer)); } -void ContainerLayer::Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix) { - PrerollChildren(frame, matrix); +void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + PrerollChildren(context, matrix); } -void ContainerLayer::PrerollChildren(PaintContext::ScopedFrame& frame, +void ContainerLayer::PrerollChildren(PrerollContext* context, const SkMatrix& matrix) { - for (auto& layer : layers_) - layer->Preroll(frame, matrix); + SkRect child_paint_bounds; + for (auto& layer : layers_) { + PrerollContext child_context = *context; + layer->Preroll(&child_context, matrix); + child_paint_bounds.join(child_context.child_paint_bounds); + } + context->child_paint_bounds = child_paint_bounds; } void ContainerLayer::PaintChildren(PaintContext::ScopedFrame& frame) const { diff --git a/sky/compositor/container_layer.h b/sky/compositor/container_layer.h index 8c3aeabdf..674ab704e 100644 --- a/sky/compositor/container_layer.h +++ b/sky/compositor/container_layer.h @@ -18,10 +18,9 @@ class ContainerLayer : public Layer { void Add(std::unique_ptr layer); - void Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix) override; + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; + void PrerollChildren(PrerollContext* context, const SkMatrix& matrix); - void PrerollChildren(PaintContext::ScopedFrame& frame, const SkMatrix& matrix); void PaintChildren(PaintContext::ScopedFrame& frame) const; const std::vector>& layers() const { return layers_; } diff --git a/sky/compositor/layer.cc b/sky/compositor/layer.cc index 43b68a756..70337b1df 100644 --- a/sky/compositor/layer.cc +++ b/sky/compositor/layer.cc @@ -18,7 +18,7 @@ Layer::Layer() Layer::~Layer() { } -void Layer::Preroll(PaintContext::ScopedFrame& frame, const SkMatrix& matrix) { +void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) { } } // namespace compositor diff --git a/sky/compositor/layer.h b/sky/compositor/layer.h index 532c8fbd9..8c91143c6 100644 --- a/sky/compositor/layer.h +++ b/sky/compositor/layer.h @@ -31,8 +31,12 @@ class Layer { Layer(); virtual ~Layer(); - virtual void Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix); + struct PrerollContext { + PaintContext::ScopedFrame& frame; + SkRect child_paint_bounds; + }; + + virtual void Preroll(PrerollContext* context, const SkMatrix& matrix); virtual void Paint(PaintContext::ScopedFrame& frame) = 0; ContainerLayer* parent() const { return parent_; } diff --git a/sky/compositor/layer_tree.cc b/sky/compositor/layer_tree.cc index 5af12a6b7..39e742cf8 100644 --- a/sky/compositor/layer_tree.cc +++ b/sky/compositor/layer_tree.cc @@ -16,7 +16,8 @@ LayerTree::~LayerTree() { } void LayerTree::Raster(PaintContext::ScopedFrame& frame) { - root_layer_->Preroll(frame, SkMatrix()); + Layer::PrerollContext context = { frame, SkRect::MakeEmpty() }; + root_layer_->Preroll(&context, SkMatrix()); root_layer_->Paint(frame); } diff --git a/sky/compositor/opacity_layer.cc b/sky/compositor/opacity_layer.cc index ff5a81431..ad77687a7 100644 --- a/sky/compositor/opacity_layer.cc +++ b/sky/compositor/opacity_layer.cc @@ -13,12 +13,17 @@ OpacityLayer::OpacityLayer() { OpacityLayer::~OpacityLayer() { } +void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { + ContainerLayer::Preroll(context, matrix); + set_paint_bounds(context->child_paint_bounds); +} + void OpacityLayer::Paint(PaintContext::ScopedFrame& frame) { SkPaint paint; paint.setColor(SkColorSetARGB(alpha_, 0, 0, 0)); paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); SkCanvas& canvas = frame.canvas(); - canvas.saveLayer(has_paint_bounds() ? &paint_bounds() : nullptr, &paint); + canvas.saveLayer(&paint_bounds(), &paint); PaintChildren(frame); canvas.restore(); } diff --git a/sky/compositor/opacity_layer.h b/sky/compositor/opacity_layer.h index 5d684f0bc..9ed79a5e5 100644 --- a/sky/compositor/opacity_layer.h +++ b/sky/compositor/opacity_layer.h @@ -18,6 +18,7 @@ class OpacityLayer : public ContainerLayer { void set_alpha(int alpha) { alpha_ = alpha; } protected: + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext::ScopedFrame& frame) override; private: diff --git a/sky/compositor/picture_layer.cc b/sky/compositor/picture_layer.cc index be87a746c..43bfa9d67 100644 --- a/sky/compositor/picture_layer.cc +++ b/sky/compositor/picture_layer.cc @@ -20,10 +20,11 @@ PictureLayer::PictureLayer() { PictureLayer::~PictureLayer() { } -void PictureLayer::Preroll(PaintContext::ScopedFrame& frame, +void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { - image_ = frame.context().raster_cache().GetPrerolledImage( - frame.gr_context(), picture_.get(), matrix); + image_ = context->frame.context().raster_cache().GetPrerolledImage( + context->frame.gr_context(), picture_.get(), matrix); + context->child_paint_bounds = picture_->cullRect(); } void PictureLayer::Paint(PaintContext::ScopedFrame& frame) { @@ -44,10 +45,9 @@ void PictureLayer::Paint(PaintContext::ScopedFrame& frame) { canvas.drawImage(image_.get(), dx, dy); canvas.restore(); - if (kDebugCheckerboardRasterizedLayers) { - SkRect rect = paint_bounds().makeOffset(offset_.x(), offset_.y()); - DrawCheckerboard(&canvas, rect); - } + if (kDebugCheckerboardRasterizedLayers) + DrawCheckerboard(&canvas, rect.makeOffset(offset_.x(), offset_.y())); + } else { canvas.save(); canvas.translate(offset_.x(), offset_.y()); diff --git a/sky/compositor/picture_layer.h b/sky/compositor/picture_layer.h index c7efba34d..1fbb29326 100644 --- a/sky/compositor/picture_layer.h +++ b/sky/compositor/picture_layer.h @@ -21,8 +21,7 @@ class PictureLayer : public Layer { SkPicture* picture() const { return picture_.get(); } - void Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix) override; + void Preroll(PrerollContext* frame, const SkMatrix& matrix) override; void Paint(PaintContext::ScopedFrame& frame) override; private: diff --git a/sky/compositor/transform_layer.cc b/sky/compositor/transform_layer.cc index 9fe8c896d..2b94c8466 100644 --- a/sky/compositor/transform_layer.cc +++ b/sky/compositor/transform_layer.cc @@ -13,11 +13,11 @@ TransformLayer::TransformLayer() { TransformLayer::~TransformLayer() { } -void TransformLayer::Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix) { +void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkMatrix childMatrix; childMatrix.setConcat(matrix, transform_); - PrerollChildren(frame, childMatrix); + PrerollChildren(context, childMatrix); + transform_.mapRect(&context->child_paint_bounds); } void TransformLayer::Paint(PaintContext::ScopedFrame& frame) { diff --git a/sky/compositor/transform_layer.h b/sky/compositor/transform_layer.h index 8f49d33b9..bd2c4e5b0 100644 --- a/sky/compositor/transform_layer.h +++ b/sky/compositor/transform_layer.h @@ -17,8 +17,7 @@ class TransformLayer : public ContainerLayer { void set_transform(const SkMatrix& transform) { transform_ = transform; } - void Preroll(PaintContext::ScopedFrame& frame, - const SkMatrix& matrix) override; + void Preroll(PrerollContext* context, const SkMatrix& matrix) override; void Paint(PaintContext::ScopedFrame& frame) override; private: diff --git a/sky/engine/core/compositing/SceneBuilder.cpp b/sky/engine/core/compositing/SceneBuilder.cpp index acdb2fabb..e360936f7 100644 --- a/sky/engine/core/compositing/SceneBuilder.cpp +++ b/sky/engine/core/compositing/SceneBuilder.cpp @@ -62,8 +62,7 @@ FOR_EACH_BINDING(DART_REGISTER_NATIVE) } SceneBuilder::SceneBuilder(const Rect& bounds) - : m_rootPaintBounds(bounds.sk_rect) - , m_currentLayer(nullptr) + : m_currentLayer(nullptr) , m_currentRasterizerTracingThreshold(0) { } @@ -106,8 +105,6 @@ void SceneBuilder::pushClipPath(const CanvasPath* path, const Rect& bounds) void SceneBuilder::pushOpacity(int alpha, const Rect& bounds) { std::unique_ptr layer(new sky::compositor::OpacityLayer()); - if (!bounds.is_null) - layer->set_paint_bounds(bounds.sk_rect); layer->set_alpha(alpha); addLayer(std::move(layer)); } @@ -115,8 +112,6 @@ void SceneBuilder::pushOpacity(int alpha, const Rect& bounds) void SceneBuilder::pushColorFilter(CanvasColor color, TransferMode transferMode, const Rect& bounds) { std::unique_ptr layer(new sky::compositor::ColorFilterLayer()); - if (!bounds.is_null) - layer->set_paint_bounds(bounds.sk_rect); layer->set_color(color); layer->set_transfer_mode(transferMode); addLayer(std::move(layer)); @@ -128,7 +123,6 @@ void SceneBuilder::addLayer(std::unique_ptr lay if (!m_rootLayer) { DCHECK(!m_currentLayer); m_rootLayer = std::move(layer); - m_rootLayer->set_paint_bounds(m_rootPaintBounds); m_currentLayer = m_rootLayer.get(); return; } @@ -153,8 +147,6 @@ void SceneBuilder::addPicture(const Offset& offset, Picture* picture, const Rect std::unique_ptr layer(new sky::compositor::PictureLayer()); layer->set_offset(SkPoint::Make(offset.sk_size.width(), offset.sk_size.height())); layer->set_picture(picture->toSkia()); - if (!paintBounds.is_null) - layer->set_paint_bounds(paintBounds.sk_rect); m_currentLayer->Add(std::move(layer)); } diff --git a/sky/engine/core/compositing/SceneBuilder.h b/sky/engine/core/compositing/SceneBuilder.h index d8d06626d..d09f8afcd 100644 --- a/sky/engine/core/compositing/SceneBuilder.h +++ b/sky/engine/core/compositing/SceneBuilder.h @@ -57,7 +57,6 @@ private: void addLayer(std::unique_ptr layer); - SkRect m_rootPaintBounds; std::unique_ptr m_rootLayer; sky::compositor::ContainerLayer* m_currentLayer; int32_t m_currentRasterizerTracingThreshold; -- GitLab