blob: 2a21a3035dff4a55891d7a00fb342363b150daf0 [file] [edit]
//
// 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_