diff --git a/engine/src/flutter/lib/ui/compositing/scene_builder.cc b/engine/src/flutter/lib/ui/compositing/scene_builder.cc index 2fc6c5b222..22f496c8c4 100644 --- a/engine/src/flutter/lib/ui/compositing/scene_builder.cc +++ b/engine/src/flutter/lib/ui/compositing/scene_builder.cc @@ -57,56 +57,78 @@ void SceneBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) { } SceneBuilder::SceneBuilder() - : m_currentLayer(nullptr), m_currentRasterizerTracingThreshold(0) {} + : m_currentLayer(nullptr), m_currentRasterizerTracingThreshold(0) { + m_cullRects.push(SkRect::MakeLargest()); +} SceneBuilder::~SceneBuilder() {} void SceneBuilder::pushTransform(const tonic::Float64List& matrix4) { SkMatrix sk_matrix = ToSkMatrix(matrix4); + SkMatrix inverse_sk_matrix; + SkRect cullRect; + if (sk_matrix.invert(&inverse_sk_matrix)) + inverse_sk_matrix.mapRect(&cullRect, m_cullRects.top()); + else + cullRect = SkRect::MakeLargest(); + std::unique_ptr layer(new flow::TransformLayer()); layer->set_transform(sk_matrix); - addLayer(std::move(layer)); + addLayer(std::move(layer), cullRect); } void SceneBuilder::pushClipRect(double left, double right, double top, double bottom) { + const SkRect clipRect = SkRect::MakeLTRB(left, top, right, bottom); + SkRect cullRect; + if (!cullRect.intersect(clipRect, m_cullRects.top())) + cullRect = SkRect::MakeEmpty(); + std::unique_ptr layer(new flow::ClipRectLayer()); - layer->set_clip_rect(SkRect::MakeLTRB(left, top, right, bottom)); - addLayer(std::move(layer)); + layer->set_clip_rect(clipRect); + addLayer(std::move(layer), cullRect); } void SceneBuilder::pushClipRRect(const RRect& rrect) { + SkRect cullRect; + if (!cullRect.intersect(rrect.sk_rrect.rect(), m_cullRects.top())) + cullRect = SkRect::MakeEmpty(); + std::unique_ptr layer(new flow::ClipRRectLayer()); layer->set_clip_rrect(rrect.sk_rrect); - addLayer(std::move(layer)); + addLayer(std::move(layer), cullRect); } void SceneBuilder::pushClipPath(const CanvasPath* path) { + SkRect cullRect; + if (!cullRect.intersect(path->path().getBounds(), m_cullRects.top())) + cullRect = SkRect::MakeEmpty(); + std::unique_ptr layer(new flow::ClipPathLayer()); layer->set_clip_path(path->path()); - addLayer(std::move(layer)); + addLayer(std::move(layer), cullRect); } void SceneBuilder::pushOpacity(int alpha) { std::unique_ptr layer(new flow::OpacityLayer()); layer->set_alpha(alpha); - addLayer(std::move(layer)); + addLayer(std::move(layer), m_cullRects.top()); } void SceneBuilder::pushColorFilter(int color, int transferMode) { std::unique_ptr layer(new flow::ColorFilterLayer()); layer->set_color(static_cast(color)); layer->set_transfer_mode(static_cast(transferMode)); - addLayer(std::move(layer)); + addLayer(std::move(layer), m_cullRects.top()); } void SceneBuilder::pushBackdropFilter(ImageFilter* filter) { std::unique_ptr layer( new flow::BackdropFilterLayer()); layer->set_filter(filter->filter()); - addLayer(std::move(layer)); + addLayer(std::move(layer), m_cullRects.top()); } void SceneBuilder::pushShaderMask(Shader* shader, @@ -120,11 +142,14 @@ void SceneBuilder::pushShaderMask(Shader* shader, layer->set_mask_rect(SkRect::MakeLTRB(maskRectLeft, maskRectTop, maskRectRight, maskRectBottom)); layer->set_transfer_mode(static_cast(transferMode)); - addLayer(std::move(layer)); + addLayer(std::move(layer), m_cullRects.top()); } -void SceneBuilder::addLayer(std::unique_ptr layer) { +void SceneBuilder::addLayer(std::unique_ptr layer, const SkRect& cullRect) { DCHECK(layer); + + m_cullRects.push(cullRect); + if (!m_rootLayer) { DCHECK(!m_currentLayer); m_rootLayer = std::move(layer); @@ -141,6 +166,7 @@ void SceneBuilder::addLayer(std::unique_ptr layer) { void SceneBuilder::pop() { if (!m_currentLayer) return; + m_cullRects.pop(); m_currentLayer = m_currentLayer->parent(); } @@ -150,6 +176,12 @@ void SceneBuilder::addPicture(double dx, int hints) { if (!m_currentLayer) return; + + SkRect pictureRect = picture->picture()->cullRect(); + pictureRect.offset(dx, dy); + if (!SkRect::Intersects(pictureRect, m_cullRects.top())) + return; + std::unique_ptr layer(new flow::PictureLayer()); layer->set_offset(SkPoint::Make(dx, dy)); layer->set_picture(picture->picture()); diff --git a/engine/src/flutter/lib/ui/compositing/scene_builder.h b/engine/src/flutter/lib/ui/compositing/scene_builder.h index f352f8b1ea..5d530f70fd 100644 --- a/engine/src/flutter/lib/ui/compositing/scene_builder.h +++ b/engine/src/flutter/lib/ui/compositing/scene_builder.h @@ -5,8 +5,8 @@ #ifndef FLUTTER_LIB_UI_COMPOSITING_SCENE_BUILDER_H_ #define FLUTTER_LIB_UI_COMPOSITING_SCENE_BUILDER_H_ +#include #include - #include #include "flutter/flow/layers/container_layer.h" @@ -70,11 +70,12 @@ class SceneBuilder : public ftl::RefCountedThreadSafe, private: explicit SceneBuilder(); - void addLayer(std::unique_ptr layer); + void addLayer(std::unique_ptr layer, const SkRect& cullRect); std::unique_ptr m_rootLayer; flow::ContainerLayer* m_currentLayer; int32_t m_currentRasterizerTracingThreshold; + std::stack m_cullRects; }; } // namespace blink