[PATCH 17/20] dri2: Add plumbing to get context version requirements and flags to drivers

Ian Romanick idr at freedesktop.org
Tue Dec 20 12:31:20 PST 2011


From: Ian Romanick <ian.d.romanick at intel.com>

This adds support for DRI_DRI2 version 3 to all of the DRI2 drivers.

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
 .../state_trackers/dri/common/dri_context.c        |   51 ++++++++++++-
 .../state_trackers/dri/common/dri_context.h        |    4 +
 src/mesa/drivers/dri/common/dri_util.c             |   22 ++++--
 src/mesa/drivers/dri/common/dri_util.h             |    4 +
 src/mesa/drivers/dri/common/drisw_util.c           |   74 ++++++++++++++++++--
 src/mesa/drivers/dri/intel/intel_screen.c          |   37 ++++++++--
 src/mesa/drivers/dri/nouveau/nouveau_context.c     |   24 ++++++-
 src/mesa/drivers/dri/nouveau/nouveau_context.h     |    3 +-
 src/mesa/drivers/dri/r200/r200_context.c           |   25 ++++++-
 src/mesa/drivers/dri/r200/r200_context.h           |    4 +
 src/mesa/drivers/dri/radeon/radeon_context.c       |   26 +++++++-
 src/mesa/drivers/dri/radeon/radeon_context.h       |    4 +
 src/mesa/drivers/dri/swrast/swrast.c               |   24 ++++++-
 13 files changed, 272 insertions(+), 30 deletions(-)

