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;
60 const EGLint d3d11_display_attributes_with_luid[] = {
61 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
62 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
67 EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
72 EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE,
73 EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
76 EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE,
77 static_cast<EGLint
>(luid.has_value() ? luid->HighPart : 0),
78 EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE,
79 static_cast<EGLint
>(luid.has_value() ? luid->LowPart : 0),
86 const EGLint d3d11_display_attributes[] = {
87 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
88 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
93 EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
98 EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE,
99 EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
106 const EGLint d3d11_fl_9_3_display_attributes[] = {
107 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
108 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
109 EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
111 EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE,
113 EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
120 const EGLint d3d11_warp_display_attributes[] = {
121 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
122 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
123 EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
128 std::vector<const EGLint*> display_attributes_configs;
132 display_attributes_configs.push_back(d3d11_display_attributes_with_luid);
134 display_attributes_configs.push_back(d3d11_display_attributes);
135 display_attributes_configs.push_back(d3d11_fl_9_3_display_attributes);
136 display_attributes_configs.push_back(d3d11_warp_display_attributes);
138 PFNEGLGETPLATFORMDISPLAYEXTPROC egl_get_platform_display_EXT =
139 reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC
>(
140 ::eglGetProcAddress(
"eglGetPlatformDisplayEXT"));
141 if (!egl_get_platform_display_EXT) {
142 LogEGLError(
"eglGetPlatformDisplayEXT not available");
148 for (
auto config : display_attributes_configs) {
149 bool is_last = (config == display_attributes_configs.back());
151 display_ = egl_get_platform_display_EXT(EGL_PLATFORM_ANGLE_ANGLE,
152 EGL_DEFAULT_DISPLAY, config);
154 if (display_ == EGL_NO_DISPLAY) {
156 LogEGLError(
"Failed to get a compatible EGLdisplay");
164 if (::eglInitialize(display_,
nullptr,
nullptr) == EGL_FALSE) {
180 bool Manager::InitializeConfig() {
181 const EGLint config_attributes[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
182 EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
183 EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8,
186 EGLint num_config = 0;
189 ::eglChooseConfig(display_, config_attributes, &config_, 1, &num_config);
191 if (result == EGL_TRUE && num_config > 0) {
199 bool Manager::InitializeContexts() {
200 const EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
203 ::eglCreateContext(display_, config_, EGL_NO_CONTEXT, context_attributes);
205 LogEGLError(
"Failed to create EGL render context");
210 ::eglCreateContext(display_, config_,
render_context, context_attributes);
212 LogEGLError(
"Failed to create EGL resource context");
216 render_context_ = std::make_unique<Context>(display_,
render_context);
221 bool Manager::InitializeDevice() {
222 const auto query_display_attrib_EXT =
223 reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC
>(
224 ::eglGetProcAddress(
"eglQueryDisplayAttribEXT"));
225 const auto query_device_attrib_EXT =
226 reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC
>(
227 ::eglGetProcAddress(
"eglQueryDeviceAttribEXT"));
229 if (query_display_attrib_EXT ==
nullptr ||
230 query_device_attrib_EXT ==
nullptr) {
234 EGLAttrib egl_device = 0;
235 EGLAttrib angle_device = 0;
237 auto result = query_display_attrib_EXT(display_, EGL_DEVICE_EXT, &egl_device);
238 if (result != EGL_TRUE) {
242 result = query_device_attrib_EXT(
reinterpret_cast<EGLDeviceEXT
>(egl_device),
243 EGL_D3D11_DEVICE_ANGLE, &angle_device);
244 if (result != EGL_TRUE) {
248 resolved_device_ =
reinterpret_cast<ID3D11Device*
>(angle_device);
252 void Manager::CleanUp() {
253 EGLBoolean result = EGL_FALSE;
256 resolved_device_.Reset();
259 render_context_.reset();
260 resource_context_.reset();
262 if (display_ != EGL_NO_DISPLAY) {
265 if (instance_count_ == 1) {
266 ::eglTerminate(display_);
268 display_ = EGL_NO_DISPLAY;
279 if (!hwnd || !is_valid_) {
286 const EGLint surface_attributes[] = {EGL_FIXED_SIZE_ANGLE,
289 static_cast<EGLint
>(width),
291 static_cast<EGLint
>(height),
294 auto const surface = ::eglCreateWindowSurface(
295 display_, config_,
static_cast<EGLNativeWindowType
>(hwnd),
297 if (surface == EGL_NO_SURFACE) {
302 return std::make_unique<WindowSurface>(display_, render_context_->GetHandle(),
303 surface, width, height);
307 return ::eglGetCurrentContext() != EGL_NO_CONTEXT;
311 EGLClientBuffer handle,
312 const EGLint* attributes)
const {
313 return ::eglCreatePbufferFromClientBuffer(display_, handle_type, handle,
314 config_, attributes);
318 if (!resolved_device_) {
319 if (!InitializeDevice()) {
324 resolved_device_.CopyTo(device);
325 return (resolved_device_ !=
nullptr);
329 return render_context_.get();
333 return resource_context_.get();
337 Microsoft::WRL::ComPtr<IDXGIFactory1> factory1 =
nullptr;
338 Microsoft::WRL::ComPtr<IDXGIFactory6> factory6 =
nullptr;
339 Microsoft::WRL::ComPtr<IDXGIAdapter1> adapter =
nullptr;
340 HRESULT hr = ::CreateDXGIFactory1(IID_PPV_ARGS(&factory1));
344 hr = factory1->QueryInterface(IID_PPV_ARGS(&factory6));
350 hr = factory6->EnumAdapterByGpuPreference(
351 0, DXGI_GPU_PREFERENCE_MINIMUM_POWER, IID_PPV_ARGS(&adapter));
352 if (FAILED(hr) || adapter ==
nullptr) {
356 DXGI_ADAPTER_DESC desc;
357 hr = adapter->GetDesc(&desc);
361 return std::make_optional(desc.AdapterLuid);