OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gl/gl_surface_egl.h" | 5 #include "ui/gl/gl_surface_egl.h" |
6 | 6 |
7 #if defined(OS_ANDROID) | 7 #if defined(OS_ANDROID) |
8 #include <android/native_window_jni.h> | 8 #include <android/native_window_jni.h> |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 #endif // defined(OS_WIN) | 54 #endif // defined(OS_WIN) |
55 | 55 |
56 using ui::GetLastEGLErrorString; | 56 using ui::GetLastEGLErrorString; |
57 | 57 |
58 namespace gfx { | 58 namespace gfx { |
59 | 59 |
60 namespace { | 60 namespace { |
61 | 61 |
62 EGLConfig g_config; | 62 EGLConfig g_config; |
63 EGLDisplay g_display; | 63 EGLDisplay g_display; |
64 EGLNativeDisplayType g_native_display; | 64 EGLNativeDisplayType g_native_display_type; |
| 65 |
| 66 // In the Cast environment, we need to destroy the EGLNativeDisplayType and |
| 67 // EGLDisplay returned by the GPU platform when we switch to an external app |
| 68 // which will temporarily own all screen and GPU resources. |
| 69 // Even though Chromium is still in the background. |
| 70 // As such, it must be reinitialized each time we come back to the foreground. |
| 71 bool g_initialized = false; |
| 72 int g_num_surfaces = 0; |
| 73 bool g_terminate_pending = false; |
65 | 74 |
66 const char* g_egl_extensions = NULL; | 75 const char* g_egl_extensions = NULL; |
67 bool g_egl_create_context_robustness_supported = false; | 76 bool g_egl_create_context_robustness_supported = false; |
68 bool g_egl_sync_control_supported = false; | 77 bool g_egl_sync_control_supported = false; |
69 bool g_egl_window_fixed_size_supported = false; | 78 bool g_egl_window_fixed_size_supported = false; |
70 bool g_egl_surfaceless_context_supported = false; | 79 bool g_egl_surfaceless_context_supported = false; |
71 | 80 |
72 class EGLSyncControlVSyncProvider | 81 class EGLSyncControlVSyncProvider |
73 : public gfx::SyncControlVSyncProvider { | 82 : public gfx::SyncControlVSyncProvider { |
74 public: | 83 public: |
(...skipping 23 matching lines...) Expand all Loading... |
98 bool GetMscRate(int32* numerator, int32* denominator) override { | 107 bool GetMscRate(int32* numerator, int32* denominator) override { |
99 return false; | 108 return false; |
100 } | 109 } |
101 | 110 |
102 private: | 111 private: |
103 EGLSurface surface_; | 112 EGLSurface surface_; |
104 | 113 |
105 DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider); | 114 DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider); |
106 }; | 115 }; |
107 | 116 |
| 117 void DeinitializeEgl() { |
| 118 if (g_initialized) { |
| 119 g_initialized = false; |
| 120 eglTerminate(g_display); |
| 121 } |
| 122 } |
| 123 |
108 } // namespace | 124 } // namespace |
109 | 125 |
110 GLSurfaceEGL::GLSurfaceEGL() {} | 126 GLSurfaceEGL::GLSurfaceEGL() { |
| 127 ++g_num_surfaces; |
| 128 if (!g_initialized) { |
| 129 bool result = GLSurfaceEGL::InitializeOneOff(); |
| 130 DCHECK(result); |
| 131 DCHECK(g_initialized); |
| 132 } |
| 133 } |
111 | 134 |
112 bool GLSurfaceEGL::InitializeOneOff() { | 135 bool GLSurfaceEGL::InitializeOneOff() { |
113 static bool initialized = false; | 136 if (g_initialized) |
114 if (initialized) | |
115 return true; | 137 return true; |
116 | 138 |
117 g_native_display = GetPlatformDefaultEGLNativeDisplay(); | 139 g_native_display_type = GetPlatformDefaultEGLNativeDisplay(); |
118 | 140 |
119 #if defined(OS_WIN) | 141 #if defined(OS_WIN) |
120 g_display = GetPlatformDisplay(g_native_display); | 142 g_display = GetPlatformDisplay(g_native_display_type); |
121 #else | 143 #else |
122 g_display = eglGetDisplay(g_native_display); | 144 g_display = eglGetDisplay(g_native_display_type); |
123 #endif | 145 #endif |
124 | 146 |
125 if (!g_display) { | 147 if (!g_display) { |
126 LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString(); | 148 LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString(); |
127 return false; | 149 return false; |
128 } | 150 } |
129 | 151 |
130 if (!eglInitialize(g_display, NULL, NULL)) { | 152 if (!eglInitialize(g_display, NULL, NULL)) { |
131 LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString(); | 153 LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString(); |
132 return false; | 154 return false; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 } | 202 } |
181 | 203 |
182 g_egl_extensions = eglQueryString(g_display, EGL_EXTENSIONS); | 204 g_egl_extensions = eglQueryString(g_display, EGL_EXTENSIONS); |
183 g_egl_create_context_robustness_supported = | 205 g_egl_create_context_robustness_supported = |
184 HasEGLExtension("EGL_EXT_create_context_robustness"); | 206 HasEGLExtension("EGL_EXT_create_context_robustness"); |
185 g_egl_sync_control_supported = | 207 g_egl_sync_control_supported = |
186 HasEGLExtension("EGL_CHROMIUM_sync_control"); | 208 HasEGLExtension("EGL_CHROMIUM_sync_control"); |
187 g_egl_window_fixed_size_supported = | 209 g_egl_window_fixed_size_supported = |
188 HasEGLExtension("EGL_ANGLE_window_fixed_size"); | 210 HasEGLExtension("EGL_ANGLE_window_fixed_size"); |
189 | 211 |
| 212 // We always succeed beyond this point so set g_initialized here to avoid |
| 213 // infinite recursion through CreateGLContext and GetDisplay |
| 214 // if g_egl_surfaceless_context_supported. |
| 215 g_initialized = true; |
| 216 g_terminate_pending = false; |
| 217 |
190 // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary | 218 // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary |
191 // workaround, since code written for Android WebView takes different paths | 219 // workaround, since code written for Android WebView takes different paths |
192 // based on whether GL surface objects have underlying EGL surface handles, | 220 // based on whether GL surface objects have underlying EGL surface handles, |
193 // conflicting with the use of surfaceless. See https://crbug.com/382349 | 221 // conflicting with the use of surfaceless. See https://crbug.com/382349 |
194 #if defined(OS_ANDROID) | 222 #if defined(OS_ANDROID) |
195 DCHECK(!g_egl_surfaceless_context_supported); | 223 DCHECK(!g_egl_surfaceless_context_supported); |
196 #else | 224 #else |
197 // Check if SurfacelessEGL is supported. | 225 // Check if SurfacelessEGL is supported. |
198 g_egl_surfaceless_context_supported = | 226 g_egl_surfaceless_context_supported = |
199 HasEGLExtension("EGL_KHR_surfaceless_context"); | 227 HasEGLExtension("EGL_KHR_surfaceless_context"); |
200 if (g_egl_surfaceless_context_supported) { | 228 if (g_egl_surfaceless_context_supported) { |
201 // EGL_KHR_surfaceless_context is supported but ensure | 229 // EGL_KHR_surfaceless_context is supported but ensure |
202 // GL_OES_surfaceless_context is also supported. We need a current context | 230 // GL_OES_surfaceless_context is also supported. We need a current context |
203 // to query for supported GL extensions. | 231 // to query for supported GL extensions. |
204 scoped_refptr<GLSurface> surface = new SurfacelessEGL(Size(1, 1)); | 232 scoped_refptr<GLSurface> surface = new SurfacelessEGL(Size(1, 1)); |
205 scoped_refptr<GLContext> context = GLContext::CreateGLContext( | 233 scoped_refptr<GLContext> context = GLContext::CreateGLContext( |
206 NULL, surface.get(), PreferIntegratedGpu); | 234 NULL, surface.get(), PreferIntegratedGpu); |
207 if (!context->MakeCurrent(surface.get())) | 235 if (!context->MakeCurrent(surface.get())) |
208 g_egl_surfaceless_context_supported = false; | 236 g_egl_surfaceless_context_supported = false; |
209 | 237 |
210 // Ensure context supports GL_OES_surfaceless_context. | 238 // Ensure context supports GL_OES_surfaceless_context. |
211 if (g_egl_surfaceless_context_supported) { | 239 if (g_egl_surfaceless_context_supported) { |
212 g_egl_surfaceless_context_supported = context->HasExtension( | 240 g_egl_surfaceless_context_supported = context->HasExtension( |
213 "GL_OES_surfaceless_context"); | 241 "GL_OES_surfaceless_context"); |
214 context->ReleaseCurrent(surface.get()); | 242 context->ReleaseCurrent(surface.get()); |
215 } | 243 } |
216 } | 244 } |
217 #endif | 245 #endif |
218 | 246 |
219 initialized = true; | |
220 | |
221 return true; | 247 return true; |
222 } | 248 } |
223 | 249 |
224 EGLDisplay GLSurfaceEGL::GetDisplay() { | 250 EGLDisplay GLSurfaceEGL::GetDisplay() { |
| 251 DCHECK(g_initialized); |
225 return g_display; | 252 return g_display; |
226 } | 253 } |
227 | 254 |
| 255 // static |
228 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() { | 256 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() { |
| 257 if (!g_initialized) { |
| 258 bool result = GLSurfaceEGL::InitializeOneOff(); |
| 259 DCHECK(result); |
| 260 } |
229 return g_display; | 261 return g_display; |
230 } | 262 } |
231 | 263 |
| 264 // static |
232 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { | 265 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { |
233 return g_native_display; | 266 if (!g_initialized) { |
| 267 bool result = GLSurfaceEGL::InitializeOneOff(); |
| 268 DCHECK(result); |
| 269 } |
| 270 return g_native_display_type; |
234 } | 271 } |
235 | 272 |
236 const char* GLSurfaceEGL::GetEGLExtensions() { | 273 const char* GLSurfaceEGL::GetEGLExtensions() { |
| 274 // No need for InitializeOneOff. Assume that extensions will not change |
| 275 // after the first initialization. |
237 return g_egl_extensions; | 276 return g_egl_extensions; |
238 } | 277 } |
239 | 278 |
240 bool GLSurfaceEGL::HasEGLExtension(const char* name) { | 279 bool GLSurfaceEGL::HasEGLExtension(const char* name) { |
241 return ExtensionsContain(GetEGLExtensions(), name); | 280 return ExtensionsContain(GetEGLExtensions(), name); |
242 } | 281 } |
243 | 282 |
244 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() { | 283 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() { |
245 return g_egl_create_context_robustness_supported; | 284 return g_egl_create_context_robustness_supported; |
246 } | 285 } |
247 | 286 |
248 bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() { | 287 bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() { |
249 return g_egl_surfaceless_context_supported; | 288 return g_egl_surfaceless_context_supported; |
250 } | 289 } |
251 | 290 |
252 GLSurfaceEGL::~GLSurfaceEGL() {} | 291 void GLSurfaceEGL::DestroyAndTerminateDisplay() { |
| 292 DCHECK(g_initialized); |
| 293 DCHECK_EQ(g_num_surfaces, 1); |
| 294 Destroy(); |
| 295 g_terminate_pending = true; |
| 296 } |
| 297 |
| 298 GLSurfaceEGL::~GLSurfaceEGL() { |
| 299 DCHECK_GT(g_num_surfaces, 0) << "Bad surface count"; |
| 300 if (--g_num_surfaces == 0 && g_terminate_pending) { |
| 301 DeinitializeEgl(); |
| 302 g_terminate_pending = false; |
| 303 } |
| 304 } |
253 | 305 |
254 #if defined(OS_WIN) | 306 #if defined(OS_WIN) |
255 static const EGLint kDisplayAttribsWarp[] { | 307 static const EGLint kDisplayAttribsWarp[] { |
256 EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, | 308 EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, |
257 EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_TRUE, | 309 EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_TRUE, |
258 EGL_NONE | 310 EGL_NONE |
259 }; | 311 }; |
260 | 312 |
261 // static | 313 // static |
262 EGLDisplay GLSurfaceEGL::GetPlatformDisplay( | 314 EGLDisplay GLSurfaceEGL::GetPlatformDisplay( |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 } | 760 } |
709 | 761 |
710 void* SurfacelessEGL::GetShareHandle() { | 762 void* SurfacelessEGL::GetShareHandle() { |
711 return NULL; | 763 return NULL; |
712 } | 764 } |
713 | 765 |
714 SurfacelessEGL::~SurfacelessEGL() { | 766 SurfacelessEGL::~SurfacelessEGL() { |
715 } | 767 } |
716 | 768 |
717 } // namespace gfx | 769 } // namespace gfx |
OLD | NEW |