//
// 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
