Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IOS Platform view transform/clipping #9075

Merged
merged 69 commits into from
Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
853cbd6
get the stack ready
May 16, 2019
72042cf
draft
May 17, 2019
8489c08
Do nothing if the params didn't change when compositing platform views.
May 17, 2019
647e66b
merge
May 17, 2019
f7d7aaa
draft
May 17, 2019
c0741b2
draft
May 18, 2019
6e95d26
draft2
May 24, 2019
a3e1d61
clip rrect
May 28, 2019
4cf9f8a
typo fix
May 28, 2019
1daacb0
Merge branch 'master' into platform_view_transform
May 28, 2019
04d1f40
counting previous clips and only add and remove uiview when number of…
May 29, 2019
5b05eb2
draft
May 30, 2019
9b290cb
draft
May 30, 2019
52a8252
comments and formatting
May 31, 2019
3a899fa
english
May 31, 2019
cabc67a
remove friend from operator==
May 31, 2019
4496b21
merge master
Jun 3, 2019
4bdae98
fix issue caused by merging
Jun 3, 2019
33513b9
review fixes
Jun 3, 2019
e8926a5
remove tranform\cilpping util method into a different file and add th…
Jun 4, 2019
3f4c586
rename after review
Jun 4, 2019
d4f88f2
move stack to paint context
Jun 4, 2019
4eeb64f
draft vector with unique_ptr
Jun 4, 2019
6d78901
more review fixes
Jun 4, 2019
e494853
unittests for mutator stack
Jun 5, 2019
81e5c19
move stack to paint context complete
Jun 5, 2019
ea11fad
formatting
Jun 5, 2019
2c79050
Merge branch 'master' into platform_view_transform
Jun 5, 2019
0f70a44
mutator stack compare fixes
Jun 6, 2019
32d2681
mutator stack compare fixes
Jun 6, 2019
b874420
revert the change that made the vector containing unique_ptr
Jun 6, 2019
a1794de
formatting
Jun 6, 2019
2f0125c
add TODO
Jun 6, 2019
d22acbd
fix a bug where the reused clip view doesn't reset transform
Jun 10, 2019
2b08642
addition to last fix
Jun 10, 2019
1599067
adding touch transparent view
Jun 10, 2019
a027fa0
some review fixes
Jun 11, 2019
12ff43a
union done
Jun 11, 2019
a9a660f
draft
Jun 11, 2019
f4b9503
review fixes
Jun 12, 2019
7c0fa63
draft
Jun 12, 2019
2eb40d6
embeded param does not delete stack when destructed
Jun 12, 2019
6d4c82c
Merge branch 'platform_view_transform' into platform_view_transform_u…
Jun 12, 2019
7d1d0e5
copy constructor for Mutator
Jun 12, 2019
46098a4
more tests
Jun 12, 2019
fa1248a
remove the move to
Jun 12, 2019
dd0eed8
merge
Jun 12, 2019
50843a0
share ptr for vector_
Jun 12, 2019
31ec192
Merge branch 'master' into platform_view_transform
Jun 12, 2019
3b6b3b0
formatting
Jun 12, 2019
b4b59ca
fixes unittest
Jun 12, 2019
ee57e42
Update BUILD.gn
iskakaushik Jun 12, 2019
979d251
license file fix
Jun 12, 2019
b45ad9a
some review fixes
Jun 13, 2019
b40944e
another fix
Jun 13, 2019
701afe5
formatting
Jun 14, 2019
551445d
add todo
Jun 14, 2019
8622d13
move back some accidentally deleted code
Jun 14, 2019
d46290e
draft
Jun 19, 2019
8f86532
refactoring
Jun 19, 2019
a5b7f8a
review fixes
Jun 20, 2019
b0d3110
formatting
Jun 20, 2019
ff442ee
let submit frame handle adding the head if detached
Jun 20, 2019
5f0a513
Merge branch 'master' into platform_view_transform
Jun 20, 2019
455a495
logs
Jun 20, 2019
cf36c46
move insert back uiview logic into recontruct method
Jun 21, 2019
fd498ee
rever unrelated changes
Jun 21, 2019
78acc1f
review fixes
Jun 24, 2019
aeb56e0
Merge branch 'master' into platform_view_transform
Jun 24, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ FILE: ../../../flutter/flow/layers/transform_layer.h
FILE: ../../../flutter/flow/matrix_decomposition.cc
FILE: ../../../flutter/flow/matrix_decomposition.h
FILE: ../../../flutter/flow/matrix_decomposition_unittests.cc
FILE: ../../../flutter/flow/mutators_stack_unittests.cc
FILE: ../../../flutter/flow/paint_utils.cc
FILE: ../../../flutter/flow/paint_utils.h
FILE: ../../../flutter/flow/raster_cache.cc
Expand Down
1 change: 1 addition & 0 deletions flow/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ executable("flow_unittests") {
"layers/performance_overlay_layer_unittests.cc",
"layers/physical_shape_layer_unittests.cc",
"matrix_decomposition_unittests.cc",
"mutators_stack_unittests.cc",
"raster_cache_unittests.cc",
]

Expand Down
30 changes: 30 additions & 0 deletions flow/embedded_views.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,34 @@ namespace flutter {
bool ExternalViewEmbedder::SubmitFrame(GrContext* context) {
return false;
};

void MutatorsStack::pushClipRect(const SkRect& rect) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rect);
vector_.push_back(element);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can save some copies by making it a vector of unique pointers

Copy link
Contributor Author

@cyanglaz cyanglaz Jun 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried it naively and caused some issue when trying to copy the stack to the params, reverting the change and adding a TODO and will work on it in future.

};

void MutatorsStack::pushClipRRect(const SkRRect& rrect) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rrect);
vector_.push_back(element);
};

void MutatorsStack::pushTransform(const SkMatrix& matrix) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(matrix);
vector_.push_back(element);
};

void MutatorsStack::pop() {
vector_.pop_back();
};

const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator
MutatorsStack::top() const {
return vector_.rend();
};

const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator
MutatorsStack::bottom() const {
return vector_.rbegin();
};

} // namespace flutter
158 changes: 156 additions & 2 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,178 @@

#include "flutter/fml/memory/ref_counted.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkSize.h"

namespace flutter {

enum MutatorType { clip_rect, clip_rrect, clip_path, transform };

// Stores mutation information like clipping or transform.
//
// The `type` indicates the type of the mutation: clip_rect, transform and etc.
// Each `type` is paired with an object that supports the mutation. For example,
// if the `type` is clip_rect, `rect()` is used the represent the rect to be
// clipped. One mutation object must only contain one type of mutation.
class Mutator {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

document

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

public:
Mutator(const Mutator& other) {
type_ = other.type_;
switch (other.type_) {
case clip_rect:
rect_ = other.rect_;
break;
case clip_rrect:
rrect_ = other.rrect_;
break;
case clip_path:
path_ = new SkPath(*other.path_);
break;
case transform:
matrix_ = other.matrix_;
break;
default:
break;
}
}

explicit Mutator(const SkRect& rect) : type_(clip_rect), rect_(rect) {}
explicit Mutator(const SkRRect& rrect) : type_(clip_rrect), rrect_(rrect) {}
explicit Mutator(const SkPath& path)
: type_(clip_path), path_(new SkPath(path)) {}
explicit Mutator(const SkMatrix& matrix)
: type_(transform), matrix_(matrix) {}

const MutatorType& type() const { return type_; }
const SkRect& rect() const { return rect_; }
const SkRRect& rrect() const { return rrect_; }
const SkPath& path() const { return *path_; }
const SkMatrix& matrix() const { return matrix_; }

bool operator==(const Mutator& other) const {
if (type_ != other.type_) {
return false;
}
if (type_ == clip_rect && rect_ == other.rect_) {
return true;
}
if (type_ == clip_rrect && rrect_ == other.rrect_) {
return true;
}
if (type_ == clip_path && *path_ == *other.path_) {
return true;
}
if (type_ == transform && matrix_ == other.matrix_) {
return true;
}

return false;
}

bool operator!=(const Mutator& other) const { return !operator==(other); }

bool isClipType() {
return type_ == clip_rect || type_ == clip_rrect || type_ == clip_path;
}

~Mutator() {
if (type_ == clip_path) {
delete path_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use a unique pointer instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f2f discussion: unique_ptr still needs to provide a destructor if it is inside a union, so we keep using a raw pointer.

}
};

private:
MutatorType type_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: A union will save a few bytes here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


union {
SkRect rect_;
SkRRect rrect_;
SkMatrix matrix_;
SkPath* path_;
};

}; // Mutator

// A stack of mutators that can be applied to an embedded platform view.
//
// The stack may include mutators like transforms and clips, each mutator
// applies to all the mutators that are below it in the stack and to the
// embedded view.
//
// For example consider the following stack: [T1, T2, T3], where T1 is the top
// of the stack and T3 is the bottom of the stack. Applying this mutators stack
// to a platform view P1 will result in T1(T2(T2(P1))).
class MutatorsStack {
public:
MutatorsStack() = default;

void pushClipRect(const SkRect& rect);
void pushClipRRect(const SkRRect& rrect);
void pushClipPath(const SkPath& path);

void pushTransform(const SkMatrix& matrix);

// Removes the `Mutator` on the top of the stack
// and destroys it.
void pop();

// Returns an iterator pointing to the top of the stack.
const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator top()
const;
// Returns an iterator pointing to the bottom of the stack.
const std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator bottom()
const;

bool operator==(const MutatorsStack& other) const {
if (vector_.size() != other.vector_.size()) {
return false;
}
for (size_t i = 0; i < vector_.size(); i++) {
if (*vector_[i] != *other.vector_[i]) {
return false;
}
}
return true;
}

bool operator!=(const MutatorsStack& other) const {
return !operator==(other);
}

private:
std::vector<std::shared_ptr<Mutator>> vector_;
}; // MutatorsStack

class EmbeddedViewParams {
public:
EmbeddedViewParams() = default;

EmbeddedViewParams(const EmbeddedViewParams& other) {
offsetPixels = other.offsetPixels;
sizePoints = other.sizePoints;
mutatorsStack = other.mutatorsStack;
};

SkPoint offsetPixels;
SkSize sizePoints;
MutatorsStack mutatorsStack;

bool operator==(const EmbeddedViewParams& other) const {
return offsetPixels == other.offsetPixels && sizePoints == other.sizePoints;
return offsetPixels == other.offsetPixels &&
sizePoints == other.sizePoints &&
mutatorsStack == other.mutatorsStack;
}
};

// This is only used on iOS when running in a non headless mode,
// in this case ExternalViewEmbedder is a reference to the
// FlutterPlatformViewsController which is owned by FlutterViewController.
class ExternalViewEmbedder {
// TODO(cyanglaz): Make embedder own the `EmbeddedViewParams`.

public:
ExternalViewEmbedder() = default;

Expand All @@ -46,7 +199,8 @@ class ExternalViewEmbedder {
virtual ~ExternalViewEmbedder() = default;

FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder);
};

}; // ExternalViewEmbedder

} // namespace flutter

