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
53 changes: 46 additions & 7 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,23 @@ static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
#endif
}

#if defined(SHELL_ENABLE_GL) && defined(IMPELLER_SUPPORTS_RENDERING)
static std::optional<impeller::PixelFormat> FlutterFormatToImpellerPixelFormat(
uint32_t format) {
switch (format) {
case GL_BGRA8_EXT:
return impeller::PixelFormat::kB8G8R8A8UNormInt;
case GL_RGBA8:
return impeller::PixelFormat::kR8G8B8A8UNormInt;
default:
FML_LOG(ERROR) << "Cannot convert format " << format
<< " to impeller::PixelFormat.";
return std::nullopt;
}
}

#endif // defined(SHELL_ENABLE_GL) && defined(IMPELLER_SUPPORTS_RENDERING)

static std::unique_ptr<flutter::EmbedderRenderTarget>
MakeRenderTargetFromBackingStoreImpeller(
FlutterBackingStore backing_store,
Expand All @@ -1046,34 +1063,56 @@ MakeRenderTargetFromBackingStoreImpeller(
const FlutterBackingStoreConfig& config,
const FlutterOpenGLFramebuffer* framebuffer) {
#if defined(SHELL_ENABLE_GL) && defined(IMPELLER_SUPPORTS_RENDERING)
auto format = FlutterFormatToImpellerPixelFormat(framebuffer->target);
if (!format.has_value()) {
return nullptr;
}

const auto& gl_context =
impeller::ContextGLES::Cast(*aiks_context->GetContext());
const bool implicit_msaa = aiks_context->GetContext()
->GetCapabilities()
->SupportsImplicitResolvingMSAA();
const auto size = impeller::ISize(config.size.width, config.size.height);

impeller::TextureDescriptor color0_tex;
color0_tex.type = impeller::TextureType::kTexture2D;
color0_tex.format = impeller::PixelFormat::kR8G8B8A8UNormInt;
if (implicit_msaa) {
color0_tex.type = impeller::TextureType::kTexture2DMultisample;
color0_tex.sample_count = impeller::SampleCount::kCount4;
} else {
color0_tex.type = impeller::TextureType::kTexture2D;
color0_tex.sample_count = impeller::SampleCount::kCount1;
}
color0_tex.format = format.value();
color0_tex.size = size;
color0_tex.usage = static_cast<impeller::TextureUsageMask>(
impeller::TextureUsage::kRenderTarget);
color0_tex.sample_count = impeller::SampleCount::kCount1;
color0_tex.storage_mode = impeller::StorageMode::kDevicePrivate;

impeller::ColorAttachment color0;
color0.texture = impeller::TextureGLES::WrapFBO(
gl_context.GetReactor(), color0_tex, framebuffer->name);
color0.clear_color = impeller::Color::DarkSlateGray();
color0.load_action = impeller::LoadAction::kClear;
color0.store_action = impeller::StoreAction::kStore;
if (implicit_msaa) {
color0.store_action = impeller::StoreAction::kMultisampleResolve;
color0.resolve_texture = color0.texture;
} else {
color0.store_action = impeller::StoreAction::kStore;
}

impeller::TextureDescriptor depth_stencil_texture_desc;
depth_stencil_texture_desc.type = impeller::TextureType::kTexture2D;
depth_stencil_texture_desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt;
depth_stencil_texture_desc.type =
impeller::TextureType::kTexture2DMultisample;
depth_stencil_texture_desc.format = impeller::PixelFormat::kD24UnormS8Uint;
depth_stencil_texture_desc.size = size;
depth_stencil_texture_desc.usage = static_cast<impeller::TextureUsageMask>(
impeller::TextureUsage::kRenderTarget);
depth_stencil_texture_desc.sample_count = impeller::SampleCount::kCount1;
if (implicit_msaa) {
depth_stencil_texture_desc.sample_count = impeller::SampleCount::kCount4;
} else {
depth_stencil_texture_desc.sample_count = impeller::SampleCount::kCount1;
}

auto depth_stencil_tex = std::make_shared<impeller::TextureGLES>(
gl_context.GetReactor(), depth_stencil_texture_desc,
Expand Down
35 changes: 30 additions & 5 deletions shell/platform/windows/compositor_opengl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ struct FramebufferBackingStore {
} // namespace

CompositorOpenGL::CompositorOpenGL(FlutterWindowsEngine* engine,
impeller::ProcTableGLES::Resolver resolver)
: engine_(engine), resolver_(resolver) {}
impeller::ProcTableGLES::Resolver resolver,
bool enable_impeller)
: engine_(engine), resolver_(resolver), enable_impeller_(enable_impeller) {}

bool CompositorOpenGL::CreateBackingStore(
const FlutterBackingStoreConfig& config,
Expand All @@ -50,8 +51,33 @@ bool CompositorOpenGL::CreateBackingStore(
GL_UNSIGNED_BYTE, nullptr);
gl_->BindTexture(GL_TEXTURE_2D, 0);

gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
store->texture_id, 0);
if (enable_impeller_) {
// Impeller requries that its onscreen surface is Multisampled and already
// has depth/stencil attached in order for anti-aliasing to work.
gl_->FramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
Copy link
Member

Choose a reason for hiding this comment

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

Could we add a very quick comment that explains why this needs to be different for Impeller?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
store->texture_id, 0, 4);

// Set up depth/stencil attachment for impeller renderer.
GLuint depth_stencil;
gl_->GenRenderbuffers(1, &depth_stencil);
gl_->BindRenderbuffer(GL_RENDERBUFFER, depth_stencil);
gl_->RenderbufferStorageMultisampleEXT(
GL_RENDERBUFFER, // target
4, // samples
GL_DEPTH24_STENCIL8, // internal format
config.size.width, // width
config.size.height // height
);
gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depth_stencil);
gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, depth_stencil);

} else {
gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, store->texture_id, 0);
}

