mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-01 05:48:11 +03:00
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:
committed by
Angle LUCI CQ
parent
2d5fb09d7f
commit
7ea61cb3a1
120
extensions/EGL_ANGLE_external_context_and_surface.txt
Normal file
120
extensions/EGL_ANGLE_external_context_and_surface.txt
Normal 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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user