[Windows] Rename and move EGL types (flutter/engine#49900)
This is a refactoring with no semantic changes. The following types were renamed: * `flutter::AngleSurfaceManager` to `flutter::egl::Manager`. In subsequent pull requests, this type will _create_ but not _own_ surfaces. Furthermore, this type will be split up to introduce `flutter::egl::Surface` and `flutter::egl::Context`. The manager will own the contexts and each surface will be owned by its view. * `flutter::GlProcTable` to `flutter::egl::ProcTable` This also introduces an `egl` directory to the Windows embedder. Previous pull request: https://github.com/flutter/engine/pull/49895 Part of https://github.com/flutter/flutter/issues/141996 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
@@ -7219,8 +7219,6 @@ ORIGIN: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_view.h + .
|
||||
ORIGIN: ../../../flutter/shell/platform/linux/public/flutter_linux/flutter_linux.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/accessibility_bridge_windows.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/accessibility_bridge_windows.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/angle_surface_manager.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/angle_surface_manager.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/client_wrapper/flutter_engine.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/client_wrapper/flutter_view_controller.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/dart_project.h + ../../../flutter/LICENSE
|
||||
@@ -7239,6 +7237,10 @@ ORIGIN: ../../../flutter/shell/platform/windows/direct_manipulation.cc + ../../.
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/direct_manipulation.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/dpi_utils.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/dpi_utils.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/egl/manager.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/egl/manager.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/egl/proc_table.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/egl/proc_table.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/event_watcher.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/event_watcher.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/external_texture.h + ../../../flutter/LICENSE
|
||||
@@ -7262,8 +7264,6 @@ ORIGIN: ../../../flutter/shell/platform/windows/flutter_windows_texture_registra
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/flutter_windows_view.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/flutter_windows_view.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/flutter_windows_view_controller.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/gl_proc_table.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/gl_proc_table.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/keyboard_handler_base.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/keyboard_key_channel_handler.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/shell/platform/windows/keyboard_key_channel_handler.h + ../../../flutter/LICENSE
|
||||
@@ -10093,8 +10093,6 @@ FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_view.h
|
||||
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/flutter_linux.h
|
||||
FILE: ../../../flutter/shell/platform/windows/accessibility_bridge_windows.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/accessibility_bridge_windows.h
|
||||
FILE: ../../../flutter/shell/platform/windows/angle_surface_manager.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/angle_surface_manager.h
|
||||
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_engine.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/client_wrapper/flutter_view_controller.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/dart_project.h
|
||||
@@ -10113,6 +10111,10 @@ FILE: ../../../flutter/shell/platform/windows/direct_manipulation.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/direct_manipulation.h
|
||||
FILE: ../../../flutter/shell/platform/windows/dpi_utils.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/dpi_utils.h
|
||||
FILE: ../../../flutter/shell/platform/windows/egl/manager.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/egl/manager.h
|
||||
FILE: ../../../flutter/shell/platform/windows/egl/proc_table.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/egl/proc_table.h
|
||||
FILE: ../../../flutter/shell/platform/windows/event_watcher.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/event_watcher.h
|
||||
FILE: ../../../flutter/shell/platform/windows/external_texture.h
|
||||
@@ -10136,8 +10138,6 @@ FILE: ../../../flutter/shell/platform/windows/flutter_windows_texture_registrar.
|
||||
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.h
|
||||
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view_controller.h
|
||||
FILE: ../../../flutter/shell/platform/windows/gl_proc_table.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/gl_proc_table.h
|
||||
FILE: ../../../flutter/shell/platform/windows/keyboard_handler_base.h
|
||||
FILE: ../../../flutter/shell/platform/windows/keyboard_key_channel_handler.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/keyboard_key_channel_handler.h
|
||||
|
||||
@@ -40,8 +40,6 @@ source_set("flutter_windows_source") {
|
||||
sources = [
|
||||
"accessibility_bridge_windows.cc",
|
||||
"accessibility_bridge_windows.h",
|
||||
"angle_surface_manager.cc",
|
||||
"angle_surface_manager.h",
|
||||
"compositor.h",
|
||||
"compositor_opengl.cc",
|
||||
"compositor_opengl.h",
|
||||
@@ -53,6 +51,10 @@ source_set("flutter_windows_source") {
|
||||
"direct_manipulation.h",
|
||||
"dpi_utils.cc",
|
||||
"dpi_utils.h",
|
||||
"egl/manager.cc",
|
||||
"egl/manager.h",
|
||||
"egl/proc_table.cc",
|
||||
"egl/proc_table.h",
|
||||
"event_watcher.cc",
|
||||
"event_watcher.h",
|
||||
"external_texture.h",
|
||||
@@ -75,8 +77,6 @@ source_set("flutter_windows_source") {
|
||||
"flutter_windows_view.cc",
|
||||
"flutter_windows_view.h",
|
||||
"flutter_windows_view_controller.h",
|
||||
"gl_proc_table.cc",
|
||||
"gl_proc_table.h",
|
||||
"keyboard_handler_base.h",
|
||||
"keyboard_key_channel_handler.cc",
|
||||
"keyboard_key_channel_handler.h",
|
||||
@@ -202,14 +202,14 @@ executable("flutter_windows_unittests") {
|
||||
"settings_plugin_unittests.cc",
|
||||
"system_utils_unittests.cc",
|
||||
"task_runner_unittests.cc",
|
||||
"testing/egl/mock_manager.h",
|
||||
"testing/egl/mock_proc_table.h",
|
||||
"testing/engine_modifier.h",
|
||||
"testing/flutter_window_test.cc",
|
||||
"testing/flutter_window_test.h",
|
||||
"testing/flutter_windows_engine_builder.cc",
|
||||
"testing/flutter_windows_engine_builder.h",
|
||||
"testing/mock_angle_surface_manager.h",
|
||||
"testing/mock_direct_manipulation.h",
|
||||
"testing/mock_gl_proc_table.h",
|
||||
"testing/mock_text_input_manager.cc",
|
||||
"testing/mock_text_input_manager.h",
|
||||
"testing/mock_window.cc",
|
||||
|
||||
@@ -128,7 +128,7 @@ bool CompositorOpenGL::Present(const FlutterLayer** layers,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!engine_->surface_manager()->MakeCurrent()) {
|
||||
if (!engine_->egl_manager()->MakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ bool CompositorOpenGL::Present(const FlutterLayer** layers,
|
||||
GL_NEAREST // filter
|
||||
);
|
||||
|
||||
if (!engine_->surface_manager()->SwapBuffers()) {
|
||||
if (!engine_->egl_manager()->SwapBuffers()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ bool CompositorOpenGL::Present(const FlutterLayer** layers,
|
||||
bool CompositorOpenGL::Initialize() {
|
||||
FML_DCHECK(!is_initialized_);
|
||||
|
||||
if (!engine_->surface_manager()->MakeCurrent()) {
|
||||
if (!engine_->egl_manager()->MakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -186,14 +186,14 @@ bool CompositorOpenGL::ClearSurface() {
|
||||
// Resize the surface if needed.
|
||||
engine_->view()->OnEmptyFrameGenerated();
|
||||
|
||||
if (!engine_->surface_manager()->MakeCurrent()) {
|
||||
if (!engine_->egl_manager()->MakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gl_->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
if (!engine_->surface_manager()->SwapBuffers()) {
|
||||
if (!engine_->egl_manager()->SwapBuffers()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/impeller/renderer/backend/gles/gles.h"
|
||||
#include "flutter/shell/platform/windows/angle_surface_manager.h"
|
||||
#include "flutter/shell/platform/windows/compositor_opengl.h"
|
||||
#include "flutter/shell/platform/windows/egl/manager.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_view.h"
|
||||
#include "flutter/shell/platform/windows/testing/egl/mock_manager.h"
|
||||
#include "flutter/shell/platform/windows/testing/engine_modifier.h"
|
||||
#include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h"
|
||||
#include "flutter/shell/platform/windows/testing/mock_angle_surface_manager.h"
|
||||
#include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
|
||||
#include "flutter/shell/platform/windows/testing/windows_test.h"
|
||||
#include "gmock/gmock.h"
|
||||
@@ -64,17 +64,17 @@ class CompositorOpenGLTest : public WindowsTest {
|
||||
|
||||
protected:
|
||||
FlutterWindowsEngine* engine() { return engine_.get(); }
|
||||
MockAngleSurfaceManager* surface_manager() { return surface_manager_; }
|
||||
egl::MockManager* egl_manager() { return egl_manager_; }
|
||||
|
||||
void UseHeadlessEngine() {
|
||||
auto surface_manager = std::make_unique<MockAngleSurfaceManager>();
|
||||
surface_manager_ = surface_manager.get();
|
||||
auto egl_manager = std::make_unique<egl::MockManager>();
|
||||
egl_manager_ = egl_manager.get();
|
||||
|
||||
FlutterWindowsEngineBuilder builder{GetContext()};
|
||||
|
||||
engine_ = builder.Build();
|
||||
EngineModifier modifier(engine_.get());
|
||||
modifier.SetSurfaceManager(std::move(surface_manager));
|
||||
modifier.SetEGLManager(std::move(egl_manager));
|
||||
}
|
||||
|
||||
void UseEngineWithView() {
|
||||
@@ -92,7 +92,7 @@ class CompositorOpenGLTest : public WindowsTest {
|
||||
private:
|
||||
std::unique_ptr<FlutterWindowsEngine> engine_;
|
||||
std::unique_ptr<FlutterWindowsView> view_;
|
||||
MockAngleSurfaceManager* surface_manager_;
|
||||
egl::MockManager* egl_manager_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(CompositorOpenGLTest);
|
||||
};
|
||||
@@ -107,7 +107,7 @@ TEST_F(CompositorOpenGLTest, CreateBackingStore) {
|
||||
FlutterBackingStoreConfig config = {};
|
||||
FlutterBackingStore backing_store = {};
|
||||
|
||||
EXPECT_CALL(*surface_manager(), MakeCurrent).WillOnce(Return(true));
|
||||
EXPECT_CALL(*egl_manager(), MakeCurrent).WillOnce(Return(true));
|
||||
ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
|
||||
ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
|
||||
}
|
||||
@@ -120,7 +120,7 @@ TEST_F(CompositorOpenGLTest, InitializationFailure) {
|
||||
FlutterBackingStoreConfig config = {};
|
||||
FlutterBackingStore backing_store = {};
|
||||
|
||||
EXPECT_CALL(*surface_manager(), MakeCurrent).WillOnce(Return(false));
|
||||
EXPECT_CALL(*egl_manager(), MakeCurrent).WillOnce(Return(false));
|
||||
EXPECT_FALSE(compositor.CreateBackingStore(config, &backing_store));
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ TEST_F(CompositorOpenGLTest, Present) {
|
||||
FlutterBackingStoreConfig config = {};
|
||||
FlutterBackingStore backing_store = {};
|
||||
|
||||
EXPECT_CALL(*surface_manager(), MakeCurrent).WillOnce(Return(true));
|
||||
EXPECT_CALL(*egl_manager(), MakeCurrent).WillOnce(Return(true));
|
||||
ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
|
||||
|
||||
FlutterLayer layer = {};
|
||||
@@ -140,8 +140,8 @@ TEST_F(CompositorOpenGLTest, Present) {
|
||||
layer.backing_store = &backing_store;
|
||||
const FlutterLayer* layer_ptr = &layer;
|
||||
|
||||
EXPECT_CALL(*surface_manager(), MakeCurrent).WillOnce(Return(true));
|
||||
EXPECT_CALL(*surface_manager(), SwapBuffers).WillOnce(Return(true));
|
||||
EXPECT_CALL(*egl_manager(), MakeCurrent).WillOnce(Return(true));
|
||||
EXPECT_CALL(*egl_manager(), SwapBuffers).WillOnce(Return(true));
|
||||
EXPECT_TRUE(compositor.Present(&layer_ptr, 1));
|
||||
|
||||
ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
|
||||
@@ -154,10 +154,10 @@ TEST_F(CompositorOpenGLTest, PresentEmpty) {
|
||||
|
||||
// The context will be bound twice: first to initialize the compositor, second
|
||||
// to clear the surface.
|
||||
EXPECT_CALL(*surface_manager(), MakeCurrent)
|
||||
EXPECT_CALL(*egl_manager(), MakeCurrent)
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(*surface_manager(), SwapBuffers).WillOnce(Return(true));
|
||||
EXPECT_CALL(*egl_manager(), SwapBuffers).WillOnce(Return(true));
|
||||
EXPECT_TRUE(compositor.Present(nullptr, 0));
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ TEST_F(CompositorOpenGLTest, HeadlessPresentIgnored) {
|
||||
FlutterBackingStoreConfig config = {};
|
||||
FlutterBackingStore backing_store = {};
|
||||
|
||||
EXPECT_CALL(*surface_manager(), MakeCurrent).WillOnce(Return(true));
|
||||
EXPECT_CALL(*egl_manager(), MakeCurrent).WillOnce(Return(true));
|
||||
ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
|
||||
|
||||
FlutterLayer layer = {};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/platform/windows/angle_surface_manager.h"
|
||||
#include "flutter/shell/platform/windows/egl/manager.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -17,20 +17,20 @@ static void LogEglError(std::string message) {
|
||||
}
|
||||
|
||||
namespace flutter {
|
||||
namespace egl {
|
||||
|
||||
int AngleSurfaceManager::instance_count_ = 0;
|
||||
int Manager::instance_count_ = 0;
|
||||
|
||||
std::unique_ptr<AngleSurfaceManager> AngleSurfaceManager::Create(
|
||||
bool enable_impeller) {
|
||||
std::unique_ptr<AngleSurfaceManager> manager;
|
||||
manager.reset(new AngleSurfaceManager(enable_impeller));
|
||||
std::unique_ptr<Manager> Manager::Create(bool enable_impeller) {
|
||||
std::unique_ptr<Manager> manager;
|
||||
manager.reset(new Manager(enable_impeller));
|
||||
if (!manager->IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::move(manager);
|
||||
}
|
||||
|
||||
AngleSurfaceManager::AngleSurfaceManager(bool enable_impeller) {
|
||||
Manager::Manager(bool enable_impeller) {
|
||||
++instance_count_;
|
||||
|
||||
if (!InitializeDisplay()) {
|
||||
@@ -48,12 +48,12 @@ AngleSurfaceManager::AngleSurfaceManager(bool enable_impeller) {
|
||||
is_valid_ = true;
|
||||
}
|
||||
|
||||
AngleSurfaceManager::~AngleSurfaceManager() {
|
||||
Manager::~Manager() {
|
||||
CleanUp();
|
||||
--instance_count_;
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::InitializeDisplay() {
|
||||
bool Manager::InitializeDisplay() {
|
||||
// These are preferred display attributes and request ANGLE's D3D11
|
||||
// renderer. eglInitialize will only succeed with these attributes if the
|
||||
// hardware supports D3D11 Feature Level 10_0+.
|
||||
@@ -147,7 +147,7 @@ bool AngleSurfaceManager::InitializeDisplay() {
|
||||
FML_UNREACHABLE();
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::InitializeConfig(bool enable_impeller) {
|
||||
bool Manager::InitializeConfig(bool enable_impeller) {
|
||||
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,
|
||||
@@ -193,7 +193,7 @@ bool AngleSurfaceManager::InitializeConfig(bool enable_impeller) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::InitializeContexts() {
|
||||
bool Manager::InitializeContexts() {
|
||||
const EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
|
||||
render_context_ =
|
||||
@@ -213,7 +213,7 @@ bool AngleSurfaceManager::InitializeContexts() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::InitializeDevice() {
|
||||
bool Manager::InitializeDevice() {
|
||||
const auto query_display_attrib_EXT =
|
||||
reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(
|
||||
::eglGetProcAddress("eglQueryDisplayAttribEXT"));
|
||||
@@ -244,7 +244,7 @@ bool AngleSurfaceManager::InitializeDevice() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void AngleSurfaceManager::CleanUp() {
|
||||
void Manager::CleanUp() {
|
||||
EGLBoolean result = EGL_FALSE;
|
||||
|
||||
// Needs to be reset before destroying the EGLContext.
|
||||
@@ -278,13 +278,11 @@ void AngleSurfaceManager::CleanUp() {
|
||||
}
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::IsValid() const {
|
||||
bool Manager::IsValid() const {
|
||||
return is_valid_;
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::CreateSurface(HWND hwnd,
|
||||
EGLint width,
|
||||
EGLint height) {
|
||||
bool Manager::CreateSurface(HWND hwnd, EGLint width, EGLint height) {
|
||||
if (!hwnd || !is_valid_) {
|
||||
return false;
|
||||
}
|
||||
@@ -312,10 +310,10 @@ bool AngleSurfaceManager::CreateSurface(HWND hwnd,
|
||||
return true;
|
||||
}
|
||||
|
||||
void AngleSurfaceManager::ResizeSurface(HWND hwnd,
|
||||
EGLint width,
|
||||
EGLint height,
|
||||
bool vsync_enabled) {
|
||||
void Manager::ResizeSurface(HWND hwnd,
|
||||
EGLint width,
|
||||
EGLint height,
|
||||
bool vsync_enabled) {
|
||||
EGLint existing_width, existing_height;
|
||||
GetSurfaceDimensions(&existing_width, &existing_height);
|
||||
if (width != existing_width || height != existing_height) {
|
||||
@@ -328,15 +326,14 @@ void AngleSurfaceManager::ResizeSurface(HWND hwnd,
|
||||
ClearContext();
|
||||
DestroySurface();
|
||||
if (!CreateSurface(hwnd, width, height)) {
|
||||
FML_LOG(ERROR)
|
||||
<< "AngleSurfaceManager::ResizeSurface failed to create surface";
|
||||
FML_LOG(ERROR) << "Manager::ResizeSurface failed to create surface";
|
||||
}
|
||||
}
|
||||
|
||||
SetVSyncEnabled(vsync_enabled);
|
||||
}
|
||||
|
||||
void AngleSurfaceManager::GetSurfaceDimensions(EGLint* width, EGLint* height) {
|
||||
void Manager::GetSurfaceDimensions(EGLint* width, EGLint* height) {
|
||||
if (surface_ == EGL_NO_SURFACE || !is_valid_) {
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
@@ -351,50 +348,49 @@ void AngleSurfaceManager::GetSurfaceDimensions(EGLint* width, EGLint* height) {
|
||||
*height = surface_height_;
|
||||
}
|
||||
|
||||
void AngleSurfaceManager::DestroySurface() {
|
||||
void Manager::DestroySurface() {
|
||||
if (display_ != EGL_NO_DISPLAY && surface_ != EGL_NO_SURFACE) {
|
||||
::eglDestroySurface(display_, surface_);
|
||||
}
|
||||
surface_ = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::HasContextCurrent() {
|
||||
bool Manager::HasContextCurrent() {
|
||||
return ::eglGetCurrentContext() != EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::MakeCurrent() {
|
||||
bool Manager::MakeCurrent() {
|
||||
return (::eglMakeCurrent(display_, surface_, surface_, render_context_) ==
|
||||
EGL_TRUE);
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::ClearCurrent() {
|
||||
bool Manager::ClearCurrent() {
|
||||
return (::eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT) == EGL_TRUE);
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::ClearContext() {
|
||||
bool Manager::ClearContext() {
|
||||
return (::eglMakeCurrent(display_, nullptr, nullptr, render_context_) ==
|
||||
EGL_TRUE);
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::MakeResourceCurrent() {
|
||||
bool Manager::MakeResourceCurrent() {
|
||||
return (::eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
resource_context_) == EGL_TRUE);
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::SwapBuffers() {
|
||||
bool Manager::SwapBuffers() {
|
||||
return (::eglSwapBuffers(display_, surface_));
|
||||
}
|
||||
|
||||
EGLSurface AngleSurfaceManager::CreateSurfaceFromHandle(
|
||||
EGLenum handle_type,
|
||||
EGLClientBuffer handle,
|
||||
const EGLint* attributes) const {
|
||||
EGLSurface Manager::CreateSurfaceFromHandle(EGLenum handle_type,
|
||||
EGLClientBuffer handle,
|
||||
const EGLint* attributes) const {
|
||||
return ::eglCreatePbufferFromClientBuffer(display_, handle_type, handle,
|
||||
config_, attributes);
|
||||
}
|
||||
|
||||
void AngleSurfaceManager::SetVSyncEnabled(bool enabled) {
|
||||
void Manager::SetVSyncEnabled(bool enabled) {
|
||||
if (!MakeCurrent()) {
|
||||
LogEglError("Unable to make surface current to update the swap interval");
|
||||
return;
|
||||
@@ -411,7 +407,7 @@ void AngleSurfaceManager::SetVSyncEnabled(bool enabled) {
|
||||
}
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::GetDevice(ID3D11Device** device) {
|
||||
bool Manager::GetDevice(ID3D11Device** device) {
|
||||
if (!resolved_device_) {
|
||||
if (!InitializeDevice()) {
|
||||
return false;
|
||||
@@ -422,4 +418,5 @@ bool AngleSurfaceManager::GetDevice(ID3D11Device** device) {
|
||||
return (resolved_device_ != nullptr);
|
||||
}
|
||||
|
||||
} // namespace egl
|
||||
} // namespace flutter
|
||||
@@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_ANGLE_SURFACE_MANAGER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_ANGLE_SURFACE_MANAGER_H_
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_EGL_MANAGER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_EGL_MANAGER_H_
|
||||
|
||||
// OpenGL ES and EGL includes
|
||||
#include <EGL/egl.h>
|
||||
@@ -19,17 +19,17 @@
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/platform/windows/window_binding_handler.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace egl {
|
||||
|
||||
// A manager for initializing ANGLE correctly and using it to create and
|
||||
// destroy surfaces
|
||||
class AngleSurfaceManager {
|
||||
class Manager {
|
||||
public:
|
||||
static std::unique_ptr<AngleSurfaceManager> Create(bool enable_impeller);
|
||||
static std::unique_ptr<Manager> Create(bool enable_impeller);
|
||||
|
||||
virtual ~AngleSurfaceManager();
|
||||
virtual ~Manager();
|
||||
|
||||
// Whether the manager is currently valid.
|
||||
bool IsValid() const;
|
||||
@@ -106,10 +106,10 @@ class AngleSurfaceManager {
|
||||
protected:
|
||||
// Creates a new surface manager retaining reference to the passed-in target
|
||||
// for the lifetime of the manager.
|
||||
explicit AngleSurfaceManager(bool enable_impeller);
|
||||
explicit Manager(bool enable_impeller);
|
||||
|
||||
private:
|
||||
// Number of active instances of AngleSurfaceManager
|
||||
// Number of active instances of Manager
|
||||
static int instance_count_;
|
||||
|
||||
// Initialize the EGL display.
|
||||
@@ -152,9 +152,10 @@ class AngleSurfaceManager {
|
||||
// The current D3D device.
|
||||
Microsoft::WRL::ComPtr<ID3D11Device> resolved_device_ = nullptr;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(AngleSurfaceManager);
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(Manager);
|
||||
};
|
||||
|
||||
} // namespace egl
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_ANGLE_SURFACE_MANAGER_H_
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_EGL_MANAGER_H_
|
||||
@@ -2,14 +2,15 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/platform/windows/gl_proc_table.h"
|
||||
#include "flutter/shell/platform/windows/egl/proc_table.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
namespace flutter {
|
||||
namespace egl {
|
||||
|
||||
std::shared_ptr<GlProcTable> GlProcTable::Create() {
|
||||
auto gl = std::shared_ptr<GlProcTable>(new GlProcTable());
|
||||
std::shared_ptr<ProcTable> ProcTable::Create() {
|
||||
auto gl = std::shared_ptr<ProcTable>(new ProcTable());
|
||||
|
||||
gl->gen_textures_ =
|
||||
reinterpret_cast<GenTexturesProc>(::eglGetProcAddress("glGenTextures"));
|
||||
@@ -30,39 +31,38 @@ std::shared_ptr<GlProcTable> GlProcTable::Create() {
|
||||
return gl;
|
||||
}
|
||||
|
||||
GlProcTable::GlProcTable() = default;
|
||||
ProcTable::ProcTable() = default;
|
||||
|
||||
GlProcTable::~GlProcTable() = default;
|
||||
ProcTable::~ProcTable() = default;
|
||||
|
||||
void GlProcTable::GenTextures(GLsizei n, GLuint* textures) const {
|
||||
void ProcTable::GenTextures(GLsizei n, GLuint* textures) const {
|
||||
gen_textures_(n, textures);
|
||||
}
|
||||
|
||||
void GlProcTable::DeleteTextures(GLsizei n, const GLuint* textures) const {
|
||||
void ProcTable::DeleteTextures(GLsizei n, const GLuint* textures) const {
|
||||
delete_textures_(n, textures);
|
||||
}
|
||||
|
||||
void GlProcTable::BindTexture(GLenum target, GLuint texture) const {
|
||||
void ProcTable::BindTexture(GLenum target, GLuint texture) const {
|
||||
bind_texture_(target, texture);
|
||||
}
|
||||
|
||||
void GlProcTable::TexParameteri(GLenum target,
|
||||
GLenum pname,
|
||||
GLint param) const {
|
||||
void ProcTable::TexParameteri(GLenum target, GLenum pname, GLint param) const {
|
||||
tex_parameteri_(target, pname, param);
|
||||
}
|
||||
|
||||
void GlProcTable::TexImage2D(GLenum target,
|
||||
GLint level,
|
||||
GLint internalformat,
|
||||
GLsizei width,
|
||||
GLsizei height,
|
||||
GLint border,
|
||||
GLenum format,
|
||||
GLenum type,
|
||||
const void* data) const {
|
||||
void ProcTable::TexImage2D(GLenum target,
|
||||
GLint level,
|
||||
GLint internalformat,
|
||||
GLsizei width,
|
||||
GLsizei height,
|
||||
GLint border,
|
||||
GLenum format,
|
||||
GLenum type,
|
||||
const void* data) const {
|
||||
tex_image_2d_(target, level, internalformat, width, height, border, format,
|
||||
type, data);
|
||||
}
|
||||
|
||||
} // namespace egl
|
||||
} // namespace flutter
|
||||
@@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_GL_PROC_TABLE_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_GL_PROC_TABLE_H_
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_EGL_PROC_TABLE_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_EGL_PROC_TABLE_H_
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
@@ -13,13 +13,14 @@
|
||||
#include "flutter/fml/macros.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace egl {
|
||||
|
||||
// Lookup table for GLES functions.
|
||||
class GlProcTable {
|
||||
class ProcTable {
|
||||
public:
|
||||
static std::shared_ptr<GlProcTable> Create();
|
||||
static std::shared_ptr<ProcTable> Create();
|
||||
|
||||
virtual ~GlProcTable();
|
||||
virtual ~ProcTable();
|
||||
|
||||
virtual void GenTextures(GLsizei n, GLuint* textures) const;
|
||||
virtual void DeleteTextures(GLsizei n, const GLuint* textures) const;
|
||||
@@ -36,7 +37,7 @@ class GlProcTable {
|
||||
const void* data) const;
|
||||
|
||||
protected:
|
||||
GlProcTable();
|
||||
ProcTable();
|
||||
|
||||
private:
|
||||
using GenTexturesProc = void(__stdcall*)(GLsizei n, GLuint* textures);
|
||||
@@ -62,9 +63,10 @@ class GlProcTable {
|
||||
TexParameteriProc tex_parameteri_;
|
||||
TexImage2DProc tex_image_2d_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(GlProcTable);
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(ProcTable);
|
||||
};
|
||||
|
||||
} // namespace egl
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_GL_PROC_TABLE_H_
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_EGL_PROC_TABLE_H_
|
||||
@@ -13,12 +13,12 @@ ExternalTextureD3d::ExternalTextureD3d(
|
||||
FlutterDesktopGpuSurfaceType type,
|
||||
const FlutterDesktopGpuSurfaceTextureCallback texture_callback,
|
||||
void* user_data,
|
||||
const AngleSurfaceManager* surface_manager,
|
||||
std::shared_ptr<GlProcTable> gl)
|
||||
const egl::Manager* egl_manager,
|
||||
std::shared_ptr<egl::ProcTable> gl)
|
||||
: type_(type),
|
||||
texture_callback_(texture_callback),
|
||||
user_data_(user_data),
|
||||
surface_manager_(surface_manager),
|
||||
egl_manager_(egl_manager),
|
||||
gl_(std::move(gl)) {}
|
||||
|
||||
ExternalTextureD3d::~ExternalTextureD3d() {
|
||||
@@ -53,9 +53,9 @@ bool ExternalTextureD3d::PopulateTexture(size_t width,
|
||||
|
||||
void ExternalTextureD3d::ReleaseImage() {
|
||||
if (egl_surface_ != EGL_NO_SURFACE) {
|
||||
eglReleaseTexImage(surface_manager_->egl_display(), egl_surface_,
|
||||
eglReleaseTexImage(egl_manager_->egl_display(), egl_surface_,
|
||||
EGL_BACK_BUFFER);
|
||||
eglDestroySurface(surface_manager_->egl_display(), egl_surface_);
|
||||
eglDestroySurface(egl_manager_->egl_display(), egl_surface_);
|
||||
egl_surface_ = EGL_NO_SURFACE;
|
||||
}
|
||||
}
|
||||
@@ -95,14 +95,14 @@ bool ExternalTextureD3d::CreateOrUpdateTexture(
|
||||
EGL_TEXTURE_RGBA, // always EGL_TEXTURE_RGBA
|
||||
EGL_NONE};
|
||||
|
||||
egl_surface_ = surface_manager_->CreateSurfaceFromHandle(
|
||||
egl_surface_ = egl_manager_->CreateSurfaceFromHandle(
|
||||
(type_ == kFlutterDesktopGpuSurfaceTypeD3d11Texture2D)
|
||||
? EGL_D3D_TEXTURE_ANGLE
|
||||
: EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
|
||||
handle, attributes);
|
||||
|
||||
if (egl_surface_ == EGL_NO_SURFACE ||
|
||||
eglBindTexImage(surface_manager_->egl_display(), egl_surface_,
|
||||
eglBindTexImage(egl_manager_->egl_display(), egl_surface_,
|
||||
EGL_BACK_BUFFER) == EGL_FALSE) {
|
||||
FML_LOG(ERROR) << "Binding D3D surface failed.";
|
||||
}
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/platform/windows/angle_surface_manager.h"
|
||||
#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
|
||||
#include "flutter/shell/platform/windows/egl/manager.h"
|
||||
#include "flutter/shell/platform/windows/egl/proc_table.h"
|
||||
#include "flutter/shell/platform/windows/external_texture.h"
|
||||
#include "flutter/shell/platform/windows/gl_proc_table.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@@ -21,8 +22,8 @@ class ExternalTextureD3d : public ExternalTexture {
|
||||
FlutterDesktopGpuSurfaceType type,
|
||||
const FlutterDesktopGpuSurfaceTextureCallback texture_callback,
|
||||
void* user_data,
|
||||
const AngleSurfaceManager* surface_manager,
|
||||
std::shared_ptr<GlProcTable> gl);
|
||||
const egl::Manager* egl_manager,
|
||||
std::shared_ptr<egl::ProcTable> gl);
|
||||
virtual ~ExternalTextureD3d();
|
||||
|
||||
// |ExternalTexture|
|
||||
@@ -41,8 +42,8 @@ class ExternalTextureD3d : public ExternalTexture {
|
||||
FlutterDesktopGpuSurfaceType type_;
|
||||
const FlutterDesktopGpuSurfaceTextureCallback texture_callback_;
|
||||
void* const user_data_;
|
||||
const AngleSurfaceManager* surface_manager_;
|
||||
std::shared_ptr<GlProcTable> gl_;
|
||||
const egl::Manager* egl_manager_;
|
||||
std::shared_ptr<egl::ProcTable> gl_;
|
||||
GLuint gl_texture_ = 0;
|
||||
EGLSurface egl_surface_ = EGL_NO_SURFACE;
|
||||
void* last_surface_handle_ = nullptr;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace flutter {
|
||||
ExternalTexturePixelBuffer::ExternalTexturePixelBuffer(
|
||||
const FlutterDesktopPixelBufferTextureCallback texture_callback,
|
||||
void* user_data,
|
||||
std::shared_ptr<GlProcTable> gl)
|
||||
std::shared_ptr<egl::ProcTable> gl)
|
||||
: texture_callback_(texture_callback),
|
||||
user_data_(user_data),
|
||||
gl_(std::move(gl)) {}
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
|
||||
#include "flutter/shell/platform/windows/egl/proc_table.h"
|
||||
#include "flutter/shell/platform/windows/external_texture.h"
|
||||
#include "flutter/shell/platform/windows/gl_proc_table.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@@ -18,7 +18,7 @@ class ExternalTexturePixelBuffer : public ExternalTexture {
|
||||
ExternalTexturePixelBuffer(
|
||||
const FlutterDesktopPixelBufferTextureCallback texture_callback,
|
||||
void* user_data,
|
||||
std::shared_ptr<GlProcTable> gl);
|
||||
std::shared_ptr<egl::ProcTable> gl);
|
||||
|
||||
virtual ~ExternalTexturePixelBuffer();
|
||||
|
||||
@@ -38,7 +38,7 @@ class ExternalTexturePixelBuffer : public ExternalTexture {
|
||||
|
||||
const FlutterDesktopPixelBufferTextureCallback texture_callback_ = nullptr;
|
||||
void* const user_data_ = nullptr;
|
||||
std::shared_ptr<GlProcTable> gl_;
|
||||
std::shared_ptr<egl::ProcTable> gl_;
|
||||
GLuint gl_texture_ = 0;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(ExternalTexturePixelBuffer);
|
||||
|
||||
@@ -215,11 +215,11 @@ HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view) {
|
||||
}
|
||||
|
||||
IDXGIAdapter* FlutterDesktopViewGetGraphicsAdapter(FlutterDesktopViewRef view) {
|
||||
auto surface_manager = ViewFromHandle(view)->GetEngine()->surface_manager();
|
||||
if (surface_manager) {
|
||||
auto egl_manager = ViewFromHandle(view)->GetEngine()->egl_manager();
|
||||
if (egl_manager) {
|
||||
Microsoft::WRL::ComPtr<ID3D11Device> d3d_device;
|
||||
Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device;
|
||||
if (surface_manager->GetDevice(d3d_device.GetAddressOf()) &&
|
||||
if (egl_manager->GetDevice(d3d_device.GetAddressOf()) &&
|
||||
SUCCEEDED(d3d_device.As(&dxgi_device))) {
|
||||
IDXGIAdapter* adapter;
|
||||
if (SUCCEEDED(dxgi_device->GetAdapter(&adapter))) {
|
||||
|
||||
@@ -55,17 +55,17 @@ FlutterRendererConfig GetOpenGLRendererConfig() {
|
||||
config.open_gl.struct_size = sizeof(config.open_gl);
|
||||
config.open_gl.make_current = [](void* user_data) -> bool {
|
||||
auto host = static_cast<FlutterWindowsEngine*>(user_data);
|
||||
if (!host->surface_manager()) {
|
||||
if (!host->egl_manager()) {
|
||||
return false;
|
||||
}
|
||||
return host->surface_manager()->MakeCurrent();
|
||||
return host->egl_manager()->MakeCurrent();
|
||||
};
|
||||
config.open_gl.clear_current = [](void* user_data) -> bool {
|
||||
auto host = static_cast<FlutterWindowsEngine*>(user_data);
|
||||
if (!host->surface_manager()) {
|
||||
if (!host->egl_manager()) {
|
||||
return false;
|
||||
}
|
||||
return host->surface_manager()->ClearContext();
|
||||
return host->egl_manager()->ClearContext();
|
||||
};
|
||||
config.open_gl.present = [](void* user_data) -> bool { FML_UNREACHABLE(); };
|
||||
config.open_gl.fbo_reset_after_present = true;
|
||||
@@ -79,10 +79,10 @@ FlutterRendererConfig GetOpenGLRendererConfig() {
|
||||
};
|
||||
config.open_gl.make_resource_current = [](void* user_data) -> bool {
|
||||
auto host = static_cast<FlutterWindowsEngine*>(user_data);
|
||||
if (!host->surface_manager()) {
|
||||
if (!host->egl_manager()) {
|
||||
return false;
|
||||
}
|
||||
return host->surface_manager()->MakeResourceCurrent();
|
||||
return host->egl_manager()->MakeResourceCurrent();
|
||||
};
|
||||
config.open_gl.gl_external_texture_frame_callback =
|
||||
[](void* user_data, int64_t texture_id, size_t width, size_t height,
|
||||
@@ -154,7 +154,7 @@ FlutterWindowsEngine::FlutterWindowsEngine(
|
||||
windows_proc_table_ = std::make_shared<WindowsProcTable>();
|
||||
}
|
||||
|
||||
gl_ = GlProcTable::Create();
|
||||
gl_ = egl::ProcTable::Create();
|
||||
|
||||
embedder_api_.struct_size = sizeof(FlutterEngineProcTable);
|
||||
FlutterEngineGetProcAddresses(&embedder_api_);
|
||||
@@ -200,7 +200,7 @@ FlutterWindowsEngine::FlutterWindowsEngine(
|
||||
enable_impeller_ = std::find(switches.begin(), switches.end(),
|
||||
"--enable-impeller=true") != switches.end();
|
||||
|
||||
surface_manager_ = AngleSurfaceManager::Create(enable_impeller_);
|
||||
egl_manager_ = egl::Manager::Create(enable_impeller_);
|
||||
window_proc_delegate_manager_ = std::make_unique<WindowProcDelegateManager>();
|
||||
window_proc_delegate_manager_->RegisterTopLevelWindowProcDelegate(
|
||||
[](HWND hwnd, UINT msg, WPARAM wpar, LPARAM lpar, void* user_data,
|
||||
@@ -380,7 +380,7 @@ bool FlutterWindowsEngine::Run(std::string_view entrypoint) {
|
||||
|
||||
args.custom_task_runners = &custom_task_runners;
|
||||
|
||||
if (surface_manager_) {
|
||||
if (egl_manager_) {
|
||||
auto resolver = [](const char* name) -> void* {
|
||||
return reinterpret_cast<void*>(::eglGetProcAddress(name));
|
||||
};
|
||||
@@ -423,22 +423,22 @@ bool FlutterWindowsEngine::Run(std::string_view entrypoint) {
|
||||
|
||||
// The platform thread creates OpenGL contexts. These
|
||||
// must be released to be used by the engine's threads.
|
||||
FML_DCHECK(!surface_manager_ || !surface_manager_->HasContextCurrent());
|
||||
FML_DCHECK(!egl_manager_ || !egl_manager_->HasContextCurrent());
|
||||
|
||||
FlutterRendererConfig renderer_config;
|
||||
|
||||
if (enable_impeller_) {
|
||||
// Impeller does not support a Software backend. Avoid falling back and
|
||||
// confusing the engine on which renderer is selected.
|
||||
if (!surface_manager_) {
|
||||
if (!egl_manager_) {
|
||||
FML_LOG(ERROR) << "Could not create surface manager. Impeller backend "
|
||||
"does not support software rendering.";
|
||||
return false;
|
||||
}
|
||||
renderer_config = GetOpenGLRendererConfig();
|
||||
} else {
|
||||
renderer_config = surface_manager_ ? GetOpenGLRendererConfig()
|
||||
: GetSoftwareRendererConfig();
|
||||
renderer_config =
|
||||
egl_manager_ ? GetOpenGLRendererConfig() : GetSoftwareRendererConfig();
|
||||
}
|
||||
|
||||
auto result = embedder_api_.Run(FLUTTER_ENGINE_VERSION, &renderer_config,
|
||||
|
||||
@@ -22,9 +22,10 @@
|
||||
#include "flutter/shell/platform/common/incoming_message_dispatcher.h"
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
#include "flutter/shell/platform/windows/accessibility_bridge_windows.h"
|
||||
#include "flutter/shell/platform/windows/angle_surface_manager.h"
|
||||
#include "flutter/shell/platform/windows/compositor.h"
|
||||
#include "flutter/shell/platform/windows/cursor_handler.h"
|
||||
#include "flutter/shell/platform/windows/egl/manager.h"
|
||||
#include "flutter/shell/platform/windows/egl/proc_table.h"
|
||||
#include "flutter/shell/platform/windows/flutter_desktop_messenger.h"
|
||||
#include "flutter/shell/platform/windows/flutter_project_bundle.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h"
|
||||
@@ -140,11 +141,9 @@ class FlutterWindowsEngine {
|
||||
return texture_registrar_.get();
|
||||
}
|
||||
|
||||
// The ANGLE surface manager object. If this is nullptr, then we are
|
||||
// The EGL manager object. If this is nullptr, then we are
|
||||
// rendering using software instead of OpenGL.
|
||||
AngleSurfaceManager* surface_manager() const {
|
||||
return surface_manager_.get();
|
||||
}
|
||||
egl::Manager* egl_manager() const { return egl_manager_.get(); }
|
||||
|
||||
WindowProcDelegateManager* window_proc_delegate_manager() {
|
||||
return window_proc_delegate_manager_.get();
|
||||
@@ -363,10 +362,10 @@ class FlutterWindowsEngine {
|
||||
// The texture registrar.
|
||||
std::unique_ptr<FlutterWindowsTextureRegistrar> texture_registrar_;
|
||||
|
||||
// An object used for intializing Angle and creating / destroying render
|
||||
// surfaces. Surface creation functionality requires a valid render_target.
|
||||
// May be nullptr if ANGLE failed to initialize.
|
||||
std::unique_ptr<AngleSurfaceManager> surface_manager_;
|
||||
// An object used for intializing ANGLE and creating / destroying render
|
||||
// surfaces. If nullptr, ANGLE failed to initialize and software rendering
|
||||
// should be used instead.
|
||||
std::unique_ptr<egl::Manager> egl_manager_;
|
||||
|
||||
// The compositor that creates backing stores for the engine to render into
|
||||
// and then presents them onto views.
|
||||
@@ -426,7 +425,7 @@ class FlutterWindowsEngine {
|
||||
|
||||
std::shared_ptr<WindowsProcTable> windows_proc_table_;
|
||||
|
||||
std::shared_ptr<GlProcTable> gl_;
|
||||
std::shared_ptr<egl::ProcTable> gl_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsEngine);
|
||||
};
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_view.h"
|
||||
#include "flutter/shell/platform/windows/public/flutter_windows.h"
|
||||
#include "flutter/shell/platform/windows/testing/egl/mock_manager.h"
|
||||
#include "flutter/shell/platform/windows/testing/engine_modifier.h"
|
||||
#include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h"
|
||||
#include "flutter/shell/platform/windows/testing/mock_angle_surface_manager.h"
|
||||
#include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
|
||||
#include "flutter/shell/platform/windows/testing/mock_windows_proc_table.h"
|
||||
#include "flutter/shell/platform/windows/testing/test_keyboard.h"
|
||||
@@ -51,7 +51,7 @@ TEST_F(FlutterWindowsEngineTest, RunDoesExpectedInitialization) {
|
||||
|
||||
EXPECT_EQ(version, FLUTTER_ENGINE_VERSION);
|
||||
EXPECT_NE(config, nullptr);
|
||||
// We have an AngleSurfaceManager, so this should be using OpenGL.
|
||||
// We have an EGL manager, so this should be using OpenGL.
|
||||
EXPECT_EQ(config->type, kOpenGL);
|
||||
EXPECT_EQ(user_data, engine_instance);
|
||||
// Spot-check arguments.
|
||||
@@ -131,8 +131,8 @@ TEST_F(FlutterWindowsEngineTest, RunDoesExpectedInitialization) {
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
// Set the AngleSurfaceManager to !nullptr to test ANGLE rendering.
|
||||
modifier.SetSurfaceManager(std::make_unique<MockAngleSurfaceManager>());
|
||||
// Set the EGL manager to !nullptr to test ANGLE rendering.
|
||||
modifier.SetEGLManager(std::make_unique<egl::MockManager>());
|
||||
|
||||
engine->Run();
|
||||
|
||||
@@ -144,7 +144,7 @@ TEST_F(FlutterWindowsEngineTest, RunDoesExpectedInitialization) {
|
||||
// Ensure that deallocation doesn't call the actual Shutdown with the bogus
|
||||
// engine pointer that the overridden Run returned.
|
||||
modifier.embedder_api().Shutdown = [](auto engine) { return kSuccess; };
|
||||
modifier.ReleaseSurfaceManager();
|
||||
modifier.ReleaseEGLManager();
|
||||
}
|
||||
|
||||
TEST_F(FlutterWindowsEngineTest, ConfiguresFrameVsync) {
|
||||
@@ -196,7 +196,7 @@ TEST_F(FlutterWindowsEngineTest, RunWithoutANGLEUsesSoftware) {
|
||||
FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
|
||||
run_called = true;
|
||||
*engine_out = reinterpret_cast<FLUTTER_API_SYMBOL(FlutterEngine)>(1);
|
||||
// We don't have an AngleSurfaceManager, so we should be using software.
|
||||
// We don't have an EGL Manager, so we should be using software.
|
||||
EXPECT_EQ(config->type, kSoftware);
|
||||
return kSuccess;
|
||||
}));
|
||||
@@ -215,8 +215,8 @@ TEST_F(FlutterWindowsEngineTest, RunWithoutANGLEUsesSoftware) {
|
||||
MOCK_ENGINE_PROC(SendPlatformMessage,
|
||||
([](auto engine, auto message) { return kSuccess; }));
|
||||
|
||||
// Set the AngleSurfaceManager to nullptr to test software fallback path.
|
||||
modifier.SetSurfaceManager(nullptr);
|
||||
// Set the EGL manager to nullptr to test software fallback path.
|
||||
modifier.SetEGLManager(nullptr);
|
||||
|
||||
engine->Run();
|
||||
|
||||
@@ -256,8 +256,8 @@ TEST_F(FlutterWindowsEngineTest, RunWithoutANGLEOnImpellerFailsToStart) {
|
||||
MOCK_ENGINE_PROC(SendPlatformMessage,
|
||||
([](auto engine, auto message) { return kSuccess; }));
|
||||
|
||||
// Set the AngleSurfaceManager to nullptr to test software fallback path.
|
||||
modifier.SetSurfaceManager(nullptr);
|
||||
// Set the EGL manager to nullptr to test software fallback path.
|
||||
modifier.SetEGLManager(nullptr);
|
||||
|
||||
EXPECT_FALSE(engine->Run());
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace flutter {
|
||||
|
||||
FlutterWindowsTextureRegistrar::FlutterWindowsTextureRegistrar(
|
||||
FlutterWindowsEngine* engine,
|
||||
std::shared_ptr<GlProcTable> gl)
|
||||
std::shared_ptr<egl::ProcTable> gl)
|
||||
: engine_(engine), gl_(std::move(gl)) {}
|
||||
|
||||
int64_t FlutterWindowsTextureRegistrar::RegisterTexture(
|
||||
@@ -53,7 +53,7 @@ int64_t FlutterWindowsTextureRegistrar::RegisterTexture(
|
||||
|
||||
auto user_data = SAFE_ACCESS(gpu_surface_config, user_data, nullptr);
|
||||
return EmplaceTexture(std::make_unique<flutter::ExternalTextureD3d>(
|
||||
surface_type, callback, user_data, engine_->surface_manager(), gl_));
|
||||
surface_type, callback, user_data, engine_->egl_manager(), gl_));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#include "flutter/fml/closure.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
|
||||
#include "flutter/shell/platform/windows/egl/proc_table.h"
|
||||
#include "flutter/shell/platform/windows/external_texture.h"
|
||||
#include "flutter/shell/platform/windows/gl_proc_table.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@@ -24,7 +24,7 @@ class FlutterWindowsEngine;
|
||||
class FlutterWindowsTextureRegistrar {
|
||||
public:
|
||||
explicit FlutterWindowsTextureRegistrar(FlutterWindowsEngine* engine,
|
||||
std::shared_ptr<GlProcTable> gl);
|
||||
std::shared_ptr<egl::ProcTable> gl);
|
||||
|
||||
// Registers a texture described by the given |texture_info| object.
|
||||
// Returns the non-zero, positive texture id or -1 on error.
|
||||
@@ -47,7 +47,7 @@ class FlutterWindowsTextureRegistrar {
|
||||
|
||||
private:
|
||||
FlutterWindowsEngine* engine_ = nullptr;
|
||||
std::shared_ptr<GlProcTable> gl_;
|
||||
std::shared_ptr<egl::ProcTable> gl_;
|
||||
|
||||
// All registered textures, keyed by their IDs.
|
||||
std::unordered_map<int64_t, std::unique_ptr<flutter::ExternalTexture>>
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
|
||||
#include "flutter/fml/synchronization/waitable_event.h"
|
||||
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
|
||||
#include "flutter/shell/platform/windows/egl/proc_table.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h"
|
||||
#include "flutter/shell/platform/windows/testing/egl/mock_proc_table.h"
|
||||
#include "flutter/shell/platform/windows/testing/engine_modifier.h"
|
||||
#include "flutter/shell/platform/windows/testing/mock_gl_proc_table.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace flutter {
|
||||
@@ -42,7 +43,7 @@ ComPtr<ID3D11Texture2D> CreateD3dTexture(FlutterWindowsEngine* engine,
|
||||
UINT height) {
|
||||
ComPtr<ID3D11Device> d3d_device;
|
||||
ComPtr<ID3D11Texture2D> d3d_texture;
|
||||
if (engine->surface_manager()->GetDevice(d3d_device.GetAddressOf())) {
|
||||
if (engine->egl_manager()->GetDevice(d3d_device.GetAddressOf())) {
|
||||
D3D11_TEXTURE2D_DESC texture_description = {};
|
||||
texture_description.MipLevels = 1;
|
||||
texture_description.SampleDesc.Count = 1;
|
||||
@@ -65,7 +66,7 @@ ComPtr<ID3D11Texture2D> CreateD3dTexture(FlutterWindowsEngine* engine,
|
||||
|
||||
TEST(FlutterWindowsTextureRegistrarTest, CreateDestroy) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
std::shared_ptr<MockGlProcTable> gl = std::make_shared<MockGlProcTable>();
|
||||
auto gl = std::make_shared<egl::MockProcTable>();
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl);
|
||||
|
||||
EXPECT_TRUE(true);
|
||||
@@ -74,7 +75,7 @@ TEST(FlutterWindowsTextureRegistrarTest, CreateDestroy) {
|
||||
TEST(FlutterWindowsTextureRegistrarTest, RegisterUnregisterTexture) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
EngineModifier modifier(engine.get());
|
||||
std::shared_ptr<MockGlProcTable> gl = std::make_shared<MockGlProcTable>();
|
||||
auto gl = std::make_shared<egl::MockProcTable>();
|
||||
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl);
|
||||
|
||||
@@ -138,7 +139,7 @@ TEST(FlutterWindowsTextureRegistrarTest, RegisterUnregisterTexture) {
|
||||
|
||||
TEST(FlutterWindowsTextureRegistrarTest, RegisterUnknownTextureType) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
std::shared_ptr<MockGlProcTable> gl = std::make_shared<MockGlProcTable>();
|
||||
auto gl = std::make_shared<egl::MockProcTable>();
|
||||
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl);
|
||||
|
||||
@@ -152,7 +153,7 @@ TEST(FlutterWindowsTextureRegistrarTest, RegisterUnknownTextureType) {
|
||||
|
||||
TEST(FlutterWindowsTextureRegistrarTest, PopulatePixelBufferTexture) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
std::shared_ptr<MockGlProcTable> gl = std::make_shared<MockGlProcTable>();
|
||||
auto gl = std::make_shared<egl::MockProcTable>();
|
||||
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl);
|
||||
|
||||
@@ -203,7 +204,7 @@ TEST(FlutterWindowsTextureRegistrarTest, PopulatePixelBufferTexture) {
|
||||
|
||||
TEST(FlutterWindowsTextureRegistrarTest, PopulateD3dTextureWithHandle) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
std::shared_ptr<MockGlProcTable> gl = std::make_shared<MockGlProcTable>();
|
||||
auto gl = std::make_shared<egl::MockProcTable>();
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl);
|
||||
|
||||
UINT width = 100;
|
||||
@@ -265,7 +266,7 @@ TEST(FlutterWindowsTextureRegistrarTest, PopulateD3dTextureWithHandle) {
|
||||
|
||||
TEST(FlutterWindowsTextureRegistrarTest, PopulateD3dTexture) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
std::shared_ptr<MockGlProcTable> gl = std::make_shared<MockGlProcTable>();
|
||||
auto gl = std::make_shared<egl::MockProcTable>();
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl);
|
||||
|
||||
UINT width = 100;
|
||||
@@ -321,7 +322,7 @@ TEST(FlutterWindowsTextureRegistrarTest, PopulateD3dTexture) {
|
||||
|
||||
TEST(FlutterWindowsTextureRegistrarTest, PopulateInvalidTexture) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
std::shared_ptr<MockGlProcTable> gl = std::make_shared<MockGlProcTable>();
|
||||
auto gl = std::make_shared<egl::MockProcTable>();
|
||||
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl);
|
||||
|
||||
@@ -332,7 +333,7 @@ TEST(FlutterWindowsTextureRegistrarTest, PopulateInvalidTexture) {
|
||||
TEST(FlutterWindowsTextureRegistrarTest,
|
||||
UnregisterTextureWithEngineDownInvokesCallback) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
std::shared_ptr<MockGlProcTable> gl = std::make_shared<MockGlProcTable>();
|
||||
auto gl = std::make_shared<egl::MockProcTable>();
|
||||
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl);
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@ bool SurfaceWillUpdate(size_t cur_width,
|
||||
/// Update the surface's swap interval to block until the v-blank iff
|
||||
/// the system compositor is disabled.
|
||||
void UpdateVsync(const FlutterWindowsEngine& engine, bool needs_vsync) {
|
||||
AngleSurfaceManager* surface_manager = engine.surface_manager();
|
||||
if (!surface_manager) {
|
||||
egl::Manager* egl_manager = engine.egl_manager();
|
||||
if (!egl_manager) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -52,14 +52,14 @@ void UpdateVsync(const FlutterWindowsEngine& engine, bool needs_vsync) {
|
||||
// exist yet and the render surface can be made current on the platform
|
||||
// thread.
|
||||
if (engine.running()) {
|
||||
engine.PostRasterThreadTask([surface_manager, needs_vsync]() {
|
||||
surface_manager->SetVSyncEnabled(needs_vsync);
|
||||
engine.PostRasterThreadTask([egl_manager, needs_vsync]() {
|
||||
egl_manager->SetVSyncEnabled(needs_vsync);
|
||||
});
|
||||
} else {
|
||||
surface_manager->SetVSyncEnabled(needs_vsync);
|
||||
egl_manager->SetVSyncEnabled(needs_vsync);
|
||||
|
||||
// Release the EGL context so that the raster thread can use it.
|
||||
if (!surface_manager->ClearCurrent()) {
|
||||
if (!egl_manager->ClearCurrent()) {
|
||||
FML_LOG(ERROR)
|
||||
<< "Unable to clear current surface after updating the swap interval";
|
||||
return;
|
||||
@@ -116,9 +116,8 @@ void FlutterWindowsView::OnEmptyFrameGenerated() {
|
||||
|
||||
// Platform thread is blocked for the entire duration until the
|
||||
// resize_status_ is set to kDone.
|
||||
engine_->surface_manager()->ResizeSurface(
|
||||
GetWindowHandle(), resize_target_width_, resize_target_height_,
|
||||
NeedsVsync());
|
||||
engine_->egl_manager()->ResizeSurface(GetWindowHandle(), resize_target_width_,
|
||||
resize_target_height_, NeedsVsync());
|
||||
resize_status_ = ResizeState::kFrameGenerated;
|
||||
}
|
||||
|
||||
@@ -133,8 +132,8 @@ bool FlutterWindowsView::OnFrameGenerated(size_t width, size_t height) {
|
||||
if (resize_target_width_ == width && resize_target_height_ == height) {
|
||||
// Platform thread is blocked for the entire duration until the
|
||||
// resize_status_ is set to kDone.
|
||||
engine_->surface_manager()->ResizeSurface(GetWindowHandle(), width, height,
|
||||
NeedsVsync());
|
||||
engine_->egl_manager()->ResizeSurface(GetWindowHandle(), width, height,
|
||||
NeedsVsync());
|
||||
resize_status_ = ResizeState::kFrameGenerated;
|
||||
return true;
|
||||
}
|
||||
@@ -161,7 +160,7 @@ bool FlutterWindowsView::OnWindowSizeChanged(size_t width, size_t height) {
|
||||
// Called on the platform thread.
|
||||
std::unique_lock<std::mutex> lock(resize_mutex_);
|
||||
|
||||
if (!engine_->surface_manager()) {
|
||||
if (!engine_->egl_manager()) {
|
||||
SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
|
||||
return true;
|
||||
}
|
||||
@@ -169,8 +168,7 @@ bool FlutterWindowsView::OnWindowSizeChanged(size_t width, size_t height) {
|
||||
// We're using OpenGL rendering. Resizing the surface must happen on the
|
||||
// raster thread.
|
||||
EGLint surface_width, surface_height;
|
||||
engine_->surface_manager()->GetSurfaceDimensions(&surface_width,
|
||||
&surface_height);
|
||||
engine_->egl_manager()->GetSurfaceDimensions(&surface_width, &surface_height);
|
||||
|
||||
bool surface_will_update =
|
||||
SurfaceWillUpdate(surface_width, surface_height, width, height);
|
||||
@@ -637,10 +635,10 @@ bool FlutterWindowsView::PresentSoftwareBitmap(const void* allocation,
|
||||
}
|
||||
|
||||
void FlutterWindowsView::CreateRenderSurface() {
|
||||
if (engine_ && engine_->surface_manager()) {
|
||||
if (engine_ && engine_->egl_manager()) {
|
||||
PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
|
||||
engine_->surface_manager()->CreateSurface(GetWindowHandle(), bounds.width,
|
||||
bounds.height);
|
||||
engine_->egl_manager()->CreateSurface(GetWindowHandle(), bounds.width,
|
||||
bounds.height);
|
||||
|
||||
UpdateVsync(*engine_, NeedsVsync());
|
||||
|
||||
@@ -650,8 +648,8 @@ void FlutterWindowsView::CreateRenderSurface() {
|
||||
}
|
||||
|
||||
void FlutterWindowsView::DestroyRenderSurface() {
|
||||
if (engine_ && engine_->surface_manager()) {
|
||||
engine_->surface_manager()->DestroySurface();
|
||||
if (engine_ && engine_->egl_manager()) {
|
||||
engine_->egl_manager()->DestroySurface();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "flutter/shell/platform/common/geometry.h"
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
#include "flutter/shell/platform/windows/accessibility_bridge_windows.h"
|
||||
#include "flutter/shell/platform/windows/angle_surface_manager.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
|
||||
#include "flutter/shell/platform/windows/public/flutter_windows.h"
|
||||
#include "flutter/shell/platform/windows/window_binding_handler.h"
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
#include "flutter/shell/platform/windows/flutter_window.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h"
|
||||
#include "flutter/shell/platform/windows/testing/egl/mock_manager.h"
|
||||
#include "flutter/shell/platform/windows/testing/engine_modifier.h"
|
||||
#include "flutter/shell/platform/windows/testing/mock_angle_surface_manager.h"
|
||||
#include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
|
||||
#include "flutter/shell/platform/windows/testing/mock_windows_proc_table.h"
|
||||
#include "flutter/shell/platform/windows/testing/test_keyboard.h"
|
||||
@@ -233,8 +233,8 @@ TEST(FlutterWindowsViewTest, Shutdown) {
|
||||
std::make_unique<MockFlutterWindowsEngine>();
|
||||
auto window_binding_handler =
|
||||
std::make_unique<NiceMock<MockWindowBindingHandler>>();
|
||||
std::unique_ptr<MockAngleSurfaceManager> surface_manager =
|
||||
std::make_unique<MockAngleSurfaceManager>();
|
||||
std::unique_ptr<egl::MockManager> egl_manager =
|
||||
std::make_unique<egl::MockManager>();
|
||||
|
||||
EngineModifier modifier(engine.get());
|
||||
FlutterWindowsView view(std::move(window_binding_handler));
|
||||
@@ -242,9 +242,9 @@ TEST(FlutterWindowsViewTest, Shutdown) {
|
||||
// The engine must be stopped before the surface can be destroyed.
|
||||
InSequence s;
|
||||
EXPECT_CALL(*engine.get(), Stop).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), DestroySurface).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), DestroySurface).Times(1);
|
||||
|
||||
modifier.SetSurfaceManager(std::move(surface_manager));
|
||||
modifier.SetEGLManager(std::move(egl_manager));
|
||||
view.SetEngine(engine.get());
|
||||
}
|
||||
|
||||
@@ -816,20 +816,20 @@ TEST(FlutterWindowsViewTest, WindowResizeTests) {
|
||||
auto window_binding_handler =
|
||||
std::make_unique<NiceMock<MockWindowBindingHandler>>();
|
||||
auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
|
||||
std::unique_ptr<MockAngleSurfaceManager> surface_manager =
|
||||
std::make_unique<MockAngleSurfaceManager>();
|
||||
std::unique_ptr<egl::MockManager> egl_manager =
|
||||
std::make_unique<egl::MockManager>();
|
||||
|
||||
EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(
|
||||
*surface_manager.get(),
|
||||
*egl_manager.get(),
|
||||
ResizeSurface(_, /*width=*/500, /*height=*/500, /*enable_vsync=*/false))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), DestroySurface).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), DestroySurface).Times(1);
|
||||
|
||||
FlutterWindowsView view(std::move(window_binding_handler),
|
||||
std::move(windows_proc_table));
|
||||
modifier.SetSurfaceManager(std::move(surface_manager));
|
||||
modifier.SetEGLManager(std::move(egl_manager));
|
||||
view.SetEngine(engine.get());
|
||||
|
||||
fml::AutoResetWaitableEvent metrics_sent_latch;
|
||||
@@ -866,20 +866,20 @@ TEST(FlutterWindowsViewTest, TestEmptyFrameResizes) {
|
||||
auto window_binding_handler =
|
||||
std::make_unique<NiceMock<MockWindowBindingHandler>>();
|
||||
auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
|
||||
std::unique_ptr<MockAngleSurfaceManager> surface_manager =
|
||||
std::make_unique<MockAngleSurfaceManager>();
|
||||
std::unique_ptr<egl::MockManager> egl_manager =
|
||||
std::make_unique<egl::MockManager>();
|
||||
|
||||
EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(
|
||||
*surface_manager.get(),
|
||||
*egl_manager.get(),
|
||||
ResizeSurface(_, /*width=*/500, /*height=*/500, /*enable_vsync=*/false))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), DestroySurface).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), DestroySurface).Times(1);
|
||||
|
||||
FlutterWindowsView view(std::move(window_binding_handler),
|
||||
std::move(windows_proc_table));
|
||||
modifier.SetSurfaceManager(std::move(surface_manager));
|
||||
modifier.SetEGLManager(std::move(egl_manager));
|
||||
view.SetEngine(engine.get());
|
||||
|
||||
fml::AutoResetWaitableEvent metrics_sent_latch;
|
||||
@@ -918,14 +918,14 @@ TEST(FlutterWindowsViewTest, WindowResizeRace) {
|
||||
auto window_binding_handler =
|
||||
std::make_unique<NiceMock<MockWindowBindingHandler>>();
|
||||
auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
|
||||
std::unique_ptr<MockAngleSurfaceManager> surface_manager =
|
||||
std::make_unique<MockAngleSurfaceManager>();
|
||||
std::unique_ptr<egl::MockManager> egl_manager =
|
||||
std::make_unique<egl::MockManager>();
|
||||
|
||||
EXPECT_CALL(*surface_manager.get(), DestroySurface).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), DestroySurface).Times(1);
|
||||
|
||||
FlutterWindowsView view(std::move(window_binding_handler),
|
||||
std::move(windows_proc_table));
|
||||
modifier.SetSurfaceManager(std::move(surface_manager));
|
||||
modifier.SetEGLManager(std::move(egl_manager));
|
||||
view.SetEngine(engine.get());
|
||||
|
||||
// Begin a frame.
|
||||
@@ -1303,8 +1303,8 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAtStartup) {
|
||||
auto window_binding_handler =
|
||||
std::make_unique<NiceMock<MockWindowBindingHandler>>();
|
||||
auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
|
||||
std::unique_ptr<MockAngleSurfaceManager> surface_manager =
|
||||
std::make_unique<MockAngleSurfaceManager>();
|
||||
std::unique_ptr<egl::MockManager> egl_manager =
|
||||
std::make_unique<egl::MockManager>();
|
||||
|
||||
EXPECT_CALL(*engine.get(), running).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(*engine.get(), PostRasterThreadTask).Times(0);
|
||||
@@ -1317,16 +1317,16 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAtStartup) {
|
||||
std::move(windows_proc_table));
|
||||
|
||||
InSequence s;
|
||||
EXPECT_CALL(*surface_manager.get(), CreateSurface(_, _, _))
|
||||
EXPECT_CALL(*egl_manager.get(), CreateSurface(_, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(*surface_manager.get(), SetVSyncEnabled(false)).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), ClearCurrent).WillOnce(Return(true));
|
||||
EXPECT_CALL(*egl_manager.get(), SetVSyncEnabled(false)).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), ClearCurrent).WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(*engine.get(), Stop).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), DestroySurface).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), DestroySurface).Times(1);
|
||||
|
||||
modifier.SetSurfaceManager(std::move(surface_manager));
|
||||
modifier.SetEGLManager(std::move(egl_manager));
|
||||
view.SetEngine(engine.get());
|
||||
|
||||
view.CreateRenderSurface();
|
||||
@@ -1340,8 +1340,8 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAtStartup) {
|
||||
auto window_binding_handler =
|
||||
std::make_unique<NiceMock<MockWindowBindingHandler>>();
|
||||
auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
|
||||
std::unique_ptr<MockAngleSurfaceManager> surface_manager =
|
||||
std::make_unique<MockAngleSurfaceManager>();
|
||||
std::unique_ptr<egl::MockManager> egl_manager =
|
||||
std::make_unique<egl::MockManager>();
|
||||
|
||||
EXPECT_CALL(*engine.get(), running).WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(*engine.get(), PostRasterThreadTask).Times(0);
|
||||
@@ -1353,16 +1353,16 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAtStartup) {
|
||||
std::move(windows_proc_table));
|
||||
|
||||
InSequence s;
|
||||
EXPECT_CALL(*surface_manager.get(), CreateSurface(_, _, _))
|
||||
EXPECT_CALL(*egl_manager.get(), CreateSurface(_, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(*surface_manager.get(), SetVSyncEnabled(true)).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), ClearCurrent).WillOnce(Return(true));
|
||||
EXPECT_CALL(*egl_manager.get(), SetVSyncEnabled(true)).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), ClearCurrent).WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(*engine.get(), Stop).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), DestroySurface).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), DestroySurface).Times(1);
|
||||
|
||||
modifier.SetSurfaceManager(std::move(surface_manager));
|
||||
modifier.SetEGLManager(std::move(egl_manager));
|
||||
view.SetEngine(engine.get());
|
||||
|
||||
view.CreateRenderSurface();
|
||||
@@ -1376,8 +1376,8 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAfterStartup) {
|
||||
auto window_binding_handler =
|
||||
std::make_unique<NiceMock<MockWindowBindingHandler>>();
|
||||
auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
|
||||
std::unique_ptr<MockAngleSurfaceManager> surface_manager =
|
||||
std::make_unique<MockAngleSurfaceManager>();
|
||||
std::unique_ptr<egl::MockManager> egl_manager =
|
||||
std::make_unique<egl::MockManager>();
|
||||
|
||||
EXPECT_CALL(*engine.get(), running).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
|
||||
@@ -1388,7 +1388,7 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAfterStartup) {
|
||||
std::move(windows_proc_table));
|
||||
|
||||
InSequence s;
|
||||
EXPECT_CALL(*surface_manager.get(), CreateSurface(_, _, _))
|
||||
EXPECT_CALL(*egl_manager.get(), CreateSurface(_, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(*engine.get(), PostRasterThreadTask)
|
||||
@@ -1396,13 +1396,13 @@ TEST(FlutterWindowsViewTest, DisablesVSyncAfterStartup) {
|
||||
callback();
|
||||
return true;
|
||||
});
|
||||
EXPECT_CALL(*surface_manager.get(), SetVSyncEnabled(false)).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), ClearCurrent).Times(0);
|
||||
EXPECT_CALL(*egl_manager.get(), SetVSyncEnabled(false)).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), ClearCurrent).Times(0);
|
||||
|
||||
EXPECT_CALL(*engine.get(), Stop).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), DestroySurface).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), DestroySurface).Times(1);
|
||||
|
||||
modifier.SetSurfaceManager(std::move(surface_manager));
|
||||
modifier.SetEGLManager(std::move(egl_manager));
|
||||
view.SetEngine(engine.get());
|
||||
|
||||
view.CreateRenderSurface();
|
||||
@@ -1416,8 +1416,8 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAfterStartup) {
|
||||
auto window_binding_handler =
|
||||
std::make_unique<NiceMock<MockWindowBindingHandler>>();
|
||||
auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
|
||||
std::unique_ptr<MockAngleSurfaceManager> surface_manager =
|
||||
std::make_unique<MockAngleSurfaceManager>();
|
||||
std::unique_ptr<egl::MockManager> egl_manager =
|
||||
std::make_unique<egl::MockManager>();
|
||||
|
||||
EXPECT_CALL(*engine.get(), running).WillRepeatedly(Return(true));
|
||||
|
||||
@@ -1429,7 +1429,7 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAfterStartup) {
|
||||
std::move(windows_proc_table));
|
||||
|
||||
InSequence s;
|
||||
EXPECT_CALL(*surface_manager.get(), CreateSurface(_, _, _))
|
||||
EXPECT_CALL(*egl_manager.get(), CreateSurface(_, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(*engine.get(), PostRasterThreadTask)
|
||||
@@ -1437,13 +1437,13 @@ TEST(FlutterWindowsViewTest, EnablesVSyncAfterStartup) {
|
||||
callback();
|
||||
return true;
|
||||
});
|
||||
EXPECT_CALL(*surface_manager.get(), SetVSyncEnabled(true)).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), ClearCurrent).Times(0);
|
||||
EXPECT_CALL(*egl_manager.get(), SetVSyncEnabled(true)).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), ClearCurrent).Times(0);
|
||||
|
||||
EXPECT_CALL(*engine.get(), Stop).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), DestroySurface).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), DestroySurface).Times(1);
|
||||
|
||||
modifier.SetSurfaceManager(std::move(surface_manager));
|
||||
modifier.SetEGLManager(std::move(egl_manager));
|
||||
view.SetEngine(engine.get());
|
||||
|
||||
view.CreateRenderSurface();
|
||||
@@ -1458,8 +1458,8 @@ TEST(FlutterWindowsViewTest, UpdatesVSyncOnDwmUpdates) {
|
||||
auto window_binding_handler =
|
||||
std::make_unique<NiceMock<MockWindowBindingHandler>>();
|
||||
auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
|
||||
std::unique_ptr<MockAngleSurfaceManager> surface_manager =
|
||||
std::make_unique<MockAngleSurfaceManager>();
|
||||
std::unique_ptr<egl::MockManager> egl_manager =
|
||||
std::make_unique<egl::MockManager>();
|
||||
|
||||
EXPECT_CALL(*engine.get(), running).WillRepeatedly(Return(true));
|
||||
|
||||
@@ -1473,20 +1473,20 @@ TEST(FlutterWindowsViewTest, UpdatesVSyncOnDwmUpdates) {
|
||||
.WillOnce(Return(false))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(*surface_manager.get(), ClearCurrent).Times(0);
|
||||
EXPECT_CALL(*egl_manager.get(), ClearCurrent).Times(0);
|
||||
|
||||
EngineModifier modifier(engine.get());
|
||||
FlutterWindowsView view(std::move(window_binding_handler),
|
||||
std::move(windows_proc_table));
|
||||
|
||||
InSequence s;
|
||||
EXPECT_CALL(*surface_manager.get(), SetVSyncEnabled(true)).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), SetVSyncEnabled(false)).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), SetVSyncEnabled(true)).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), SetVSyncEnabled(false)).Times(1);
|
||||
|
||||
EXPECT_CALL(*engine.get(), Stop).Times(1);
|
||||
EXPECT_CALL(*surface_manager.get(), DestroySurface).Times(1);
|
||||
EXPECT_CALL(*egl_manager.get(), DestroySurface).Times(1);
|
||||
|
||||
modifier.SetSurfaceManager(std::move(surface_manager));
|
||||
modifier.SetEGLManager(std::move(egl_manager));
|
||||
view.SetEngine(engine.get());
|
||||
|
||||
view.GetEngine()->OnDwmCompositionChanged();
|
||||
|
||||
@@ -2,20 +2,21 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_ANGLE_SURFACE_MANAGER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_ANGLE_SURFACE_MANAGER_H_
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_EGL_MOCK_MANAGER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_EGL_MOCK_MANAGER_H_
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/platform/windows/angle_surface_manager.h"
|
||||
#include "flutter/shell/platform/windows/egl/manager.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
namespace egl {
|
||||
|
||||
/// Mock for the |AngleSurfaceManager| base class.
|
||||
class MockAngleSurfaceManager : public AngleSurfaceManager {
|
||||
/// Mock for the |Manager| base class.
|
||||
class MockManager : public flutter::egl::Manager {
|
||||
public:
|
||||
MockAngleSurfaceManager() : AngleSurfaceManager(false) {}
|
||||
MockManager() : Manager(false) {}
|
||||
|
||||
MOCK_METHOD(bool, CreateSurface, (HWND, EGLint, EGLint), (override));
|
||||
MOCK_METHOD(void, ResizeSurface, (HWND, EGLint, EGLint, bool), (override));
|
||||
@@ -28,10 +29,11 @@ class MockAngleSurfaceManager : public AngleSurfaceManager {
|
||||
MOCK_METHOD(bool, SwapBuffers, (), (override));
|
||||
|
||||
private:
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(MockAngleSurfaceManager);
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(MockManager);
|
||||
};
|
||||
|
||||
} // namespace egl
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_ANGLE_SURFACE_MANAGER_H_
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_EGL_MOCK_MANAGER_H_
|
||||
@@ -2,21 +2,22 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_GL_PROC_TABLE_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_GL_PROC_TABLE_H_
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_EGL_MOCK_PROC_TABLE_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_EGL_MOCK_PROC_TABLE_H_
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/shell/platform/windows/gl_proc_table.h"
|
||||
#include "flutter/shell/platform/windows/egl/proc_table.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
namespace egl {
|
||||
|
||||
/// Mock for the |GlProcTable| base class.
|
||||
class MockGlProcTable : public GlProcTable {
|
||||
/// Mock for the |ProcTable| base class.
|
||||
class MockProcTable : public ::flutter::egl::ProcTable {
|
||||
public:
|
||||
MockGlProcTable() = default;
|
||||
virtual ~MockGlProcTable() = default;
|
||||
MockProcTable() = default;
|
||||
virtual ~MockProcTable() = default;
|
||||
|
||||
MOCK_METHOD(void,
|
||||
GenTextures,
|
||||
@@ -48,10 +49,11 @@ class MockGlProcTable : public GlProcTable {
|
||||
(const override));
|
||||
|
||||
private:
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(MockGlProcTable);
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(MockProcTable);
|
||||
};
|
||||
|
||||
} // namespace egl
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_GL_PROC_TABLE_H_
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_EGL_MOCK_PROC_TABLE_H_
|
||||
@@ -29,12 +29,12 @@ class EngineModifier {
|
||||
// engine unless overwritten again.
|
||||
FlutterEngineProcTable& embedder_api() { return engine_->embedder_api_; }
|
||||
|
||||
// Override the surface manager used by the engine.
|
||||
// Override the EGL manager used by the engine.
|
||||
//
|
||||
// Modifications are to the engine, and will last for the lifetime of the
|
||||
// engine unless overwritten again.
|
||||
void SetSurfaceManager(std::unique_ptr<AngleSurfaceManager> surface_manager) {
|
||||
engine_->surface_manager_ = std::move(surface_manager);
|
||||
void SetEGLManager(std::unique_ptr<egl::Manager> egl_manager) {
|
||||
engine_->egl_manager_ = std::move(egl_manager);
|
||||
}
|
||||
|
||||
/// Reset the start_time field that is used to align vsync events.
|
||||
@@ -51,14 +51,14 @@ class EngineModifier {
|
||||
std::optional<std::chrono::nanoseconds>(frame_interval_nanos);
|
||||
}
|
||||
|
||||
// Explicitly releases the SurfaceManager being used by the
|
||||
// FlutterWindowsEngine instance. This should be used if SetSurfaceManager is
|
||||
// Explicitly releases the egl::Manager being used by the
|
||||
// FlutterWindowsEngine instance. This should be used if SetEGLManager is
|
||||
// used to explicitly set to a non-null value (but not a valid object) to test
|
||||
// a successful ANGLE initialization.
|
||||
//
|
||||
// Modifications are to the engine, and will last for the lifetime of the
|
||||
// engine unless overwritten again.
|
||||
void ReleaseSurfaceManager() { engine_->surface_manager_.release(); }
|
||||
void ReleaseEGLManager() { engine_->egl_manager_.release(); }
|
||||
|
||||
// Run the FlutterWindowsEngine's handler that runs right before an engine
|
||||
// restart. This resets the keyboard's state if it exists.
|
||||
|
||||
Reference in New Issue
Block a user