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
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,8 @@ FILE: ../../../flutter/shell/common/skia_event_tracer_impl.cc
FILE: ../../../flutter/shell/common/skia_event_tracer_impl.h
FILE: ../../../flutter/shell/common/surface.cc
FILE: ../../../flutter/shell/common/surface.h
FILE: ../../../flutter/shell/common/surface_frame.cc
FILE: ../../../flutter/shell/common/surface_frame.h
FILE: ../../../flutter/shell/common/switches.cc
FILE: ../../../flutter/shell/common/switches.h
FILE: ../../../flutter/shell/common/thread_host.cc
Expand Down
1 change: 1 addition & 0 deletions flow/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ source_set("flow") {
deps = [
"//flutter/common",
"//flutter/fml",
"//flutter/shell/common:surface_frame",
"//third_party/skia",
]

Expand Down
6 changes: 2 additions & 4 deletions flow/embedded_views.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
namespace flutter {

bool ExternalViewEmbedder::SubmitFrame(GrContext* context,
SkCanvas* background_canvas) {
return false;
std::unique_ptr<SurfaceFrame> frame) {
return frame->Submit();
};

void ExternalViewEmbedder::FinishFrame(){};

void MutatorsStack::PushClipRect(const SkRect& rect) {
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rect);
vector_.push_back(element);
Expand Down
12 changes: 8 additions & 4 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "flutter/fml/memory/ref_counted.h"
#include "flutter/fml/raster_thread_merger.h"
#include "flutter/shell/common/surface_frame.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"
Expand Down Expand Up @@ -248,10 +249,13 @@ class ExternalViewEmbedder {
// Must be called on the UI thread.
virtual SkCanvas* CompositeEmbeddedView(int view_id) = 0;

virtual bool SubmitFrame(GrContext* context, SkCanvas* background_canvas);

// This is called after submitting the embedder frame and the surface frame.
virtual void FinishFrame();
// Implementers must submit the frame by calling frame.Submit().
//
// This method can mutate the root Skia canvas before submitting the frame.
//
// It can also allocate frames for overlay surfaces to compose hybrid views.
virtual bool SubmitFrame(GrContext* context,
std::unique_ptr<SurfaceFrame> frame);

// This should only be called after |SubmitFrame|.
// This method provides the embedder a way to do additional tasks after
Expand Down
13 changes: 13 additions & 0 deletions shell/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ source_set("common") {
]

deps = [
":surface_frame",
"//flutter/assets",
"//flutter/common",
"//flutter/flow",
Expand All @@ -141,6 +142,18 @@ source_set("common") {
public_configs = [ "//flutter:config" ]
}

source_set("surface_frame") {
Copy link
Member

Choose a reason for hiding this comment

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

Why is this in its own target? The only place this is being included (flow) also includes common.

Copy link
Author

Choose a reason for hiding this comment

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

To workaround a circular dependency. :common depends on //flutter/flow, but //flutter/flow depends on :surface_frame.

sources = [
"surface_frame.cc",
"surface_frame.h",
]

deps = [
"//flutter/fml",
"//third_party/skia",
]
}

template("shell_host_executable") {
executable(target_name) {
testonly = true
Expand Down
9 changes: 2 additions & 7 deletions shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -421,14 +421,9 @@ RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) {
return raster_status;
}
if (external_view_embedder != nullptr) {
FML_DCHECK(!frame->IsSubmitted());
external_view_embedder->SubmitFrame(surface_->GetContext(),
root_surface_canvas);
// The external view embedder may mutate the root surface canvas while
// submitting the frame.
// Therefore, submit the final frame after asking the external view
// embedder to submit the frame.
frame->Submit();
external_view_embedder->FinishFrame();
std::move(frame));
} else {
frame->Submit();
}
Expand Down
10 changes: 4 additions & 6 deletions shell/common/shell_test_external_view_embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,12 @@ SkCanvas* ShellTestExternalViewEmbedder::CompositeEmbeddedView(int view_id) {
}

// |ExternalViewEmbedder|
bool ShellTestExternalViewEmbedder::SubmitFrame(GrContext* context,
SkCanvas* background_canvas) {
return true;
bool ShellTestExternalViewEmbedder::SubmitFrame(
GrContext* context,
std::unique_ptr<SurfaceFrame> frame) {
return frame->Submit();
}

// |ExternalViewEmbedder|
void ShellTestExternalViewEmbedder::FinishFrame() {}

// |ExternalViewEmbedder|
void ShellTestExternalViewEmbedder::EndFrame(
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
Expand Down
6 changes: 2 additions & 4 deletions shell/common/shell_test_external_view_embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {
SkCanvas* CompositeEmbeddedView(int view_id) override;

// |ExternalViewEmbedder|
bool SubmitFrame(GrContext* context, SkCanvas* background_canvas) override;

// |ExternalViewEmbedder|
void FinishFrame() override;
bool SubmitFrame(GrContext* context,
std::unique_ptr<SurfaceFrame> frame) override;

// |ExternalViewEmbedder|
void EndFrame(
Expand Down
50 changes: 0 additions & 50 deletions shell/common/surface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,8 @@

#include "flutter/shell/common/surface.h"

#include "flutter/fml/logging.h"
#include "third_party/skia/include/core/SkSurface.h"

namespace flutter {

SurfaceFrame::SurfaceFrame(sk_sp<SkSurface> surface,
bool supports_readback,
const SubmitCallback& submit_callback)
: submitted_(false),
surface_(surface),
supports_readback_(supports_readback),
submit_callback_(submit_callback) {
FML_DCHECK(submit_callback_);
}

SurfaceFrame::~SurfaceFrame() {
if (submit_callback_ && !submitted_) {
// Dropping without a Submit.
submit_callback_(*this, nullptr);
}
}

bool SurfaceFrame::Submit() {
if (submitted_) {
return false;
}

submitted_ = PerformSubmit();

return submitted_;
}

SkCanvas* SurfaceFrame::SkiaCanvas() {
return surface_ != nullptr ? surface_->getCanvas() : nullptr;
}

sk_sp<SkSurface> SurfaceFrame::SkiaSurface() const {
return surface_;
}

bool SurfaceFrame::PerformSubmit() {
if (submit_callback_ == nullptr) {
return false;
}

if (submit_callback_(*this, SkiaCanvas())) {
return true;
}

return false;
}

Surface::Surface() = default;

Surface::~Surface() = default;
Expand Down
34 changes: 1 addition & 33 deletions shell/common/surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,10 @@
#include "flutter/flow/compositor_context.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/macros.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "flutter/shell/common/surface_frame.h"

namespace flutter {

/// Represents a Frame that has been fully configured for the underlying client
/// rendering API. A frame may only be submitted once.
class SurfaceFrame {
public:
using SubmitCallback =
std::function<bool(const SurfaceFrame& surface_frame, SkCanvas* canvas)>;

SurfaceFrame(sk_sp<SkSurface> surface,
bool supports_readback,
const SubmitCallback& submit_callback);

~SurfaceFrame();

bool Submit();

SkCanvas* SkiaCanvas();

sk_sp<SkSurface> SkiaSurface() const;

bool supports_readback() { return supports_readback_; }

private:
bool submitted_;
sk_sp<SkSurface> surface_;
bool supports_readback_;
SubmitCallback submit_callback_;

bool PerformSubmit();

FML_DISALLOW_COPY_AND_ASSIGN(SurfaceFrame);
};

/// Abstract Base Class that represents where we will be rendering content.
class Surface {
public:
Expand Down
61 changes: 61 additions & 0 deletions shell/common/surface_frame.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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/common/surface_frame.h"

#include "flutter/fml/logging.h"

namespace flutter {

SurfaceFrame::SurfaceFrame(sk_sp<SkSurface> surface,
bool supports_readback,
const SubmitCallback& submit_callback)
: surface_(surface),
supports_readback_(supports_readback),
submit_callback_(submit_callback) {
FML_DCHECK(submit_callback_);
}

SurfaceFrame::~SurfaceFrame() {
if (submit_callback_ && !submitted_) {
// Dropping without a Submit.
submit_callback_(*this, nullptr);
}
}

bool SurfaceFrame::Submit() {
if (submitted_) {
return false;
}

submitted_ = PerformSubmit();

return submitted_;
}

bool SurfaceFrame::IsSubmitted() const {
return submitted_;
}

SkCanvas* SurfaceFrame::SkiaCanvas() {
return surface_ != nullptr ? surface_->getCanvas() : nullptr;
}

sk_sp<SkSurface> SurfaceFrame::SkiaSurface() const {
return surface_;
}

bool SurfaceFrame::PerformSubmit() {
if (submit_callback_ == nullptr) {
return false;
}

if (submit_callback_(*this, SkiaCanvas())) {
return true;
}

return false;
}

} // namespace flutter
52 changes: 52 additions & 0 deletions shell/common/surface_frame.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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_COMMON_SURFACE_FRAME_H_
#define FLUTTER_SHELL_COMMON_SURFACE_FRAME_H_

#include <memory>

#include "flutter/fml/macros.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"

namespace flutter {

/// Represents a Frame that has been fully configured for the underlying client
/// rendering API. A frame may only be submitted once.
class SurfaceFrame {
public:
using SubmitCallback =
std::function<bool(const SurfaceFrame& surface_frame, SkCanvas* canvas)>;

SurfaceFrame(sk_sp<SkSurface> surface,
bool supports_readback,
const SubmitCallback& submit_callback);

~SurfaceFrame();

bool Submit();

bool IsSubmitted() const;

SkCanvas* SkiaCanvas();

sk_sp<SkSurface> SkiaSurface() const;

bool supports_readback() { return supports_readback_; }

private:
bool submitted_ = false;
sk_sp<SkSurface> surface_;
bool supports_readback_;
SubmitCallback submit_callback_;

bool PerformSubmit();

FML_DISALLOW_COPY_AND_ASSIGN(SurfaceFrame);
};

} // namespace flutter

#endif // FLUTTER_SHELL_COMMON_SURFACE_FRAME_H_
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,18 @@ std::vector<SkCanvas*> AndroidExternalViewEmbedder::GetCurrentCanvases() {
}

// |ExternalViewEmbedder|
bool AndroidExternalViewEmbedder::SubmitFrame(GrContext* context,
SkCanvas* background_canvas) {
bool AndroidExternalViewEmbedder::SubmitFrame(
GrContext* context,
std::unique_ptr<SurfaceFrame> frame) {
// TODO(egarciad): Implement hybrid composition.
// https://github.com/flutter/flutter/issues/55270
TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder::SubmitFrame");
for (size_t i = 0; i < composition_order_.size(); i++) {
int64_t view_id = composition_order_[i];
background_canvas->drawPicture(
frame->SkiaCanvas()->drawPicture(
picture_recorders_[view_id]->finishRecordingAsPicture());
}
return true;
return frame->Submit();
}

// |ExternalViewEmbedder|
Expand Down Expand Up @@ -83,11 +84,6 @@ void AndroidExternalViewEmbedder::CancelFrame() {
ClearFrame();
}

// |ExternalViewEmbedder|
void AndroidExternalViewEmbedder::FinishFrame() {
ClearFrame();
}

// |ExternalViewEmbedder|
void AndroidExternalViewEmbedder::EndFrame(
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {}
Expand Down
Loading