Expand Down
3 changes: 3 additions & 0 deletions flow/layers/clip_rect_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,16 @@ void ClipRectLayer::Paint(PaintContext& context) const {
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
context.internal_nodes_canvas->clipRect(clip_rect_,
clip_behavior_ != Clip::hardEdge);
context.mutators_stack.pushClipRect(clip_rect_);

if (clip_behavior_ == Clip::antiAliasWithSaveLayer) {
context.internal_nodes_canvas->saveLayer(clip_rect_, nullptr);
}
PaintChildren(context);
if (clip_behavior_ == Clip::antiAliasWithSaveLayer) {
context.internal_nodes_canvas->restore();
}
context.mutators_stack.pop();
}

} // namespace flutter
3 changes: 3 additions & 0 deletions flow/layers/clip_rrect_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,16 @@ void ClipRRectLayer::Paint(PaintContext& context) const {
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
context.internal_nodes_canvas->clipRRect(clip_rrect_,
clip_behavior_ != Clip::hardEdge);
context.mutators_stack.pushClipRRect(clip_rrect_);

if (clip_behavior_ == Clip::antiAliasWithSaveLayer) {
context.internal_nodes_canvas->saveLayer(paint_bounds(), nullptr);
}
PaintChildren(context);
if (clip_behavior_ == Clip::antiAliasWithSaveLayer) {
context.internal_nodes_canvas->restore();
}
context.mutators_stack.pop();
}

} // namespace flutter
1 change: 1 addition & 0 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class Layer {
SkCanvas* leaf_nodes_canvas;
GrContext* gr_context;
ExternalViewEmbedder* view_embedder;
MutatorsStack& mutators_stack;
const Stopwatch& raster_time;
const Stopwatch& ui_time;
TextureRegistry& texture_registry;
Expand Down
4 changes: 4 additions & 0 deletions flow/layers/layer_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame,
}
}

