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 |