| 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 unsigned int NativeViewGLSurfaceEGL::swaps_this_generation_ = 0; | 78 unsigned int NativeViewGLSurfaceEGL::swaps_this_generation_ = 0; |
| 79 unsigned int NativeViewGLSurfaceEGL::last_multiswap_generation_ = 0; | 79 unsigned int NativeViewGLSurfaceEGL::last_multiswap_generation_ = 0; |
| 80 | 80 |
| 81 const unsigned int MULTISWAP_FRAME_VSYNC_THRESHOLD = 60; | 81 const unsigned int MULTISWAP_FRAME_VSYNC_THRESHOLD = 60; |
| 82 #endif | 82 #endif |
| 83 | 83 |
| 84 namespace { | 84 namespace { |
| 85 | 85 |
| 86 EGLConfig g_config; | 86 EGLConfig g_config; |
| 87 EGLDisplay g_display; | 87 EGLDisplay g_display; |
| 88 EGLNativeDisplayType g_native_display_type; | 88 EGLNativeDisplayType g_native_display; |
| 89 | |
| 90 // In the Cast environment, we need to destroy the EGLNativeDisplayType and | |
| 91 // EGLDisplay returned by the GPU platform when we switch to an external app | |
| 92 // which will temporarily own all screen and GPU resources. | |
| 93 // Even though Chromium is still in the background. | |
| 94 // As such, it must be reinitialized each time we come back to the foreground. | |
| 95 bool g_initialized = false; | |
| 96 int g_num_surfaces = 0; | |
| 97 bool g_terminate_pending = false; | |
| 98 | 89 |
| 99 const char* g_egl_extensions = NULL; | 90 const char* g_egl_extensions = NULL; |
| 100 bool g_egl_create_context_robustness_supported = false; | 91 bool g_egl_create_context_robustness_supported = false; |
| 101 bool g_egl_sync_control_supported = false; | 92 bool g_egl_sync_control_supported = false; |
| 102 bool g_egl_window_fixed_size_supported = false; | 93 bool g_egl_window_fixed_size_supported = false; |
| 103 bool g_egl_surfaceless_context_supported = false; | 94 bool g_egl_surfaceless_context_supported = false; |
| 104 | 95 |
| 105 class EGLSyncControlVSyncProvider | 96 class EGLSyncControlVSyncProvider |
| 106 : public gfx::SyncControlVSyncProvider { | 97 : public gfx::SyncControlVSyncProvider { |
| 107 public: | 98 public: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 131 bool GetMscRate(int32* numerator, int32* denominator) override { | 122 bool GetMscRate(int32* numerator, int32* denominator) override { |
| 132 return false; | 123 return false; |
| 133 } | 124 } |
| 134 | 125 |
| 135 private: | 126 private: |
| 136 EGLSurface surface_; | 127 EGLSurface surface_; |
| 137 | 128 |
| 138 DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider); | 129 DISALLOW_COPY_AND_ASSIGN(EGLSyncControlVSyncProvider); |
| 139 }; | 130 }; |
| 140 | 131 |
| 141 void DeinitializeEgl() { | |
| 142 if (g_initialized) { | |
| 143 g_initialized = false; | |
| 144 eglTerminate(g_display); | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 EGLDisplay GetPlatformANGLEDisplay(EGLNativeDisplayType native_display, | 132 EGLDisplay GetPlatformANGLEDisplay(EGLNativeDisplayType native_display, |
| 149 EGLenum platform_type, | 133 EGLenum platform_type, |
| 150 bool warpDevice) { | 134 bool warpDevice) { |
| 151 std::vector<EGLint> display_attribs; | 135 std::vector<EGLint> display_attribs; |
| 152 | 136 |
| 153 display_attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); | 137 display_attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); |
| 154 display_attribs.push_back(platform_type); | 138 display_attribs.push_back(platform_type); |
| 155 | 139 |
| 156 if (warpDevice) { | 140 if (warpDevice) { |
| 157 display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE); | 141 display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 } | 247 } |
| 264 } | 248 } |
| 265 | 249 |
| 266 // If no displays are available due to missing angle extensions or invalid | 250 // If no displays are available due to missing angle extensions or invalid |
| 267 // flags, request the default display. | 251 // flags, request the default display. |
| 268 if (init_displays->empty()) { | 252 if (init_displays->empty()) { |
| 269 init_displays->push_back(DEFAULT); | 253 init_displays->push_back(DEFAULT); |
| 270 } | 254 } |
| 271 } | 255 } |
| 272 | 256 |
| 273 GLSurfaceEGL::GLSurfaceEGL() { | 257 GLSurfaceEGL::GLSurfaceEGL() {} |
| 274 ++g_num_surfaces; | |
| 275 if (!g_initialized) { | |
| 276 bool result = GLSurfaceEGL::InitializeOneOff(); | |
| 277 DCHECK(result); | |
| 278 DCHECK(g_initialized); | |
| 279 } | |
| 280 } | |
| 281 | 258 |
| 282 bool GLSurfaceEGL::InitializeOneOff() { | 259 bool GLSurfaceEGL::InitializeOneOff() { |
| 283 if (g_initialized) | 260 static bool initialized = false; |
| 261 if (initialized) |
| 284 return true; | 262 return true; |
| 285 | 263 |
| 286 InitializeDisplay(); | 264 InitializeDisplay(); |
| 287 if (g_display == EGL_NO_DISPLAY) | 265 if (g_display == EGL_NO_DISPLAY) |
| 288 return false; | 266 return false; |
| 289 | 267 |
| 290 // Choose an EGL configuration. | 268 // Choose an EGL configuration. |
| 291 // On X this is only used for PBuffer surfaces. | 269 // On X this is only used for PBuffer surfaces. |
| 292 EGLint renderable_type = EGL_OPENGL_ES2_BIT; | 270 EGLint renderable_type = EGL_OPENGL_ES2_BIT; |
| 293 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 271 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 } | 318 } |
| 341 | 319 |
| 342 g_egl_extensions = eglQueryString(g_display, EGL_EXTENSIONS); | 320 g_egl_extensions = eglQueryString(g_display, EGL_EXTENSIONS); |
| 343 g_egl_create_context_robustness_supported = | 321 g_egl_create_context_robustness_supported = |
| 344 HasEGLExtension("EGL_EXT_create_context_robustness"); | 322 HasEGLExtension("EGL_EXT_create_context_robustness"); |
| 345 g_egl_sync_control_supported = | 323 g_egl_sync_control_supported = |
| 346 HasEGLExtension("EGL_CHROMIUM_sync_control"); | 324 HasEGLExtension("EGL_CHROMIUM_sync_control"); |
| 347 g_egl_window_fixed_size_supported = | 325 g_egl_window_fixed_size_supported = |
| 348 HasEGLExtension("EGL_ANGLE_window_fixed_size"); | 326 HasEGLExtension("EGL_ANGLE_window_fixed_size"); |
| 349 | 327 |
| 350 // We always succeed beyond this point so set g_initialized here to avoid | |
| 351 // infinite recursion through CreateGLContext and GetDisplay | |
| 352 // if g_egl_surfaceless_context_supported. | |
| 353 g_initialized = true; | |
| 354 g_terminate_pending = false; | |
| 355 | |
| 356 // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary | 328 // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary |
| 357 // workaround, since code written for Android WebView takes different paths | 329 // workaround, since code written for Android WebView takes different paths |
| 358 // based on whether GL surface objects have underlying EGL surface handles, | 330 // based on whether GL surface objects have underlying EGL surface handles, |
| 359 // conflicting with the use of surfaceless. See https://crbug.com/382349 | 331 // conflicting with the use of surfaceless. See https://crbug.com/382349 |
| 360 #if defined(OS_ANDROID) | 332 #if defined(OS_ANDROID) |
| 361 DCHECK(!g_egl_surfaceless_context_supported); | 333 DCHECK(!g_egl_surfaceless_context_supported); |
| 362 #else | 334 #else |
| 363 // Check if SurfacelessEGL is supported. | 335 // Check if SurfacelessEGL is supported. |
| 364 g_egl_surfaceless_context_supported = | 336 g_egl_surfaceless_context_supported = |
| 365 HasEGLExtension("EGL_KHR_surfaceless_context"); | 337 HasEGLExtension("EGL_KHR_surfaceless_context"); |
| 366 if (g_egl_surfaceless_context_supported) { | 338 if (g_egl_surfaceless_context_supported) { |
| 367 // EGL_KHR_surfaceless_context is supported but ensure | 339 // EGL_KHR_surfaceless_context is supported but ensure |
| 368 // GL_OES_surfaceless_context is also supported. We need a current context | 340 // GL_OES_surfaceless_context is also supported. We need a current context |
| 369 // to query for supported GL extensions. | 341 // to query for supported GL extensions. |
| 370 scoped_refptr<GLSurface> surface = new SurfacelessEGL(Size(1, 1)); | 342 scoped_refptr<GLSurface> surface = new SurfacelessEGL(Size(1, 1)); |
| 371 scoped_refptr<GLContext> context = GLContext::CreateGLContext( | 343 scoped_refptr<GLContext> context = GLContext::CreateGLContext( |
| 372 NULL, surface.get(), PreferIntegratedGpu); | 344 NULL, surface.get(), PreferIntegratedGpu); |
| 373 if (!context->MakeCurrent(surface.get())) | 345 if (!context->MakeCurrent(surface.get())) |
| 374 g_egl_surfaceless_context_supported = false; | 346 g_egl_surfaceless_context_supported = false; |
| 375 | 347 |
| 376 // Ensure context supports GL_OES_surfaceless_context. | 348 // Ensure context supports GL_OES_surfaceless_context. |
| 377 if (g_egl_surfaceless_context_supported) { | 349 if (g_egl_surfaceless_context_supported) { |
| 378 g_egl_surfaceless_context_supported = context->HasExtension( | 350 g_egl_surfaceless_context_supported = context->HasExtension( |
| 379 "GL_OES_surfaceless_context"); | 351 "GL_OES_surfaceless_context"); |
| 380 context->ReleaseCurrent(surface.get()); | 352 context->ReleaseCurrent(surface.get()); |
| 381 } | 353 } |
| 382 } | 354 } |
| 383 #endif | 355 #endif |
| 384 | 356 |
| 357 initialized = true; |
| 358 |
| 385 return true; | 359 return true; |
| 386 } | 360 } |
| 387 | 361 |
| 388 EGLDisplay GLSurfaceEGL::GetDisplay() { | 362 EGLDisplay GLSurfaceEGL::GetDisplay() { |
| 389 DCHECK(g_initialized); | |
| 390 return g_display; | 363 return g_display; |
| 391 } | 364 } |
| 392 | 365 |
| 393 // static | |
| 394 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() { | 366 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() { |
| 395 if (!g_initialized) { | |
| 396 bool result = GLSurfaceEGL::InitializeOneOff(); | |
| 397 DCHECK(result); | |
| 398 } | |
| 399 return g_display; | 367 return g_display; |
| 400 } | 368 } |
| 401 | 369 |
| 402 // static | |
| 403 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { | 370 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { |
| 404 if (!g_initialized) { | 371 return g_native_display; |
| 405 bool result = GLSurfaceEGL::InitializeOneOff(); | |
| 406 DCHECK(result); | |
| 407 } | |
| 408 return g_native_display_type; | |
| 409 } | 372 } |
| 410 | 373 |
| 411 const char* GLSurfaceEGL::GetEGLExtensions() { | 374 const char* GLSurfaceEGL::GetEGLExtensions() { |
| 412 // No need for InitializeOneOff. Assume that extensions will not change | |
| 413 // after the first initialization. | |
| 414 return g_egl_extensions; | 375 return g_egl_extensions; |
| 415 } | 376 } |
| 416 | 377 |
| 417 bool GLSurfaceEGL::HasEGLExtension(const char* name) { | 378 bool GLSurfaceEGL::HasEGLExtension(const char* name) { |
| 418 return ExtensionsContain(GetEGLExtensions(), name); | 379 return ExtensionsContain(GetEGLExtensions(), name); |
| 419 } | 380 } |
| 420 | 381 |
| 421 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() { | 382 bool GLSurfaceEGL::IsCreateContextRobustnessSupported() { |
| 422 return g_egl_create_context_robustness_supported; | 383 return g_egl_create_context_robustness_supported; |
| 423 } | 384 } |
| 424 | 385 |
| 425 bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() { | 386 bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() { |
| 426 return g_egl_surfaceless_context_supported; | 387 return g_egl_surfaceless_context_supported; |
| 427 } | 388 } |
| 428 | 389 |
| 429 void GLSurfaceEGL::DestroyAndTerminateDisplay() { | 390 GLSurfaceEGL::~GLSurfaceEGL() {} |
| 430 DCHECK(g_initialized); | |
| 431 DCHECK_EQ(g_num_surfaces, 1); | |
| 432 Destroy(); | |
| 433 g_terminate_pending = true; | |
| 434 } | |
| 435 | |
| 436 GLSurfaceEGL::~GLSurfaceEGL() { | |
| 437 DCHECK_GT(g_num_surfaces, 0) << "Bad surface count"; | |
| 438 if (--g_num_surfaces == 0 && g_terminate_pending) { | |
| 439 DeinitializeEgl(); | |
| 440 g_terminate_pending = false; | |
| 441 } | |
| 442 } | |
| 443 | 391 |
| 444 // InitializeDisplay is necessary because the static binding code | 392 // InitializeDisplay is necessary because the static binding code |
| 445 // needs a full Display init before it can query the Display extensions. | 393 // needs a full Display init before it can query the Display extensions. |
| 446 // static | 394 // static |
| 447 EGLDisplay GLSurfaceEGL::InitializeDisplay() { | 395 EGLDisplay GLSurfaceEGL::InitializeDisplay() { |
| 448 if (g_display != EGL_NO_DISPLAY) { | 396 if (g_display != EGL_NO_DISPLAY) { |
| 449 return g_display; | 397 return g_display; |
| 450 } | 398 } |
| 451 | 399 |
| 452 g_native_display_type = GetPlatformDefaultEGLNativeDisplay(); | 400 g_native_display = GetPlatformDefaultEGLNativeDisplay(); |
| 453 | 401 |
| 454 // If EGL_EXT_client_extensions not supported this call to eglQueryString | 402 // If EGL_EXT_client_extensions not supported this call to eglQueryString |
| 455 // will return NULL. | 403 // will return NULL. |
| 456 const char* client_extensions = | 404 const char* client_extensions = |
| 457 eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); | 405 eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); |
| 458 | 406 |
| 459 bool supports_angle_d3d = false; | 407 bool supports_angle_d3d = false; |
| 460 bool supports_angle_opengl = false; | 408 bool supports_angle_opengl = false; |
| 461 // Check for availability of ANGLE extensions. | 409 // Check for availability of ANGLE extensions. |
| 462 if (client_extensions && | 410 if (client_extensions && |
| 463 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle")) { | 411 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle")) { |
| 464 supports_angle_d3d = | 412 supports_angle_d3d = |
| 465 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_d3d"); | 413 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_d3d"); |
| 466 supports_angle_opengl = | 414 supports_angle_opengl = |
| 467 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_opengl"); | 415 ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_opengl"); |
| 468 } | 416 } |
| 469 | 417 |
| 470 std::vector<DisplayType> init_displays; | 418 std::vector<DisplayType> init_displays; |
| 471 GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl, | 419 GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl, |
| 472 base::CommandLine::ForCurrentProcess(), &init_displays); | 420 base::CommandLine::ForCurrentProcess(), &init_displays); |
| 473 | 421 |
| 474 for (size_t disp_index = 0; disp_index < init_displays.size(); ++disp_index) { | 422 for (size_t disp_index = 0; disp_index < init_displays.size(); ++disp_index) { |
| 475 DisplayType display_type = init_displays[disp_index]; | 423 DisplayType display_type = init_displays[disp_index]; |
| 476 EGLDisplay display = | 424 EGLDisplay display = |
| 477 GetDisplayFromType(display_type, g_native_display_type); | 425 GetDisplayFromType(display_type, g_native_display); |
| 478 if (display == EGL_NO_DISPLAY) { | 426 if (display == EGL_NO_DISPLAY) { |
| 479 LOG(ERROR) << "EGL display query failed with error " | 427 LOG(ERROR) << "EGL display query failed with error " |
| 480 << GetLastEGLErrorString(); | 428 << GetLastEGLErrorString(); |
| 481 } | 429 } |
| 482 | 430 |
| 483 if (!eglInitialize(display, nullptr, nullptr)) { | 431 if (!eglInitialize(display, nullptr, nullptr)) { |
| 484 bool is_last = disp_index == init_displays.size() - 1; | 432 bool is_last = disp_index == init_displays.size() - 1; |
| 485 | 433 |
| 486 LOG(ERROR) << "eglInitialize " << DisplayTypeString(display_type) | 434 LOG(ERROR) << "eglInitialize " << DisplayTypeString(display_type) |
| 487 << " failed with error " << GetLastEGLErrorString() | 435 << " failed with error " << GetLastEGLErrorString() |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 963 } | 911 } |
| 964 | 912 |
| 965 void* SurfacelessEGL::GetShareHandle() { | 913 void* SurfacelessEGL::GetShareHandle() { |
| 966 return NULL; | 914 return NULL; |
| 967 } | 915 } |
| 968 | 916 |
| 969 SurfacelessEGL::~SurfacelessEGL() { | 917 SurfacelessEGL::~SurfacelessEGL() { |
| 970 } | 918 } |
| 971 | 919 |
| 972 } // namespace gfx | 920 } // namespace gfx |
| OLD | NEW |