GL: Complete EGL_ANGLE_external_context_and_surface

This change implements two new entry points added for
EGL_ANGLE_external_context_and_surface: glAcquireExternalContextANGLE
and glReleaseExternalContextANGLE.

These functions remove the need to overload eglMakeCurrent for the
purposes of syncing to and from the external context.

Bug: angleproject:5509
Change-Id: I5d46299ee0c8addaef7066914a8a8aacb0ea2c17
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4706027
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Peng Huang <penghuang@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Shahbaz Youssefi
2023-07-23 21:53:50 -04:00
committed by Angle LUCI CQ
parent 2d5fb09d7f
commit 7ea61cb3a1
6 changed files with 180 additions and 33 deletions

View File

@@ -0,0 +1,120 @@
Name
ANGLE_external_context_and_surface
Name Strings
EGL_ANGLE_external_context_and_surface
Contributors
Peng Huang
Shahbaz Youssefi
Contacts
Shahbaz Youssefi, Google (syoussefi 'at' google.com)
Status
Draft
Version
Version 2, July 24, 2023
Number
EGL Extension #??
Dependencies
This extension is written against the wording of the EGL 1.4
Specification.
Overview
This extension allows plugging an external OpenGL context and surface to
the OpenGL backend of ANGLE.
New Types
None
New Procedures and Functions
void eglAcquireExternalContextANGLE(
EGLDisplay dpy);
void eglReleaseExternalContextANGLE(
EGLDisplay dpy);
New Tokens
Accepted as an attribute name in the <*attrib_list> argument to
eglCreateContext:
EGL_EXTERNAL_CONTEXT_ANGLE 0x348E
EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE 0x3490
Accepted in the <buftype> parameter of eglCreatePbufferFromClientBuffer:
EGL_EXTERNAL_SURFACE_ANGLE 0x348F
Additions to the EGL 1.4 Specification
Add the following to section 3.7.1 "Creating Rendering Contexts":
EGL_EXTERNAL_CONTEXT_ANGLE indicates whether the context is externally
managed, and that no internal context is created.
In this case, the context must be made current by the application before
calling other EGL or GL functions that may access the context.
EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE indicates whether the context state
is automatically synchronized from and to the external context when
eglMakeCurrent is called.
eglAcquireExternalContextANGLE and eglReleaseExternalContextANGLE can be
used to perform this synchronization independently from MakeCurrent.
Add the following to section 3.5.3 "Binding Off-Screen Rendering Surfaces
To Client Buffers":
EGL_EXTERNAL_SURFACE_ANGLE indicates whether the surface is externally
managed, and that no internal surface is created.
In this case, the surface must be made current by the application before
calling other EGL or GL functions that may access the surface.
Add the following to section 3.7.3 "Binding Contexts and Drawables":
Before making a call that uses a context created with
EGL_EXTERNAL_CONTEXT_ANGLE, the context must be synchronized from external.
If EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE is specified when creating the
context, this can be done with a call to eglMakeCurrent.
Alternatively, eglAcquireExternalContextANGLE can be called to perform this
synchronization.
The eglAcquireExternalContextANGLE call ensures that the implementation is
up-to-date with respect to changes that external has made to the context.
Before the application (external) can continue using the context after the
implementation has modified it, the context must be synchronized to
external, restoring the state from when the external context was
"acquired".
If EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE is specified when creating the
context, this can be done with a call to eglMakeCurrent that sets the
context to NULL.
Alternatively, eglReleaseExternalContextANGLE can be called to perform this
synchronization.
The eglReleaseExternalContextANGLE call ensures that the context is
restored to its original state from before the
eglAcquireExternalContextANGLE call.
Issues
None yet.
Revision History
Rev. Date Author Changes
---- ------------- --------- ----------------------------------------
1 Jan 7, 2021 penghuang Initial version
2 July 24, 2023 syoussefi Add eglAcquireExternalContextANGLE, and
eglReleaseExternalContextANGLE

View File

@@ -9647,13 +9647,13 @@ void Context::onGPUSwitch()
egl::Error Context::acquireExternalContext()
{
UNIMPLEMENTED();
mImplementation->acquireExternalContext(this);
return egl::NoError();
}
egl::Error Context::releaseExternalContext()
{
UNIMPLEMENTED();
mImplementation->releaseExternalContext(this);
return egl::NoError();
}

View File

