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

Commit 641b1c3

Browse files
committed
[Impeller] Add a TextureGLES API for wrapping a framebuffer and use it to implement OpenGL FBO targets in the embedder library
The Linux embedder is rendering to a FlutterOpenGLFramebuffer that specifies an OpenGL FBO. This API allows the embedder to create a color attachment that wraps the FBO so that the render pass will bind to that FBO during encoding.
1 parent 6c1751b commit 641b1c3

File tree

6 files changed

+56
-19
lines changed

6 files changed

+56
-19
lines changed

impeller/renderer/backend/gles/render_pass_gles.cc

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,19 +172,21 @@ struct RenderPassData {
172172
}
173173
});
174174

175-
const auto is_default_fbo =
176-
TextureGLES::Cast(*pass_data.color_attachment).IsWrapped();
175+
TextureGLES& color_gles = TextureGLES::Cast(*pass_data.color_attachment);
176+
const bool is_default_fbo = color_gles.IsWrapped();
177177

178-
if (!is_default_fbo) {
178+
if (is_default_fbo) {
179+
if (color_gles.GetFBO().has_value()) {
180+
gl.BindFramebuffer(GL_FRAMEBUFFER, *color_gles.GetFBO());
181+
}
182+
} else {
179183
// Create and bind an offscreen FBO.
180184
gl.GenFramebuffers(1u, &fbo);
181185
gl.BindFramebuffer(GL_FRAMEBUFFER, fbo);
182186

183-
if (auto color = TextureGLES::Cast(pass_data.color_attachment.get())) {
184-
if (!color->SetAsFramebufferAttachment(
185-
GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) {
186-
return false;
187-
}
187+
if (!color_gles.SetAsFramebufferAttachment(
188+
GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) {
189+
return false;
188190
}
189191

190192
if (auto depth = TextureGLES::Cast(pass_data.depth_attachment.get())) {

impeller/renderer/backend/gles/texture_gles.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,21 +69,30 @@ HandleType ToHandleType(TextureGLES::Type type) {
6969
}
7070

7171
TextureGLES::TextureGLES(ReactorGLES::Ref reactor, TextureDescriptor desc)
72-
: TextureGLES(std::move(reactor), desc, false) {}
72+
: TextureGLES(std::move(reactor), desc, false, std::nullopt) {}
7373

7474
TextureGLES::TextureGLES(ReactorGLES::Ref reactor,
7575
TextureDescriptor desc,
7676
enum IsWrapped wrapped)
77-
: TextureGLES(std::move(reactor), desc, true) {}
77+
: TextureGLES(std::move(reactor), desc, true, std::nullopt) {}
78+
79+
std::shared_ptr<TextureGLES> TextureGLES::WrapFBO(ReactorGLES::Ref reactor,
80+
TextureDescriptor desc,
81+
GLuint fbo) {
82+
return std::shared_ptr<TextureGLES>(
83+
new TextureGLES(reactor, desc, true, fbo));
84+
}
7885

7986
TextureGLES::TextureGLES(std::shared_ptr<ReactorGLES> reactor,
8087
TextureDescriptor desc,
81-
bool is_wrapped)
88+
bool is_wrapped,
89+
std::optional<GLuint> fbo)
8290
: Texture(desc),
8391
reactor_(std::move(reactor)),
8492
type_(GetTextureTypeFromDescriptor(GetTextureDescriptor())),
8593
handle_(reactor_->CreateHandle(ToHandleType(type_))),
86-
is_wrapped_(is_wrapped) {
94+
is_wrapped_(is_wrapped),
95+
fbo_(fbo) {
8796
// Ensure the texture descriptor itself is valid.
8897
if (!GetTextureDescriptor().IsValid()) {
8998
VALIDATION_LOG << "Invalid texture descriptor.";

impeller/renderer/backend/gles/texture_gles.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ class TextureGLES final : public Texture,
3232
TextureDescriptor desc,
3333
IsWrapped wrapped);
3434

35+
static std::shared_ptr<TextureGLES> WrapFBO(ReactorGLES::Ref reactor,
36+
TextureDescriptor desc,
37+
GLuint fbo);
38+
3539
// |Texture|
3640
~TextureGLES() override;
3741

@@ -54,6 +58,8 @@ class TextureGLES final : public Texture,
5458

5559
bool IsWrapped() const { return is_wrapped_; }
5660

61+
std::optional<GLuint> GetFBO() const { return fbo_; }
62+
5763
private:
5864
friend class AllocatorMTL;
5965

@@ -62,11 +68,13 @@ class TextureGLES final : public Texture,
6268
HandleGLES handle_;
6369
mutable bool contents_initialized_ = false;
6470
const bool is_wrapped_;
71+
const std::optional<GLuint> fbo_;
6572
bool is_valid_ = false;
6673

6774
TextureGLES(std::shared_ptr<ReactorGLES> reactor,
6875
TextureDescriptor desc,
69-
bool is_wrapped);
76+
bool is_wrapped,
77+
std::optional<GLuint> fbo);
7078

7179
// |Texture|
7280
void SetLabel(std::string_view label) override;

shell/platform/embedder/embedder.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -979,9 +979,8 @@ MakeRenderTargetFromBackingStoreImpeller(
979979
color0_tex.storage_mode = impeller::StorageMode::kDevicePrivate;
980980

981981
impeller::ColorAttachment color0;
982-
color0.texture = std::make_shared<impeller::TextureGLES>(
983-
gl_context.GetReactor(), color0_tex,
984-
impeller::TextureGLES::IsWrapped::kWrapped);
982+
color0.texture = impeller::TextureGLES::WrapFBO(
983+
gl_context.GetReactor(), color0_tex, framebuffer->name);
985984
color0.clear_color = impeller::Color::DarkSlateGray();
986985
color0.load_action = impeller::LoadAction::kClear;
987986
color0.store_action = impeller::StoreAction::kStore;

shell/platform/embedder/tests/embedder_gl_unittests.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4701,7 +4701,8 @@ TEST_F(EmbedderTest,
47014701
}
47024702

47034703
TEST_F(EmbedderTest, CanRenderWithImpellerOpenGL) {
4704-
auto& context = GetEmbedderContext(EmbedderTestContextType::kOpenGLContext);
4704+
EmbedderTestContextGL& context = static_cast<EmbedderTestContextGL&>(
4705+
GetEmbedderContext(EmbedderTestContextType::kOpenGLContext));
47054706
EmbedderConfigBuilder builder(context);
47064707

47074708
bool present_called = false;
@@ -4722,6 +4723,24 @@ TEST_F(EmbedderTest, CanRenderWithImpellerOpenGL) {
47224723
auto engine = builder.LaunchEngine();
47234724
ASSERT_TRUE(engine.is_valid());
47244725

4726+
// Bind to an arbitrary FBO in order to verify that Impeller binds to the
4727+
// provided FBO during rendering.
4728+
typedef void (*glGenFramebuffersProc)(GLsizei n, GLuint* ids);
4729+
typedef void (*glBindFramebufferProc)(GLenum target, GLuint framebuffer);
4730+
auto glGenFramebuffers = reinterpret_cast<glGenFramebuffersProc>(
4731+
context.GLGetProcAddress("glGenFramebuffers"));
4732+
auto glBindFramebuffer = reinterpret_cast<glBindFramebufferProc>(
4733+
context.GLGetProcAddress("glBindFramebuffer"));
4734+
const flutter::Shell& shell = ToEmbedderEngine(engine.get())->GetShell();
4735+
fml::AutoResetWaitableEvent raster_event;
4736+
shell.GetTaskRunners().GetRasterTaskRunner()->PostTask([&] {
4737+
GLuint fbo;
4738+
glGenFramebuffers(1, &fbo);
4739+
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4740+
raster_event.Signal();
4741+
});
4742+
raster_event.Wait();
4743+
47254744
// Send a window metrics events so frames may be scheduled.
47264745
FlutterWindowMetricsEvent event = {};
47274746
event.struct_size = sizeof(event);

shell/platform/embedder/tests/embedder_test_context_gl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class EmbedderTestContextGL : public EmbedderTestContext {
6262
void GLPopulateExistingDamage(const intptr_t id,
6363
FlutterDamage* existing_damage);
6464

65+
void* GLGetProcAddress(const char* name);
66+
6567
protected:
6668
virtual void SetupCompositor() override;
6769

@@ -88,8 +90,6 @@ class EmbedderTestContextGL : public EmbedderTestContext {
8890

8991
bool GLMakeResourceCurrent();
9092

91-
void* GLGetProcAddress(const char* name);
92-
9393
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderTestContextGL);
9494
};
9595

0 commit comments

Comments
 (0)