• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/shell/platform/windows/angle_surface_manager.h"
6 
7 namespace flutter {
8 
AngleSurfaceManager()9 AngleSurfaceManager::AngleSurfaceManager()
10     : egl_config_(nullptr),
11       egl_display_(EGL_NO_DISPLAY),
12       egl_context_(EGL_NO_CONTEXT) {
13   initialize_succeeded_ = Initialize();
14 }
15 
~AngleSurfaceManager()16 AngleSurfaceManager::~AngleSurfaceManager() {
17   CleanUp();
18 }
19 
Initialize()20 bool AngleSurfaceManager::Initialize() {
21   const EGLint configAttributes[] = {EGL_RED_SIZE,   8, EGL_GREEN_SIZE,   8,
22                                      EGL_BLUE_SIZE,  8, EGL_ALPHA_SIZE,   8,
23                                      EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8,
24                                      EGL_NONE};
25 
26   const EGLint display_context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2,
27                                                EGL_NONE};
28 
29   const EGLint default_display_attributes[] = {
30       // These are prefered display attributes and request ANGLE's D3D11
31       // renderer. eglInitialize will only succeed with these attributes if the
32       // hardware supports D3D11 Feature Level 10_0+.
33       EGL_PLATFORM_ANGLE_TYPE_ANGLE,
34       EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
35 
36       // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that will
37       // enable ANGLE to automatically call the IDXGIDevice3::Trim method on
38       // behalf of the application when it gets suspended.
39       EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
40       EGL_TRUE,
41       EGL_NONE,
42   };
43 
44   const EGLint fl9_3_display_attributes[] = {
45       // These are used to request ANGLE's D3D11 renderer, with D3D11 Feature
46       // Level 9_3.
47       EGL_PLATFORM_ANGLE_TYPE_ANGLE,
48       EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
49       EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
50       9,
51       EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE,
52       3,
53       EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
54       EGL_TRUE,
55       EGL_NONE,
56   };
57 
58   const EGLint warp_display_attributes[] = {
59       // These attributes request D3D11 WARP (software rendering fallback) as a
60       // last resort.
61       EGL_PLATFORM_ANGLE_TYPE_ANGLE,
62       EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
63       EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
64       EGL_TRUE,
65       EGL_NONE,
66   };
67 
68   PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
69       reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
70           eglGetProcAddress("eglGetPlatformDisplayEXT"));
71   if (!eglGetPlatformDisplayEXT) {
72     OutputDebugString(L"EGL: Failed to get a compatible EGLdisplay");
73     return false;
74   }
75 
76   // Try to initialize EGL to D3D11 Feature Level 10_0+.
77   egl_display_ =
78       eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY,
79                                default_display_attributes);
80   if (egl_display_ == EGL_NO_DISPLAY) {
81     OutputDebugString(L"EGL: Failed to get a compatible EGLdisplay");
82     return false;
83   }
84 
85   if (eglInitialize(egl_display_, nullptr, nullptr) == EGL_FALSE) {
86     // If above failed, try to initialize EGL to D3D11 Feature Level 9_3, if
87     // 10_0+ is unavailable.
88     egl_display_ =
89         eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY,
90                                  fl9_3_display_attributes);
91     if (egl_display_ == EGL_NO_DISPLAY) {
92       OutputDebugString(L"EGL: Failed to get a compatible EGLdisplay");
93       return false;
94     }
95 
96     if (eglInitialize(egl_display_, nullptr, nullptr) == EGL_FALSE) {
97       // If all else fails, attempt D3D11 Feature Level 11_0 on WARP as a last
98       // resort
99       egl_display_ = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
100                                               EGL_DEFAULT_DISPLAY,
101                                               warp_display_attributes);
102       if (egl_display_ == EGL_NO_DISPLAY) {
103         OutputDebugString(L"EGL: Failed to get a compatible EGLdisplay");
104         return false;
105       }
106 
107       if (eglInitialize(egl_display_, nullptr, nullptr) == EGL_FALSE) {
108         OutputDebugString(L"EGL: Failed to initialize EGL");
109         return false;
110       }
111     }
112   }
113 
114   EGLint numConfigs = 0;
115   if ((eglChooseConfig(egl_display_, configAttributes, &egl_config_, 1,
116                        &numConfigs) == EGL_FALSE) ||
117       (numConfigs == 0)) {
118     OutputDebugString(L"EGL: Failed to choose first context");
119     return false;
120   }
121 
122   egl_context_ = eglCreateContext(egl_display_, egl_config_, EGL_NO_CONTEXT,
123                                   display_context_attributes);
124   if (egl_context_ == EGL_NO_CONTEXT) {
125     OutputDebugString(L"EGL: Failed to create EGL context");
126     return false;
127   }
128 
129   return true;
130 }
131 
CleanUp()132 void AngleSurfaceManager::CleanUp() {
133   if (egl_display_ != EGL_NO_DISPLAY && egl_context_ != EGL_NO_CONTEXT) {
134     eglDestroyContext(egl_display_, egl_context_);
135     egl_context_ = EGL_NO_CONTEXT;
136   }
137 
138   if (egl_display_ != EGL_NO_DISPLAY) {
139     eglTerminate(egl_display_);
140     egl_display_ = EGL_NO_DISPLAY;
141   }
142 }
143 
CreateSurface(HWND window)144 EGLSurface AngleSurfaceManager::CreateSurface(HWND window) {
145   if (!window || !initialize_succeeded_) {
146     return EGL_NO_SURFACE;
147   }
148 
149   EGLSurface surface = EGL_NO_SURFACE;
150 
151   const EGLint surfaceAttributes[] = {EGL_NONE};
152 
153   surface = eglCreateWindowSurface(egl_display_, egl_config_,
154                                    static_cast<EGLNativeWindowType>(window),
155                                    surfaceAttributes);
156   return surface;
157 }
158 
GetSurfaceDimensions(const EGLSurface surface,EGLint * width,EGLint * height)159 void AngleSurfaceManager::GetSurfaceDimensions(const EGLSurface surface,
160                                                EGLint* width,
161                                                EGLint* height) {
162   if (surface == EGL_NO_SURFACE || !initialize_succeeded_) {
163     width = 0;
164     height = 0;
165     return;
166   }
167 
168   eglQuerySurface(egl_display_, surface, EGL_WIDTH, width);
169   eglQuerySurface(egl_display_, surface, EGL_HEIGHT, height);
170 }
171 
DestroySurface(const EGLSurface surface)172 void AngleSurfaceManager::DestroySurface(const EGLSurface surface) {
173   if (egl_display_ != EGL_NO_DISPLAY && surface != EGL_NO_SURFACE) {
174     eglDestroySurface(egl_display_, surface);
175   }
176 }
177 
MakeCurrent(const EGLSurface surface)178 bool AngleSurfaceManager::MakeCurrent(const EGLSurface surface) {
179   return (eglMakeCurrent(egl_display_, surface, surface, egl_context_) ==
180           EGL_TRUE);
181 }
182 
SwapBuffers(const EGLSurface surface)183 EGLBoolean AngleSurfaceManager::SwapBuffers(const EGLSurface surface) {
184   return (eglSwapBuffers(egl_display_, surface));
185 }
186 
187 }  // namespace flutter