aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/glx
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/glx')
-rw-r--r--xorg-server/glx/clientinfo.c27
-rw-r--r--xorg-server/glx/createcontext.c101
-rw-r--r--xorg-server/glx/extension_string.c2
-rw-r--r--xorg-server/glx/extension_string.h2
-rw-r--r--xorg-server/glx/glxcmds.c10
-rw-r--r--xorg-server/glx/glxcontext.h5
-rw-r--r--xorg-server/glx/glxdri2.c97
-rw-r--r--xorg-server/glx/glxserver.h1
8 files changed, 232 insertions, 13 deletions
diff --git a/xorg-server/glx/clientinfo.c b/xorg-server/glx/clientinfo.c
index b26ac1a72..4aaa4c967 100644
--- a/xorg-server/glx/clientinfo.c
+++ b/xorg-server/glx/clientinfo.c
@@ -29,10 +29,10 @@
#include "glxbyteorder.h"
#include "unpack.h"
-int
-__glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc)
+static int
+set_client_info(__GLXclientState * cl, xGLXSetClientInfoARBReq * req,
+ unsigned bytes_per_version)
{
- xGLXSetClientInfoARBReq *req = (xGLXSetClientInfoARBReq *) pc;
char *gl_extensions;
char *glx_extensions;
@@ -40,7 +40,7 @@ __glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc)
* sizes specified for the various fields.
*/
const unsigned expected_size = sz_xGLXSetClientInfoARBReq
- + (req->numVersions * 8)
+ + (req->numVersions * bytes_per_version)
+ __GLX_PAD(req->numGLExtensionBytes)
+ __GLX_PAD(req->numGLXExtensionBytes);
@@ -50,7 +50,7 @@ __glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc)
/* Verify that the actual length of the GL extension string matches what's
* encoded in protocol packet.
*/
- gl_extensions = (char *) (req + 1) + (req->numVersions * 8);
+ gl_extensions = (char *) (req + 1) + (req->numVersions * bytes_per_version);
if (req->numGLExtensionBytes != 0
&& memchr(gl_extensions, 0,
__GLX_PAD(req->numGLExtensionBytes)) == NULL)
@@ -72,6 +72,12 @@ __glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc)
}
int
+__glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc)
+{
+ return set_client_info(cl, (xGLXSetClientInfoARBReq *) pc, 8);
+}
+
+int
__glXDispSwap_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc)
{
xGLXSetClientInfoARBReq *req = (xGLXSetClientInfoARBReq *) pc;
@@ -87,11 +93,18 @@ __glXDispSwap_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc)
int
__glXDisp_SetClientInfo2ARB(__GLXclientState * cl, GLbyte * pc)
{
- return BadRequest;
+ return set_client_info(cl, (xGLXSetClientInfoARBReq *) pc, 12);
}
int
__glXDispSwap_SetClientInfo2ARB(__GLXclientState * cl, GLbyte * pc)
{
- return BadRequest;
+ xGLXSetClientInfoARBReq *req = (xGLXSetClientInfoARBReq *) pc;
+
+ req->length = bswap_16(req->length);
+ req->numVersions = bswap_32(req->numVersions);
+ req->numGLExtensionBytes = bswap_32(req->numGLExtensionBytes);
+ req->numGLXExtensionBytes = bswap_32(req->numGLXExtensionBytes);
+
+ return __glXDisp_SetClientInfo2ARB(cl, pc);
}
diff --git a/xorg-server/glx/createcontext.c b/xorg-server/glx/createcontext.c
index 025c423fe..13d21ccb9 100644
--- a/xorg-server/glx/createcontext.c
+++ b/xorg-server/glx/createcontext.c
@@ -30,7 +30,8 @@
#include "indirect_dispatch.h"
#define ALL_VALID_FLAGS \
- (GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
+ (GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB \
+ | GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB)
static Bool
validate_GL_version(int major_version, int minor_version)
@@ -90,6 +91,24 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
__GLXconfig *config;
int err;
+ /* The GLX_ARB_create_context_robustness spec says:
+ *
+ * "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
+ * is GLX_NO_RESET_NOTIFICATION_ARB."
+ */
+ int reset = GLX_NO_RESET_NOTIFICATION_ARB;
+
+ /* The GLX_ARB_create_context_profile spec says:
+ *
+ * "The default value for GLX_CONTEXT_PROFILE_MASK_ARB is
+ * GLX_CONTEXT_CORE_PROFILE_BIT_ARB."
+ *
+ * The core profile only makes sense for OpenGL versions 3.2 and later.
+ * If the version ultimately specified is less than 3.2, the core profile
+ * bit is cleared (see below).
+ */
+ int profile = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+
/* Verify that the size of the packet matches the size inferred from the
* sizes specified for the various fields.
*/
@@ -161,6 +180,18 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
render_type = attribs[2 * i + 1];
break;
+ case GLX_CONTEXT_PROFILE_MASK_ARB:
+ profile = attribs[2 * i + 1];
+ break;
+
+ case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
+ reset = attribs[2 * i + 1];
+ if (reset != GLX_NO_RESET_NOTIFICATION_ARB
+ && reset != GLX_LOSE_CONTEXT_ON_RESET_ARB)
+ return BadValue;
+
+ break;
+
default:
return BadValue;
}
@@ -202,6 +233,73 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
if ((flags & ~ALL_VALID_FLAGS) != 0)
return BadValue;
+ /* The GLX_ARB_create_context_profile spec says:
+ *
+ * "* If attribute GLX_CONTEXT_PROFILE_MASK_ARB has no bits set; has
+ * any bits set other than GLX_CONTEXT_CORE_PROFILE_BIT_ARB and
+ * GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; has more than one of
+ * these bits set; or if the implementation does not support the
+ * requested profile, then GLXBadProfileARB is generated."
+ */
+ switch (profile) {
+ case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
+ case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
+ break;
+ case GLX_CONTEXT_ES2_PROFILE_BIT_EXT:
+ /* The GLX_EXT_create_context_es2_profile spec says:
+ *
+ * "... If the version requested is 2.0, and the
+ * GLX_CONTEXT_ES2_PROFILE_BIT_EXT bit is set in the
+ * GLX_CONTEXT_PROFILE_MASK_ARB attribute (see below), then the
+ * context returned will implement OpenGL ES 2.0."
+ *
+ * It also says:
+ *
+ * "* If attribute GLX_CONTEXT_PROFILE_MASK_ARB has no bits set;
+ * has any bits set other than
+ * GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+ * GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, or
+ * GLX_CONTEXT_ES2_PROFILE_BIT_EXT; has more than one of these
+ * bits set; or if the implementation does not supported the
+ * requested profile, then GLXBadProfileARB is generated."
+ *
+ * It does not specifically say what is supposed to happen if
+ * GLX_CONTEXT_ES2_PROFILE_BIT_EXT is set but the version requested is
+ * not 2.0. We choose to generate GLXBadProfileARB as this matches
+ * NVIDIA's behavior.
+ */
+ if (major_version != 2 || minor_version != 0)
+ return __glXError(GLXBadProfileARB);
+ break;
+ default:
+ return __glXError(GLXBadProfileARB);
+ }
+
+ /* The GLX_ARB_create_context_robustness spec says:
+ *
+ * "* If the reset notification behavior of <share_context> and the
+ * newly created context are different, BadMatch is generated."
+ */
+ if (shareCtx != NULL && shareCtx->resetNotificationStrategy != reset)
+ return BadMatch;
+
+ /* There is no GLX protocol for desktop OpenGL versions after 1.4. There
+ * is no GLX protocol for any version of OpenGL ES. If the application is
+ * requested an indirect rendering context for a version that cannot be
+ * satisfied, reject it.
+ *
+ * The GLX_ARB_create_context spec says:
+ *
+ * "* If <config> does not support compatible OpenGL contexts
+ * providing the requested API major and minor version,
+ * forward-compatible flag, and debug context flag, GLXBadFBConfig
+ * is generated."
+ */
+ if (!req->isDirect && (major_version > 1 || minor_version > 4
+ || profile == GLX_CONTEXT_ES2_PROFILE_BIT_EXT)) {
+ return __glXError(GLXBadFBConfig);
+ }
+
/* Allocate memory for the new context
*/
if (req->isDirect) {
@@ -232,6 +330,7 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
ctx->selectBufSize = 0;
ctx->drawPriv = NULL;
ctx->readPriv = NULL;
+ ctx->resetNotificationStrategy = reset;
/* Add the new context to the various global tables of GLX contexts.
*/
diff --git a/xorg-server/glx/extension_string.c b/xorg-server/glx/extension_string.c
index 6a1a6c6b2..ee9864e64 100644
--- a/xorg-server/glx/extension_string.c
+++ b/xorg-server/glx/extension_string.c
@@ -70,8 +70,10 @@ static const struct extension_info known_glx_extensions[] = {
/* *INDENT-OFF* */
{ GLX(ARB_create_context), VER(0,0), N, },
{ GLX(ARB_create_context_profile), VER(0,0), N, },
+ { GLX(ARB_create_context_robustness), VER(0,0), N, },
{ GLX(ARB_multisample), VER(1,4), Y, },
+ { GLX(EXT_create_context_es2_profile), VER(0,0), N, },
{ GLX(EXT_import_context), VER(0,0), Y, },
{ GLX(EXT_texture_from_pixmap), VER(0,0), Y, },
{ GLX(EXT_visual_info), VER(0,0), Y, },
diff --git a/xorg-server/glx/extension_string.h b/xorg-server/glx/extension_string.h
index 947bf89e6..7a4a8b1c2 100644
--- a/xorg-server/glx/extension_string.h
+++ b/xorg-server/glx/extension_string.h
@@ -38,7 +38,9 @@ enum {
/* GLX_ARB_get_proc_address is implemented on the client. */
ARB_create_context_bit = 0,
ARB_create_context_profile_bit,
+ ARB_create_context_robustness_bit,
ARB_multisample_bit,
+ EXT_create_context_es2_profile_bit,
EXT_import_context_bit,
EXT_texture_from_pixmap_bit,
EXT_visual_info_bit,
diff --git a/xorg-server/glx/glxcmds.c b/xorg-server/glx/glxcmds.c
index 265b8efa5..5e6e74f8b 100644
--- a/xorg-server/glx/glxcmds.c
+++ b/xorg-server/glx/glxcmds.c
@@ -318,6 +318,16 @@ DoCreateContext(__GLXclientState * cl, GLXContextID gcId,
glxc->drawPriv = NULL;
glxc->readPriv = NULL;
+ /* The GLX_ARB_create_context_robustness spec says:
+ *
+ * "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
+ * is GLX_NO_RESET_NOTIFICATION_ARB."
+ *
+ * Without using glXCreateContextAttribsARB, there is no way to specify a
+ * non-default reset notification strategy.
+ */
+ glxc->resetNotificationStrategy = GLX_NO_RESET_NOTIFICATION_ARB;
+
/* Add the new context to the various global tables of GLX contexts.
*/
if (!__glXAddContext(glxc)) {
diff --git a/xorg-server/glx/glxcontext.h b/xorg-server/glx/glxcontext.h
index b803a7fd1..4764e56f5 100644
--- a/xorg-server/glx/glxcontext.h
+++ b/xorg-server/glx/glxcontext.h
@@ -104,6 +104,11 @@ struct __GLXcontext {
*/
GLenum renderMode;
+ /**
+ * Reset notification strategy used when a GPU reset occurs.
+ */
+ GLenum resetNotificationStrategy;
+
/*
** Buffers for feedback and selection.
*/
diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c
index 7b76c3a5f..1e99179d4 100644
--- a/xorg-server/glx/glxdri2.c
+++ b/xorg-server/glx/glxdri2.c
@@ -59,6 +59,16 @@ typedef struct __GLXDRIscreen __GLXDRIscreen;
typedef struct __GLXDRIcontext __GLXDRIcontext;
typedef struct __GLXDRIdrawable __GLXDRIdrawable;
+
+#ifdef __DRI2_ROBUSTNESS
+#define ALL_DRI_CTX_FLAGS (__DRI_CTX_FLAG_DEBUG \
+ | __DRI_CTX_FLAG_FORWARD_COMPATIBLE \
+ | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)
+#else
+#define ALL_DRI_CTX_FLAGS (__DRI_CTX_FLAG_DEBUG \
+ | __DRI_CTX_FLAG_FORWARD_COMPATIBLE)
+#endif
+
struct __GLXDRIscreen {
__GLXscreen base;
__DRIscreen *driScreen;
@@ -381,7 +391,7 @@ __glXDRIscreenDestroy(__GLXscreen * baseScreen)
static Bool
dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs,
unsigned *major_ver, unsigned *minor_ver,
- uint32_t *flags, unsigned *error)
+ uint32_t *flags, int *api, int *reset, unsigned *error)
{
unsigned i;
@@ -395,6 +405,11 @@ dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs,
*major_ver = 1;
*minor_ver = 0;
+#ifdef __DRI2_ROBUSTNESS
+ *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
+#else
+ (void) reset;
+#endif
for (i = 0; i < num_attribs; i++) {
switch (attribs[i * 2]) {
@@ -409,6 +424,42 @@ dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs,
break;
case GLX_RENDER_TYPE:
break;
+ case GLX_CONTEXT_PROFILE_MASK_ARB:
+ switch (attribs[i * 2 + 1]) {
+ case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
+ *api = __DRI_API_OPENGL_CORE;
+ break;
+ case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
+ *api = __DRI_API_OPENGL;
+ break;
+ case GLX_CONTEXT_ES2_PROFILE_BIT_EXT:
+ *api = __DRI_API_GLES2;
+ break;
+ default:
+ *error = __glXError(GLXBadProfileARB);
+ return False;
+ }
+ break;
+#ifdef __DRI2_ROBUSTNESS
+ case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
+ if (screen->dri2->base.version >= 4) {
+ *error = BadValue;
+ return False;
+ }
+
+ switch (attribs[i * 2 + 1]) {
+ case GLX_NO_RESET_NOTIFICATION_ARB:
+ *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
+ break;
+ case GLX_LOSE_CONTEXT_ON_RESET_ARB:
+ *reset = __DRI_CTX_RESET_LOSE_CONTEXT;
+ break;
+ default:
+ *error = BadValue;
+ return False;
+ }
+ break;
+#endif
default:
/* If an unknown attribute is received, fail.
*/
@@ -419,11 +470,21 @@ dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs,
/* Unknown flag value.
*/
- if (*flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE)) {
+ if ((*flags & ~ALL_DRI_CTX_FLAGS) != 0) {
*error = BadValue;
return False;
}
+ /* If the core profile is requested for a GL version is less than 3.2,
+ * request the non-core profile from the DRI driver. The core profile
+ * only makes sense for GL versions >= 3.2, and many DRI drivers that
+ * don't support OpenGL 3.2 may fail the request for a core profile.
+ */
+ if (*api == __DRI_API_OPENGL_CORE
+ && (*major_ver < 3 || (*major_ver < 3 && *minor_ver < 2))) {
+ *api == __DRI_API_OPENGL;
+ }
+
*error = Success;
return True;
}
@@ -447,11 +508,14 @@ create_driver_context(__GLXDRIcontext * context,
unsigned major_ver;
unsigned minor_ver;
uint32_t flags;
+ int reset;
+ int api;
if (num_attribs != 0) {
if (!dri2_convert_glx_attribs(num_attribs, attribs,
&major_ver, &minor_ver,
- &flags, (unsigned *) error))
+ &flags, &api, &reset,
+ (unsigned *) error))
return NULL;
ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
@@ -467,11 +531,19 @@ create_driver_context(__GLXDRIcontext * context,
*/
ctx_attribs[num_ctx_attribs++] = flags;
}
+
+#ifdef __DRI2_ROBUSTNESS
+ if (reset != __DRI_CTX_NO_RESET_NOTIFICATION) {
+ ctx_attribs[num_ctx_attribs++] =
+ __DRI_CTX_ATTRIB_RESET_NOTIFICATION;
+ ctx_attribs[num_ctx_attribs++] = reset;
+ }
+#endif
}
context->driContext =
(*screen->dri2->createContextAttribs)(screen->driScreen,
- __DRI_API_OPENGL,
+ api,
config->driConfig,
driShare,
num_ctx_attribs / 2,
@@ -786,7 +858,14 @@ initializeExtensions(__GLXDRIscreen * screen)
if (screen->dri2->base.version >= 3) {
__glXEnableExtension(screen->glx_enable_bits,
"GLX_ARB_create_context");
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_ARB_create_context_profile");
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_EXT_create_context_es2_profile");
LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_create_context\n");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_create_context_profile\n");
+ LogMessage(X_INFO,
+ "AIGLX: enabled GLX_EXT_create_context_es2_profile\n");
}
#endif
@@ -823,6 +902,16 @@ initializeExtensions(__GLXDRIscreen * screen)
}
#endif
+#ifdef __DRI2_ROBUSTNESS
+ if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0 &&
+ screen->dri2->base.version >= 3) {
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_ARB_create_context_robustness");
+ LogMessage(X_INFO,
+ "AIGLX: enabled GLX_ARB_create_context_robustness\n");
+ }
+#endif
+
/* Ignore unknown extensions */
}
}
diff --git a/xorg-server/glx/glxserver.h b/xorg-server/glx/glxserver.h
index 098130436..1b44c50bd 100644
--- a/xorg-server/glx/glxserver.h
+++ b/xorg-server/glx/glxserver.h
@@ -46,7 +46,6 @@
#include <resource.h>
#include <scrnintstr.h>
-#define GL_GLEXT_PROTOTYPES /* we want prototypes */
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glxproto.h>