15int Manager::instance_count_ = 0;
18 std::unique_ptr<Manager>
manager;
29 if (!InitializeDisplay(gpu_preference)) {
33 if (!InitializeConfig()) {
37 if (!InitializeContexts()) {
49bool 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) {
180bool 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) {
199bool 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);
221bool 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);
252void 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;
272bool Manager::IsValid()
const {
276std::unique_ptr<WindowSurface> Manager::CreateWindowSurface(HWND hwnd,
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(),
306bool Manager::HasContextCurrent() {
307 return ::eglGetCurrentContext() != EGL_NO_CONTEXT;
310EGLSurface Manager::CreateSurfaceFromHandle(EGLenum handle_type,
311 EGLClientBuffer handle,
312 const EGLint* attributes)
const {
313 return ::eglCreatePbufferFromClientBuffer(display_, handle_type, handle,
314 config_, attributes);
317bool Manager::GetDevice(ID3D11Device**
device) {
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();
336std::optional<LUID> Manager::GetLowPowerGpuLuid() {
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);
virtual Context * resource_context() const
static std::optional< LUID > GetLowPowerGpuLuid()
virtual Context * render_context() const
#define FML_UNREACHABLE()
void LogEGLError(std::string_view message)
Log the last EGL error with an error message.
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font manager