Reland "Add GetBoundingRectAfterMutations to EmbeddedViewParams to calculate the final bounding rect for platform view #19170" (#19212)

This commit is contained in:
Chris Yang 2020-06-22 15:10:02 -07:00 committed by GitHub
parent 2a5053f299
commit 5b1b59a34d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 182 additions and 41 deletions

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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 };

View File

@ -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));
}

View File

@ -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_ //
);
}

View File

@ -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));
@ -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));
@ -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);
@ -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);

View File

@ -407,13 +407,14 @@ void FlutterPlatformViewsController::ApplyMutators(const MutatorsStack& mutators
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;
@ -424,7 +425,7 @@ void FlutterPlatformViewsController::CompositeWithParams(int view_id,
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) {

View File

@ -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;
@ -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 =