mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-03 14:09:33 +03:00
Release the global texture manager with the last referencing context.
This ensures that when the global texture manager is released, there is a valid context. BUG=angleproject:1639 Change-Id: I1b75885e9dc02b607bb1a386de394f6087429f5d Reviewed-on: https://chromium-review.googlesource.com/442074 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
@@ -66,7 +66,16 @@ Additions to the EGL 1.5 Specification
|
||||
|
||||
Issues
|
||||
|
||||
None
|
||||
(1) What happens to the shared textures when a context in the global share
|
||||
group is destroyed?
|
||||
|
||||
RESOLOVED: When the last context in the global texture share group is
|
||||
destroyed, all textures in the global texture share group are released. If
|
||||
a new context is created in the global texture share group, no textures
|
||||
will exist.
|
||||
|
||||
This mirrors how regular share groups work, releasing all objects when the
|
||||
last context is destroyed.
|
||||
|
||||
Revision History
|
||||
|
||||
|
||||
@@ -360,7 +360,8 @@ Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDe
|
||||
mVendorString(),
|
||||
mDevice(eglDevice),
|
||||
mPlatform(platform),
|
||||
mTextureManager(nullptr)
|
||||
mTextureManager(nullptr),
|
||||
mGlobalTextureShareGroupUsers(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -464,9 +465,6 @@ Error Display::initialize()
|
||||
ASSERT(mDevice != nullptr);
|
||||
}
|
||||
|
||||
ASSERT(mTextureManager == nullptr);
|
||||
mTextureManager = new gl::TextureManager();
|
||||
|
||||
mInitialized = true;
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
@@ -474,12 +472,6 @@ Error Display::initialize()
|
||||
|
||||
void Display::terminate()
|
||||
{
|
||||
if (mTextureManager)
|
||||
{
|
||||
mTextureManager->release();
|
||||
mTextureManager = nullptr;
|
||||
}
|
||||
|
||||
makeCurrent(nullptr, nullptr, nullptr);
|
||||
|
||||
while (!mContextSet.empty())
|
||||
@@ -487,6 +479,9 @@ void Display::terminate()
|
||||
destroyContext(*mContextSet.begin());
|
||||
}
|
||||
|
||||
// The global texture manager should be deleted with the last context that uses it.
|
||||
ASSERT(mGlobalTextureShareGroupUsers == 0 && mTextureManager == nullptr);
|
||||
|
||||
while (!mImageSet.empty())
|
||||
{
|
||||
destroyImage(*mImageSet.begin());
|
||||
@@ -686,7 +681,19 @@ Error Display::createContext(const Config *configuration, gl::Context *shareCont
|
||||
|
||||
bool usingDisplayTextureShareGroup =
|
||||
attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
|
||||
gl::TextureManager *shareTextures = usingDisplayTextureShareGroup ? mTextureManager : nullptr;
|
||||
gl::TextureManager *shareTextures = nullptr;
|
||||
|
||||
if (usingDisplayTextureShareGroup)
|
||||
{
|
||||
ASSERT((mTextureManager == nullptr) == (mGlobalTextureShareGroupUsers == 0));
|
||||
if (mTextureManager == nullptr)
|
||||
{
|
||||
mTextureManager = new gl::TextureManager();
|
||||
}
|
||||
|
||||
mGlobalTextureShareGroupUsers++;
|
||||
shareTextures = mTextureManager;
|
||||
}
|
||||
|
||||
gl::Context *context = new gl::Context(mImplementation, configuration, shareContext,
|
||||
shareTextures, attribs, mDisplayExtensions);
|
||||
@@ -767,6 +774,19 @@ void Display::destroyStream(egl::Stream *stream)
|
||||
|
||||
void Display::destroyContext(gl::Context *context)
|
||||
{
|
||||
if (context->usingDisplayTextureShareGroup())
|
||||
{
|
||||
ASSERT(mGlobalTextureShareGroupUsers >= 1 && mTextureManager != nullptr);
|
||||
if (mGlobalTextureShareGroupUsers == 1)
|
||||
{
|
||||
// If this is the last context using the global share group, destroy the global texture
|
||||
// manager so that the textures can be destroyed while a context still exists
|
||||
mTextureManager->release();
|
||||
mTextureManager = nullptr;
|
||||
}
|
||||
mGlobalTextureShareGroupUsers--;
|
||||
}
|
||||
|
||||
context->destroy(this);
|
||||
mContextSet.erase(context);
|
||||
SafeDelete(context);
|
||||
|
||||
@@ -175,6 +175,7 @@ class Display final : angle::NonCopyable
|
||||
angle::LoggingAnnotator mAnnotator;
|
||||
|
||||
gl::TextureManager *mTextureManager;
|
||||
size_t mGlobalTextureShareGroupUsers;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -199,6 +199,51 @@ TEST_P(EGLContextSharingTest, DisplayShareGroupObjectSharing)
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
// Tests that shared textures using EGL_ANGLE_display_texture_share_group are released when the last
|
||||
// context is destroyed
|
||||
TEST_P(EGLContextSharingTest, DisplayShareGroupReleasedWithLastContext)
|
||||
{
|
||||
EGLDisplay display = getEGLWindow()->getDisplay();
|
||||
if (!ANGLETest::eglDisplayExtensionEnabled(display, "EGL_ANGLE_display_texture_share_group"))
|
||||
{
|
||||
std::cout << "Test skipped because EGL_ANGLE_display_texture_share_group is not present."
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
EGLConfig config = getEGLWindow()->getConfig();
|
||||
EGLSurface surface = getEGLWindow()->getSurface();
|
||||
|
||||
const EGLint inShareGroupContextAttribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2, EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_TRUE, EGL_NONE};
|
||||
|
||||
// Create two contexts in the global share group but not in the same context share group
|
||||
mContexts[0] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
|
||||
mContexts[1] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
|
||||
|
||||
// Create a texture and buffer in ctx 0
|
||||
ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[0]));
|
||||
GLuint textureFromCtx0 = 0;
|
||||
glGenTextures(1, &textureFromCtx0);
|
||||
glBindTexture(GL_TEXTURE_2D, textureFromCtx0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
ASSERT_GL_TRUE(glIsTexture(textureFromCtx0));
|
||||
|
||||
// Switch to context 1 and verify that the texture is accessible
|
||||
ASSERT_EGL_TRUE(eglMakeCurrent(display, surface, surface, mContexts[1]));
|
||||
ASSERT_GL_TRUE(glIsTexture(textureFromCtx0));
|
||||
|
||||
// Destroy both contexts, the texture should be cleaned up automatically
|
||||
ASSERT_EGL_TRUE(eglDestroyContext(display, mContexts[0]));
|
||||
ASSERT_EGL_TRUE(eglDestroyContext(display, mContexts[1]));
|
||||
|
||||
// Create a new context and verify it cannot access the texture previously created
|
||||
mContexts[0] = eglCreateContext(display, config, nullptr, inShareGroupContextAttribs);
|
||||
|
||||
ASSERT_GL_FALSE(glIsTexture(textureFromCtx0));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
ANGLE_INSTANTIATE_TEST(EGLContextSharingTest,
|
||||
|
||||
Reference in New Issue
Block a user