MutatorsStack stack;
Layer::PaintContext context = {
(SkCanvas*)&internal_nodes_canvas,
frame.canvas(),
frame.gr_context(),
frame.view_embedder(),
stack,
frame.context().raster_time(),
frame.context().ui_time(),
frame.context().texture_registry(),
Expand All @@ -108,6 +110,7 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
return nullptr;
}

MutatorsStack unused_stack;
const Stopwatch unused_stopwatch;
TextureRegistry unused_texture_registry;
SkMatrix root_surface_transformation;
Expand Down Expand Up @@ -135,6 +138,7 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
canvas, // canvas
nullptr,
nullptr,
unused_stack,
unused_stopwatch, // frame time (dont care)
unused_stopwatch, // engine time (dont care)
unused_texture_registry, // texture registry (not supported)
Expand Down
9 changes: 6 additions & 3 deletions flow/layers/performance_overlay_layer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,13 @@ TEST(PerformanceOverlayLayer, Gold) {
ASSERT_TRUE(surface != nullptr);

flutter::TextureRegistry unused_texture_registry;

flutter::MutatorsStack unused_stack;
flutter::Layer::PaintContext paintContext = {
nullptr, surface->getCanvas(), nullptr, nullptr, mock_stopwatch,
mock_stopwatch, unused_texture_registry, nullptr, false};
nullptr, surface->getCanvas(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one per line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is auto formatted.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😟 really that's what clang format is doing?

nullptr, nullptr,
unused_stack, mock_stopwatch,
mock_stopwatch, unused_texture_registry,
nullptr, false};

// Specify font file to ensure the same font across different operation
// systems.
Expand Down
1 change: 1 addition & 0 deletions flow/layers/platform_view_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void PlatformViewLayer::Paint(PaintContext& context) const {
params.offsetPixels =
SkPoint::Make(transform.getTranslateX(), transform.getTranslateY());
params.sizePoints = size_;
params.mutatorsStack = context.mutators_stack;

SkCanvas* canvas =
context.view_embedder->CompositeEmbeddedView(view_id_, params);
Expand Down
3 changes: 3 additions & 0 deletions flow/layers/transform_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ void TransformLayer::Paint(PaintContext& context) const {

SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
context.internal_nodes_canvas->concat(transform_);
context.mutators_stack.pushTransform(transform_);

PaintChildren(context);
context.mutators_stack.pop();
}

} // namespace flutter
Loading