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

// ShareGroup.h: Defines the egl::ShareGroup class, representing the collection of contexts in a
// share group.

#ifndef LIBANGLE_SHAREGROUP_H_
#define LIBANGLE_SHAREGROUP_H_

#include <mutex>
#include <type_traits>
#include <vector>

#include "common/FastVector.h"
#include "common/SimpleMutex.h"
#include "libANGLE/Context.h"
#include "libANGLE/ObjectMap.h"

namespace gl
{
class Context;
}  // namespace gl

namespace rx
{
class EGLImplFactory;
class ShareGroupImpl;
}  // namespace rx

namespace egl
{
class ContextMap final : public priv::ObjectMap<gl::Context, angle::SimpleMutex>
{
  public:
    void pruneUnreferenced(ContextMap *invalidContextMap)
    {
        std::lock_guard<angle::SimpleMutex> lock(mMutex);
        std::lock_guard<angle::SimpleMutex> invalidLock(invalidContextMap->mMutex);

        // Cache total number of contexts before invalidation. This is used as a check to verify
        // that no context is "lost" while being moved between the various sets.
        size_t contextSetSizeBeforeInvalidation =
            this->mObjects.size() + invalidContextMap->mObjects.size();

        // If app called eglTerminate and no active threads remain,
        // force release any context that is still current.
        angle::HashMap<GLuint, gl::Context *> contextsStillCurrent = {};
        for (auto context : this->mObjects)
        {
            if (context.second->isReferenced())
            {
                contextsStillCurrent.emplace(context);
                continue;
            }

            // Add context that is not current to mInvalidContextSet for cleanup.
            invalidContextMap->mObjects.emplace(context);
        }

        // There are many methods that require contexts that are still current to be present in
        // display's contextSet like during context release or to notify of state changes in a
        // subject. So as to not interrupt this flow, do not remove contexts that are still
        // current on some thread from display's contextSet even though eglTerminate marks such
        // contexts as invalid.
        //
        // "mState.contextSet" will now contain only those contexts that are still current on
        // some thread.
        this->mObjects = std::move(contextsStillCurrent);

        // Assert that the total number of contexts is the same before and after context
        // invalidation.
        ASSERT(contextSetSizeBeforeInvalidation ==
               this->mObjects.size() + invalidContextMap->mObjects.size());
    }

    template <typename ConditionType>
    void notifyDeviceLost(ConditionType *deviceLost) const
    {
        std::lock_guard<angle::SimpleMutex> lock(mMutex);
        if (*deviceLost)
        {
            return;
        }
        for (const auto &pair : this->mObjects)
        {
            pair.second->markContextLost(gl::GraphicsResetStatus::UnknownContextReset);
        }
        *deviceLost = true;
    }
};

class UnlockedContextMap final : public priv::ObjectMap<gl::Context, angle::NoOpMutex>
{
  public:
    size_t size() const { return mObjects.size(); }
};

using SharedContextMap = UnlockedContextMap;

class ShareGroupState final : angle::NonCopyable
{
  public:
    ShareGroupState();
    ~ShareGroupState();

    const SharedContextMap &getContexts() const { return mContexts; }
    void addSharedContext(gl::Context *context);
    void removeSharedContext(gl::Context *context);

    bool hasAnyContextWithRobustness() const { return mAnyContextWithRobustness; }
    bool hasAnyContextWithDisplayTextureShareGroup() const
    {
        return mAnyContextWithDisplayTextureShareGroup;
    }

  private:
    // The list of contexts within the share group
    SharedContextMap mContexts;

    // Whether any context in the share group has robustness enabled.  If any context in the share
    // group is robust, any program created in any context of the share group must have robustness
    // enabled.  This is because programs are shared between the share group contexts.
    bool mAnyContextWithRobustness;

    // Whether any context in the share group uses display shared textures.  This functionality is
    // provided by ANGLE_display_texture_share_group and allows textures to be shared between
    // contexts that are not in the same share group.
    bool mAnyContextWithDisplayTextureShareGroup;
};

class ShareGroup final : angle::NonCopyable
{
  public:
    ShareGroup(rx::EGLImplFactory *factory);

    void addRef();

    void release(const egl::Display *display);

    rx::ShareGroupImpl *getImplementation() const { return mImplementation; }

    rx::UniqueSerial generateFramebufferSerial() { return mFramebufferSerialFactory.generate(); }

    angle::FrameCaptureShared *getFrameCaptureShared() { return mFrameCaptureShared.get(); }

    void finishAllContexts();

    const SharedContextMap &getContexts() const { return mState.getContexts(); }
    void addSharedContext(gl::Context *context);
    void removeSharedContext(gl::Context *context);

  protected:
    ~ShareGroup();

  private:
    size_t mRefCount;
    rx::ShareGroupImpl *mImplementation;
    rx::UniqueSerialFactory mFramebufferSerialFactory;

    // Note: we use a raw pointer here so we can exclude frame capture sources from the build.
    std::unique_ptr<angle::FrameCaptureShared> mFrameCaptureShared;

    ShareGroupState mState;
};

}  // namespace egl

#endif  // LIBANGLE_SHAREGROUP_H_