diff --git a/src/gallium/state_trackers/dri/common/dri_context.c b/src/gallium/state_trackers/dri/common/dri_context.c
index 3e5a040..b47d8d9 100644
--- a/src/gallium/state_trackers/dri/common/dri_context.c
+++ b/src/gallium/state_trackers/dri/common/dri_context.c
@@ -50,7 +50,12 @@ dri_pp_query(struct dri_context *ctx)
 
 GLboolean
 dri_create_context(gl_api api, const struct gl_config * visual,
-		   __DRIcontext * cPriv, void *sharedContextPrivate)
+		   __DRIcontext * cPriv,
+		   unsigned major_version,
+		   unsigned minor_version,
+		   uint32_t flags,
+		   unsigned *error,
+		   void *sharedContextPrivate)
 {
    __DRIscreen *sPriv = cPriv->driScreenPriv;
    struct dri_screen *screen = dri_screen(sPriv);
@@ -68,9 +73,20 @@ dri_create_context(gl_api api, const struct gl_config * visual,
    case API_OPENGLES2:
       attribs.profile = ST_PROFILE_OPENGL_ES2;
       break;
-   default:
+   case API_OPENGL:
       attribs.profile = ST_PROFILE_DEFAULT;
+      attribs.major = major_version;
+      attribs.minor = minor_version;
+
+      if ((flags & __DRI_CTX_FLAG_DEBUG) != 0)
+	 attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
+
+      if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0)
+	 attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
       break;
+   default:
+      *error = __DRI_CTX_ERROR_BAD_API;
+      goto fail;
    }
 
    if (sharedContextPrivate) {
@@ -78,8 +94,10 @@ dri_create_context(gl_api api, const struct gl_config * visual,
    }
 
    ctx = CALLOC_STRUCT(dri_context);
-   if (ctx == NULL)
+   if (ctx == NULL) {
+      *error = __DRI_CTX_ERROR_NO_MEMORY;
       goto fail;
+   }
 
    cPriv->driverPrivate = ctx;
    ctx->cPriv = cPriv;
@@ -91,8 +109,32 @@ dri_create_context(gl_api api, const struct gl_config * visual,
    dri_fill_st_visual(&attribs.visual, screen, visual);
    ctx->st = stapi->create_context(stapi, &screen->base, &attribs, &ctx_err,
 				   st_share);
-   if (ctx->st == NULL)
+   if (ctx->st == NULL) {
+      switch (ctx_err) {
+      case ST_CONTEXT_SUCCESS:
+	 *error = __DRI_CTX_ERROR_SUCCESS;
+	 break;
+      case ST_CONTEXT_ERROR_NO_MEMORY:
+	 *error = __DRI_CTX_ERROR_NO_MEMORY;
+	 break;
+      case ST_CONTEXT_ERROR_BAD_API:
+	 *error = __DRI_CTX_ERROR_BAD_API;
+	 break;
+      case ST_CONTEXT_ERROR_BAD_VERSION:
+	 *error = __DRI_CTX_ERROR_BAD_VERSION;
+	 break;
+      case ST_CONTEXT_ERROR_BAD_FLAG:
+	 *error = __DRI_CTX_ERROR_BAD_FLAG;
+	 break;
+      case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE:
+	 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
+	 break;
+      case ST_CONTEXT_ERROR_UNKNOWN_FLAG:
+	 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
+	 break;
+      }
       goto fail;
+   }
    ctx->st->st_manager_private = (void *) ctx;
    ctx->stapi = stapi;
 
@@ -101,6 +143,7 @@ dri_create_context(gl_api api, const struct gl_config * visual,
 
    ctx->pp = pp_init(screen->base.screen, ctx->pp_enabled);
 
+   *error = __DRI_CTX_ERROR_SUCCESS;
    return GL_TRUE;
 
  fail:
diff --git a/src/gallium/state_trackers/dri/common/dri_context.h b/src/gallium/state_trackers/dri/common/dri_context.h
index 5fc8119..484b756 100644
--- a/src/gallium/state_trackers/dri/common/dri_context.h
+++ b/src/gallium/state_trackers/dri/common/dri_context.h
@@ -88,6 +88,10 @@ boolean
 dri_create_context(gl_api api,
 		   const struct gl_config * visual,
 		   __DRIcontext * driContextPriv,
+		   unsigned major_version,
+		   unsigned minor_version,
+		   uint32_t flags,
+		   unsigned *error,
 		   void *sharedContextPrivate);
 
 #endif
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index 7751167..948eb07 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -194,6 +194,8 @@ dri2CreateContextAttribs(__DRIscreen *screen, int api,
 	    /* We can't create a context that satisfies the requirements of an
 	     * attribute that we don't understand.  Return failure.
 	     */
+	    assert(!"Should not get here.");
+	    *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
 	    return NULL;
 	}
     }
@@ -209,9 +211,14 @@ dri2CreateContextAttribs(__DRIscreen *screen, int api,
      *
      * In Mesa, a debug context is the same as a regular context.
      */
-    if (major_version >= 3) {
-	if ((flags & ~__DRI_CTX_FLAG_DEBUG) != 0)
-	    return NULL;
+    if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) {
+	*error = __DRI_CTX_ERROR_BAD_FLAG;
+	return NULL;
+    }
+
+    if ((flags & ~__DRI_CTX_FLAG_DEBUG) != 0) {
+	*error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
+	return NULL;
     }
 
     context = malloc(sizeof *context);
@@ -226,7 +233,9 @@ dri2CreateContextAttribs(__DRIscreen *screen, int api,
     context->driDrawablePriv = NULL;
     context->driReadablePriv = NULL;
 
-    if (!driDriverAPI.CreateContext(mesa_api, modes, context, shareCtx) ) {
+    if (!driDriverAPI.CreateContext(mesa_api, modes, context,
+				    major_version, minor_version,
+				    flags, error, shareCtx) ) {
         free(context);
         return NULL;
     }
@@ -521,10 +530,7 @@ const __DRIcoreExtension driCoreExtension = {
 
 /** DRI2 interface */
 const __DRIdri2Extension driDRI2Extension = {
-    /* Force the version to 2 because the underlying drivers don't (can't!)
-     * support the extra requirements of CreateContextAttribs.
-     */
-    { __DRI_DRI2, 2 },
+    { __DRI_DRI2, __DRI_DRI2_VERSION },
     dri2CreateNewScreen,
     dri2CreateNewDrawable,
     dri2CreateNewContext,
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index bebb021..900f048 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -84,6 +84,10 @@ struct __DriverAPIRec {
     GLboolean (*CreateContext)(gl_api api,
                                const struct gl_config *glVis,
                                __DRIcontext *driContextPriv,
+			       unsigned major_version,
+			       unsigned minor_version,
+			       uint32_t flags,
+			       unsigned *error,
                                void *sharedContextPrivate);
 
     void (*DestroyContext)(__DRIcontext *driContextPriv);
diff --git a/src/mesa/drivers/dri/common/drisw_util.c b/src/mesa/drivers/dri/common/drisw_util.c
index 614339e..0ec124a 100644
--- a/src/mesa/drivers/dri/common/drisw_util.c
+++ b/src/mesa/drivers/dri/common/drisw_util.c
@@ -94,14 +94,26 @@ static const __DRIextension **driGetExtensions(__DRIscreen *psp)
  */
 
 static __DRIcontext *
-driCreateNewContextForAPI(__DRIscreen *psp, int api,
-                          const __DRIconfig *config,
-                          __DRIcontext *shared, void *data)
+driCreateContextAttribs(__DRIscreen *screen, int api,
+			const __DRIconfig *config,
+			__DRIcontext *shared,
+			unsigned num_attribs,
+			const uint32_t *attribs,
+			unsigned *error,
+			void *data)
 {
     __DRIcontext *pcp;
     const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
     void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
     gl_api mesa_api;
+    unsigned major_version = 1;
+    unsigned minor_version = 0;
+    uint32_t flags = 0;
+
+    /* Either num_attribs is zero and attribs is NULL, or num_attribs is not
+     * zero and attribs is not NULL.
+     */
+    assert((num_attribs == 0) == (attribs == NULL));
 
     switch (api) {
     case __DRI_API_OPENGL:
@@ -113,21 +125,59 @@ driCreateNewContextForAPI(__DRIscreen *psp, int api,
     case __DRI_API_GLES2:
             mesa_api = API_OPENGLES2;
             break;
+    case __DRI_API_OPENGL_CORE:
     default:
             return NULL;
     }
 
+    for (unsigned i = 0; i < num_attribs; i++) {
+	switch (attribs[i * 2]) {
+	case __DRI_CTX_ATTRIB_MAJOR_VERSION:
+	    major_version = attribs[i * 2 + 1];
+	    break;
+	case __DRI_CTX_ATTRIB_MINOR_VERSION:
+	    minor_version = attribs[i * 2 + 1];
+	    break;
+	case __DRI_CTX_ATTRIB_FLAGS:
+	    flags = attribs[i * 2 + 1];
+	    break;
+	default:
+	    /* We can't create a context that satisfies the requirements of an
+	     * attribute that we don't understand.  Return failure.
+	     */
+	    return NULL;
+	}
+    }
+
+    /* There are no forward-compatible contexts before OpenGL 3.0.  The
+     * GLX_ARB_create_context spec says:
+     *
+     *     "Forward-compatible contexts are defined only for OpenGL versions
+     *     3.0 and later."
+     *
+     * Moreover, Mesa can't fulfill the requirements of a forward-looking
+     * context.  Return failure if a forward-looking context is requested.
+     *
+     * In Mesa, a debug context is the same as a regular context.
+     */
+    if (major_version >= 3) {
+	if ((flags & ~__DRI_CTX_FLAG_DEBUG) != 0)
+	    return NULL;
+    }
+
     pcp = CALLOC_STRUCT(__DRIcontextRec);
     if (!pcp)
         return NULL;
 
     pcp->loaderPrivate = data;
 
-    pcp->driScreenPriv = psp;
+    pcp->driScreenPriv = screen;
     pcp->driDrawablePriv = NULL;
     pcp->driReadablePriv = NULL;
 
-    if (!driDriverAPI.CreateContext(mesa_api, modes, pcp, shareCtx)) {
+    if (!driDriverAPI.CreateContext(mesa_api, modes, pcp,
+				    major_version, minor_version,
+				    flags, error, shareCtx)) {
         FREE(pcp);
         return NULL;
     }
@@ -136,6 +186,17 @@ driCreateNewContextForAPI(__DRIscreen *psp, int api,
 }
 
 static __DRIcontext *
+driCreateNewContextForAPI(__DRIscreen *psp, int api,
+                          const __DRIconfig *config,
+                          __DRIcontext *shared, void *data)
+{
+    unsigned error;
+
+    return driCreateContextAttribs(psp, api, config, shared, 0, NULL,
+				   &error, data);
+}
+
+static __DRIcontext *
 driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
 		    __DRIcontext *shared, void *data)
 {
@@ -291,5 +352,6 @@ const __DRIswrastExtension driSWRastExtension = {
     { __DRI_SWRAST, __DRI_SWRAST_VERSION },
     driCreateNewScreen,
     driCreateNewDrawable,
-    driCreateNewContextForAPI
+    driCreateNewContextForAPI,
+    driCreateContextAttribs
 };
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index e4cc5b0..76b231b 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -516,27 +516,52 @@ static GLboolean
 intelCreateContext(gl_api api,
 		   const struct gl_config * mesaVis,
                    __DRIcontext * driContextPriv,
+		   unsigned major_version,
+		   unsigned minor_version,
+		   uint32_t flags,
+		   unsigned *error,
                    void *sharedContextPrivate)
 {
    __DRIscreen *sPriv = driContextPriv->driScreenPriv;
    struct intel_screen *intelScreen = sPriv->driverPrivate;
+   bool success;
 
 #ifdef I915
    if (IS_9XX(intelScreen->deviceID)) {
       if (!IS_965(intelScreen->deviceID)) {
-	 return i915CreateContext(api, mesaVis, driContextPriv,
-				  sharedContextPrivate);
+	 success = i915CreateContext(api, mesaVis, driContextPriv,
+				     sharedContextPrivate);
       }
    } else {
       intelScreen->no_vbo = true;
-      return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
+      success = i830CreateContext(mesaVis, driContextPriv,
+				  sharedContextPrivate);
    }
 #else
    if (IS_965(intelScreen->deviceID))
-      return brwCreateContext(api, mesaVis,
-			      driContextPriv, sharedContextPrivate);
+      success = brwCreateContext(api, mesaVis,
+			      driContextPriv,
+			      sharedContextPrivate);
 #endif
-   fprintf(stderr, "Unrecognized deviceID 0x%x\n", intelScreen->deviceID);
+
+   if (success) {
+      struct gl_context *ctx =
+	 (struct gl_context *) driContextPriv->driverPrivate;
+
+      _mesa_compute_version(ctx);
+      if (ctx->VersionMajor > major_version
+	  || (ctx->VersionMajor == major_version
+	      && ctx->VersionMinor >= minor_version)) {
+	 *error = __DRI_CTX_ERROR_BAD_VERSION;
+	 return true;
+      }
+
+      intelDestroyContext(driContextPriv);
+   } else {
+      *error = __DRI_CTX_ERROR_NO_MEMORY;
+      fprintf(stderr, "Unrecognized deviceID 0x%x\n", intelScreen->deviceID);
+   }
+
    return false;
 }
 
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index 0e3321e..0cb918e 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -34,6 +34,7 @@
 #include "main/framebuffer.h"
 #include "main/light.h"
 #include "main/state.h"
+#include "main/version.h"
 #include "drivers/common/meta.h"
 #include "drivers/common/driverfuncs.h"
 #include "swrast/swrast.h"
@@ -55,6 +56,10 @@ nouveau_channel_flush_notify(struct nouveau_channel *chan)
 GLboolean
 nouveau_context_create(gl_api api,
 		       const struct gl_config *visual, __DRIcontext *dri_ctx,
+		       unsigned major_version,
+		       unsigned minor_version,
+		       uint32_t flags,
+		       unsigned *error,
 		       void *share_ctx)
 {
 	__DRIscreen *dri_screen = dri_ctx->driScreenPriv;
@@ -62,14 +67,31 @@ nouveau_context_create(gl_api api,
 	struct nouveau_context *nctx;
 	struct gl_context *ctx;
 
+	/* API and flag filtering is handled in dri2CreateContextAttribs.
+	 */
+	(void) api;
+	(void) flags;
+
 	ctx = screen->driver->context_create(screen, visual, share_ctx);
-	if (!ctx)
+	if (!ctx) {
+		*error = __DRI_CTX_ERROR_NO_MEMORY;
 		return GL_FALSE;
+	}
 
 	nctx = to_nouveau_context(ctx);
 	nctx->dri_context = dri_ctx;
 	dri_ctx->driverPrivate = ctx;
 
+	_mesa_compute_version(ctx);
+	if (ctx->VersionMajor < major_version
+	    || (ctx->VersionMajor == major_version
+		&& ctx->VersionMinor < minor_version)) {
+	   nouveau_context_destroy(dri_ctx);
+	   *error = __DRI_CTX_ERROR_BAD_VERSION;
+	   return GL_FALSE;
+	}
+
+	*error = __DRI_CTX_ERROR_SUCCESS;
 	return GL_TRUE;
 }
 
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h
index 7ebc676..cd4a9fb 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h
@@ -98,7 +98,8 @@ struct nouveau_context {
 GLboolean
 nouveau_context_create(gl_api api,
 		       const struct gl_config *visual, __DRIcontext *dri_ctx,
-		       void *share_ctx);
+		       unsigned major_version, unsigned minor_version,
+		       uint32_t flags, unsigned *error, void *share_ctx);
 
 GLboolean
 nouveau_context_init(struct gl_context *ctx, struct nouveau_screen *screen,
diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c
index 90cccf5..d7a6489 100644
--- a/src/mesa/drivers/dri/r200/r200_context.c
+++ b/src/mesa/drivers/dri/r200/r200_context.c
@@ -40,6 +40,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "main/imports.h"
 #include "main/extensions.h"
 #include "main/mfeatures.h"
+#include "main/version.h"
 
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
@@ -196,6 +197,10 @@ static void r200_init_vtbl(radeonContextPtr radeon)
 GLboolean r200CreateContext( gl_api api,
 			     const struct gl_config *glVisual,
 			     __DRIcontext *driContextPriv,
+			     unsigned major_version,
+			     unsigned minor_version,
+			     uint32_t flags,
+			     unsigned *error,
 			     void *sharedContextPrivate)
 {
    __DRIscreen *sPriv = driContextPriv->driScreenPriv;
@@ -206,14 +211,21 @@ GLboolean r200CreateContext( gl_api api,
    int i;
    int tcl_mode;
 
+   /* API and flag filtering is handled in dri2CreateContextAttribs.
+    */
+   (void) api;
+   (void) flags;
+
    assert(glVisual);
    assert(driContextPriv);
    assert(screen);
 
    /* Allocate the R200 context */
    rmesa = (r200ContextPtr) CALLOC( sizeof(*rmesa) );
-   if ( !rmesa )
+   if ( !rmesa ) {
+      *error = __DRI_CTX_ERROR_NO_MEMORY;
       return GL_FALSE;
+   }
 
    rmesa->radeon.radeonScreen = screen;
    r200_init_vtbl(&rmesa->radeon);
@@ -256,6 +268,7 @@ GLboolean r200CreateContext( gl_api api,
 			  glVisual, driContextPriv,
 			  sharedContextPrivate)) {
      FREE(rmesa);
+     *error = __DRI_CTX_ERROR_NO_MEMORY;
      return GL_FALSE;
    }
 
@@ -439,6 +452,16 @@ GLboolean r200CreateContext( gl_api api,
       TCL_FALLBACK(rmesa->radeon.glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
    }
 
+   _mesa_compute_version(ctx);
+   if (ctx->VersionMajor < major_version
+       || (ctx->VersionMajor == major_version
+	   && ctx->VersionMinor < minor_version)) {
+      r200DestroyContext(driContextPriv);
+      *error = __DRI_CTX_ERROR_BAD_VERSION;
+      return GL_FALSE;
+   }
+
+   *error = __DRI_CTX_ERROR_SUCCESS;
    return GL_TRUE;
 }
 
diff --git a/src/mesa/drivers/dri/r200/r200_context.h b/src/mesa/drivers/dri/r200/r200_context.h
index 720219f..e0d5693 100644
--- a/src/mesa/drivers/dri/r200/r200_context.h
+++ b/src/mesa/drivers/dri/r200/r200_context.h
@@ -635,6 +635,10 @@ extern void r200DestroyContext( __DRIcontext *driContextPriv );
 extern GLboolean r200CreateContext( gl_api api,
 				    const struct gl_config *glVisual,
 				    __DRIcontext *driContextPriv,
+				    unsigned major_version,
+				    unsigned minor_version,
+				    uint32_t flags,
+				    unsigned *error,
 				    void *sharedContextPrivate);
 extern GLboolean r200MakeCurrent( __DRIcontext *driContextPriv,
 				  __DRIdrawable *driDrawPriv,
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c
index e7d461f..40fd4dc 100644
--- a/src/mesa/drivers/dri/radeon/radeon_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_context.c
@@ -42,6 +42,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "main/imports.h"
 #include "main/extensions.h"
 #include "main/mfeatures.h"
+#include "main/version.h"
 
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
@@ -162,6 +163,10 @@ GLboolean
 r100CreateContext( gl_api api,
 		   const struct gl_config *glVisual,
 		   __DRIcontext *driContextPriv,
+		   unsigned major_version,
+		   unsigned minor_version,
+		   uint32_t flags,
+		   unsigned *error,
 		   void *sharedContextPrivate)
 {
    __DRIscreen *sPriv = driContextPriv->driScreenPriv;
@@ -172,14 +177,21 @@ r100CreateContext( gl_api api,
    int i;
    int tcl_mode, fthrottle_mode;
 
+   /* API and flag filtering is handled in dri2CreateContextAttribs.
+    */
+   (void) api;
+   (void) flags;
+
    assert(glVisual);
    assert(driContextPriv);
    assert(screen);
 
    /* Allocate the Radeon context */
    rmesa = (r100ContextPtr) CALLOC( sizeof(*rmesa) );
-   if ( !rmesa )
+   if ( !rmesa ) {
+      *error = __DRI_CTX_ERROR_NO_MEMORY;
       return GL_FALSE;
+   }
 
    rmesa->radeon.radeonScreen = screen;
    r100_init_vtbl(&rmesa->radeon);
@@ -218,6 +230,7 @@ r100CreateContext( gl_api api,
 			  glVisual, driContextPriv,
 			  sharedContextPrivate)) {
      FREE(rmesa);
+     *error = __DRI_CTX_ERROR_NO_MEMORY;
      return GL_FALSE;
    }
 
@@ -386,5 +399,16 @@ r100CreateContext( gl_api api,
    if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
 /*       _tnl_need_dlist_norm_lengths( ctx, GL_FALSE ); */
    }
+
+   _mesa_compute_version(ctx);
+   if (ctx->VersionMajor < major_version
+       || (ctx->VersionMajor == major_version
+	   && ctx->VersionMinor < minor_version)) {
+      radeonDestroyContext(driContextPriv);
+      *error = __DRI_CTX_ERROR_BAD_VERSION;
+      return GL_FALSE;
+   }
+
+   *error = __DRI_CTX_ERROR_SUCCESS;
    return GL_TRUE;
 }
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.h b/src/mesa/drivers/dri/radeon/radeon_context.h
index e7d51ef..cb036cd 100644
--- a/src/mesa/drivers/dri/radeon/radeon_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_context.h
@@ -450,6 +450,10 @@ struct r100_context {
 extern GLboolean r100CreateContext( gl_api api,
 				    const struct gl_config *glVisual,
 				    __DRIcontext *driContextPriv,
+				    unsigned major_version,
+				    unsigned minor_version,
+				    uint32_t flags,
+				    unsigned *error,
 				    void *sharedContextPrivate);
 
 
diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c
index ac82dc7..ff74cc5 100644
--- a/src/mesa/drivers/dri/swrast/swrast.c
+++ b/src/mesa/drivers/dri/swrast/swrast.c
@@ -702,7 +702,12 @@ InitExtensionsES2(struct gl_context *ctx)
 static GLboolean
 dri_create_context(gl_api api,
 		   const struct gl_config * visual,
-		   __DRIcontext * cPriv, void *sharedContextPrivate)
+		   __DRIcontext * cPriv,
+		   unsigned major_version,
+		   unsigned minor_version,
+		   uint32_t flags,
+		   unsigned *error,
+		   void *sharedContextPrivate)
 {
     struct dri_context *ctx = NULL;
     struct dri_context *share = (struct dri_context *)sharedContextPrivate;
@@ -712,9 +717,22 @@ dri_create_context(gl_api api,
 
     TRACE;
 
+    /* Flag filtering is handled in dri2CreateContextAttribs.
+     */
+    (void) flags;
+
+    if (api == API_OPENGL
+	&& (major_version > 2
+	    || (major_version == 2 && minor_version > 1))) {
+       *error = __DRI_CTX_ERROR_BAD_VERSION;
+       goto context_fail;
+    }
+
     ctx = CALLOC_STRUCT(dri_context);
-    if (ctx == NULL)
+    if (ctx == NULL) {
+	*error = __DRI_CTX_ERROR_NO_MEMORY;
 	goto context_fail;
+    }
 
     cPriv->driverPrivate = ctx;
     ctx->cPriv = cPriv;
@@ -731,6 +749,7 @@ dri_create_context(gl_api api,
 
     /* basic context setup */
     if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions, (void *) cPriv)) {
+	*error = __DRI_CTX_ERROR_NO_MEMORY;
 	goto context_fail;
     }
 
@@ -772,6 +791,7 @@ dri_create_context(gl_api api,
         break;
     }
 
+    *error = __DRI_CTX_ERROR_SUCCESS;
     return GL_TRUE;
 
 context_fail:
-- 
1.7.6.4



More information about the xorg-devel mailing list