Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 92abb22

Browse files
authored
Reland "Lift restriction that embedders may not trample the render thread OpenGL context in composition callbacks." (#16711)
This reverts commit ef9e7b1 with the following changes to accommodate an embedder for whom the original optimizations caused issues: * Ensure stable order in the backing stores presented to the embedder. This is a pessimization that will be reverted when the embedder migrates. Tracked in flutter/flutter#51228 * Forego the optimization where the unused layers would be collected before allocation of new layers needs to happen. This is a pessimization that will be reverted when the embedder migrates. Tracked in flutter/flutter#51229 More context in b/146142979.
1 parent 38dc2ea commit 92abb22

18 files changed

+955
-269
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ FILE: ../../../flutter/fml/file_unittest.cc
126126
FILE: ../../../flutter/fml/gpu_thread_merger.cc
127127
FILE: ../../../flutter/fml/gpu_thread_merger.h
128128
FILE: ../../../flutter/fml/gpu_thread_merger_unittests.cc
129+
FILE: ../../../flutter/fml/hash_combine.h
130+
FILE: ../../../flutter/fml/hash_combine_unittests.cc
129131
FILE: ../../../flutter/fml/icu_util.cc
130132
FILE: ../../../flutter/fml/icu_util.h
131133
FILE: ../../../flutter/fml/log_level.h
@@ -912,15 +914,20 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_engine.cc
912914
FILE: ../../../flutter/shell/platform/embedder/embedder_engine.h
913915
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_gl.cc
914916
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_gl.h
917+
FILE: ../../../flutter/shell/platform/embedder/embedder_external_view.cc
918+
FILE: ../../../flutter/shell/platform/embedder/embedder_external_view.h
915919
FILE: ../../../flutter/shell/platform/embedder/embedder_external_view_embedder.cc
916920
FILE: ../../../flutter/shell/platform/embedder/embedder_external_view_embedder.h
917921
FILE: ../../../flutter/shell/platform/embedder/embedder_include.c
922+
FILE: ../../../flutter/shell/platform/embedder/embedder_include2.c
918923
FILE: ../../../flutter/shell/platform/embedder/embedder_layers.cc
919924
FILE: ../../../flutter/shell/platform/embedder/embedder_layers.h
920925
FILE: ../../../flutter/shell/platform/embedder/embedder_platform_message_response.cc
921926
FILE: ../../../flutter/shell/platform/embedder/embedder_platform_message_response.h
922927
FILE: ../../../flutter/shell/platform/embedder/embedder_render_target.cc
923928
FILE: ../../../flutter/shell/platform/embedder/embedder_render_target.h
929+
FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_cache.cc
930+
FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_cache.h
924931
FILE: ../../../flutter/shell/platform/embedder/embedder_safe_access.h
925932
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.cc
926933
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.h

fml/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ source_set("fml") {
2626
"file.h",
2727
"gpu_thread_merger.cc",
2828
"gpu_thread_merger.h",
29+
"hash_combine.h",
2930
"icu_util.cc",
3031
"icu_util.h",
3132
"log_level.h",
@@ -232,6 +233,7 @@ executable("fml_unittests") {
232233
"command_line_unittest.cc",
233234
"file_unittest.cc",
234235
"gpu_thread_merger_unittests.cc",
236+
"hash_combine_unittests.cc",
235237
"memory/ref_counted_unittest.cc",
236238
"memory/weak_ptr_unittest.cc",
237239
"message_loop_task_queues_merge_unmerge_unittests.cc",

fml/hash_combine.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_FML_HASH_COMBINE_H_
6+
#define FLUTTER_FML_HASH_COMBINE_H_
7+
8+
#include <functional>
9+
10+
namespace fml {
11+
12+
template <class Type>
13+
constexpr void HashCombineSeed(std::size_t& seed, Type arg) {
14+
seed ^= std::hash<Type>{}(arg) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
15+
}
16+
17+
template <class Type, class... Rest>
18+
constexpr void HashCombineSeed(std::size_t& seed,
19+
Type arg,
20+
Rest... other_args) {
21+
HashCombineSeed(seed, arg);
22+
HashCombineSeed(seed, other_args...);
23+
}
24+
25+
constexpr std::size_t HashCombine() {
26+
return 0xdabbad00;
27+
}
28+
29+
template <class... Type>
30+
constexpr std::size_t HashCombine(Type... args) {
31+
std::size_t seed = HashCombine();
32+
HashCombineSeed(seed, args...);
33+
return seed;
34+
}
35+
36+
} // namespace fml
37+
38+
#endif // FLUTTER_FML_HASH_COMBINE_H_

fml/hash_combine_unittests.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/fml/hash_combine.h"
6+
#include "flutter/testing/testing.h"
7+
8+
namespace fml {
9+
namespace testing {
10+
11+
TEST(HashCombineTest, CanHash) {
12+
ASSERT_EQ(HashCombine(), HashCombine());
13+
ASSERT_EQ(HashCombine("Hello"), HashCombine("Hello"));
14+
ASSERT_NE(HashCombine("Hello"), HashCombine("World"));
15+
ASSERT_EQ(HashCombine("Hello", "World"), HashCombine("Hello", "World"));
16+
ASSERT_NE(HashCombine("World", "Hello"), HashCombine("Hello", "World"));
17+
ASSERT_EQ(HashCombine(12u), HashCombine(12u));
18+
ASSERT_NE(HashCombine(12u), HashCombine(12.0f));
19+
ASSERT_EQ(HashCombine('a'), HashCombine('a'));
20+
}
21+
22+
} // namespace testing
23+
} // namespace fml

shell/common/canvas_spy.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ class CanvasSpy {
2626
public:
2727
CanvasSpy(SkCanvas* target_canvas);
2828

29-
//------------------------------------------------------------------------------
30-
/// @brief Returns true if any non trasnparent content has been drawn
29+
//----------------------------------------------------------------------------
30+
/// @brief Returns true if any non transparent content has been drawn
3131
/// into
3232
/// the spying canvas. Note that this class does tries to detect
3333
/// empty canvases but in some cases may return true even for
3434
/// empty canvases (e.g when a transparent image is drawn into the
3535
/// canvas).
3636
bool DidDrawIntoCanvas();
3737

38-
//------------------------------------------------------------------------------
38+
//----------------------------------------------------------------------------
3939
/// @brief The returned canvas delegate all operations to the target
4040
/// canvas
4141
/// while spying on them.

shell/platform/embedder/BUILD.gn

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,20 @@ template("embedder_source_set") {
2929
"embedder_engine.h",
3030
"embedder_external_texture_gl.cc",
3131
"embedder_external_texture_gl.h",
32+
"embedder_external_view.cc",
33+
"embedder_external_view.h",
3234
"embedder_external_view_embedder.cc",
3335
"embedder_external_view_embedder.h",
3436
"embedder_include.c",
37+
"embedder_include2.c",
3538
"embedder_layers.cc",
3639
"embedder_layers.h",
3740
"embedder_platform_message_response.cc",
3841
"embedder_platform_message_response.h",
3942
"embedder_render_target.cc",
4043
"embedder_render_target.h",
44+
"embedder_render_target_cache.cc",
45+
"embedder_render_target_cache.h",
4146
"embedder_safe_access.h",
4247
"embedder_surface.cc",
4348
"embedder_surface.h",
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/shell/platform/embedder/embedder_external_view.h"
6+
#include "flutter/fml/trace_event.h"
7+
#include "flutter/shell/common/canvas_spy.h"
8+
9+
namespace flutter {
10+
11+
static SkISize TransformedSurfaceSize(const SkISize& size,
12+
const SkMatrix& transformation) {
13+
const auto source_rect = SkRect::MakeWH(size.width(), size.height());
14+
const auto transformed_rect = transformation.mapRect(source_rect);
15+
return SkISize::Make(transformed_rect.width(), transformed_rect.height());
16+
}
17+
18+
EmbedderExternalView::EmbedderExternalView(
19+
const SkISize& frame_size,
20+
const SkMatrix& surface_transformation)
21+
: EmbedderExternalView(frame_size, surface_transformation, {}, nullptr) {}
22+
23+
EmbedderExternalView::EmbedderExternalView(
24+
const SkISize& frame_size,
25+
const SkMatrix& surface_transformation,
26+
ViewIdentifier view_identifier,
27+
std::unique_ptr<EmbeddedViewParams> params)
28+
: render_surface_size_(
29+
TransformedSurfaceSize(frame_size, surface_transformation)),
30+
surface_transformation_(surface_transformation),
31+
view_identifier_(view_identifier),
32+
embedded_view_params_(std::move(params)),
33+
recorder_(std::make_unique<SkPictureRecorder>()),
34+
canvas_spy_(std::make_unique<CanvasSpy>(
35+
recorder_->beginRecording(frame_size.width(), frame_size.height()))) {
36+
}
37+
38+
EmbedderExternalView::~EmbedderExternalView() = default;
39+
40+
EmbedderExternalView::RenderTargetDescriptor
41+
EmbedderExternalView::CreateRenderTargetDescriptor() const {
42+
return {view_identifier_, render_surface_size_};
43+
}
44+
45+
SkCanvas* EmbedderExternalView::GetCanvas() const {
46+
return canvas_spy_->GetSpyingCanvas();
47+
}
48+
49+
SkISize EmbedderExternalView::GetRenderSurfaceSize() const {
50+
return render_surface_size_;
51+
}
52+
53+
bool EmbedderExternalView::IsRootView() const {
54+
return !HasPlatformView();
55+
}
56+
57+
bool EmbedderExternalView::HasPlatformView() const {
58+
return view_identifier_.platform_view_id.has_value();
59+
}
60+
61+
bool EmbedderExternalView::HasEngineRenderedContents() const {
62+
return canvas_spy_->DidDrawIntoCanvas();
63+
}
64+
65+
EmbedderExternalView::ViewIdentifier EmbedderExternalView::GetViewIdentifier()
66+
const {
67+
return view_identifier_;
68+
}
69+
70+
const EmbeddedViewParams* EmbedderExternalView::GetEmbeddedViewParams() const {
71+
return embedded_view_params_.get();
72+
}
73+
74+
bool EmbedderExternalView::Render(const EmbedderRenderTarget& render_target) {
75+
TRACE_EVENT0("flutter", "EmbedderExternalView::Render");
76+
77+
FML_DCHECK(HasEngineRenderedContents())
78+
<< "Unnecessarily asked to render into a render target when there was "
79+
"nothing to render.";
80+
81+
auto picture = recorder_->finishRecordingAsPicture();
82+
if (!picture) {
83+
return false;
84+
}
85+
86+
auto surface = render_target.GetRenderSurface();
87+
if (!surface) {
88+
return false;
89+
}
90+
91+
FML_DCHECK(SkISize::Make(surface->width(), surface->height()) ==
92+
render_surface_size_);
93+
94+
auto canvas = surface->getCanvas();
95+
if (!canvas) {
96+
return false;
97+
}
98+
99+
canvas->setMatrix(surface_transformation_);
100+
canvas->clear(SK_ColorTRANSPARENT);
101+
canvas->drawPicture(picture);
102+
canvas->flush();
103+
104+
return true;
105+
}
106+
107+
} // namespace flutter
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_VIEW_H_
6+
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_VIEW_H_
7+
8+
#include <optional>
9+
#include <unordered_map>
10+
#include <unordered_set>
11+
12+
#include "flutter/flow/embedded_views.h"
13+
#include "flutter/fml/hash_combine.h"
14+
#include "flutter/fml/macros.h"
15+
#include "flutter/shell/common/canvas_spy.h"
16+
#include "flutter/shell/platform/embedder/embedder_render_target.h"
17+
#include "third_party/skia/include/core/SkPictureRecorder.h"
18+
19+
namespace flutter {
20+
21+
class EmbedderExternalView {
22+
public:
23+
using PlatformViewID = int64_t;
24+
struct ViewIdentifier {
25+
std::optional<PlatformViewID> platform_view_id;
26+
27+
ViewIdentifier() {}
28+
29+
ViewIdentifier(PlatformViewID view_id) : platform_view_id(view_id) {}
30+
31+
struct Hash {
32+
constexpr std::size_t operator()(const ViewIdentifier& desc) const {
33+
if (!desc.platform_view_id.has_value()) {
34+
return fml::HashCombine();
35+
}
36+
37+
return fml::HashCombine(desc.platform_view_id.value());
38+
}
39+
};
40+
41+
struct Equal {
42+
constexpr bool operator()(const ViewIdentifier& lhs,
43+
const ViewIdentifier& rhs) const {
44+
return lhs.platform_view_id == rhs.platform_view_id;
45+
}
46+
};
47+
};
48+
49+
struct RenderTargetDescriptor {
50+
ViewIdentifier view_identifier;
51+
SkISize surface_size;
52+
53+
RenderTargetDescriptor(ViewIdentifier p_view_identifier,
54+
SkISize p_surface_size)
55+
: view_identifier(p_view_identifier), surface_size(p_surface_size) {}
56+
57+
struct Hash {
58+
constexpr std::size_t operator()(
59+
const RenderTargetDescriptor& desc) const {
60+
return fml::HashCombine(desc.surface_size.width(),
61+
desc.surface_size.height(),
62+
ViewIdentifier::Hash{}(desc.view_identifier));
63+
}
64+
};
65+
66+
struct Equal {
67+
bool operator()(const RenderTargetDescriptor& lhs,
68+
const RenderTargetDescriptor& rhs) const {
69+
return lhs.surface_size == rhs.surface_size &&
70+
ViewIdentifier::Equal{}(lhs.view_identifier,
71+
rhs.view_identifier);
72+
}
73+
};
74+
};
75+
76+
using ViewIdentifierSet = std::unordered_set<ViewIdentifier,
77+
ViewIdentifier::Hash,
78+
ViewIdentifier::Equal>;
79+
80+
using PendingViews = std::unordered_map<ViewIdentifier,
81+
std::unique_ptr<EmbedderExternalView>,
82+
ViewIdentifier::Hash,
83+
ViewIdentifier::Equal>;
84+
85+
EmbedderExternalView(const SkISize& frame_size,
86+
const SkMatrix& surface_transformation);
87+
88+
EmbedderExternalView(const SkISize& frame_size,
89+
const SkMatrix& surface_transformation,
90+
ViewIdentifier view_identifier,
91+
std::unique_ptr<EmbeddedViewParams> params);
92+
93+
~EmbedderExternalView();
94+
95+
bool IsRootView() const;
96+
97+
bool HasPlatformView() const;
98+
99+
bool HasEngineRenderedContents() const;
100+
101+
ViewIdentifier GetViewIdentifier() const;
102+
103+
const EmbeddedViewParams* GetEmbeddedViewParams() const;
104+
105+
RenderTargetDescriptor CreateRenderTargetDescriptor() const;
106+
107+
SkCanvas* GetCanvas() const;
108+
109+
SkISize GetRenderSurfaceSize() const;
110+
111+
bool Render(const EmbedderRenderTarget& render_target);
112+
113+
private:
114+
const SkISize render_surface_size_;
115+
const SkMatrix surface_transformation_;
116+
ViewIdentifier view_identifier_;
117+
std::unique_ptr<EmbeddedViewParams> embedded_view_params_;
118+
std::unique_ptr<SkPictureRecorder> recorder_;
119+
std::unique_ptr<CanvasSpy> canvas_spy_;
120+
121+
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalView);
122+
};
123+
124+
} // namespace flutter
125+
126+
#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_VIEW_H_

0 commit comments

Comments
 (0)