Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -26,6 +26,7 @@ FILE: ../../../flutter/common/task_runners.cc
FILE: ../../../flutter/common/task_runners.h
FILE: ../../../flutter/flow/compositor_context.cc
FILE: ../../../flutter/flow/compositor_context.h
FILE: ../../../flutter/flow/embedded_view_params_unittests.cc
FILE: ../../../flutter/flow/embedded_views.cc
FILE: ../../../flutter/flow/embedded_views.h
FILE: ../../../flutter/flow/gl_context_switch.cc
Expand Down
1 change: 1 addition & 0 deletions flow/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ executable("flow_unittests") {
testonly = true

sources = [
"embedded_view_params_unittests.cc",
"flow_run_all_unittests.cc",
"flow_test_utils.cc",
"flow_test_utils.h",
Expand Down
98 changes: 98 additions & 0 deletions flow/embedded_view_params_unittests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2013 The Flutter 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 "flutter/flow/embedded_views.h"
#include "flutter/fml/logging.h"
#include "gtest/gtest.h"

namespace flutter {
namespace testing {

TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithNoMutations) {
MutatorsStack stack;
SkMatrix matrix;

EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 0));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 1));
}

TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithScale) {
MutatorsStack stack;
SkMatrix matrix = SkMatrix::Scale(2, 2);
stack.PushTransform(matrix);

EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 0));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 2));
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 2));
}

TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithTranslate) {
MutatorsStack stack;
SkMatrix matrix = SkMatrix::MakeTrans(1, 1);
stack.PushTransform(matrix);

EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), 1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 1));
}

TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation90) {
MutatorsStack stack;
SkMatrix matrix;
matrix.setRotate(90);
stack.PushTransform(matrix);

EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect();

FML_DLOG(ERROR) << rect.x();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 1));
}

TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithRotation45) {
MutatorsStack stack;
SkMatrix matrix;
matrix.setRotate(45);
stack.PushTransform(matrix);

EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -sqrt(2) / 2));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 0));
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), sqrt(2)));
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), sqrt(2)));
}

TEST(EmbeddedViewParams,
GetBoundingRectAfterMutationsWithTranslateScaleAndRotation) {
SkMatrix matrix = SkMatrix::MakeTrans(2, 2);
matrix.preScale(3, 3);
matrix.preRotate(90);

MutatorsStack stack;
stack.PushTransform(matrix);

EmbeddedViewParams params(matrix, SkSize::Make(1, 1), stack);
const SkRect& rect = params.finalBoundingRect();
ASSERT_TRUE(SkScalarNearlyEqual(rect.x(), -1));
ASSERT_TRUE(SkScalarNearlyEqual(rect.y(), 2));
ASSERT_TRUE(SkScalarNearlyEqual(rect.width(), 3));
ASSERT_TRUE(SkScalarNearlyEqual(rect.height(), 3));
}

} // namespace testing
} // namespace flutter
46 changes: 37 additions & 9 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,21 +186,49 @@ class EmbeddedViewParams {
public:
EmbeddedViewParams() = default;

EmbeddedViewParams(SkMatrix matrix,
SkSize size_points,
MutatorsStack mutators_stack)
: matrix_(matrix),
size_points_(size_points),
mutators_stack_(mutators_stack) {
SkPath path;
SkRect starting_rect = SkRect::MakeSize(size_points);
path.addRect(starting_rect);
path.transform(matrix);
final_bounding_rect_ = path.computeTightBounds();
}

EmbeddedViewParams(const EmbeddedViewParams& other) {
offsetPixels = other.offsetPixels;
sizePoints = other.sizePoints;
mutatorsStack = other.mutatorsStack;
size_points_ = other.size_points_;
mutators_stack_ = other.mutators_stack_;
matrix_ = other.matrix_;
final_bounding_rect_ = other.final_bounding_rect_;
};

SkPoint offsetPixels;
SkSize sizePoints;
MutatorsStack mutatorsStack;
// The original size of the platform view before any mutation matrix is
// applied.
const SkSize& sizePoints() const { return size_points_; };
// The mutators stack contains the detailed step by step mutations for this
// platform view.
const MutatorsStack& mutatorsStack() const { return mutators_stack_; };
// The bounding rect of the platform view after applying all the mutations.
//
// Clippings are ignored.
const SkRect& finalBoundingRect() const { return final_bounding_rect_; }

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

private:
SkMatrix matrix_;
SkSize size_points_;
MutatorsStack mutators_stack_;
SkRect final_bounding_rect_;
};

enum class PostPrerollResult { kResubmitFrame, kSuccess };
Expand Down
7 changes: 2 additions & 5 deletions flow/layers/platform_view_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@ void PlatformViewLayer::Preroll(PrerollContext* context,
}
context->has_platform_view = true;
std::unique_ptr<EmbeddedViewParams> params =
std::make_unique<EmbeddedViewParams>();
params->offsetPixels =
SkPoint::Make(matrix.getTranslateX(), matrix.getTranslateY());
params->sizePoints = size_;
params->mutatorsStack = context->mutators_stack;
std::make_unique<EmbeddedViewParams>(matrix, size_,
context->mutators_stack);
context->view_embedder->PrerollCompositeEmbeddedView(view_id_,
std::move(params));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ SkRect AndroidExternalViewEmbedder::GetViewRect(int view_id) const {
const EmbeddedViewParams& params = view_params_.at(view_id);
// TODO(egarciad): The rect should be computed from the mutator stack.
// https://github.com/flutter/flutter/issues/59821
return SkRect::MakeXYWH(params.offsetPixels.x(), //
params.offsetPixels.y(), //
params.sizePoints.width() * device_pixel_ratio_, //
params.sizePoints.height() * device_pixel_ratio_ //
return SkRect::MakeXYWH(params.finalBoundingRect().x(), //
params.finalBoundingRect().y(), //
params.sizePoints().width() * device_pixel_ratio_, //
params.sizePoints().height() * device_pixel_ratio_ //
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,11 @@ TEST(AndroidExternalViewEmbedder, PlatformViewRect) {
embedder->BeginFrame(SkISize::Make(100, 100), nullptr, 1.5,
raster_thread_merger);

auto view_params = std::make_unique<EmbeddedViewParams>();
view_params->offsetPixels = SkPoint::Make(10, 20);
view_params->sizePoints = SkSize::Make(30, 40);
MutatorsStack stack;
SkMatrix matrix = SkMatrix::MakeTrans(10, 20);
stack.PushTransform(matrix);
auto view_params =
std::make_unique<EmbeddedViewParams>(matrix, SkSize::Make(30, 40), stack);

auto view_id = 0;
embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params));
Expand All @@ -219,14 +221,21 @@ TEST(AndroidExternalViewEmbedder, PlatformViewRect__ChangedParams) {
raster_thread_merger);

auto view_id = 0;
auto view_params_1 = std::make_unique<EmbeddedViewParams>();
view_params_1->offsetPixels = SkPoint::Make(10, 20);
view_params_1->sizePoints = SkSize::Make(30, 40);

MutatorsStack stack1;
SkMatrix matrix1 = SkMatrix::MakeTrans(10, 20);
stack1.PushTransform(matrix1);
auto view_params_1 = std::make_unique<EmbeddedViewParams>(
matrix1, SkSize::Make(30, 40), stack1);

embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params_1));

auto view_params_2 = std::make_unique<EmbeddedViewParams>();
view_params_2->offsetPixels = SkPoint::Make(50, 60);
view_params_2->sizePoints = SkSize::Make(70, 80);
MutatorsStack stack2;
SkMatrix matrix2 = SkMatrix::MakeTrans(50, 60);
stack2.PushTransform(matrix2);
auto view_params_2 = std::make_unique<EmbeddedViewParams>(
matrix2, SkSize::Make(70, 80), stack2);

embedder->PrerollCompositeEmbeddedView(view_id, std::move(view_params_2));

ASSERT_EQ(SkRect::MakeXYWH(50, 60, 105, 120), embedder->GetViewRect(view_id));
Expand Down Expand Up @@ -281,11 +290,14 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame__RecycleSurfaces) {
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);

// Add an Android view.
auto view_params_1 = std::make_unique<EmbeddedViewParams>();
view_params_1->offsetPixels = SkPoint::Make(100, 100);
MutatorsStack stack1;
SkMatrix matrix1 = SkMatrix::MakeTrans(100, 100);
stack1.PushTransform(matrix1);
// TODO(egarciad): Investigate why Flow applies the device pixel ratio to
// the offsetPixels, but not the sizePoints.
view_params_1->sizePoints = SkSize::Make(200, 200);
auto view_params_1 = std::make_unique<EmbeddedViewParams>(
matrix1, SkSize::Make(200, 200), stack1);

embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
// This is the recording canvas flow writes to.
auto canvas_1 = embedder->CompositeEmbeddedView(0);
Expand Down Expand Up @@ -329,11 +341,14 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame__RecycleSurfaces) {
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);

// Add an Android view.
auto view_params_1 = std::make_unique<EmbeddedViewParams>();
view_params_1->offsetPixels = SkPoint::Make(100, 100);
MutatorsStack stack1;
SkMatrix matrix1 = SkMatrix::MakeTrans(100, 100);
stack1.PushTransform(matrix1);
// TODO(egarciad): Investigate why Flow applies the device pixel ratio to
// the offsetPixels, but not the sizePoints.
view_params_1->sizePoints = SkSize::Make(200, 200);
auto view_params_1 = std::make_unique<EmbeddedViewParams>(
matrix1, SkSize::Make(200, 200), stack1);

embedder->PrerollCompositeEmbeddedView(0, std::move(view_params_1));
// This is the recording canvas flow writes to.
auto canvas_1 = embedder->CompositeEmbeddedView(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,13 +407,14 @@

void FlutterPlatformViewsController::CompositeWithParams(int view_id,
const EmbeddedViewParams& params) {
CGRect frame = CGRectMake(0, 0, params.sizePoints.width(), params.sizePoints.height());
CGRect frame = CGRectMake(0, 0, params.sizePoints().width(), params.sizePoints().height());
UIView* touchInterceptor = touch_interceptors_[view_id].get();
touchInterceptor.layer.transform = CATransform3DIdentity;
touchInterceptor.frame = frame;
touchInterceptor.alpha = 1;

int currentClippingCount = CountClips(params.mutatorsStack);
const MutatorsStack& mutatorStack = params.mutatorsStack();
int currentClippingCount = CountClips(mutatorStack);
int previousClippingCount = clip_count_[view_id];
if (currentClippingCount != previousClippingCount) {
clip_count_[view_id] = currentClippingCount;
Expand All @@ -424,7 +425,7 @@
ReconstructClipViewsChain(currentClippingCount, touchInterceptor, oldPlatformViewRoot);
root_views_[view_id] = fml::scoped_nsobject<UIView>([newPlatformViewRoot retain]);
}
ApplyMutators(params.mutatorsStack, touchInterceptor);
ApplyMutators(mutatorStack, touchInterceptor);
}

SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView(int view_id) {
Expand Down
10 changes: 5 additions & 5 deletions shell/platform/embedder/embedder_layers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void EmbedderLayers::PushPlatformViewLayer(
view.struct_size = sizeof(FlutterPlatformView);
view.identifier = identifier;

const auto& mutators = params.mutatorsStack;
const auto& mutators = params.mutatorsStack();

std::vector<const FlutterPlatformViewMutation*> mutations_array;

Expand Down Expand Up @@ -180,10 +180,10 @@ void EmbedderLayers::PushPlatformViewLayer(
layer.platform_view = platform_views_referenced_.back().get();

const auto layer_bounds =
SkRect::MakeXYWH(params.offsetPixels.x(), //
params.offsetPixels.y(), //
params.sizePoints.width() * device_pixel_ratio_, //
params.sizePoints.height() * device_pixel_ratio_ //
SkRect::MakeXYWH(params.finalBoundingRect().x(), //
params.finalBoundingRect().y(), //
params.sizePoints().width() * device_pixel_ratio_, //
params.sizePoints().height() * device_pixel_ratio_ //
);

const auto transformed_layer_bounds =
Expand Down