| // |
| // Copyright 2020 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // EGLReusableSync.cpp: Implements the egl::ReusableSync class. |
| |
| #include "libANGLE/renderer/EGLReusableSync.h" |
| |
| #include "libANGLE/Context.h" |
| #include "libANGLE/renderer/ContextImpl.h" |
| |
| namespace rx |
| { |
| |
| ReusableSync::ReusableSync(const egl::AttributeMap &attribs) |
| : EGLSyncImpl(), mStatus(EGL_UNSIGNALED) |
| {} |
| |
| void ReusableSync::onDestroy(const egl::Display *display) {} |
| |
| ReusableSync::~ReusableSync() |
| { |
| // Release any waiting thread. |
| mCondVar.notify_all(); |
| } |
| |
| egl::Error ReusableSync::initialize(const egl::Display *display, |
| const gl::Context *context, |
| EGLenum type) |
| { |
| return egl::NoError(); |
| } |
| |
| egl::Error ReusableSync::clientWait(const egl::Display *display, |
| const gl::Context *context, |
| EGLint flags, |
| EGLTime timeout, |
| EGLint *outResult) |
| { |
| if (mStatus == EGL_SIGNALED) |
| { |
| *outResult = EGL_CONDITION_SATISFIED_KHR; |
| return egl::NoError(); |
| } |
| if (((flags & EGL_SYNC_FLUSH_COMMANDS_BIT) != 0) && (context != nullptr)) |
| { |
| angle::Result result = context->getImplementation()->flush(context); |
| if (result != angle::Result::Continue) |
| { |
| return ResultToEGL(result); |
| } |
| } |
| if (timeout == 0) |
| { |
| *outResult = EGL_TIMEOUT_EXPIRED_KHR; |
| return egl::NoError(); |
| } |
| |
| using NanoSeconds = std::chrono::duration<int64_t, std::nano>; |
| NanoSeconds duration = (timeout == EGL_FOREVER) ? NanoSeconds::max() : NanoSeconds(timeout); |
| std::cv_status waitStatus = std::cv_status::no_timeout; |
| mMutex.lock(); |
| waitStatus = mCondVar.wait_for(mMutex, duration); |
| mMutex.unlock(); |
| |
| switch (waitStatus) |
| { |
| case std::cv_status::no_timeout: // Signaled. |
| *outResult = EGL_CONDITION_SATISFIED_KHR; |
| break; |
| case std::cv_status::timeout: // Timed-out. |
| *outResult = EGL_TIMEOUT_EXPIRED_KHR; |
| break; |
| default: |
| break; |
| } |
| return egl::NoError(); |
| } |
| |
| egl::Error ReusableSync::serverWait(const egl::Display *display, |
| const gl::Context *context, |
| EGLint flags) |
| { |
| // Does not support server wait. |
| return egl::EglBadMatch(); |
| } |
| |
| egl::Error ReusableSync::signal(const egl::Display *display, |
| const gl::Context *context, |
| EGLint mode) |
| { |
| if (mode == EGL_SIGNALED) |
| { |
| if (mStatus == EGL_UNSIGNALED) |
| { |
| // Release all threads. |
| mCondVar.notify_all(); |
| } |
| mStatus = EGL_SIGNALED; |
| } |
| else |
| { |
| mStatus = EGL_UNSIGNALED; |
| } |
| return egl::NoError(); |
| } |
| |
| egl::Error ReusableSync::getStatus(const egl::Display *display, EGLint *outStatus) |
| { |
| *outStatus = mStatus; |
| return egl::NoError(); |
| } |
| |
| } // namespace rx |