13#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
15#ifdef IMPELLER_SUPPORTS_RENDERING
24 bool avoid_backing_store_cache,
27 : avoid_backing_store_cache_(avoid_backing_store_cache),
28 create_render_target_callback_(create_render_target_callback),
29 present_callback_(present_callback) {
37 render_target_caches_.erase(
view_id);
42 surface_transformation_callback_ = std::move(surface_transformation_callback);
45DlMatrix EmbedderExternalViewEmbedder::GetSurfaceTransformation()
const {
46 if (!surface_transformation_callback_) {
50 return surface_transformation_callback_();
53void EmbedderExternalViewEmbedder::Reset() {
54 pending_views_.clear();
55 composition_order_.clear();
59void EmbedderExternalViewEmbedder::CancelFrame() {
64void EmbedderExternalViewEmbedder::BeginFrame(
65 GrDirectContext* context,
69void EmbedderExternalViewEmbedder::PrepareFlutterView(
71 double device_pixel_ratio) {
74 pending_frame_size_ = frame_size;
75 pending_device_pixel_ratio_ = device_pixel_ratio;
76 pending_surface_transformation_ = GetSurfaceTransformation();
79 pending_frame_size_, pending_surface_transformation_);
84void EmbedderExternalViewEmbedder::PrerollCompositeEmbeddedView(
86 std::unique_ptr<EmbeddedViewParams>
params) {
87 auto vid = EmbedderExternalView::ViewIdentifier(
view_id);
90 pending_views_[vid] = std::make_unique<EmbedderExternalView>(
92 pending_surface_transformation_,
96 composition_order_.push_back(vid);
100DlCanvas* EmbedderExternalViewEmbedder::GetRootCanvas() {
102 if (found == pending_views_.end()) {
104 <<
"No root canvas could be found. This is extremely unlikely and "
105 "indicates that the external view embedder did not receive the "
106 "notification to begin the frame.";
109 return found->second->GetCanvas();
113DlCanvas* EmbedderExternalViewEmbedder::CompositeEmbeddedView(int64_t
view_id) {
114 auto vid = EmbedderExternalView::ViewIdentifier(
view_id);
115 auto found = pending_views_.find(vid);
116 if (found == pending_views_.end()) {
117 FML_DCHECK(
false) <<
"Attempted to composite a view that was not "
121 return found->second->GetCanvas();
126 const DlISize& backing_store_size) {
147 explicit PlatformView(
const EmbedderExternalView* view) {
152 DlRect clip =
view->GetEmbeddedViewParams()->finalBoundingRect();
154 for (
auto i =
params->mutatorsStack().Begin();
155 i !=
params->mutatorsStack().End(); ++
i) {
157 switch (m->GetType()) {
159 auto rect = m->GetRect().TransformAndClipBounds(matrix);
160 clip = clip.IntersectionOrEmpty(rect);
164 auto rect = m->GetRRect().GetBounds().TransformAndClipBounds(matrix);
165 clip = clip.IntersectionOrEmpty(rect);
169 auto rect = m->GetRSE().GetBounds().TransformAndClipBounds(matrix);
170 clip = clip.IntersectionOrEmpty(rect);
174 auto rect = m->GetPath().GetBounds().TransformAndClipBounds(matrix);
175 clip = clip.IntersectionOrEmpty(rect);
179 matrix = matrix * m->GetMatrix();
205 bool IntersectsPlatformView(
const SkRect& rect) {
216 bool IntersectsPlatformView(
const DlRegion& region) {
228 bool IntersectsFlutterContents(
const SkRect& rect) {
229 return flutter_contents_region_.intersects(
ToDlIRect(rect.roundOut()));
234 bool IntersectsFlutterContents(
const DlRegion& region) {
235 return flutter_contents_region_.intersects(region);
244 void AddFlutterContents(EmbedderExternalView* contents,
245 const DlRegion& contents_region) {
246 flutter_contents_.push_back(contents);
247 flutter_contents_region_ =
251 bool has_flutter_contents()
const {
return !flutter_contents_.empty(); }
253 void SetRenderTarget(std::unique_ptr<EmbedderRenderTarget>
target) {
256 render_target_ = std::move(
target);
261 void RenderFlutterContents(
bool frame_boundary) {
263 if (!render_target_) {
267#ifdef IMPELLER_SUPPORTS_RENDERING
268 if (render_target_->GetImpellerRenderTarget()) {
269 RenderFlutterContentsImpeller(frame_boundary);
275 FML_LOG(FATAL) <<
"Impeller opt-out unavailable.";
277 RenderFlutterContentsSkia();
283 const std::vector<PlatformView>& platform_views()
const {
284 return platform_views_;
287 EmbedderRenderTarget* render_target() {
return render_target_.get(); }
289 std::vector<DlIRect> coverage() {
290 return flutter_contents_region_.getRects();
297 static void InvalidateApiState(SkSurface& skia_surface) {
298 auto recording_context = skia_surface.recordingContext();
301 FML_DCHECK(recording_context) <<
"Recording context was null.";
303 auto direct_context = recording_context->asDirectContext();
304 if (direct_context ==
nullptr) {
307 FML_LOG(ERROR) <<
"Embedder asked to invalidate cached graphics API "
308 "state but Flutter is not using a graphics API.";
310 direct_context->resetContext(kAll_GrBackendState);
314 void RenderFlutterContentsSkia() {
315 auto skia_surface = render_target_->GetSkiaSurface();
320 auto [ok, invalidate_api_state] = render_target_->MaybeMakeCurrent();
322 if (invalidate_api_state) {
323 InvalidateApiState(*skia_surface);
326 FML_LOG(ERROR) <<
"Could not make the surface current.";
333 auto [ok, invalidate_api_state] = render_target_->MaybeClearCurrent();
334 if (invalidate_api_state) {
335 InvalidateApiState(*skia_surface);
338 FML_LOG(ERROR) <<
"Could not clear the current surface.";
342 auto canvas = skia_surface->getCanvas();
347 DlSkCanvasAdapter dl_canvas(canvas);
348 bool clear_surface =
true;
349 for (
auto c : flutter_contents_) {
350 FML_DCHECK(render_target_->GetRenderTargetSize() ==
351 c->GetRenderSurfaceSize());
352 c->Render(dl_canvas, clear_surface);
353 clear_surface =
false;
359#ifdef IMPELLER_SUPPORTS_RENDERING
360 void RenderFlutterContentsImpeller(
bool frame_boundary) {
361 auto dl_builder = DisplayListBuilder();
362 bool clear_surface =
true;
363 for (
auto c : flutter_contents_) {
364 FML_DCHECK(render_target_->GetRenderTargetSize() ==
365 c->GetRenderSurfaceSize());
366 c->Render(dl_builder, clear_surface);
367 clear_surface =
false;
369 auto display_list = dl_builder.Build();
371 auto* impeller_target = render_target_->GetImpellerRenderTarget();
372 auto aiks_context = render_target_->GetAiksContext();
386 std::vector<PlatformView> platform_views_;
387 std::vector<EmbedderExternalView*> flutter_contents_;
388 DlRegion flutter_contents_region_;
389 std::unique_ptr<EmbedderRenderTarget> render_target_;
390 friend class LayerBuilder;
403 using RenderTargetProvider =
404 std::function<std::unique_ptr<EmbedderRenderTarget>(
407 explicit LayerBuilder(
DlISize frame_size) : frame_size_(frame_size) {
408 layers_.push_back(Layer());
416 void AddExternalView(EmbedderExternalView* view) {
417 if (
view->HasPlatformView()) {
421 if (
view->HasEngineRenderedContents()) {
422 AddFlutterContents(view);
427 void PrepareBackingStore(
const RenderTargetProvider& target_provider) {
428 for (
auto& layer : layers_) {
429 if (layer.has_flutter_contents()) {
430 layer.SetRenderTarget(target_provider(frame_size_));
440 auto last_flutter_layer_rev_iter =
441 std::find_if(layers_.rbegin(), layers_.rend(),
442 [](
const Layer& l) { return l.has_flutter_contents(); });
443 if (last_flutter_layer_rev_iter == layers_.rend()) {
446 auto last_flutter_layer_iter = last_flutter_layer_rev_iter.base() - 1;
448 for (
auto iter = layers_.begin(); iter != layers_.end(); iter++) {
449 bool frame_boundary = iter == last_flutter_layer_iter;
450 if (iter->has_flutter_contents()) {
451 iter->RenderFlutterContents(frame_boundary);
457 void PushLayers(EmbedderLayers&
layers) {
458 for (
auto& layer : layers_) {
459 for (
auto& view : layer.platform_views()) {
460 auto platform_view_id =
view.view_identifier.platform_view_id;
461 if (platform_view_id.has_value()) {
462 layers.PushPlatformViewLayer(platform_view_id.value(), *
view.params);
465 if (layer.render_target() !=
nullptr) {
466 layers.PushBackingStoreLayer(layer.render_target()->GetBackingStore(),
473 std::vector<std::unique_ptr<EmbedderRenderTarget>>
474 ClearAndCollectRenderTargets() {
475 std::vector<std::unique_ptr<EmbedderRenderTarget>> result;
476 for (
auto& layer : layers_) {
477 if (layer.render_target() !=
nullptr) {
478 result.push_back(std::move(layer.render_target_));
486 void AddPlatformView(PlatformView view) {
487 GetLayerForPlatformView(view).AddPlatformView(view);
490 void AddFlutterContents(EmbedderExternalView* contents) {
491 FML_DCHECK(contents->HasEngineRenderedContents());
493 DlRegion region = contents->GetDlRegion();
494 GetLayerForFlutterContentsRegion(region).AddFlutterContents(contents,
504 Layer& GetLayerForPlatformView(PlatformView view) {
505 for (
auto iter = layers_.rbegin(); iter != layers_.rend(); ++iter) {
508 if (iter->IntersectsFlutterContents(
view.clipped_frame)) {
509 if (iter == layers_.rbegin()) {
510 layers_.emplace_back();
511 return layers_.back();
517 if (iter->IntersectsPlatformView(
view.clipped_frame)) {
521 return layers_.front();
526 Layer& GetLayerForFlutterContentsRegion(
const DlRegion& region) {
527 for (
auto iter = layers_.rbegin(); iter != layers_.rend(); ++iter) {
528 if (iter->IntersectsPlatformView(region) ||
529 iter->IntersectsFlutterContents(region)) {
533 return layers_.front();
536 std::vector<Layer> layers_;
542void EmbedderExternalViewEmbedder::SubmitFlutterView(
543 int64_t flutter_view_id,
544 GrDirectContext* context,
545 const std::shared_ptr<impeller::AiksContext>& aiks_context,
546 std::unique_ptr<SurfaceFrame> frame) {
549 EmbedderRenderTargetCache& render_target_cache =
550 render_target_caches_[flutter_view_id];
556 for (
auto view_id : composition_order_) {
558 builder.AddExternalView(
view.get());
561 builder.PrepareBackingStore([&](
const DlISize& frame_size) {
562 if (!avoid_backing_store_cache_) {
563 std::unique_ptr<EmbedderRenderTarget>
target =
564 render_target_cache.GetRenderTarget(
565 EmbedderExternalView::RenderTargetDescriptor(frame_size));
571 return create_render_target_callback_(context, aiks_context, config);
586 auto deferred_cleanup_render_targets =
587 render_target_cache.ClearAllRenderTargetsInCache();
594 context->resetContext(kAll_GrBackendState);
607 context->flushAndSubmit();
612 auto presentation_time_optional = frame->submit_info().presentation_time;
613 uint64_t presentation_time =
614 presentation_time_optional.has_value()
615 ? presentation_time_optional->ToEpochDelta().ToNanoseconds()
621 EmbedderLayers presented_layers(
622 pending_frame_size_, pending_device_pixel_ratio_,
623 pending_surface_transformation_, presentation_time);
625 builder.PushLayers(presented_layers);
627 presented_layers.InvokePresentCallback(flutter_view_id, present_callback_);
634 deferred_cleanup_render_targets.clear();
636 auto render_targets = builder.ClearAndCollectRenderTargets();
637 for (
auto& render_target : render_targets) {
638 if (!avoid_backing_store_cache_) {
639 render_target_cache.CacheRenderTarget(std::move(render_target));
static DlRegion MakeUnion(const DlRegion &a, const DlRegion &b)
void CollectView(int64_t view_id) override
EmbedderExternalViewEmbedder(bool avoid_backing_store_cache, const CreateRenderTargetCallback &create_render_target_callback, const PresentCallback &present_callback)
Creates an external view embedder used by the generic embedder API.
~EmbedderExternalViewEmbedder() override
Collects the external view embedder.
std::function< bool(FlutterViewId view_id, const std::vector< const FlutterLayer * > &layers)> PresentCallback
std::function< std::unique_ptr< EmbedderRenderTarget >(GrDirectContext *context, const std::shared_ptr< impeller::AiksContext > &aiks_context, const FlutterBackingStoreConfig &config)> CreateRenderTargetCallback
void SetSurfaceTransformationCallback(SurfaceTransformationCallback surface_transformation_callback)
Sets the surface transformation callback used by the external view embedder to ask the platform for t...
std::function< DlMatrix(void)> SurfaceTransformationCallback
Wraps a closure that is invoked in the destructor unless released by the caller.
EmbedderExternalView::ViewIdentifier view_identifier
const EmbeddedViewParams * params
const FlutterLayer ** layers
G_BEGIN_DECLS FlutterViewId view_id
#define FML_DLOG(severity)
#define FML_LOG(severity)
#define FML_DCHECK(condition)
impeller::Matrix DlMatrix
impeller::ISize32 DlISize
static FlutterBackingStoreConfig MakeBackingStoreConfig(int64_t view_id, const DlISize &backing_store_size)
@ kBackdropClipRSuperellipse
const DlIRect & ToDlIRect(const SkIRect &rect)
static const auto kRootViewIdentifier
const SkRect & ToSkRect(const DlRect &rect)
bool RenderToTarget(ContentContext &context, RenderTarget render_target, const sk_sp< flutter::DisplayList > &display_list, Rect cull_rect, bool reset_host_buffer, bool is_onscreen)
Render the provided display list to the render target.
flutter::DlCanvas DlCanvas
size_t struct_size
The size of this struct. Must be sizeof(FlutterBackingStoreConfig).
FlutterSize size
The size of the render target the engine expects to render into.
A 4x4 matrix using column-major storage.
RoundOut(const TRect< U > &r)
constexpr TRect TransformAndClipBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle, clipped against the near clippin...
static constexpr TRect MakeSize(const TSize< U > &size)