9 #include "flutter/fml/logging.h"
15 int Manager::instance_count_ = 0;
18 std::unique_ptr<Manager> manager;
19 manager.reset(
new Manager(gpu_preference));
20 if (!manager->IsValid()) {
23 return std::move(manager);
29 if (!InitializeDisplay(gpu_preference)) {
33 if (!InitializeConfig()) {
37 if (!InitializeContexts()) {
49 bool Manager::InitializeDisplay(
GpuPreference gpu_preference) {
53 std::optional<LUID> luid = std::nullopt;
54 switch (gpu_preference) {
67 const EGLint d3d11_display_attributes_with_luid[] = {
68 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
69 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
74 EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
79 EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE,
80 EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
83 EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE,
84 static_cast<EGLint
>(luid.has_value() ? luid->HighPart : 0),
85 EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE,
86 static_cast<EGLint
>(luid.has_value() ? luid->LowPart : 0),
93 const EGLint d3d11_display_attributes[] = {
94 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
95 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
100 EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
105 EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE,
106 EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
113 const EGLint d3d11_fl_9_3_display_attributes[] = {
114 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
115 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
116 EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
118 EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE,
120 EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
127 const EGLint d3d11_warp_display_attributes[] = {
128 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
129 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
130 EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
135 std::vector<const EGLint*> display_attributes_configs;
139 display_attributes_configs.push_back(d3d11_display_attributes_with_luid);
141 display_attributes_configs.push_back(d3d11_display_attributes);
142 display_attributes_configs.push_back(d3d11_fl_9_3_display_attributes);
143 display_attributes_configs.push_back(d3d11_warp_display_attributes);
145 PFNEGLGETPLATFORMDISPLAYEXTPROC egl_get_platform_display_EXT =
146 reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC
>(
147 ::eglGetProcAddress(
"eglGetPlatformDisplayEXT"));
148 if (!egl_get_platform_display_EXT) {
149 LogEGLError(
"eglGetPlatformDisplayEXT not available");
155 for (
auto config : display_attributes_configs) {
156 bool is_last = (config == display_attributes_configs.back());
158 display_ = egl_get_platform_display_EXT(EGL_PLATFORM_ANGLE_ANGLE,
159 EGL_DEFAULT_DISPLAY, config);
161 if (display_ == EGL_NO_DISPLAY) {
163 LogEGLError(
"Failed to get a compatible EGLdisplay");
171 if (::eglInitialize(display_,
nullptr,
nullptr) == EGL_FALSE) {
187 bool Manager::InitializeConfig() {
188 const EGLint config_attributes[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
189 EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
190 EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8,
193 EGLint num_config = 0;
196 ::eglChooseConfig(display_, config_attributes, &config_, 1, &num_config);
198 if (result == EGL_TRUE && num_config > 0) {
206 bool Manager::InitializeContexts() {
207 const EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
210 ::eglCreateContext(display_, config_, EGL_NO_CONTEXT, context_attributes);
212 LogEGLError(
"Failed to create EGL render context");
217 ::eglCreateContext(display_, config_,
render_context, context_attributes);
219 LogEGLError(
"Failed to create EGL resource context");
223 render_context_ = std::make_unique<Context>(display_,
render_context);
228 bool Manager::InitializeDevice() {
229 const auto query_display_attrib_EXT =
230 reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC
>(
231 ::eglGetProcAddress(
"eglQueryDisplayAttribEXT"));
232 const auto query_device_attrib_EXT =
233 reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC
>(
234 ::eglGetProcAddress(
"eglQueryDeviceAttribEXT"));
236 if (query_display_attrib_EXT ==
nullptr ||
237 query_device_attrib_EXT ==
nullptr) {
241 EGLAttrib egl_device = 0;
242 EGLAttrib angle_device = 0;
244 auto result = query_display_attrib_EXT(display_, EGL_DEVICE_EXT, &egl_device);
245 if (result != EGL_TRUE) {
249 result = query_device_attrib_EXT(
reinterpret_cast<EGLDeviceEXT
>(egl_device),
250 EGL_D3D11_DEVICE_ANGLE, &angle_device);
251 if (result != EGL_TRUE) {
255 resolved_device_ =
reinterpret_cast<ID3D11Device*
>(angle_device);
259 void Manager::CleanUp() {
260 EGLBoolean result = EGL_FALSE;
263 resolved_device_.Reset();
266 render_context_.reset();
267 resource_context_.reset();
269 if (display_ != EGL_NO_DISPLAY) {
272 if (instance_count_ == 1) {
273 ::eglTerminate(display_);
275 display_ = EGL_NO_DISPLAY;
286 if (!hwnd || !is_valid_) {
293 const EGLint surface_attributes[] = {EGL_FIXED_SIZE_ANGLE,
296 static_cast<EGLint
>(width),
298 static_cast<EGLint
>(height),
301 auto const surface = ::eglCreateWindowSurface(
302 display_, config_,
static_cast<EGLNativeWindowType
>(hwnd),
304 if (surface == EGL_NO_SURFACE) {
309 return std::make_unique<WindowSurface>(display_, render_context_->GetHandle(),
310 surface, width, height);
314 return ::eglGetCurrentContext() != EGL_NO_CONTEXT;
318 EGLClientBuffer handle,
319 const EGLint* attributes)
const {
320 return ::eglCreatePbufferFromClientBuffer(display_, handle_type, handle,
321 config_, attributes);
325 if (!resolved_device_) {
326 if (!InitializeDevice()) {
331 resolved_device_.CopyTo(device);
332 return (resolved_device_ !=
nullptr);
336 return render_context_.get();
340 return resource_context_.get();
343 std::optional<LUID> Manager::GetGpuLuidByPreference(
344 DXGI_GPU_PREFERENCE preference) {
345 Microsoft::WRL::ComPtr<IDXGIFactory1> factory1;
346 HRESULT hr = ::CreateDXGIFactory1(IID_PPV_ARGS(&factory1));
351 Microsoft::WRL::ComPtr<IDXGIFactory6> factory6;
352 hr = factory1->QueryInterface(IID_PPV_ARGS(&factory6));
359 Microsoft::WRL::ComPtr<IDXGIAdapter1> adapter;
360 hr = factory6->EnumAdapterByGpuPreference(0, preference,
361 IID_PPV_ARGS(&adapter));
362 if (FAILED(hr) || !adapter) {
367 DXGI_ADAPTER_DESC desc;
368 hr = adapter->GetDesc(&desc);
373 return desc.AdapterLuid;
377 return GetGpuLuidByPreference(DXGI_GPU_PREFERENCE_MINIMUM_POWER);
381 return GetGpuLuidByPreference(DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE);
virtual Context * resource_context() const
Manager(GpuPreference gpu_preference)
EGLSurface CreateSurfaceFromHandle(EGLenum handle_type, EGLClientBuffer handle, const EGLint *attributes) const
static std::optional< LUID > GetLowPowerGpuLuid()
virtual Context * render_context() const
static std::optional< LUID > GetHighPerformanceGpuLuid()
static std::unique_ptr< Manager > Create(GpuPreference gpu_preference)
virtual std::unique_ptr< WindowSurface > CreateWindowSurface(HWND hwnd, size_t width, size_t height)
bool GetDevice(ID3D11Device **device)
void LogEGLError(std::string_view message)
Log the last EGL error with an error message.
@ HighPerformancePreference