@@ -66,6 +66,10 @@ egl::Error ContextImpl::reacquireHighPowerGPU(gl::Context *)
return egl::NoError();
}
void ContextImpl::acquireExternalContext(const gl::Context *context) {}
void ContextImpl::releaseExternalContext(const gl::Context *context) {}
angle::Result ContextImpl::acquireTextures(const gl::Context *context,
const gl::TextureBarrierVector &textureBarriers)
{

View File

@@ -257,6 +257,10 @@ class ContextImpl : public GLImplFactory
virtual egl::Error releaseHighPowerGPU(gl::Context *context);
virtual egl::Error reacquireHighPowerGPU(gl::Context *context);
// EGL_ANGLE_external_context_and_surface
virtual void acquireExternalContext(const gl::Context *context);
virtual void releaseExternalContext(const gl::Context *context);
// GL_ANGLE_vulkan_image
virtual angle::Result acquireTextures(const gl::Context *context,
const gl::TextureBarrierVector &textureBarriers);

View File

@@ -27,54 +27,70 @@ angle::Result ContextEGL::onMakeCurrent(const gl::Context *context)
// that external context when first making this context current.
if (!mIsCurrent && context->isExternal())
{
if (!mExtState)
// TODO: The following is done if saveAndRestoreState() until chrome is switched to using
// glAcquireExternalContextANGLE and drops usage of EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE.
// After that, this code can be removed. http://anglebug.com/5509
if (context->saveAndRestoreState())
{
mExtState = std::make_unique<ExternalContextState>();
const auto &caps = getCaps();
mExtState->textureBindings.resize(
static_cast<size_t>(caps.maxCombinedTextureImageUnits));
acquireExternalContext(context);
}
getStateManager()->syncFromNativeContext(getNativeExtensions(), mExtState.get());
// Use current FBO as the default framebuffer when the external context is current.
// First save the current ID of the default framebuffer to restore in
// onUnMakeCurrent().
gl::Framebuffer *framebuffer = mState.getDefaultFramebuffer();
auto framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
mPrevDefaultFramebufferID = framebufferGL->getFramebufferID();
framebufferGL->updateDefaultFramebufferID(mExtState->framebufferBinding);
}
mIsCurrent = true;
return ContextGL::onMakeCurrent(context);
}
void ContextEGL::acquireExternalContext(const gl::Context *context)
{
ASSERT(context->isExternal());
if (!mExtState)
{
mExtState = std::make_unique<ExternalContextState>();
const auto &caps = getCaps();
mExtState->textureBindings.resize(static_cast<size_t>(caps.maxCombinedTextureImageUnits));
}
getStateManager()->syncFromNativeContext(getNativeExtensions(), mExtState.get());
// Use current FBO as the default framebuffer when the external context is current.
// First save the current ID of the default framebuffer to restore in
// onUnMakeCurrent().
gl::Framebuffer *framebuffer = mState.getDefaultFramebuffer();
auto framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
mPrevDefaultFramebufferID = framebufferGL->getFramebufferID();
framebufferGL->updateDefaultFramebufferID(mExtState->framebufferBinding);
}
angle::Result ContextEGL::onUnMakeCurrent(const gl::Context *context)
{
mIsCurrent = false;
if (context->saveAndRestoreState())
if (context->isExternal() && context->saveAndRestoreState())
{
ASSERT(context->isExternal());
ASSERT(mExtState);
getStateManager()->restoreNativeContext(getNativeExtensions(), mExtState.get());
}
if (context->isExternal())
{
// If the default framebuffer exists, update its ID (note that there can
// be multiple consecutive onUnMakeCurrent() calls in destruction, and
// the default FBO will have been unset by the first one).
gl::Framebuffer *framebuffer = mState.getDefaultFramebuffer();
if (framebuffer)
{
auto framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
framebufferGL->updateDefaultFramebufferID(mPrevDefaultFramebufferID);
}
releaseExternalContext(context);
}
return ContextGL::onUnMakeCurrent(context);
}
void ContextEGL::releaseExternalContext(const gl::Context *context)
{
ASSERT(context->isExternal());
ASSERT(mExtState);
getStateManager()->restoreNativeContext(getNativeExtensions(), mExtState.get());
// If the default framebuffer exists, update its ID (note that there can
// be multiple consecutive onUnMakeCurrent() calls in destruction, and
// the default FBO will have been unset by the first one).
gl::Framebuffer *framebuffer = mState.getDefaultFramebuffer();
if (framebuffer)
{
auto framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
framebufferGL->updateDefaultFramebufferID(mPrevDefaultFramebufferID);
}
}
EGLContext ContextEGL::getContext() const
{
return mRendererEGL->getContext();

View File

@@ -29,6 +29,9 @@ class ContextEGL : public ContextGL
angle::Result onMakeCurrent(const gl::Context *context) override;
angle::Result onUnMakeCurrent(const gl::Context *context) override;
void acquireExternalContext(const gl::Context *context) override;
void releaseExternalContext(const gl::Context *context) override;
EGLContext getContext() const;
private: