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;
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) {
187bool 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) {
206bool 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);
228bool 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);
259void 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;
279bool Manager::IsValid()
const {
283std::unique_ptr<WindowSurface> Manager::CreateWindowSurface(HWND hwnd,
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(),
313bool Manager::HasContextCurrent() {
314 return ::eglGetCurrentContext() != EGL_NO_CONTEXT;
317EGLSurface Manager::CreateSurfaceFromHandle(EGLenum handle_type,
318 EGLClientBuffer handle,
319 const EGLint* attributes)
const {
320 return ::eglCreatePbufferFromClientBuffer(display_, handle_type, handle,
321 config_, attributes);
324bool Manager::GetDevice(ID3D11Device**
device) {
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();
343std::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;
376std::optional<LUID> Manager::GetLowPowerGpuLuid() {
377 return GetGpuLuidByPreference(DXGI_GPU_PREFERENCE_MINIMUM_POWER);
380std::optional<LUID> Manager::GetHighPerformanceGpuLuid() {
381 return GetGpuLuidByPreference(DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE);
virtual Context * resource_context() const
static std::optional< LUID > GetLowPowerGpuLuid()
virtual Context * render_context() const
static std::optional< LUID > GetHighPerformanceGpuLuid()
#define FML_UNREACHABLE()
void LogEGLError(std::string_view message)
Log the last EGL error with an error message.
@ HighPerformancePreference
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