gl_fence_egl.cc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/gl/gl_fence_egl.h"
  5. #include "base/memory/ptr_util.h"
  6. #include "ui/gl/egl_util.h"
  7. #include "ui/gl/gl_bindings.h"
  8. #include "ui/gl/gl_surface_egl.h"
  9. namespace gl {
  10. namespace {
  11. bool g_check_egl_fence_before_wait = false;
  12. } // namespace
  13. GLFenceEGL::GLFenceEGL() = default;
  14. // static
  15. std::unique_ptr<GLFenceEGL> GLFenceEGL::Create() {
  16. auto fence = Create(EGL_SYNC_FENCE_KHR, nullptr);
  17. // Default creation isn't supposed to fail.
  18. DCHECK(fence);
  19. return fence;
  20. }
  21. // static
  22. std::unique_ptr<GLFenceEGL> GLFenceEGL::Create(EGLenum type, EGLint* attribs) {
  23. // Can't use MakeUnique, the no-args constructor is private.
  24. auto fence = base::WrapUnique(new GLFenceEGL());
  25. if (!fence->InitializeInternal(type, attribs))
  26. return nullptr;
  27. return fence;
  28. }
  29. // static
  30. void GLFenceEGL::CheckEGLFenceBeforeWait() {
  31. g_check_egl_fence_before_wait = true;
  32. }
  33. bool GLFenceEGL::InitializeInternal(EGLenum type, EGLint* attribs) {
  34. sync_ = EGL_NO_SYNC_KHR;
  35. display_ = eglGetCurrentDisplay();
  36. if (display_ != EGL_NO_DISPLAY) {
  37. sync_ = eglCreateSyncKHR(display_, type, attribs);
  38. glFlush();
  39. }
  40. return sync_ != EGL_NO_SYNC_KHR;
  41. }
  42. bool GLFenceEGL::HasCompleted() {
  43. EGLint value = 0;
  44. if (eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value) !=
  45. EGL_TRUE) {
  46. LOG(ERROR) << "Failed to get EGLSync attribute. error code:"
  47. << eglGetError();
  48. return true;
  49. }
  50. DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR);
  51. return !value || value == EGL_SIGNALED_KHR;
  52. }
  53. void GLFenceEGL::ClientWait() {
  54. EGLint result = ClientWaitWithTimeoutNanos(EGL_FOREVER_KHR);
  55. DCHECK_NE(EGL_TIMEOUT_EXPIRED_KHR, result);
  56. }
  57. EGLint GLFenceEGL::ClientWaitWithTimeoutNanos(EGLTimeKHR timeout) {
  58. EGLint flags = 0;
  59. EGLint result = eglClientWaitSyncKHR(display_, sync_, flags, timeout);
  60. if (result == EGL_FALSE) {
  61. LOG(ERROR) << "Failed to wait for EGLSync. error:"
  62. << ui::GetLastEGLErrorString();
  63. CHECK(false);
  64. }
  65. return result;
  66. }
  67. void GLFenceEGL::ServerWait() {
  68. GLDisplayEGL* display = GLSurfaceEGL::GetGLDisplayEGL();
  69. if (!display->ext->b_EGL_KHR_wait_sync) {
  70. ClientWait();
  71. return;
  72. }
  73. EGLint flags = 0;
  74. bool completed = false;
  75. if (g_check_egl_fence_before_wait) {
  76. // The i965 driver ends up doing a bunch of flushing if an already
  77. // signalled fence is waited on. This causes performance to suffer.
  78. // Check whether the fence is signalled before waiting.
  79. completed = HasCompleted();
  80. }
  81. if (!completed && eglWaitSyncKHR(display_, sync_, flags) == EGL_FALSE) {
  82. LOG(ERROR) << "Failed to wait for EGLSync. error:"
  83. << ui::GetLastEGLErrorString();
  84. CHECK(false);
  85. }
  86. }
  87. void GLFenceEGL::Invalidate() {
  88. // Do nothing. We want the destructor to destroy the EGL fence even if the GL
  89. // context was lost. The EGLDisplay may still be valid, and this helps avoid
  90. // leaks.
  91. }
  92. GLFenceEGL::~GLFenceEGL() {
  93. eglDestroySyncKHR(display_, sync_);
  94. }
  95. } // namespace gl