result->type = kFlutterBackingStoreTypeOpenGL;
result->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
Expand Down Expand Up @@ -131,7 +157,6 @@ bool CompositorOpenGL::Present(FlutterWindowsView* view,
// Prevents regressions like: https://github.com/flutter/flutter/issues/140828
// See OpenGL specification version 4.6, section 18.3.1.
gl_->Disable(GL_SCISSOR_TEST);

gl_->BindFramebuffer(GL_READ_FRAMEBUFFER, source_id);
gl_->BindFramebuffer(GL_DRAW_FRAMEBUFFER, kWindowFrameBufferId);

Expand Down
6 changes: 5 additions & 1 deletion shell/platform/windows/compositor_opengl.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ namespace flutter {
class CompositorOpenGL : public Compositor {
public:
CompositorOpenGL(FlutterWindowsEngine* engine,
impeller::ProcTableGLES::Resolver resolver);
impeller::ProcTableGLES::Resolver resolver,
bool enable_impeller);

/// |Compositor|
bool CreateBackingStore(const FlutterBackingStoreConfig& config,
Expand Down Expand Up @@ -59,6 +60,9 @@ class CompositorOpenGL : public Compositor {
// the compositor is initialized.
TextureFormat format_;

// Whether the Impeller rendering backend is enabled.
bool enable_impeller_ = false;

// Initialize the compositor. This must run on the raster thread.
bool Initialize();

Expand Down
29 changes: 24 additions & 5 deletions shell/platform/windows/compositor_opengl_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,22 @@ class CompositorOpenGLTest : public WindowsTest {
TEST_F(CompositorOpenGLTest, CreateBackingStore) {
UseHeadlessEngine();

auto compositor = CompositorOpenGL{engine(), kMockResolver};
auto compositor =
CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};

FlutterBackingStoreConfig config = {};
FlutterBackingStore backing_store = {};

EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
}

TEST_F(CompositorOpenGLTest, CreateBackingStoreImpeller) {
UseHeadlessEngine();

auto compositor =
CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/true};

FlutterBackingStoreConfig config = {};
FlutterBackingStore backing_store = {};
Expand All @@ -138,7 +153,8 @@ TEST_F(CompositorOpenGLTest, CreateBackingStore) {
TEST_F(CompositorOpenGLTest, InitializationFailure) {
UseHeadlessEngine();

auto compositor = CompositorOpenGL{engine(), kMockResolver};
auto compositor =
CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};

FlutterBackingStoreConfig config = {};
FlutterBackingStore backing_store = {};
Expand All @@ -150,7 +166,8 @@ TEST_F(CompositorOpenGLTest, InitializationFailure) {
TEST_F(CompositorOpenGLTest, Present) {
UseEngineWithView();

auto compositor = CompositorOpenGL{engine(), kMockResolver};
auto compositor =
CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};

FlutterBackingStoreConfig config = {};
FlutterBackingStore backing_store = {};
Expand All @@ -174,7 +191,8 @@ TEST_F(CompositorOpenGLTest, Present) {
TEST_F(CompositorOpenGLTest, PresentEmpty) {
UseEngineWithView();

auto compositor = CompositorOpenGL{engine(), kMockResolver};
auto compositor =
CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};

// The context will be bound twice: first to initialize the compositor, second
// to clear the surface.
Expand All @@ -188,7 +206,8 @@ TEST_F(CompositorOpenGLTest, PresentEmpty) {
TEST_F(CompositorOpenGLTest, NoSurfaceIgnored) {
UseEngineWithView(/*add_surface = */ false);

auto compositor = CompositorOpenGL{engine(), kMockResolver};
auto compositor =
CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};

FlutterBackingStoreConfig config = {};
FlutterBackingStore backing_store = {};
Expand Down
45 changes: 9 additions & 36 deletions shell/platform/windows/egl/manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ namespace egl {

int Manager::instance_count_ = 0;

std::unique_ptr<Manager> Manager::Create(bool enable_impeller) {
std::unique_ptr<Manager> Manager::Create() {
std::unique_ptr<Manager> manager;
manager.reset(new Manager(enable_impeller));
manager.reset(new Manager());
if (!manager->IsValid()) {
return nullptr;
}
return std::move(manager);
}

Manager::Manager(bool enable_impeller) {
Manager::Manager() {
++instance_count_;

if (!InitializeDisplay()) {
return;
}

if (!InitializeConfig(enable_impeller)) {
if (!InitializeConfig()) {
return;
}

Expand Down Expand Up @@ -140,46 +140,19 @@ bool Manager::InitializeDisplay() {
FML_UNREACHABLE();
}

bool Manager::InitializeConfig(bool enable_impeller) {
bool Manager::InitializeConfig() {
const EGLint config_attributes[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8,
EGL_NONE};

const EGLint impeller_config_attributes[] = {
EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 8,
EGL_SAMPLE_BUFFERS, 1, EGL_SAMPLES, 4, EGL_NONE};
const EGLint impeller_config_attributes_no_msaa[] = {
EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 8,
EGL_NONE};

EGLBoolean result;
EGLint num_config = 0;

if (enable_impeller) {
// First try the MSAA configuration.
result = ::eglChooseConfig(display_, impeller_config_attributes, &config_,
1, &num_config);

if (result == EGL_TRUE && num_config > 0) {
return true;
}
EGLBoolean result =
::eglChooseConfig(display_, config_attributes, &config_, 1, &num_config);

// Next fall back to disabled MSAA.
result = ::eglChooseConfig(display_, impeller_config_attributes_no_msaa,
&config_, 1, &num_config);
if (result == EGL_TRUE && num_config == 0) {
return true;
}
} else {
result = ::eglChooseConfig(display_, config_attributes, &config_, 1,
&num_config);

if (result == EGL_TRUE && num_config > 0) {
return true;
}
if (result == EGL_TRUE && num_config > 0) {
return true;
}

LogEGLError("Failed to choose EGL config");
Expand Down
6 changes: 3 additions & 3 deletions shell/platform/windows/egl/manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace egl {
// destroy surfaces
class Manager {
public:
static std::unique_ptr<Manager> Create(bool enable_impeller);
static std::unique_ptr<Manager> Create();

virtual ~Manager();

Expand Down Expand Up @@ -74,7 +74,7 @@ class Manager {
protected:
// Creates a new surface manager retaining reference to the passed-in target
// for the lifetime of the manager.
explicit Manager(bool enable_impeller);
explicit Manager();

private:
// Number of active instances of Manager
Expand All @@ -84,7 +84,7 @@ class Manager {
bool InitializeDisplay();

// Initialize the EGL configs.
bool InitializeConfig(bool enable_impeller);
bool InitializeConfig();

// Initialize the EGL render and resource contexts.
bool InitializeContexts();
Expand Down
5 changes: 3 additions & 2 deletions shell/platform/windows/flutter_windows_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ FlutterWindowsEngine::FlutterWindowsEngine(
enable_impeller_ = std::find(switches.begin(), switches.end(),
"--enable-impeller=true") != switches.end();

egl_manager_ = egl::Manager::Create(enable_impeller_);
egl_manager_ = egl::Manager::Create();
window_proc_delegate_manager_ = std::make_unique<WindowProcDelegateManager>();
window_proc_delegate_manager_->RegisterTopLevelWindowProcDelegate(
[](HWND hwnd, UINT msg, WPARAM wpar, LPARAM lpar, void* user_data,
Expand Down Expand Up @@ -393,7 +393,8 @@ bool FlutterWindowsEngine::Run(std::string_view entrypoint) {

// TODO(schectman) Pass the platform view manager to the compositor
// constructors: https://github.com/flutter/flutter/issues/143375
compositor_ = std::make_unique<CompositorOpenGL>(this, resolver);
compositor_ =
std::make_unique<CompositorOpenGL>(this, resolver, enable_impeller_);
} else {
compositor_ = std::make_unique<CompositorSoftware>();
}
Expand Down
2 changes: 1 addition & 1 deletion shell/platform/windows/flutter_windows_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace {
// An EGL manager that initializes EGL but fails to create surfaces.
class HalfBrokenEGLManager : public egl::Manager {
public:
HalfBrokenEGLManager() : egl::Manager(/*enable_impeller = */ false) {}
HalfBrokenEGLManager() : egl::Manager() {}

std::unique_ptr<egl::WindowSurface>
CreateWindowSurface(HWND hwnd, size_t width, size_t height) override {
Expand Down
2 changes: 1 addition & 1 deletion shell/platform/windows/testing/egl/mock_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace egl {
/// Mock for the |Manager| base class.
class MockManager : public flutter::egl::Manager {
public:
MockManager() : Manager(false) {}
MockManager() : Manager() {}

MOCK_METHOD(std::unique_ptr<flutter::egl::WindowSurface>,
CreateWindowSurface,
Expand Down