123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ui/gl/gl_fence_egl.h"
- #include "base/memory/ptr_util.h"
- #include "ui/gl/egl_util.h"
- #include "ui/gl/gl_bindings.h"
- #include "ui/gl/gl_surface_egl.h"
- namespace gl {
- namespace {
- bool g_check_egl_fence_before_wait = false;
- } // namespace
- GLFenceEGL::GLFenceEGL() = default;
- // static
- std::unique_ptr<GLFenceEGL> GLFenceEGL::Create() {
- auto fence = Create(EGL_SYNC_FENCE_KHR, nullptr);
- // Default creation isn't supposed to fail.
- DCHECK(fence);
- return fence;
- }
- // static
- std::unique_ptr<GLFenceEGL> GLFenceEGL::Create(EGLenum type, EGLint* attribs) {
- // Can't use MakeUnique, the no-args constructor is private.
- auto fence = base::WrapUnique(new GLFenceEGL());
- if (!fence->InitializeInternal(type, attribs))
- return nullptr;
- return fence;
- }
- // static
- void GLFenceEGL::CheckEGLFenceBeforeWait() {
- g_check_egl_fence_before_wait = true;
- }
- bool GLFenceEGL::InitializeInternal(EGLenum type, EGLint* attribs) {
- sync_ = EGL_NO_SYNC_KHR;
- display_ = eglGetCurrentDisplay();
- if (display_ != EGL_NO_DISPLAY) {
- sync_ = eglCreateSyncKHR(display_, type, attribs);
- glFlush();
- }
- return sync_ != EGL_NO_SYNC_KHR;
- }
- bool GLFenceEGL::HasCompleted() {
- EGLint value = 0;
- if (eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value) !=
- EGL_TRUE) {
- LOG(ERROR) << "Failed to get EGLSync attribute. error code:"
- << eglGetError();
- return true;
- }
- DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR);
- return !value || value == EGL_SIGNALED_KHR;
- }
- void GLFenceEGL::ClientWait() {
- EGLint result = ClientWaitWithTimeoutNanos(EGL_FOREVER_KHR);
- DCHECK_NE(EGL_TIMEOUT_EXPIRED_KHR, result);
- }
- EGLint GLFenceEGL::ClientWaitWithTimeoutNanos(EGLTimeKHR timeout) {
- EGLint flags = 0;
- EGLint result = eglClientWaitSyncKHR(display_, sync_, flags, timeout);
- if (result == EGL_FALSE) {
- LOG(ERROR) << "Failed to wait for EGLSync. error:"
- << ui::GetLastEGLErrorString();
- CHECK(false);
- }
- return result;
- }
- void GLFenceEGL::ServerWait() {
- GLDisplayEGL* display = GLSurfaceEGL::GetGLDisplayEGL();
- if (!display->ext->b_EGL_KHR_wait_sync) {
- ClientWait();
- return;
- }
- EGLint flags = 0;
- bool completed = false;
- if (g_check_egl_fence_before_wait) {
- // The i965 driver ends up doing a bunch of flushing if an already
- // signalled fence is waited on. This causes performance to suffer.
- // Check whether the fence is signalled before waiting.
- completed = HasCompleted();
- }
- if (!completed && eglWaitSyncKHR(display_, sync_, flags) == EGL_FALSE) {
- LOG(ERROR) << "Failed to wait for EGLSync. error:"
- << ui::GetLastEGLErrorString();
- CHECK(false);
- }
- }
- void GLFenceEGL::Invalidate() {
- // Do nothing. We want the destructor to destroy the EGL fence even if the GL
- // context was lost. The EGLDisplay may still be valid, and this helps avoid
- // leaks.
- }
- GLFenceEGL::~GLFenceEGL() {
- eglDestroySyncKHR(display_, sync_);
- }
- } // namespace gl
|