Chromium Code Reviews| 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 if (g_initialized) { | |
| 236 g_initialized = false; | |
| 237 eglTerminate(g_display); | |
| 238 } | |
| 239 } | |
| 240 | |
| 223 EGLDisplay GLSurfaceEGL::GetDisplay() { | 241 EGLDisplay GLSurfaceEGL::GetDisplay() { |
| 242 if (!g_initialized) { | |
| 243 bool result = GLSurfaceEGL::InitializeOneOff(); | |
| 244 DCHECK(result); | |
| 245 } | |
| 224 return g_display; | 246 return g_display; |
| 225 } | 247 } |
| 226 | 248 |
| 227 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() { | 249 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() { |
| 250 if (!g_initialized) { | |
| 251 bool result = GLSurfaceEGL::InitializeOneOff(); | |
| 252 DCHECK(result); | |
| 253 } | |
| 228 return g_display; | 254 return g_display; |
| 229 } | 255 } |
| 230 | 256 |
| 231 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { | 257 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { |
| 258 if (!g_initialized) { | |
| 259 bool result = GLSurfaceEGL::InitializeOneOff(); | |
| 260 DCHECK(result); | |
| 261 } | |
| 232 return g_native_display; | 262 return g_native_display; |
| 233 } | 263 } |
| 234 | 264 |
| 235 const char* GLSurfaceEGL::GetEGLExtensions() { | 265 const char* GLSurfaceEGL::GetEGLExtensions() { |
| 266 // No need for InitializeOneOff. Assume that extensions will not change | |
| 267 // after the first initialization. | |
| 236 return g_egl_extensions; | 268 return g_egl_extensions; |
| 237 } | 269 } |
| 238 | 270 |
| 239 bool GLSurfaceEGL::HasEGLExtension(const char* name) { | 271 bool GLSurfaceEGL::HasEGLExtension(const char* name) { |
| 240 return ExtensionsContain(GetEGLExtensions(), name); | 272 return ExtensionsContain(GetEGLExtensions(), name); |
| 241 } | 273 } |
| 242 | 274 |
| 243 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() { | 275 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() { |
| 244 return g_egl_create_context_robustness_supported; | 276 return g_egl_create_context_robustness_supported; |
| 245 } | 277 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 348 EGLBoolean retVal = eglQuerySurface(GetDisplay(), | 380 EGLBoolean retVal = eglQuerySurface(GetDisplay(), |
| 349 surface_, | 381 surface_, |
| 350 EGL_POST_SUB_BUFFER_SUPPORTED_NV, | 382 EGL_POST_SUB_BUFFER_SUPPORTED_NV, |
| 351 &surfaceVal); | 383 &surfaceVal); |
| 352 supports_post_sub_buffer_ = (surfaceVal && retVal) == EGL_TRUE; | 384 supports_post_sub_buffer_ = (surfaceVal && retVal) == EGL_TRUE; |
| 353 | 385 |
| 354 if (sync_provider) | 386 if (sync_provider) |
| 355 vsync_provider_.reset(sync_provider.release()); | 387 vsync_provider_.reset(sync_provider.release()); |
| 356 else if (g_egl_sync_control_supported) | 388 else if (g_egl_sync_control_supported) |
| 357 vsync_provider_.reset(new EGLSyncControlVSyncProvider(surface_)); | 389 vsync_provider_.reset(new EGLSyncControlVSyncProvider(surface_)); |
| 390 ++g_num_surfaces; | |
|
piman
2014/11/18 20:55:34
Could that tracking be done in the constructor/des
GusFernandez
2014/11/19 18:50:13
Good idea. This simplified the code somewhat.
| |
| 358 return true; | 391 return true; |
| 359 } | 392 } |
| 360 | 393 |
| 361 void NativeViewGLSurfaceEGL::Destroy() { | 394 void NativeViewGLSurfaceEGL::Destroy() { |
| 362 if (surface_) { | 395 if (surface_) { |
| 363 if (!eglDestroySurface(GetDisplay(), surface_)) { | 396 if (!eglDestroySurface(GetDisplay(), surface_)) { |
| 364 LOG(ERROR) << "eglDestroySurface failed with error " | 397 LOG(ERROR) << "eglDestroySurface failed with error " |
| 365 << GetLastEGLErrorString(); | 398 << GetLastEGLErrorString(); |
| 366 } | 399 } |
| 367 surface_ = NULL; | 400 surface_ = NULL; |
| 401 DCHECK_GT(g_num_surfaces, 0) << "Bad surface count"; | |
| 402 if (--g_num_surfaces == 0) { | |
| 403 DVLOG(2) << "Destroyed last (native) EGL surface. Deinitializing."; | |
| 404 GLSurfaceEGL::Deinitialize(); | |
| 405 } | |
| 368 } | 406 } |
| 369 } | 407 } |
| 370 | 408 |
| 371 EGLConfig NativeViewGLSurfaceEGL::GetConfig() { | 409 EGLConfig NativeViewGLSurfaceEGL::GetConfig() { |
| 372 #if !defined(USE_X11) | 410 #if !defined(USE_X11) |
| 373 return g_config; | 411 return g_config; |
| 374 #else | 412 #else |
| 375 if (!config_) { | 413 if (!config_) { |
| 376 // Get a config compatible with the window | 414 // Get a config compatible with the window |
| 377 DCHECK(window_); | 415 DCHECK(window_); |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 601 | 639 |
| 602 EGLSurface new_surface = eglCreatePbufferSurface(display, | 640 EGLSurface new_surface = eglCreatePbufferSurface(display, |
| 603 GetConfig(), | 641 GetConfig(), |
| 604 pbuffer_attribs); | 642 pbuffer_attribs); |
| 605 if (!new_surface) { | 643 if (!new_surface) { |
| 606 LOG(ERROR) << "eglCreatePbufferSurface failed with error " | 644 LOG(ERROR) << "eglCreatePbufferSurface failed with error " |
| 607 << GetLastEGLErrorString(); | 645 << GetLastEGLErrorString(); |
| 608 return false; | 646 return false; |
| 609 } | 647 } |
| 610 | 648 |
| 611 if (old_surface) | 649 if (old_surface) { |
| 612 eglDestroySurface(display, old_surface); | 650 eglDestroySurface(display, old_surface); |
| 651 DVLOG(2) << "Reinitialized pbuffer surface. EGL surface count remains at " | |
| 652 << g_num_surfaces; | |
| 653 } else { | |
| 654 ++g_num_surfaces; | |
| 655 DVLOG(2) << "Initialized new pbuffer surface. EGL surface count now " | |
| 656 << g_num_surfaces; | |
| 657 } | |
| 613 | 658 |
| 614 surface_ = new_surface; | 659 surface_ = new_surface; |
| 615 return true; | 660 return true; |
| 616 } | 661 } |
| 617 | 662 |
| 618 void PbufferGLSurfaceEGL::Destroy() { | 663 void PbufferGLSurfaceEGL::Destroy() { |
| 619 if (surface_) { | 664 if (surface_) { |
| 620 if (!eglDestroySurface(GetDisplay(), surface_)) { | 665 if (!eglDestroySurface(GetDisplay(), surface_)) { |
| 621 LOG(ERROR) << "eglDestroySurface failed with error " | 666 LOG(ERROR) << "eglDestroySurface failed with error " |
| 622 << GetLastEGLErrorString(); | 667 << GetLastEGLErrorString(); |
| 623 } | 668 } |
| 669 CHECK_GT(g_num_surfaces, 0) << "Bad surface count"; | |
|
piman
2014/11/18 20:55:34
nit: DCHECK_GT
GusFernandez
2014/11/19 18:50:13
Irrelevant after the change above.
| |
| 670 if (--g_num_surfaces == 0) { | |
| 671 DVLOG(2) << "Destroyed last (pbuffer) EGL surface. Deinitializing."; | |
| 672 GLSurfaceEGL::Deinitialize(); | |
| 673 } | |
| 624 surface_ = NULL; | 674 surface_ = NULL; |
| 625 } | 675 } |
| 626 } | 676 } |
| 627 | 677 |
| 628 EGLConfig PbufferGLSurfaceEGL::GetConfig() { | 678 EGLConfig PbufferGLSurfaceEGL::GetConfig() { |
| 629 return g_config; | 679 return g_config; |
| 630 } | 680 } |
| 631 | 681 |
| 632 bool PbufferGLSurfaceEGL::IsOffscreen() { | 682 bool PbufferGLSurfaceEGL::IsOffscreen() { |
| 633 return true; | 683 return true; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 738 } | 788 } |
| 739 | 789 |
| 740 void* SurfacelessEGL::GetShareHandle() { | 790 void* SurfacelessEGL::GetShareHandle() { |
| 741 return NULL; | 791 return NULL; |
| 742 } | 792 } |
| 743 | 793 |
| 744 SurfacelessEGL::~SurfacelessEGL() { | 794 SurfacelessEGL::~SurfacelessEGL() { |
| 745 } | 795 } |
| 746 | 796 |
| 747 } // namespace gfx | 797 } // namespace gfx |
| OLD | NEW |