Commit 33b6ae54 by Geoff Lang

Move eglCreateContext validation into validationEGL.

BUG=angle:658 Change-Id: Ibdf601725536edf40c0499aba0402fb160b2c841 Reviewed-on: https://chromium-review.googlesource.com/242035Reviewed-by: 's avatarBrandon Jones <bajones@chromium.org> Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent dd43fccc
...@@ -436,8 +436,8 @@ Error Display::createOffscreenSurface(const Config *configuration, EGLClientBuff ...@@ -436,8 +436,8 @@ Error Display::createOffscreenSurface(const Config *configuration, EGLClientBuff
return Error(EGL_SUCCESS); return Error(EGL_SUCCESS);
} }
Error Display::createContext(const Config *configuration, EGLContext shareContext, const egl::AttributeMap &attribs, Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
EGLContext *outContext) gl::Context **outContext)
{ {
ASSERT(isInitialized()); ASSERT(isInitialized());
...@@ -450,14 +450,8 @@ Error Display::createContext(const Config *configuration, EGLContext shareContex ...@@ -450,14 +450,8 @@ Error Display::createContext(const Config *configuration, EGLContext shareContex
} }
} }
if (attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1) == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR))
{
return Error(EGL_BAD_CONFIG);
}
gl::Context *context = nullptr; gl::Context *context = nullptr;
Error error = mImplementation->createContext(configuration, reinterpret_cast<gl::Context*>(shareContext), Error error = mImplementation->createContext(configuration, shareContext, attribs, &context);
attribs, &context);
if (error.isError()) if (error.isError())
{ {
return error; return error;
......
...@@ -51,7 +51,8 @@ class Display final ...@@ -51,7 +51,8 @@ class Display final
Error createWindowSurface(EGLNativeWindowType window, const Config *configuration, const EGLint *attribList, EGLSurface *outSurface); Error createWindowSurface(EGLNativeWindowType window, const Config *configuration, const EGLint *attribList, EGLSurface *outSurface);
Error createOffscreenSurface(const Config *configuration, EGLClientBuffer shareHandle, const EGLint *attribList, EGLSurface *outSurface); Error createOffscreenSurface(const Config *configuration, EGLClientBuffer shareHandle, const EGLint *attribList, EGLSurface *outSurface);
Error createContext(const Config *configuration, EGLContext shareContext, const egl::AttributeMap &attribs, EGLContext *outContext); Error createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
gl::Context **outContext);
Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context); Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context);
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "libANGLE/Display.h" #include "libANGLE/Display.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include <EGL/eglext.h>
namespace egl namespace egl
{ {
...@@ -79,4 +81,129 @@ Error ValidateContext(const Display *display, gl::Context *context) ...@@ -79,4 +81,129 @@ Error ValidateContext(const Display *display, gl::Context *context)
return Error(EGL_SUCCESS); return Error(EGL_SUCCESS);
} }
Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext,
const AttributeMap& attributes)
{
Error error = ValidateConfig(display, configuration);
if (error.isError())
{
return error;
}
// Get the requested client version (default is 1) and check it is 2 or 3.
EGLint clientMajorVersion = 1;
EGLint clientMinorVersion = 0;
EGLint contextFlags = 0;
bool resetNotification = false;
bool robustAccess = false;
for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
{
EGLint attribute = attributeIter->first;
EGLint value = attributeIter->second;
switch (attribute)
{
case EGL_CONTEXT_CLIENT_VERSION:
clientMajorVersion = value;
break;
case EGL_CONTEXT_MINOR_VERSION:
clientMinorVersion = value;
break;
case EGL_CONTEXT_FLAGS_KHR:
contextFlags = value;
break;
case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
// Only valid for OpenGL (non-ES) contexts
return Error(EGL_BAD_ATTRIBUTE);
case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
if (!display->getExtensions().createContextRobustness)
{
return Error(EGL_BAD_ATTRIBUTE);
}
if (value != EGL_TRUE && value != EGL_FALSE)
{
return Error(EGL_BAD_ATTRIBUTE);
}
robustAccess = (value == EGL_TRUE);
break;
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
META_ASSERT(EGL_LOSE_CONTEXT_ON_RESET_EXT == EGL_LOSE_CONTEXT_ON_RESET_KHR);
META_ASSERT(EGL_NO_RESET_NOTIFICATION_EXT == EGL_NO_RESET_NOTIFICATION_KHR);
// same as EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, fall through
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
if (!display->getExtensions().createContextRobustness)
{
return Error(EGL_BAD_ATTRIBUTE);
}
if (value == EGL_LOSE_CONTEXT_ON_RESET_EXT)
{
resetNotification = true;
}
else if (value != EGL_NO_RESET_NOTIFICATION_EXT)
{
return Error(EGL_BAD_ATTRIBUTE);
}
break;
default:
return Error(EGL_BAD_ATTRIBUTE);
}
}
if ((clientMajorVersion != 2 && clientMajorVersion != 3) || clientMinorVersion != 0)
{
return Error(EGL_BAD_CONFIG);
}
if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR))
{
return Error(EGL_BAD_CONFIG);
}
// Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
const EGLint validContextFlags = (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR |
EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
if ((contextFlags & ~validContextFlags) != 0)
{
return Error(EGL_BAD_ATTRIBUTE);
}
if ((contextFlags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) > 0)
{
robustAccess = true;
}
if (robustAccess)
{
// Unimplemented
return Error(EGL_BAD_CONFIG);
}
if (shareContext)
{
// Shared context is invalid or is owned by another display
if (!display->isValidContext(shareContext))
{
return Error(EGL_BAD_MATCH);
}
if (shareContext->isResetNotificationEnabled() != resetNotification)
{
return Error(EGL_BAD_MATCH);
}
if (shareContext->getClientVersion() != clientMajorVersion)
{
return Error(EGL_BAD_CONTEXT);
}
}
return Error(EGL_SUCCESS);
}
} }
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include <EGL/egl.h>
namespace gl namespace gl
{ {
class Context; class Context;
...@@ -19,6 +21,7 @@ class Context; ...@@ -19,6 +21,7 @@ class Context;
namespace egl namespace egl
{ {
class AttributeMap;
struct Config; struct Config;
class Display; class Display;
class Surface; class Surface;
...@@ -29,6 +32,10 @@ Error ValidateSurface(const Display *display, Surface *surface); ...@@ -29,6 +32,10 @@ Error ValidateSurface(const Display *display, Surface *surface);
Error ValidateConfig(const Display *display, const Config *config); Error ValidateConfig(const Display *display, const Config *config);
Error ValidateContext(const Display *display, gl::Context *context); Error ValidateContext(const Display *display, gl::Context *context);
// Entry point validation
Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext,
const AttributeMap& attributes);
} }
#endif // LIBANGLE_VALIDATIONEGL_H_ #endif // LIBANGLE_VALIDATIONEGL_H_
...@@ -446,146 +446,26 @@ EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContex ...@@ -446,146 +446,26 @@ EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContex
Display *display = static_cast<Display*>(dpy); Display *display = static_cast<Display*>(dpy);
Config *configuration = static_cast<Config*>(config); Config *configuration = static_cast<Config*>(config);
gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context);
AttributeMap attributes(attrib_list);
Error error = ValidateConfig(display, configuration); Error error = ValidateCreateContext(display, configuration, sharedGLContext, attributes);
if (error.isError()) if (error.isError())
{ {
SetGlobalError(error); SetGlobalError(error);
return EGL_NO_CONTEXT; return EGL_NO_CONTEXT;
} }
// Get the requested client version (default is 1) and check it is 2 or 3. gl::Context *context = nullptr;
EGLint clientMajorVersion = 1; error = display->createContext(configuration, sharedGLContext, attributes, &context);
EGLint clientMinorVersion = 0;
EGLint contextFlags = 0;
bool resetNotification = false;
bool robustAccess = false;
if (attrib_list)
{
for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
{
switch (attribute[0])
{
case EGL_CONTEXT_CLIENT_VERSION:
clientMajorVersion = attribute[1];
break;
case EGL_CONTEXT_MINOR_VERSION:
clientMinorVersion = attribute[1];
break;
case EGL_CONTEXT_FLAGS_KHR:
contextFlags = attribute[1];
break;
case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
// Only valid for OpenGL (non-ES) contexts
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
if (!display->getExtensions().createContextRobustness)
{
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
if (attribute[1] != EGL_TRUE && attribute[1] != EGL_FALSE)
{
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
robustAccess = (attribute[1] == EGL_TRUE);
break;
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
META_ASSERT(EGL_LOSE_CONTEXT_ON_RESET_EXT == EGL_LOSE_CONTEXT_ON_RESET_KHR);
META_ASSERT(EGL_NO_RESET_NOTIFICATION_EXT == EGL_NO_RESET_NOTIFICATION_KHR);
// same as EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, fall through
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
if (!display->getExtensions().createContextRobustness)
{
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
{
resetNotification = true;
}
else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
{
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
break;
default:
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
}
}
if ((clientMajorVersion != 2 && clientMajorVersion != 3) || clientMinorVersion != 0)
{
SetGlobalError(Error(EGL_BAD_CONFIG));
return EGL_NO_CONTEXT;
}
// Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
const EGLint validContextFlags = (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR |
EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
if ((contextFlags & ~validContextFlags) != 0)
{
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
if ((contextFlags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) > 0)
{
robustAccess = true;
}
if (robustAccess)
{
// Unimplemented
SetGlobalError(Error(EGL_BAD_CONFIG));
return EGL_NO_CONTEXT;
}
if (share_context)
{
gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context);
// Shared context is invalid or is owned by another display
if (!display->isValidContext(sharedGLContext))
{
SetGlobalError(Error(EGL_BAD_MATCH));
return EGL_NO_CONTEXT;
}
if (sharedGLContext->isResetNotificationEnabled() != resetNotification)
{
SetGlobalError(Error(EGL_BAD_MATCH));
return EGL_NO_CONTEXT;
}
if (sharedGLContext->getClientVersion() != clientMajorVersion)
{
SetGlobalError(Error(EGL_BAD_CONTEXT));
return EGL_NO_CONTEXT;
}
}
EGLContext context = EGL_NO_CONTEXT;
error = display->createContext(configuration, share_context, egl::AttributeMap(attrib_list), &context);
if (error.isError()) if (error.isError())
{ {
SetGlobalError(error); SetGlobalError(error);
return EGL_NO_CONTEXT; return EGL_NO_CONTEXT;
} }
return context; SetGlobalError(Error(EGL_SUCCESS));
return static_cast<EGLContext>(context);
} }
EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx) EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
......
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