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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
55 namespace gfx { | 55 namespace gfx { |
56 | 56 |
57 unsigned int NativeViewGLSurfaceEGL::current_swap_generation_ = 0; | 57 unsigned int NativeViewGLSurfaceEGL::current_swap_generation_ = 0; |
58 | 58 |
59 namespace { | 59 namespace { |
60 | 60 |
61 EGLConfig g_config; | 61 EGLConfig g_config; |
62 EGLDisplay g_display; | 62 EGLDisplay g_display; |
63 EGLNativeDisplayType g_native_display; | 63 EGLNativeDisplayType g_native_display; |
64 | 64 |
65 // In the Cast environment, we need to destroy the displayType | |
66 // returned by the GPU platform when we switch to an external app | |
67 // which will temporarily own all screen and GPU resources. | |
68 // Even though Chromium is still in the background. | |
69 // As such, it must be reinitialized each time we come back to the foreground. | |
70 bool g_initialized = false; | |
71 int g_num_surfaces = 0; | |
72 | |
65 const char* g_egl_extensions = NULL; | 73 const char* g_egl_extensions = NULL; |
66 bool g_egl_create_context_robustness_supported = false; | 74 bool g_egl_create_context_robustness_supported = false; |
67 bool g_egl_sync_control_supported = false; | 75 bool g_egl_sync_control_supported = false; |
68 bool g_egl_window_fixed_size_supported = false; | 76 bool g_egl_window_fixed_size_supported = false; |
69 bool g_egl_surfaceless_context_supported = false; | 77 bool g_egl_surfaceless_context_supported = false; |
70 | 78 |
71 class EGLSyncControlVSyncProvider | 79 class EGLSyncControlVSyncProvider |
72 : public gfx::SyncControlVSyncProvider { | 80 : public gfx::SyncControlVSyncProvider { |
73 public: | 81 public: |
74 explicit EGLSyncControlVSyncProvider(EGLSurface surface) | 82 explicit EGLSyncControlVSyncProvider(EGLSurface surface) |
(...skipping 27 matching lines...) Expand all Loading... | |
102 EGLSurface surface_; | 110 EGLSurface surface_; |
103 | 111 |
104 DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider); | 112 DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider); |
105 }; | 113 }; |
106 | 114 |
107 } // namespace | 115 } // namespace |
108 | 116 |
109 GLSurfaceEGL::GLSurfaceEGL() {} | 117 GLSurfaceEGL::GLSurfaceEGL() {} |
110 | 118 |
111 bool GLSurfaceEGL::InitializeOneOff() { | 119 bool GLSurfaceEGL::InitializeOneOff() { |
112 static bool initialized = false; | 120 if (g_initialized) |
113 if (initialized) | |
114 return true; | 121 return true; |
115 | 122 |
116 g_native_display = GetPlatformDefaultEGLNativeDisplay(); | 123 g_native_display = GetPlatformDefaultEGLNativeDisplay(); |
117 | 124 |
118 #if defined(OS_WIN) | 125 #if defined(OS_WIN) |
119 g_display = GetPlatformDisplay(g_native_display); | 126 g_display = GetPlatformDisplay(g_native_display); |
120 #else | 127 #else |
121 g_display = eglGetDisplay(g_native_display); | 128 g_display = eglGetDisplay(g_native_display); |
122 #endif | 129 #endif |
123 | 130 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 } | 186 } |
180 | 187 |
181 g_egl_extensions = eglQueryString(g_display, EGL_EXTENSIONS); | 188 g_egl_extensions = eglQueryString(g_display, EGL_EXTENSIONS); |
182 g_egl_create_context_robustness_supported = | 189 g_egl_create_context_robustness_supported = |
183 HasEGLExtension("EGL_EXT_create_context_robustness"); | 190 HasEGLExtension("EGL_EXT_create_context_robustness"); |
184 g_egl_sync_control_supported = | 191 g_egl_sync_control_supported = |
185 HasEGLExtension("EGL_CHROMIUM_sync_control"); | 192 HasEGLExtension("EGL_CHROMIUM_sync_control"); |
186 g_egl_window_fixed_size_supported = | 193 g_egl_window_fixed_size_supported = |
187 HasEGLExtension("EGL_ANGLE_window_fixed_size"); | 194 HasEGLExtension("EGL_ANGLE_window_fixed_size"); |
188 | 195 |
196 // We always succeed beyond this point so set g_initialized here to avoid | |
197 // infinite recursion through CreateGLContext and GetDisplay | |
198 // if g_egl_surfaceless_context_supported. | |
199 g_initialized = true; | |
200 | |
189 // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary | 201 // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary |
190 // workaround, since code written for Android WebView takes different paths | 202 // workaround, since code written for Android WebView takes different paths |
191 // based on whether GL surface objects have underlying EGL surface handles, | 203 // based on whether GL surface objects have underlying EGL surface handles, |
192 // conflicting with the use of surfaceless. See https://crbug.com/382349 | 204 // conflicting with the use of surfaceless. See https://crbug.com/382349 |
193 #if defined(OS_ANDROID) | 205 #if defined(OS_ANDROID) |
194 DCHECK(!g_egl_surfaceless_context_supported); | 206 DCHECK(!g_egl_surfaceless_context_supported); |
195 #else | 207 #else |
196 // Check if SurfacelessEGL is supported. | 208 // Check if SurfacelessEGL is supported. |
197 g_egl_surfaceless_context_supported = | 209 g_egl_surfaceless_context_supported = |
198 HasEGLExtension("EGL_KHR_surfaceless_context"); | 210 HasEGLExtension("EGL_KHR_surfaceless_context"); |
199 if (g_egl_surfaceless_context_supported) { | 211 if (g_egl_surfaceless_context_supported) { |
200 // EGL_KHR_surfaceless_context is supported but ensure | 212 // EGL_KHR_surfaceless_context is supported but ensure |
201 // GL_OES_surfaceless_context is also supported. We need a current context | 213 // GL_OES_surfaceless_context is also supported. We need a current context |
202 // to query for supported GL extensions. | 214 // to query for supported GL extensions. |
203 scoped_refptr<GLSurface> surface = new SurfacelessEGL(Size(1, 1)); | 215 scoped_refptr<GLSurface> surface = new SurfacelessEGL(Size(1, 1)); |
204 scoped_refptr<GLContext> context = GLContext::CreateGLContext( | 216 scoped_refptr<GLContext> context = GLContext::CreateGLContext( |
205 NULL, surface.get(), PreferIntegratedGpu); | 217 NULL, surface.get(), PreferIntegratedGpu); |
206 if (!context->MakeCurrent(surface.get())) | 218 if (!context->MakeCurrent(surface.get())) |
207 g_egl_surfaceless_context_supported = false; | 219 g_egl_surfaceless_context_supported = false; |
208 | 220 |
209 // Ensure context supports GL_OES_surfaceless_context. | 221 // Ensure context supports GL_OES_surfaceless_context. |
210 if (g_egl_surfaceless_context_supported) { | 222 if (g_egl_surfaceless_context_supported) { |
211 g_egl_surfaceless_context_supported = context->HasExtension( | 223 g_egl_surfaceless_context_supported = context->HasExtension( |
212 "GL_OES_surfaceless_context"); | 224 "GL_OES_surfaceless_context"); |
213 context->ReleaseCurrent(surface.get()); | 225 context->ReleaseCurrent(surface.get()); |
214 } | 226 } |
215 } | 227 } |
216 #endif | 228 #endif |
217 | 229 |
218 initialized = true; | |
219 | |
220 return true; | 230 return true; |
221 } | 231 } |
222 | 232 |
233 // static | |
234 void GLSurfaceEGL::Deinitialize() { | |
235 g_initialized = false; | |
236 } | |
237 | |
223 EGLDisplay GLSurfaceEGL::GetDisplay() { | 238 EGLDisplay GLSurfaceEGL::GetDisplay() { |
239 if (!g_initialized) { | |
240 bool result = GLSurfaceEGL::InitializeOneOff(); | |
241 DCHECK(result); | |
242 } | |
224 return g_display; | 243 return g_display; |
225 } | 244 } |
226 | 245 |
227 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() { | 246 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() { |
247 if (!g_initialized) { | |
248 bool result = GLSurfaceEGL::InitializeOneOff(); | |
249 DCHECK(result); | |
250 } | |
228 return g_display; | 251 return g_display; |
229 } | 252 } |
230 | 253 |
231 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { | 254 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { |
255 if (!g_initialized) { | |
256 bool result = GLSurfaceEGL::InitializeOneOff(); | |
257 DCHECK(result); | |
258 } | |
232 return g_native_display; | 259 return g_native_display; |
233 } | 260 } |
234 | 261 |
235 const char* GLSurfaceEGL::GetEGLExtensions() { | 262 const char* GLSurfaceEGL::GetEGLExtensions() { |
263 // No need for InitializeOneOff. Assume that extensions will not change | |
264 // after the first initialization. | |
236 return g_egl_extensions; | 265 return g_egl_extensions; |
237 } | 266 } |
238 | 267 |
239 bool GLSurfaceEGL::HasEGLExtension(const char* name) { | 268 bool GLSurfaceEGL::HasEGLExtension(const char* name) { |
240 return ExtensionsContain(GetEGLExtensions(), name); | 269 return ExtensionsContain(GetEGLExtensions(), name); |
241 } | 270 } |
242 | 271 |
243 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() { | 272 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() { |
244 return g_egl_create_context_robustness_supported; | 273 return g_egl_create_context_robustness_supported; |
245 } | 274 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 EGLBoolean retVal = eglQuerySurface(GetDisplay(), | 377 EGLBoolean retVal = eglQuerySurface(GetDisplay(), |
349 surface_, | 378 surface_, |
350 EGL_POST_SUB_BUFFER_SUPPORTED_NV, | 379 EGL_POST_SUB_BUFFER_SUPPORTED_NV, |
351 &surfaceVal); | 380 &surfaceVal); |
352 supports_post_sub_buffer_ = (surfaceVal && retVal) == EGL_TRUE; | 381 supports_post_sub_buffer_ = (surfaceVal && retVal) == EGL_TRUE; |
353 | 382 |
354 if (sync_provider) | 383 if (sync_provider) |
355 vsync_provider_.reset(sync_provider.release()); | 384 vsync_provider_.reset(sync_provider.release()); |
356 else if (g_egl_sync_control_supported) | 385 else if (g_egl_sync_control_supported) |
357 vsync_provider_.reset(new EGLSyncControlVSyncProvider(surface_)); | 386 vsync_provider_.reset(new EGLSyncControlVSyncProvider(surface_)); |
387 ++g_num_surfaces; | |
358 return true; | 388 return true; |
359 } | 389 } |
360 | 390 |
361 void NativeViewGLSurfaceEGL::Destroy() { | 391 void NativeViewGLSurfaceEGL::Destroy() { |
362 if (surface_) { | 392 if (surface_) { |
363 if (!eglDestroySurface(GetDisplay(), surface_)) { | 393 if (!eglDestroySurface(GetDisplay(), surface_)) { |
364 LOG(ERROR) << "eglDestroySurface failed with error " | 394 LOG(ERROR) << "eglDestroySurface failed with error " |
365 << GetLastEGLErrorString(); | 395 << GetLastEGLErrorString(); |
366 } | 396 } |
367 surface_ = NULL; | 397 surface_ = NULL; |
398 CHECK(g_num_surfaces > 0) << "Bad surface count"; | |
jbauman
2014/11/12 01:47:28
DCHECK probably makes more sense here.
GusFernandez
2014/11/15 02:11:56
Done.
| |
399 if (--g_num_surfaces == 0) { | |
400 GLSurfaceEGL::Deinitialize(); | |
401 } | |
368 } | 402 } |
369 } | 403 } |
370 | 404 |
371 EGLConfig NativeViewGLSurfaceEGL::GetConfig() { | 405 EGLConfig NativeViewGLSurfaceEGL::GetConfig() { |
372 #if !defined(USE_X11) | 406 #if !defined(USE_X11) |
373 return g_config; | 407 return g_config; |
374 #else | 408 #else |
375 if (!config_) { | 409 if (!config_) { |
376 // Get a config compatible with the window | 410 // Get a config compatible with the window |
377 DCHECK(window_); | 411 DCHECK(window_); |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
601 | 635 |
602 EGLSurface new_surface = eglCreatePbufferSurface(display, | 636 EGLSurface new_surface = eglCreatePbufferSurface(display, |
603 GetConfig(), | 637 GetConfig(), |
604 pbuffer_attribs); | 638 pbuffer_attribs); |
605 if (!new_surface) { | 639 if (!new_surface) { |
606 LOG(ERROR) << "eglCreatePbufferSurface failed with error " | 640 LOG(ERROR) << "eglCreatePbufferSurface failed with error " |
607 << GetLastEGLErrorString(); | 641 << GetLastEGLErrorString(); |
608 return false; | 642 return false; |
609 } | 643 } |
610 | 644 |
611 if (old_surface) | 645 if (old_surface) { |
612 eglDestroySurface(display, old_surface); | 646 eglDestroySurface(display, old_surface); |
647 } else { | |
648 ++g_num_surfaces; | |
649 } | |
613 | 650 |
614 surface_ = new_surface; | 651 surface_ = new_surface; |
615 return true; | 652 return true; |
616 } | 653 } |
617 | 654 |
618 void PbufferGLSurfaceEGL::Destroy() { | 655 void PbufferGLSurfaceEGL::Destroy() { |
619 if (surface_) { | 656 if (surface_) { |
620 if (!eglDestroySurface(GetDisplay(), surface_)) { | 657 if (!eglDestroySurface(GetDisplay(), surface_)) { |
621 LOG(ERROR) << "eglDestroySurface failed with error " | 658 LOG(ERROR) << "eglDestroySurface failed with error " |
622 << GetLastEGLErrorString(); | 659 << GetLastEGLErrorString(); |
623 } | 660 } |
661 CHECK(g_num_surfaces > 0) << "Bad surface count"; | |
662 if (--g_num_surfaces == 0) { | |
663 GLSurfaceEGL::Deinitialize(); | |
664 } | |
624 surface_ = NULL; | 665 surface_ = NULL; |
625 } | 666 } |
626 } | 667 } |
627 | 668 |
628 EGLConfig PbufferGLSurfaceEGL::GetConfig() { | 669 EGLConfig PbufferGLSurfaceEGL::GetConfig() { |
629 return g_config; | 670 return g_config; |
630 } | 671 } |
631 | 672 |
632 bool PbufferGLSurfaceEGL::IsOffscreen() { | 673 bool PbufferGLSurfaceEGL::IsOffscreen() { |
633 return true; | 674 return true; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 } | 779 } |
739 | 780 |
740 void* SurfacelessEGL::GetShareHandle() { | 781 void* SurfacelessEGL::GetShareHandle() { |
741 return NULL; | 782 return NULL; |
742 } | 783 } |
743 | 784 |
744 SurfacelessEGL::~SurfacelessEGL() { | 785 SurfacelessEGL::~SurfacelessEGL() { |
745 } | 786 } |
746 | 787 |
747 } // namespace gfx | 788 } // namespace gfx |
OLD | NEW |