//
// Copyright 2019 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.
//

// EGLSync.h: Defines the egl::Sync classes, which support the EGL_KHR_fence_sync,
// EGL_KHR_wait_sync and EGL 1.5 sync objects.

#ifndef LIBANGLE_EGLSYNC_H_
#define LIBANGLE_EGLSYNC_H_

#include "libANGLE/Debug.h"
#include "libANGLE/Display.h"
#include "libANGLE/Error.h"
#include "libANGLE/RefCountObject.h"

#include "common/angleutils.h"

namespace rx
{
class EGLSyncImpl;
class ThreadSafeDisplayImpl;
}  // namespace rx

namespace gl
{
class Context;
}  // namespace gl

namespace egl
{
class Sync final : public LabeledObject
{
  public:
    Sync(rx::ThreadSafeDisplayImpl *factory, EGLenum type);
    ~Sync() override;

    void setLabel(EGLLabelKHR label) override;
    EGLLabelKHR getLabel() const override;

    const SyncID &id() const { return mId; }

    void onDestroy(const ThreadSafeDisplay *display);

    Error initialize(const ThreadSafeDisplay *display,
                     const gl::Context *context,
                     const SyncID &id,
                     const AttributeMap &attribs);
    Error clientWait(const ThreadSafeDisplay *display,
                     const gl::Context *context,
                     EGLint flags,
                     EGLTime timeout,
                     EGLint *outResult);
    Error serverWait(const ThreadSafeDisplay *display, const gl::Context *context, EGLint flags);
    Error signal(const ThreadSafeDisplay *display, const gl::Context *context, EGLint mode);
    Error getStatus(const ThreadSafeDisplay *display, EGLint *outStatus) const;

    Error copyMetalSharedEventANGLE(const ThreadSafeDisplay *display, void **result) const;
    Error dupNativeFenceFD(const ThreadSafeDisplay *display, EGLint *result) const;

    EGLenum getType() const { return mType; }
    const AttributeMap &getAttributeMap() const { return mAttributeMap; }
    EGLint getCondition() const { return mCondition; }
    EGLint getNativeFenceFD() const { return mNativeFenceFD; }

    void addRef() const { mRefCount.fetch_add(1, std::memory_order_relaxed); }
    bool releaseRef() const { return mRefCount.fetch_sub(1, std::memory_order_acq_rel) == 1; }
    uint32_t getRefCount() const { return mRefCount.load(std::memory_order_acquire); }

  private:
    std::unique_ptr<rx::EGLSyncImpl> mFence;

    EGLLabelKHR mLabel;

    SyncID mId;
    EGLenum mType;
    AttributeMap mAttributeMap;
    EGLint mCondition;
    EGLint mNativeFenceFD;

    mutable std::atomic<uint32_t> mRefCount{0};
};

class [[nodiscard]] ScopedSyncRef final
{
  public:
    ScopedSyncRef() = default;
    ScopedSyncRef(ThreadSafeDisplay &display, Sync *sync) : mDisplay(display), mSync(sync)
    {
        // Callers only invoke this with valid Sync* objects; if lookup fails, ScopedSyncRef() is
        // used instead.
        ASSERT(mSync != nullptr);
        mSync->addRef();
    }
    ScopedSyncRef(ThreadSafeDisplay *display, Sync *sync)
        : mDisplay(display ? ScopedThreadSafeDisplayRef(*display) : ScopedThreadSafeDisplayRef()),
          mSync(sync)
    {
        if (mSync)
        {
            mSync->addRef();
        }
    }
    ~ScopedSyncRef()
    {
        if (mSync)
        {
            mDisplay.get()->releaseSync(mSync);
        }
    }
    ScopedSyncRef(const ScopedSyncRef &other) : mDisplay(other.mDisplay), mSync(other.mSync)
    {
        if (mSync)
        {
            mSync->addRef();
        }
    }
    ScopedSyncRef(ScopedSyncRef &&other) noexcept
        : mDisplay(std::move(other.mDisplay)), mSync(other.mSync)
    {
        other.mSync = nullptr;
    }

    Sync *get() const { return mSync; }

  private:
    // Use ScopedThreadSafeDisplayRef here because we need to be able to hold onto a
    // ThreadSafeDisplay and release it when the SyncRef goes out of scope.
    ScopedThreadSafeDisplayRef mDisplay;
    Sync *mSync = nullptr;
};

}  // namespace egl

#endif  // LIBANGLE_EGLSYNC_H_
