Commit c295e516 by Corentin Wallez Committed by Commit Bot

Implement EGL_KHR_surfaceless_context

BUG=angleproject:1651 Change-Id: I710df14c2bfa55db2fb9b9715001756d1c1a8f1b Reviewed-on: https://chromium-review.googlesource.com/434763Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
parent bcb3f9ba
...@@ -1031,7 +1031,8 @@ DisplayExtensions::DisplayExtensions() ...@@ -1031,7 +1031,8 @@ DisplayExtensions::DisplayExtensions()
createContextWebGLCompatibility(false), createContextWebGLCompatibility(false),
createContextBindGeneratesResource(false), createContextBindGeneratesResource(false),
swapBuffersWithDamage(false), swapBuffersWithDamage(false),
pixelFormatFloat(false) pixelFormatFloat(false),
surfacelessContext(false)
{ {
} }
...@@ -1070,6 +1071,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const ...@@ -1070,6 +1071,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_CHROMIUM_create_context_bind_generates_resource", createContextBindGeneratesResource, &extensionStrings); InsertExtensionString("EGL_CHROMIUM_create_context_bind_generates_resource", createContextBindGeneratesResource, &extensionStrings);
InsertExtensionString("EGL_EXT_swap_buffers_with_damage", swapBuffersWithDamage, &extensionStrings); InsertExtensionString("EGL_EXT_swap_buffers_with_damage", swapBuffersWithDamage, &extensionStrings);
InsertExtensionString("EGL_EXT_pixel_format_float", pixelFormatFloat, &extensionStrings); InsertExtensionString("EGL_EXT_pixel_format_float", pixelFormatFloat, &extensionStrings);
InsertExtensionString("EGL_KHR_surfaceless_context", surfacelessContext, &extensionStrings);
// TODO(jmadill): Enable this when complete. // TODO(jmadill): Enable this when complete.
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings); //InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
// clang-format on // clang-format on
......
...@@ -643,6 +643,9 @@ struct DisplayExtensions ...@@ -643,6 +643,9 @@ struct DisplayExtensions
// EGL_EXT_pixel_format_float // EGL_EXT_pixel_format_float
bool pixelFormatFloat; bool pixelFormatFloat;
// EGL_KHR_surfaceless_context
bool surfacelessContext;
}; };
struct DeviceExtensions struct DeviceExtensions
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include "common/version.h" #include "common/version.h"
#include "libANGLE/Buffer.h" #include "libANGLE/Buffer.h"
#include "libANGLE/Compiler.h" #include "libANGLE/Compiler.h"
#include "libANGLE/Display.h"
#include "libANGLE/Fence.h" #include "libANGLE/Fence.h"
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/FramebufferAttachment.h"
...@@ -237,7 +236,8 @@ namespace gl ...@@ -237,7 +236,8 @@ namespace gl
Context::Context(rx::EGLImplFactory *implFactory, Context::Context(rx::EGLImplFactory *implFactory,
const egl::Config *config, const egl::Config *config,
const Context *shareContext, const Context *shareContext,
const egl::AttributeMap &attribs) const egl::AttributeMap &attribs,
const egl::DisplayExtensions &displayExtensions)
: ValidationContext(shareContext, : ValidationContext(shareContext,
GetClientVersion(attribs), GetClientVersion(attribs),
...@@ -265,7 +265,7 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -265,7 +265,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
initCaps(GetWebGLContext(attribs)); initCaps(GetWebGLContext(attribs), displayExtensions);
initWorkarounds(); initWorkarounds();
mGLState.initialize(mCaps, mExtensions, getClientVersion(), GetDebug(attribs), mGLState.initialize(mCaps, mExtensions, getClientVersion(), GetDebug(attribs),
...@@ -419,10 +419,7 @@ Context::~Context() ...@@ -419,10 +419,7 @@ Context::~Context()
SafeDelete(mSurfacelessFramebuffer); SafeDelete(mSurfacelessFramebuffer);
if (mCurrentSurface != nullptr) releaseSurface();
{
releaseSurface();
}
SafeDelete(mCompiler); SafeDelete(mCompiler);
} }
...@@ -435,8 +432,16 @@ void Context::makeCurrent(egl::Surface *surface) ...@@ -435,8 +432,16 @@ void Context::makeCurrent(egl::Surface *surface)
initVersionStrings(); initVersionStrings();
initExtensionStrings(); initExtensionStrings();
mGLState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight()); int width = 0;
mGLState.setScissorParams(0, 0, surface->getWidth(), surface->getHeight()); int height = 0;
if (surface != nullptr)
{
width = surface->getWidth();
height = surface->getHeight();
}
mGLState.setViewportParams(0, 0, width, height);
mGLState.setScissorParams(0, 0, width, height);
mHasBeenCurrent = true; mHasBeenCurrent = true;
} }
...@@ -444,10 +449,7 @@ void Context::makeCurrent(egl::Surface *surface) ...@@ -444,10 +449,7 @@ void Context::makeCurrent(egl::Surface *surface)
// TODO(jmadill): Rework this when we support ContextImpl // TODO(jmadill): Rework this when we support ContextImpl
mGLState.setAllDirtyBits(); mGLState.setAllDirtyBits();
if (mCurrentSurface) releaseSurface();
{
releaseSurface();
}
Framebuffer *newDefault = nullptr; Framebuffer *newDefault = nullptr;
if (surface != nullptr) if (surface != nullptr)
...@@ -486,24 +488,32 @@ void Context::makeCurrent(egl::Surface *surface) ...@@ -486,24 +488,32 @@ void Context::makeCurrent(egl::Surface *surface)
void Context::releaseSurface() void Context::releaseSurface()
{ {
ASSERT(mCurrentSurface != nullptr);
// Remove the default framebuffer // Remove the default framebuffer
Framebuffer *currentDefault = nullptr;
if (mCurrentSurface != nullptr)
{ {
Framebuffer *currentDefault = mCurrentSurface->getDefaultFramebuffer(); currentDefault = mCurrentSurface->getDefaultFramebuffer();
if (mGLState.getReadFramebuffer() == currentDefault) }
{ else if (mSurfacelessFramebuffer != nullptr)
mGLState.setReadFramebufferBinding(nullptr); {
} currentDefault = mSurfacelessFramebuffer;
if (mGLState.getDrawFramebuffer() == currentDefault) }
{
mGLState.setDrawFramebufferBinding(nullptr); if (mGLState.getReadFramebuffer() == currentDefault)
} {
mState.mFramebuffers->setDefaultFramebuffer(nullptr); mGLState.setReadFramebufferBinding(nullptr);
}
if (mGLState.getDrawFramebuffer() == currentDefault)
{
mGLState.setDrawFramebufferBinding(nullptr);
} }
mState.mFramebuffers->setDefaultFramebuffer(nullptr);
mCurrentSurface->setIsCurrent(false); if (mCurrentSurface)
mCurrentSurface = nullptr; {
mCurrentSurface->setIsCurrent(false);
mCurrentSurface = nullptr;
}
} }
GLuint Context::createBuffer() GLuint Context::createBuffer()
...@@ -2378,7 +2388,7 @@ bool Context::hasActiveTransformFeedback(GLuint program) const ...@@ -2378,7 +2388,7 @@ bool Context::hasActiveTransformFeedback(GLuint program) const
return false; return false;
} }
void Context::initCaps(bool webGLContext) void Context::initCaps(bool webGLContext, const egl::DisplayExtensions &displayExtensions)
{ {
mCaps = mImplementation->getNativeCaps(); mCaps = mImplementation->getNativeCaps();
...@@ -2410,7 +2420,7 @@ void Context::initCaps(bool webGLContext) ...@@ -2410,7 +2420,7 @@ void Context::initCaps(bool webGLContext)
mExtensions.noError = mSkipValidation; mExtensions.noError = mSkipValidation;
// Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO // Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO
mExtensions.surfacelessContext = true; mExtensions.surfacelessContext = displayExtensions.surfacelessContext;
// Explicitly enable GL_KHR_debug // Explicitly enable GL_KHR_debug
mExtensions.debug = true; mExtensions.debug = true;
......
...@@ -61,7 +61,8 @@ class Context final : public ValidationContext ...@@ -61,7 +61,8 @@ class Context final : public ValidationContext
Context(rx::EGLImplFactory *implFactory, Context(rx::EGLImplFactory *implFactory,
const egl::Config *config, const egl::Config *config,
const Context *shareContext, const Context *shareContext,
const egl::AttributeMap &attribs); const egl::AttributeMap &attribs,
const egl::DisplayExtensions &displayExtensions);
virtual ~Context(); virtual ~Context();
...@@ -641,7 +642,7 @@ class Context final : public ValidationContext ...@@ -641,7 +642,7 @@ class Context final : public ValidationContext
void initVersionStrings(); void initVersionStrings();
void initExtensionStrings(); void initExtensionStrings();
void initCaps(bool webGLContext); void initCaps(bool webGLContext, const egl::DisplayExtensions &displayExtensions);
void updateCaps(); void updateCaps();
void initWorkarounds(); void initWorkarounds();
......
...@@ -673,7 +673,8 @@ Error Display::createContext(const Config *configuration, gl::Context *shareCont ...@@ -673,7 +673,8 @@ Error Display::createContext(const Config *configuration, gl::Context *shareCont
ANGLE_TRY(restoreLostDevice()); ANGLE_TRY(restoreLostDevice());
} }
gl::Context *context = new gl::Context(mImplementation, configuration, shareContext, attribs); gl::Context *context =
new gl::Context(mImplementation, configuration, shareContext, attribs, mDisplayExtensions);
ASSERT(context != nullptr); ASSERT(context != nullptr);
mContextSet.insert(context); mContextSet.insert(context);
...@@ -687,7 +688,7 @@ Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, ...@@ -687,7 +688,7 @@ Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface,
{ {
ANGLE_TRY(mImplementation->makeCurrent(drawSurface, readSurface, context)); ANGLE_TRY(mImplementation->makeCurrent(drawSurface, readSurface, context));
if (context != nullptr && drawSurface != nullptr) if (context != nullptr)
{ {
ASSERT(readSurface == drawSurface); ASSERT(readSurface == drawSurface);
context->makeCurrent(drawSurface); context->makeCurrent(drawSurface);
......
...@@ -81,7 +81,7 @@ egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readS ...@@ -81,7 +81,7 @@ egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readS
} }
mCurrentDrawSurface = nullptr; mCurrentDrawSurface = nullptr;
if (!drawSurface) if (!context)
{ {
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
...@@ -90,11 +90,17 @@ egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readS ...@@ -90,11 +90,17 @@ egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readS
ContextGL *glContext = GetImplAs<ContextGL>(context); ContextGL *glContext = GetImplAs<ContextGL>(context);
glContext->getStateManager()->pauseTransformFeedback(); glContext->getStateManager()->pauseTransformFeedback();
SurfaceGL *glDrawSurface = GetImplAs<SurfaceGL>(drawSurface); if (drawSurface != nullptr)
ANGLE_TRY(glDrawSurface->makeCurrent()); {
mCurrentDrawSurface = drawSurface; SurfaceGL *glDrawSurface = GetImplAs<SurfaceGL>(drawSurface);
ANGLE_TRY(glDrawSurface->makeCurrent());
return egl::Error(EGL_SUCCESS); mCurrentDrawSurface = drawSurface;
return egl::Error(EGL_SUCCESS);
}
else
{
return makeCurrentSurfaceless(context);
}
} }
gl::Version DisplayGL::getMaxSupportedESVersion() const gl::Version DisplayGL::getMaxSupportedESVersion() const
...@@ -102,4 +108,10 @@ gl::Version DisplayGL::getMaxSupportedESVersion() const ...@@ -102,4 +108,10 @@ gl::Version DisplayGL::getMaxSupportedESVersion() const
ASSERT(mRenderer != nullptr); ASSERT(mRenderer != nullptr);
return mRenderer->getMaxSupportedESVersion(); return mRenderer->getMaxSupportedESVersion();
} }
egl::Error DisplayGL::makeCurrentSurfaceless(gl::Context *context)
{
UNIMPLEMENTED();
return egl::NoError();
}
} }
...@@ -51,6 +51,7 @@ class DisplayGL : public DisplayImpl ...@@ -51,6 +51,7 @@ class DisplayGL : public DisplayImpl
private: private:
virtual const FunctionsGL *getFunctionsGL() const = 0; virtual const FunctionsGL *getFunctionsGL() const = 0;
virtual egl::Error makeCurrentSurfaceless(gl::Context *context);
RendererGL *mRenderer; RendererGL *mRenderer;
......
...@@ -59,6 +59,7 @@ class DisplayCGL : public DisplayGL ...@@ -59,6 +59,7 @@ class DisplayCGL : public DisplayGL
private: private:
const FunctionsGL *getFunctionsGL() const override; const FunctionsGL *getFunctionsGL() const override;
egl::Error makeCurrentSurfaceless(gl::Context *context) override;
void generateExtensions(egl::DisplayExtensions *outExtensions) const override; void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override; void generateCaps(egl::Caps *outCaps) const override;
......
...@@ -245,6 +245,7 @@ const FunctionsGL *DisplayCGL::getFunctionsGL() const ...@@ -245,6 +245,7 @@ const FunctionsGL *DisplayCGL::getFunctionsGL() const
void DisplayCGL::generateExtensions(egl::DisplayExtensions *outExtensions) const void DisplayCGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
{ {
outExtensions->surfacelessContext = true;
} }
void DisplayCGL::generateCaps(egl::Caps *outCaps) const void DisplayCGL::generateCaps(egl::Caps *outCaps) const
...@@ -271,4 +272,11 @@ egl::Error DisplayCGL::getDriverVersion(std::string *version) const ...@@ -271,4 +272,11 @@ egl::Error DisplayCGL::getDriverVersion(std::string *version) const
*version = ""; *version = "";
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
egl::Error DisplayCGL::makeCurrentSurfaceless(gl::Context *context)
{
// We have nothing to do as mContext is always current, and that CGL is surfaceless by
// default.
return egl::NoError();
}
} }
...@@ -828,6 +828,94 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E ...@@ -828,6 +828,94 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E
return Error(EGL_SUCCESS); return Error(EGL_SUCCESS);
} }
Error ValidateMakeCurrent(Display *display, EGLSurface draw, EGLSurface read, gl::Context *context)
{
if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
{
return Error(EGL_BAD_MATCH, "If ctx is EGL_NO_CONTEXT, surfaces must be EGL_NO_SURFACE");
}
// If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
// error is generated. EGL_KHR_surfaceless_context allows both surfaces to be EGL_NO_SURFACE.
if (context != EGL_NO_CONTEXT && (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE))
{
if (display->getExtensions().surfacelessContext)
{
if ((draw == EGL_NO_SURFACE) != (read == EGL_NO_SURFACE))
{
return Error(EGL_BAD_MATCH,
"If ctx is not EGL_NOT_CONTEXT, draw or read must both be "
"EGL_NO_SURFACE, or both not");
}
}
else
{
return Error(EGL_BAD_MATCH,
"If ctx is not EGL_NO_CONTEXT, surfaces must not be EGL_NO_SURFACE");
}
}
// If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
// EGL_BAD_MATCH error is generated.
if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
{
return Error(EGL_BAD_MATCH,
"read and draw must both be valid surfaces, or both be EGL_NO_SURFACE");
}
if (display == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
{
return Error(EGL_BAD_DISPLAY, "'dpy' not a valid EGLDisplay handle");
}
// EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
if (!display->isInitialized() &&
(context != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
{
return Error(EGL_NOT_INITIALIZED, "'dpy' not initialized");
}
if (context != EGL_NO_CONTEXT)
{
ANGLE_TRY(ValidateContext(display, context));
}
if (display->isInitialized() && display->testDeviceLost())
{
return Error(EGL_CONTEXT_LOST);
}
Surface *drawSurface = static_cast<Surface *>(draw);
if (draw != EGL_NO_SURFACE)
{
ANGLE_TRY(ValidateSurface(display, drawSurface));
}
Surface *readSurface = static_cast<Surface *>(read);
if (read != EGL_NO_SURFACE)
{
ANGLE_TRY(ValidateSurface(display, readSurface));
}
if (readSurface)
{
ANGLE_TRY(ValidateCompatibleConfigs(display, readSurface->getConfig(), readSurface,
context->getConfig(), readSurface->getType()));
}
if (draw != read)
{
UNIMPLEMENTED(); // FIXME
if (drawSurface)
{
ANGLE_TRY(ValidateCompatibleConfigs(display, drawSurface->getConfig(), drawSurface,
context->getConfig(), drawSurface->getType()));
}
}
return egl::NoError();
}
Error ValidateCompatibleConfigs(const Display *display, Error ValidateCompatibleConfigs(const Display *display,
const Config *config1, const Config *config1,
const Surface *surface, const Surface *surface,
......
...@@ -49,6 +49,8 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri ...@@ -49,6 +49,8 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri
Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer, Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer,
Config *config, const AttributeMap& attributes); Config *config, const AttributeMap& attributes);
Error ValidateMakeCurrent(Display *display, EGLSurface draw, EGLSurface read, gl::Context *context);
Error ValidateCreateImageKHR(const Display *display, Error ValidateCreateImageKHR(const Display *display,
gl::Context *context, gl::Context *context,
EGLenum target, EGLenum target,
......
...@@ -548,109 +548,15 @@ EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface r ...@@ -548,109 +548,15 @@ EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface r
Display *display = static_cast<Display*>(dpy); Display *display = static_cast<Display*>(dpy);
gl::Context *context = static_cast<gl::Context*>(ctx); gl::Context *context = static_cast<gl::Context*>(ctx);
// If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH Error error = ValidateMakeCurrent(display, draw, read, context);
// error is generated. if (error.isError())
if (ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
{
thread->setError(Error(EGL_BAD_MATCH));
return EGL_FALSE;
}
if (ctx != EGL_NO_CONTEXT && draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE)
{
thread->setError(Error(EGL_BAD_MATCH));
return EGL_FALSE;
}
// If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
// EGL_BAD_MATCH error is generated.
if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
{
thread->setError(Error(
EGL_BAD_MATCH, "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE"));
return EGL_FALSE;
}
if (dpy == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
{
thread->setError(Error(EGL_BAD_DISPLAY, "'dpy' not a valid EGLDisplay handle"));
return EGL_FALSE;
}
// EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
if (!display->isInitialized() && (ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
{
thread->setError(Error(EGL_NOT_INITIALIZED, "'dpy' not initialized"));
return EGL_FALSE;
}
if (ctx != EGL_NO_CONTEXT)
{
Error error = ValidateContext(display, context);
if (error.isError())
{
thread->setError(error);
return EGL_FALSE;
}
}
if (display->isInitialized() && display->testDeviceLost())
{ {
thread->setError(Error(EGL_CONTEXT_LOST)); thread->setError(error);
return EGL_FALSE; return EGL_FALSE;
} }
Surface *drawSurface = static_cast<Surface*>(draw);
if (draw != EGL_NO_SURFACE)
{
Error error = ValidateSurface(display, drawSurface);
if (error.isError())
{
thread->setError(error);
return EGL_FALSE;
}
}
Surface *readSurface = static_cast<Surface*>(read); Surface *readSurface = static_cast<Surface*>(read);
if (read != EGL_NO_SURFACE) Surface *drawSurface = static_cast<Surface *>(draw);
{
Error error = ValidateSurface(display, readSurface);
if (error.isError())
{
thread->setError(error);
return EGL_FALSE;
}
}
if (readSurface)
{
Error readCompatError =
ValidateCompatibleConfigs(display, readSurface->getConfig(), readSurface,
context->getConfig(), readSurface->getType());
if (readCompatError.isError())
{
thread->setError(readCompatError);
return EGL_FALSE;
}
}
if (draw != read)
{
UNIMPLEMENTED(); // FIXME
if (drawSurface)
{
Error drawCompatError =
ValidateCompatibleConfigs(display, drawSurface->getConfig(), drawSurface,
context->getConfig(), drawSurface->getType());
if (drawCompatError.isError())
{
thread->setError(drawCompatError);
return EGL_FALSE;
}
}
}
Error makeCurrentError = display->makeCurrent(drawSurface, readSurface, context); Error makeCurrentError = display->makeCurrent(drawSurface, readSurface, context);
if (makeCurrentError.isError()) if (makeCurrentError.isError())
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment