未验证 提交 75ea3e24 编写于 作者: C Chinmay Garde 提交者: GitHub

Expose the platform view mutator stack to custom compositors. (#13731)

This allows custom compositors to affect scene builder modifications made
to the platform view.

Fixes https://github.com/flutter/flutter/issues/44211
Fixes b/143612326
上级 c812a62b
......@@ -856,6 +856,8 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_gl.h
FILE: ../../../flutter/shell/platform/embedder/embedder_external_view_embedder.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_external_view_embedder.h
FILE: ../../../flutter/shell/platform/embedder/embedder_include.c
FILE: ../../../flutter/shell/platform/embedder/embedder_layers.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_layers.h
FILE: ../../../flutter/shell/platform/embedder/embedder_platform_message_response.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_platform_message_response.h
FILE: ../../../flutter/shell/platform/embedder/embedder_render_target.cc
......
......@@ -19,6 +19,7 @@
namespace flutter {
// TODO(chinmaygarde): Make these enum names match the style guide.
enum MutatorType { clip_rect, clip_rrect, clip_path, transform, opacity };
// Stores mutation information like clipping or transform.
......
......@@ -32,6 +32,8 @@ template("embedder_source_set") {
"embedder_external_view_embedder.cc",
"embedder_external_view_embedder.h",
"embedder_include.c",
"embedder_layers.cc",
"embedder_layers.h",
"embedder_platform_message_response.cc",
"embedder_platform_message_response.h",
"embedder_render_target.cc",
......
......@@ -464,6 +464,24 @@ typedef struct {
double bottom;
} FlutterRect;
typedef struct {
double x;
double y;
} FlutterPoint;
typedef struct {
double width;
double height;
} FlutterSize;
typedef struct {
FlutterRect rect;
FlutterSize upper_left_corner_radius;
FlutterSize upper_right_corner_radius;
FlutterSize lower_right_corner_radius;
FlutterSize lower_left_corner_radius;
} FlutterRoundedRect;
/// The identifier of the platform view. This identifier is specified by the
/// application when a platform view is added to the scene via the
/// `SceneBuilder.addPlatformView` call.
......@@ -667,6 +685,32 @@ typedef struct {
VoidCallback destruction_callback;
} FlutterSoftwareBackingStore;
typedef enum {
/// Indicates that the Flutter application requested that an opacity be
/// applied to the platform view.
kFlutterPlatformViewMutationTypeOpacity,
/// Indicates that the Flutter application requested that the platform view be
/// clipped using a rectangle.
kFlutterPlatformViewMutationTypeClipRect,
/// Indicates that the Flutter application requested that the platform view be
/// clipped using a rounded rectangle.
kFlutterPlatformViewMutationTypeClipRoundedRect,
/// Indicates that the Flutter application requested that the platform view be
/// transformed before composition.
kFlutterPlatformViewMutationTypeTransformation,
} FlutterPlatformViewMutationType;
typedef struct {
/// The type of the mutation described by the subsequent union.
FlutterPlatformViewMutationType type;
union {
double opacity;
FlutterRect clip_rect;
FlutterRoundedRect clip_rounded_rect;
FlutterTransformation transformation;
};
} FlutterPlatformViewMutation;
typedef struct {
/// The size of this struct. Must be sizeof(FlutterPlatformView).
size_t struct_size;
......@@ -674,6 +718,22 @@ typedef struct {
/// application when a platform view is added to the scene via the
/// `SceneBuilder.addPlatformView` call.
FlutterPlatformViewIdentifier identifier;
/// The number of mutations to be applied to the platform view by the embedder
/// before on-screen composition.
size_t mutations_count;
/// The mutations to be applied by this platform view before it is composited
/// on-screen. The Flutter application may transform the platform view but
/// these transformations cannot be affected by the Flutter compositor because
/// it does not render platform views. Since the embedder is responsible for
/// composition of these views, it is also the embedder's responsibility to
/// affect the appropriate transformation.
///
/// The mutations must be applied in order. The mutations done in the
/// collection don't take into account the device pixel ratio or the root
/// surface transformation. If these exist, the first mutation in the list
/// will be a transformation mutation to make sure subsequent mutations are in
/// the correct coordinate space.
const FlutterPlatformViewMutation** mutations;
} FlutterPlatformView;
typedef enum {
......@@ -704,16 +764,6 @@ typedef struct {
};
} FlutterBackingStore;
typedef struct {
double x;
double y;
} FlutterPoint;
typedef struct {
double width;
double height;
} FlutterSize;
typedef struct {
/// The size of this struct. Must be sizeof(FlutterBackingStoreConfig).
size_t struct_size;
......
......@@ -6,6 +6,7 @@
#include <algorithm>
#include "flutter/shell/platform/embedder/embedder_layers.h"
#include "flutter/shell/platform/embedder/embedder_render_target.h"
namespace flutter {
......@@ -146,71 +147,6 @@ SkCanvas* EmbedderExternalViewEmbedder::CompositeEmbeddedView(int view_id) {
return found->second->GetSpyingCanvas();
}
static FlutterLayer MakeBackingStoreLayer(
const SkISize& frame_size,
const FlutterBackingStore* store,
const SkMatrix& surface_transformation) {
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = store;
const auto layer_bounds =
SkRect::MakeWH(frame_size.width(), frame_size.height());
const auto transformed_layer_bounds =
surface_transformation.mapRect(layer_bounds);
layer.offset.x = transformed_layer_bounds.x();
layer.offset.y = transformed_layer_bounds.y();
layer.size.width = transformed_layer_bounds.width();
layer.size.height = transformed_layer_bounds.height();
return layer;
}
static FlutterPlatformView MakePlatformView(
FlutterPlatformViewIdentifier identifier) {
FlutterPlatformView view = {};
view.struct_size = sizeof(view);
view.identifier = identifier;
return view;
}
static FlutterLayer MakePlatformViewLayer(
const EmbeddedViewParams& params,
const FlutterPlatformView& platform_view,
const SkMatrix& surface_transformation,
double device_pixel_ratio) {
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypePlatformView;
layer.platform_view = &platform_view;
const auto layer_bounds = SkRect::MakeXYWH(params.offsetPixels.x(), //
params.offsetPixels.y(), //
params.sizePoints.width(), //
params.sizePoints.height() //
);
const auto transformed_layer_bounds =
SkMatrix::Concat(surface_transformation,
SkMatrix::MakeScale(device_pixel_ratio))
.mapRect(layer_bounds);
layer.offset.x = transformed_layer_bounds.x();
layer.offset.y = transformed_layer_bounds.y();
layer.size.width = transformed_layer_bounds.width();
layer.size.height = transformed_layer_bounds.height();
return layer;
}
bool EmbedderExternalViewEmbedder::RenderPictureToRenderTarget(
sk_sp<SkPicture> picture,
const EmbedderRenderTarget* render_target) const {
......@@ -240,11 +176,10 @@ bool EmbedderExternalViewEmbedder::RenderPictureToRenderTarget(
// |ExternalViewEmbedder|
bool EmbedderExternalViewEmbedder::SubmitFrame(GrContext* context) {
std::map<FlutterPlatformViewIdentifier, FlutterPlatformView>
presented_platform_views;
// Layers may contain pointers to platform views in the collection above.
std::vector<FlutterLayer> presented_layers;
Registry render_targets_used;
EmbedderLayers presented_layers(pending_frame_size_,
pending_device_pixel_ratio_,
pending_surface_transformation_);
if (!root_render_target_) {
FML_LOG(ERROR)
......@@ -264,11 +199,8 @@ bool EmbedderExternalViewEmbedder::SubmitFrame(GrContext* context) {
{
// The root surface is expressed as a layer.
presented_layers.push_back(MakeBackingStoreLayer(
pending_frame_size_, // frame size
root_render_target_->GetBackingStore(), // backing store
pending_surface_transformation_ // surface transformation
));
presented_layers.PushBackingStoreLayer(
root_render_target_->GetBackingStore());
}
const auto surface_size = TransformedSurfaceSize(
......@@ -289,21 +221,12 @@ bool EmbedderExternalViewEmbedder::SubmitFrame(GrContext* context) {
return false;
}
// Indicate a layer for the platform view. Add to `presented_platform_views`
// in order to keep at allocated just for the scope of the current method.
// The layers presented to the embedder will contain a back pointer to this
// struct. It is safe to deallocate when the embedder callback is done.
presented_platform_views[view_id] = MakePlatformView(view_id);
presented_layers.push_back(MakePlatformViewLayer(
params, // embedded view params
presented_platform_views.at(view_id), // platform view
pending_surface_transformation_, // surface transformation
pending_device_pixel_ratio_ // device pixel ratio
));
// Tell the embedder that a platform view layer is present at this point.
presented_layers.PushPlatformViewLayer(view_id, params);
if (!pending_canvas_spies_.at(view_id)->DidDrawIntoCanvas()) {
// Nothing was drawn into the overlay canvas, we don't need to composite
// it.
// Nothing was drawn into the overlay canvas, we don't need to tell the
// embedder to composite it.
continue;
}
......@@ -340,22 +263,14 @@ bool EmbedderExternalViewEmbedder::SubmitFrame(GrContext* context) {
// Indicate a layer for the backing store containing contents rendered by
// Flutter.
presented_layers.push_back(MakeBackingStoreLayer(
pending_frame_size_, // frame size
render_target->GetBackingStore(), // backing store
pending_surface_transformation_ // surface transformation
));
presented_layers.PushBackingStoreLayer(render_target->GetBackingStore());
}
{
std::vector<const FlutterLayer*> presented_layers_pointers;
presented_layers_pointers.reserve(presented_layers.size());
for (const auto& layer : presented_layers) {
presented_layers_pointers.push_back(&layer);
}
present_callback_(std::move(presented_layers_pointers));
}
// Flush the layer description down to the embedder for presentation.
presented_layers.InvokePresentCallback(present_callback_);
// Keep the previously used render target around in case they are required
// next frame.
registry_ = std::move(render_targets_used);
return true;
......
// 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/shell/platform/embedder/embedder_layers.h"
#include <algorithm>
namespace flutter {
EmbedderLayers::EmbedderLayers(SkISize frame_size,
double device_pixel_ratio,
SkMatrix root_surface_transformation)
: frame_size_(frame_size),
device_pixel_ratio_(device_pixel_ratio),
root_surface_transformation_(root_surface_transformation) {}
EmbedderLayers::~EmbedderLayers() = default;
void EmbedderLayers::PushBackingStoreLayer(const FlutterBackingStore* store) {
FlutterLayer layer = {};
layer.struct_size = sizeof(FlutterLayer);
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = store;
const auto layer_bounds =
SkRect::MakeWH(frame_size_.width(), frame_size_.height());
const auto transformed_layer_bounds =
root_surface_transformation_.mapRect(layer_bounds);
layer.offset.x = transformed_layer_bounds.x();
layer.offset.y = transformed_layer_bounds.y();
layer.size.width = transformed_layer_bounds.width();
layer.size.height = transformed_layer_bounds.height();
presented_layers_.push_back(layer);
}
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
double opacity) {
FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeOpacity;
mutation.opacity = opacity;
return std::make_unique<FlutterPlatformViewMutation>(mutation);
}
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
const SkRect& rect) {
FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeClipRect;
mutation.clip_rect.left = rect.left();
mutation.clip_rect.top = rect.top();
mutation.clip_rect.right = rect.right();
mutation.clip_rect.bottom = rect.bottom();
return std::make_unique<FlutterPlatformViewMutation>(mutation);
}
static FlutterSize VectorToSize(const SkVector& vector) {
FlutterSize size = {};
size.width = vector.x();
size.height = vector.y();
return size;
}
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
const SkRRect& rrect) {
FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeClipRoundedRect;
const auto& rect = rrect.rect();
mutation.clip_rounded_rect.rect.left = rect.left();
mutation.clip_rounded_rect.rect.top = rect.top();
mutation.clip_rounded_rect.rect.right = rect.right();
mutation.clip_rounded_rect.rect.bottom = rect.bottom();
mutation.clip_rounded_rect.upper_left_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kUpperLeft_Corner));
mutation.clip_rounded_rect.upper_right_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kUpperRight_Corner));
mutation.clip_rounded_rect.lower_right_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kLowerRight_Corner));
mutation.clip_rounded_rect.lower_left_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kLowerLeft_Corner));
return std::make_unique<FlutterPlatformViewMutation>(mutation);
}
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
const SkMatrix& matrix) {
FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeTransformation;
mutation.transformation.scaleX = matrix[SkMatrix::kMScaleX];
mutation.transformation.skewX = matrix[SkMatrix::kMSkewX];
mutation.transformation.transX = matrix[SkMatrix::kMTransX];
mutation.transformation.skewY = matrix[SkMatrix::kMSkewY];
mutation.transformation.scaleY = matrix[SkMatrix::kMScaleY];
mutation.transformation.transY = matrix[SkMatrix::kMTransY];
mutation.transformation.pers0 = matrix[SkMatrix::kMPersp0];
mutation.transformation.pers1 = matrix[SkMatrix::kMPersp1];
mutation.transformation.pers2 = matrix[SkMatrix::kMPersp2];
return std::make_unique<FlutterPlatformViewMutation>(mutation);
}
void EmbedderLayers::PushPlatformViewLayer(
FlutterPlatformViewIdentifier identifier,
const EmbeddedViewParams& params) {
{
FlutterPlatformView view = {};
view.struct_size = sizeof(FlutterPlatformView);
view.identifier = identifier;
const auto& mutators = params.mutatorsStack;
std::vector<const FlutterPlatformViewMutation*> mutations_array;
if (std::distance(mutators.Bottom(), mutators.Top()) > 0) {
// If there are going to be any mutations, they must first take into
// account the transformation for the device pixel ratio and root surface
// transformation.
auto base_xformation =
SkMatrix::Concat(root_surface_transformation_,
SkMatrix::MakeScale(device_pixel_ratio_));
if (!base_xformation.isIdentity()) {
mutations_array.push_back(
mutations_referenced_.emplace_back(ConvertMutation(base_xformation))
.get());
}
}
for (auto i = mutators.Bottom(); i != mutators.Top(); ++i) {
const auto& mutator = *i;
switch (mutator->GetType()) {
case MutatorType::clip_rect: {
mutations_array.push_back(
mutations_referenced_
.emplace_back(ConvertMutation(mutator->GetRect()))
.get());
} break;
case MutatorType::clip_rrect: {
mutations_array.push_back(
mutations_referenced_
.emplace_back(ConvertMutation(mutator->GetRRect()))
.get());
} break;
case MutatorType::clip_path: {
// Unsupported mutation.
} break;
case MutatorType::transform: {
const auto& matrix = mutator->GetMatrix();
if (!matrix.isIdentity()) {
mutations_array.push_back(
mutations_referenced_.emplace_back(ConvertMutation(matrix))
.get());
}
} break;
case MutatorType::opacity: {
const double opacity =
std::clamp(mutator->GetAlphaFloat(), 0.0f, 1.0f);
if (opacity < 1.0) {
mutations_array.push_back(
mutations_referenced_.emplace_back(ConvertMutation(opacity))
.get());
}
} break;
}
}
if (mutations_array.size() > 0) {
auto mutations =
std::make_unique<std::vector<const FlutterPlatformViewMutation*>>(
mutations_array);
mutations_arrays_referenced_.emplace_back(std::move(mutations));
view.mutations_count = mutations_array.size();
view.mutations = mutations_arrays_referenced_.back().get()->data();
}
platform_views_referenced_.emplace_back(
std::make_unique<FlutterPlatformView>(view));
}
FlutterLayer layer = {};
layer.struct_size = sizeof(FlutterLayer);
layer.type = kFlutterLayerContentTypePlatformView;
layer.platform_view = platform_views_referenced_.back().get();
const auto layer_bounds = SkRect::MakeXYWH(params.offsetPixels.x(), //
params.offsetPixels.y(), //
params.sizePoints.width(), //
params.sizePoints.height() //
);
const auto transformed_layer_bounds =
SkMatrix::Concat(root_surface_transformation_,
SkMatrix::MakeScale(device_pixel_ratio_))
.mapRect(layer_bounds);
layer.offset.x = transformed_layer_bounds.x();
layer.offset.y = transformed_layer_bounds.y();
layer.size.width = transformed_layer_bounds.width();
layer.size.height = transformed_layer_bounds.height();
presented_layers_.push_back(layer);
} // namespace flutter
void EmbedderLayers::InvokePresentCallback(PresentCallback callback) const {
std::vector<const FlutterLayer*> presented_layers_pointers;
presented_layers_pointers.reserve(presented_layers_.size());
for (const auto& layer : presented_layers_) {
presented_layers_pointers.push_back(&layer);
}
callback(std::move(presented_layers_pointers));
}
} // namespace flutter
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_FLUTTER_LAYERS_H_
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_FLUTTER_LAYERS_H_
#include <memory>
#include <vector>
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/macros.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkSize.h"
namespace flutter {
class EmbedderLayers {
public:
EmbedderLayers(SkISize frame_size,
double device_pixel_ratio,
SkMatrix root_surface_transformation);
~EmbedderLayers();
void PushBackingStoreLayer(const FlutterBackingStore* store);
void PushPlatformViewLayer(FlutterPlatformViewIdentifier identifier,
const EmbeddedViewParams& params);
using PresentCallback =
std::function<bool(const std::vector<const FlutterLayer*>& layers)>;
void InvokePresentCallback(PresentCallback callback) const;
private:
const SkISize frame_size_;
const double device_pixel_ratio_;
const SkMatrix root_surface_transformation_;
std::vector<std::unique_ptr<FlutterPlatformView>> platform_views_referenced_;
std::vector<std::unique_ptr<FlutterPlatformViewMutation>>
mutations_referenced_;
std::vector<std::unique_ptr<std::vector<const FlutterPlatformViewMutation*>>>
mutations_arrays_referenced_;
std::vector<FlutterLayer> presented_layers_;
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderLayers);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_FLUTTER_LAYERS_H_
......@@ -557,3 +557,46 @@ void push_frames_over_and_over() {
};
window.scheduleFrame();
}
@pragma('vm:entry-point')
void platform_view_mutators() {
window.onBeginFrame = (Duration duration) {
SceneBuilder builder = SceneBuilder();
builder.pushOffset(0.0, 0.0); // base
builder.addPicture(Offset(0.0, 0.0), CreateGradientBox(Size(800.0, 600.0)));
builder.pushOpacity(128);
builder.pushClipRect(Rect.fromLTWH(10.0, 10.0, 800.0 - 20.0, 600.0 - 20.0));
builder.pushClipRRect(RRect.fromLTRBR(10.0, 10.0, 800.0 - 10.0, 600.0 - 10.0, Radius.circular(14.0)));
builder.addPlatformView(42, width: 800.0, height: 600.0);
builder.pop(); // clip rrect
builder.pop(); // clip rect
builder.pop(); // opacity
builder.pop(); // base
window.render(builder.build());
};
window.scheduleFrame();
}
@pragma('vm:entry-point')
void platform_view_mutators_with_pixel_ratio() {
window.onBeginFrame = (Duration duration) {
SceneBuilder builder = SceneBuilder();
builder.pushOffset(0.0, 0.0); // base
builder.addPicture(Offset(0.0, 0.0), CreateGradientBox(Size(400.0, 300.0)));
builder.pushOpacity(128);
builder.pushClipRect(Rect.fromLTWH(5.0, 5.0, 400.0 - 10.0, 300.0 - 10.0));
builder.pushClipRRect(RRect.fromLTRBR(5.0, 5.0, 400.0 - 5.0, 300.0 - 5.0, Radius.circular(7.0)));
builder.addPlatformView(42, width: 400.0, height: 300.0);
builder.pop(); // clip rrect
builder.pop(); // clip rect
builder.pop(); // opacity
builder.pop(); // base
window.render(builder.build());
};
window.scheduleFrame();
}
......@@ -23,11 +23,34 @@ inline bool operator==(const FlutterPoint& a, const FlutterPoint& b) {
flutter::testing::NumberNear(a.y, b.y);
}
inline bool operator==(const FlutterRect& a, const FlutterRect& b) {
return flutter::testing::NumberNear(a.left, b.left) &&
flutter::testing::NumberNear(a.top, b.top) &&
flutter::testing::NumberNear(a.right, b.right) &&
flutter::testing::NumberNear(a.bottom, b.bottom);
}
inline bool operator==(const FlutterSize& a, const FlutterSize& b) {
return flutter::testing::NumberNear(a.width, b.width) &&
flutter::testing::NumberNear(a.height, b.height);
}
inline bool operator==(const FlutterRoundedRect& a,
const FlutterRoundedRect& b) {
return a.rect == b.rect &&
a.upper_left_corner_radius == b.upper_left_corner_radius &&
a.upper_right_corner_radius == b.upper_right_corner_radius &&
a.lower_right_corner_radius == b.lower_right_corner_radius &&
a.lower_left_corner_radius == b.lower_left_corner_radius;
}
inline bool operator==(const FlutterTransformation& a,
const FlutterTransformation& b) {
return a.scaleX == b.scaleX && a.skewX == b.skewX && a.transX == b.transX &&
a.skewY == b.skewY && a.scaleY == b.scaleY && a.transY == b.transY &&
a.pers0 == b.pers0 && a.pers1 == b.pers1 && a.pers2 == b.pers2;
}
inline bool operator==(const FlutterOpenGLTexture& a,
const FlutterOpenGLTexture& b) {
return a.target == b.target && a.name == b.name && a.format == b.format &&
......@@ -82,9 +105,40 @@ inline bool operator==(const FlutterBackingStore& a,
return false;
}
inline bool operator==(const FlutterPlatformViewMutation& a,
const FlutterPlatformViewMutation& b) {
if (a.type != b.type) {
return false;
}
switch (a.type) {
case kFlutterPlatformViewMutationTypeOpacity:
return flutter::testing::NumberNear(a.opacity, b.opacity);
case kFlutterPlatformViewMutationTypeClipRect:
return a.clip_rect == b.clip_rect;
case kFlutterPlatformViewMutationTypeClipRoundedRect:
return a.clip_rounded_rect == b.clip_rounded_rect;
case kFlutterPlatformViewMutationTypeTransformation:
return a.transformation == b.transformation;
}
return false;
}
inline bool operator==(const FlutterPlatformView& a,
const FlutterPlatformView& b) {
return a.struct_size == b.struct_size && a.identifier == b.identifier;
if (!(a.struct_size == b.struct_size && a.identifier == b.identifier &&
a.mutations_count == b.mutations_count)) {
return false;
}
for (size_t i = 0; i < a.mutations_count; ++i) {
if (!(*a.mutations[i] == *b.mutations[i])) {
return false;
}
}
return true;
}
inline bool operator==(const FlutterLayer& a, const FlutterLayer& b) {
......@@ -111,10 +165,39 @@ inline std::ostream& operator<<(std::ostream& out, const FlutterPoint& point) {
return out << "(" << point.x << ", " << point.y << ")";
}
inline std::ostream& operator<<(std::ostream& out, const FlutterRect& r) {
return out << "LTRB (" << r.left << ", " << r.top << ", " << r.right << ", "
<< r.bottom << ")";
}
inline std::ostream& operator<<(std::ostream& out, const FlutterSize& size) {
return out << "(" << size.width << ", " << size.height << ")";
}
inline std::ostream& operator<<(std::ostream& out,
const FlutterRoundedRect& r) {
out << "Rect: " << r.rect << ", ";
out << "Upper Left Corner Radius: " << r.upper_left_corner_radius << ", ";
out << "Upper Right Corner Radius: " << r.upper_right_corner_radius << ", ";
out << "Lower Right Corner Radius: " << r.lower_right_corner_radius << ", ";
out << "Lower Left Corner Radius: " << r.lower_left_corner_radius;
return out;
}
inline std::ostream& operator<<(std::ostream& out,
const FlutterTransformation& t) {
out << "Scale X: " << t.scaleX << ", ";
out << "Skew X: " << t.skewX << ", ";
out << "Trans X: " << t.transX << ", ";
out << "Skew Y: " << t.skewY << ", ";
out << "Scale Y: " << t.scaleY << ", ";
out << "Trans Y: " << t.transY << ", ";
out << "Pers 0: " << t.pers0 << ", ";
out << "Pers 1: " << t.pers1 << ", ";
out << "Pers 2: " << t.pers2;
return out;
}
inline std::string FlutterLayerContentTypeToString(
FlutterLayerContentType type) {
switch (type) {
......@@ -153,11 +236,56 @@ inline std::ostream& operator<<(std::ostream& out,
<< " Destruction Callback: " << item.destruction_callback;
}
inline std::string FlutterPlatformViewMutationTypeToString(
FlutterPlatformViewMutationType type) {
switch (type) {
case kFlutterPlatformViewMutationTypeOpacity:
return "kFlutterPlatformViewMutationTypeOpacity";
case kFlutterPlatformViewMutationTypeClipRect:
return "kFlutterPlatformViewMutationTypeClipRect";
case kFlutterPlatformViewMutationTypeClipRoundedRect:
return "kFlutterPlatformViewMutationTypeClipRoundedRect";
case kFlutterPlatformViewMutationTypeTransformation:
return "kFlutterPlatformViewMutationTypeTransformation";
}
return "Unknown";
}
inline std::ostream& operator<<(std::ostream& out,
const FlutterPlatformViewMutation& m) {
out << "(FlutterPlatformViewMutation) Type: "
<< FlutterPlatformViewMutationTypeToString(m.type) << " ";
switch (m.type) {
case kFlutterPlatformViewMutationTypeOpacity:
out << "Opacity: " << m.opacity;
case kFlutterPlatformViewMutationTypeClipRect:
out << "Clip Rect: " << m.clip_rect;
case kFlutterPlatformViewMutationTypeClipRoundedRect:
out << "Clip Rounded Rect: " << m.clip_rounded_rect;
case kFlutterPlatformViewMutationTypeTransformation:
out << "Transformation: " << m.transformation;
}
return out;
}
inline std::ostream& operator<<(std::ostream& out,
const FlutterPlatformView& platform_view) {
return out << "(FlutterPlatformView) Struct Size: "
<< platform_view.struct_size
<< " Identifier: " << platform_view.identifier;
out << "["
<< "(FlutterPlatformView) Struct Size: " << platform_view.struct_size
<< " Identifier: " << platform_view.identifier
<< " Mutations Count: " << platform_view.mutations_count;
if (platform_view.mutations_count > 0) {
out << std::endl;
for (size_t i = 0; i < platform_view.mutations_count; i++) {
out << "Mutation " << i << ": " << *platform_view.mutations[i]
<< std::endl;
}
}
out << "]";
return out;
}
inline std::string FlutterOpenGLTargetTypeToString(
......@@ -248,6 +376,13 @@ inline FlutterSize FlutterSizeMake(double width, double height) {
return size;
}
inline FlutterSize FlutterSizeMake(const SkVector& vector) {
FlutterSize size = {};
size.width = vector.x();
size.height = vector.y();
return size;
}
inline FlutterTransformation FlutterTransformationMake(const SkMatrix& matrix) {
FlutterTransformation transformation = {};
transformation.scaleX = matrix[SkMatrix::kMScaleX];
......@@ -266,4 +401,27 @@ inline flutter::EmbedderEngine* ToEmbedderEngine(const FlutterEngine& engine) {
return reinterpret_cast<flutter::EmbedderEngine*>(engine);
}
inline FlutterRect FlutterRectMake(const SkRect& rect) {
FlutterRect r = {};
r.left = rect.left();
r.top = rect.top();
r.right = rect.right();
r.bottom = rect.bottom();
return r;
}
inline FlutterRoundedRect FlutterRoundedRectMake(const SkRRect& rect) {
FlutterRoundedRect r = {};
r.rect = FlutterRectMake(rect.rect());
r.upper_left_corner_radius =
FlutterSizeMake(rect.radii(SkRRect::Corner::kUpperLeft_Corner));
r.upper_right_corner_radius =
FlutterSizeMake(rect.radii(SkRRect::Corner::kUpperRight_Corner));
r.lower_right_corner_radius =
FlutterSizeMake(rect.radii(SkRRect::Corner::kLowerRight_Corner));
r.lower_left_corner_radius =
FlutterSizeMake(rect.radii(SkRRect::Corner::kLowerLeft_Corner));
return r;
}
#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_ASSERTIONS_H_
......@@ -608,7 +608,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderToOpenGLFramebuffer) {
}
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
......@@ -701,7 +701,7 @@ TEST_F(EmbedderTest, RasterCacheDisabledWithPlatformViews) {
}
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
......@@ -874,7 +874,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderToOpenGLTexture) {
}
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
......@@ -968,7 +968,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderToSoftwareBuffer) {
}
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
......@@ -1189,7 +1189,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderKnownScene) {
// Layer 1
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 1;
......@@ -1222,7 +1222,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderKnownScene) {
// Layer 3
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[3]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 2;
......@@ -1365,7 +1365,7 @@ TEST_F(EmbedderTest,
// Layer 1
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 1;
......@@ -1398,7 +1398,7 @@ TEST_F(EmbedderTest,
// Layer 3
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[3]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 2;
......@@ -1549,7 +1549,7 @@ TEST_F(EmbedderTest, CustomCompositorMustWorkWithCustomTaskRunner) {
}
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
......@@ -1740,7 +1740,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderWithPlatformLayerOnBottom) {
// Layer 1
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 1;
......@@ -1863,7 +1863,7 @@ TEST_F(EmbedderTest,
// Layer 1
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 1;
......@@ -1896,7 +1896,7 @@ TEST_F(EmbedderTest,
// Layer 3
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[3]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 2;
......@@ -2258,7 +2258,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithCompositorOnNonRootLayer) {
// Layer 1
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 1;
......@@ -2377,7 +2377,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithCompositorOnNonRootLayerWithXform) {
// Layer 1
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 1;
......@@ -2507,7 +2507,7 @@ TEST_F(EmbedderTest, VerifyB141980393) {
// Layer 1
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 1337;
......@@ -2794,7 +2794,7 @@ TEST_F(EmbedderTest,
// Layer 1
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
......@@ -2893,7 +2893,7 @@ TEST_F(
// Layer 1
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
......@@ -3041,7 +3041,7 @@ TEST_F(EmbedderTest, VerifyB143464703WithSoftwareBackend) {
// Layer 1
{
FlutterPlatformView platform_view = {};
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
......@@ -3203,5 +3203,301 @@ TEST_F(EmbedderTest,
ASSERT_EQ(frames_expected, frames_seen);
}
TEST_F(EmbedderTest, PlatformViewMutatorsAreValid) {
auto& context = GetEmbedderContext();
EmbedderConfigBuilder builder(context);
builder.SetOpenGLRendererConfig(SkISize::Make(800, 600));
builder.SetCompositor();
builder.SetDartEntrypoint("platform_view_mutators");
context.GetCompositor().SetRenderTargetType(
EmbedderTestCompositor::RenderTargetType::kOpenGLTexture);
fml::CountDownLatch latch(1);
context.GetCompositor().SetNextPresentCallback(
[&](const FlutterLayer** layers, size_t layers_count) {
ASSERT_EQ(layers_count, 2u);
// Layer 0 (Root)
{
FlutterBackingStore backing_store = *layers[0]->backing_store;
backing_store.type = kFlutterBackingStoreTypeOpenGL;
backing_store.did_update = true;
backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = &backing_store;
layer.size = FlutterSizeMake(800.0, 600.0);
layer.offset = FlutterPointMake(0.0, 0.0);
ASSERT_EQ(*layers[0], layer);
}
// Layer 2
{
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
platform_view.mutations_count = 3;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypePlatformView;
layer.platform_view = &platform_view;
layer.size = FlutterSizeMake(800.0, 600.0);
layer.offset = FlutterPointMake(0.0, 0.0);
ASSERT_EQ(*layers[1], layer);
// There are no ordering guarantees.
for (size_t i = 0; i < platform_view.mutations_count; i++) {
FlutterPlatformViewMutation mutation = *platform_view.mutations[i];
switch (mutation.type) {
case kFlutterPlatformViewMutationTypeClipRoundedRect:
mutation.clip_rounded_rect =
FlutterRoundedRectMake(SkRRect::MakeRectXY(
SkRect::MakeLTRB(10.0, 10.0, 800.0 - 10.0,
600.0 - 10.0),
14.0, 14.0));
break;
case kFlutterPlatformViewMutationTypeClipRect:
mutation.type = kFlutterPlatformViewMutationTypeClipRect;
mutation.clip_rect = FlutterRectMake(
SkRect::MakeXYWH(10.0, 10.0, 800.0 - 20.0, 600.0 - 20.0));
break;
case kFlutterPlatformViewMutationTypeOpacity:
mutation.type = kFlutterPlatformViewMutationTypeOpacity;
mutation.opacity = 128.0 / 255.0;
break;
case kFlutterPlatformViewMutationTypeTransformation:
FML_CHECK(false)
<< "There should be no transformation in the test.";
break;
}
ASSERT_EQ(*platform_view.mutations[i], mutation);
}
}
latch.CountDown();
});
auto engine = builder.LaunchEngine();
// Send a window metrics events so frames may be scheduled.
FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
latch.Wait();
}
TEST_F(EmbedderTest, PlatformViewMutatorsAreValidWithPixelRatio) {
auto& context = GetEmbedderContext();
EmbedderConfigBuilder builder(context);
builder.SetOpenGLRendererConfig(SkISize::Make(800, 600));
builder.SetCompositor();
builder.SetDartEntrypoint("platform_view_mutators_with_pixel_ratio");
context.GetCompositor().SetRenderTargetType(
EmbedderTestCompositor::RenderTargetType::kOpenGLTexture);
fml::CountDownLatch latch(1);
context.GetCompositor().SetNextPresentCallback(
[&](const FlutterLayer** layers, size_t layers_count) {
ASSERT_EQ(layers_count, 2u);
// Layer 0 (Root)
{
FlutterBackingStore backing_store = *layers[0]->backing_store;
backing_store.type = kFlutterBackingStoreTypeOpenGL;
backing_store.did_update = true;
backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = &backing_store;
layer.size = FlutterSizeMake(800.0, 600.0);
layer.offset = FlutterPointMake(0.0, 0.0);
ASSERT_EQ(*layers[0], layer);
}
// Layer 2
{
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
platform_view.mutations_count = 4;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypePlatformView;
layer.platform_view = &platform_view;
layer.size = FlutterSizeMake(800.0, 600.0);
layer.offset = FlutterPointMake(0.0, 0.0);
ASSERT_EQ(*layers[1], layer);
// There are no ordering guarantees.
for (size_t i = 0; i < platform_view.mutations_count; i++) {
FlutterPlatformViewMutation mutation = *platform_view.mutations[i];
switch (mutation.type) {
case kFlutterPlatformViewMutationTypeClipRoundedRect:
mutation.clip_rounded_rect =
FlutterRoundedRectMake(SkRRect::MakeRectXY(
SkRect::MakeLTRB(5.0, 5.0, 400.0 - 5.0, 300.0 - 5.0),
7.0, 7.0));
break;
case kFlutterPlatformViewMutationTypeClipRect:
mutation.type = kFlutterPlatformViewMutationTypeClipRect;
mutation.clip_rect = FlutterRectMake(
SkRect::MakeXYWH(5.0, 5.0, 400.0 - 10.0, 300.0 - 10.0));
break;
case kFlutterPlatformViewMutationTypeOpacity:
mutation.type = kFlutterPlatformViewMutationTypeOpacity;
mutation.opacity = 128.0 / 255.0;
break;
case kFlutterPlatformViewMutationTypeTransformation:
mutation.type = kFlutterPlatformViewMutationTypeTransformation;
mutation.transformation =
FlutterTransformationMake(SkMatrix::MakeScale(2.0));
break;
}
ASSERT_EQ(*platform_view.mutations[i], mutation);
}
}
latch.CountDown();
});
auto engine = builder.LaunchEngine();
// Send a window metrics events so frames may be scheduled.
FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 2.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
latch.Wait();
}
TEST_F(EmbedderTest,
PlatformViewMutatorsAreValidWithPixelRatioAndRootSurfaceTransformation) {
auto& context = GetEmbedderContext();
EmbedderConfigBuilder builder(context);
builder.SetOpenGLRendererConfig(SkISize::Make(800, 600));
builder.SetCompositor();
builder.SetDartEntrypoint("platform_view_mutators_with_pixel_ratio");
context.GetCompositor().SetRenderTargetType(
EmbedderTestCompositor::RenderTargetType::kOpenGLTexture);
static const auto root_surface_transformation =
SkMatrix().preTranslate(0, 800).preRotate(-90, 0, 0);
context.SetRootSurfaceTransformation(root_surface_transformation);
fml::CountDownLatch latch(1);
context.GetCompositor().SetNextPresentCallback(
[&](const FlutterLayer** layers, size_t layers_count) {
ASSERT_EQ(layers_count, 2u);
// Layer 0 (Root)
{
FlutterBackingStore backing_store = *layers[0]->backing_store;
backing_store.type = kFlutterBackingStoreTypeOpenGL;
backing_store.did_update = true;
backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = &backing_store;
layer.size = FlutterSizeMake(600.0, 800.0);
layer.offset = FlutterPointMake(0.0, 0.0);
ASSERT_EQ(*layers[0], layer);
}
// Layer 2
{
FlutterPlatformView platform_view = *layers[1]->platform_view;
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
platform_view.mutations_count = 4;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypePlatformView;
layer.platform_view = &platform_view;
layer.size = FlutterSizeMake(600.0, 800.0);
layer.offset = FlutterPointMake(0.0, 0.0);
ASSERT_EQ(*layers[1], layer);
// There are no ordering guarantees.
for (size_t i = 0; i < platform_view.mutations_count; i++) {
FlutterPlatformViewMutation mutation = *platform_view.mutations[i];
switch (mutation.type) {
case kFlutterPlatformViewMutationTypeClipRoundedRect:
mutation.clip_rounded_rect =
FlutterRoundedRectMake(SkRRect::MakeRectXY(
SkRect::MakeLTRB(5.0, 5.0, 400.0 - 5.0, 300.0 - 5.0),
7.0, 7.0));
break;
case kFlutterPlatformViewMutationTypeClipRect:
mutation.type = kFlutterPlatformViewMutationTypeClipRect;
mutation.clip_rect = FlutterRectMake(
SkRect::MakeXYWH(5.0, 5.0, 400.0 - 10.0, 300.0 - 10.0));
break;
case kFlutterPlatformViewMutationTypeOpacity:
mutation.type = kFlutterPlatformViewMutationTypeOpacity;
mutation.opacity = 128.0 / 255.0;
break;
case kFlutterPlatformViewMutationTypeTransformation:
mutation.type = kFlutterPlatformViewMutationTypeTransformation;
mutation.transformation =
FlutterTransformationMake(SkMatrix::Concat(
root_surface_transformation, SkMatrix::MakeScale(2.0)));
break;
}
ASSERT_EQ(*platform_view.mutations[i], mutation);
}
}
latch.CountDown();
});
auto engine = builder.LaunchEngine();
// Send a window metrics events so frames may be scheduled.
FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 2.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
latch.Wait();
}
} // namespace testing
} // namespace flutter
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册