This adds support for DRI_DRI2 version 3 to all of the DRI2 drivers.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
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);
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) {
}
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;
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;
ctx->pp = pp_init(screen->base.screen, ctx->pp_enabled);
+ *error = __DRI_CTX_ERROR_SUCCESS;
return GL_TRUE;
fail:
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
/* 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;
}
}
*
* 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);
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;
}
/** 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,
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);
*/
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:
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;
}
return pcp;
}
+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)
};
const __DRIswrastExtension driSWRastExtension = {
- /* Force the version to 2 because the underlying driver don't (can't!)
- * support the extra requirements of CreateContextAttribs.
- */
- { __DRI_SWRAST, 2 },
+ { __DRI_SWRAST, __DRI_SWRAST_VERSION },
driCreateNewScreen,
driCreateNewDrawable,
driCreateNewContextForAPI,
- NULL
+ driCreateContextAttribs
};
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;
}
#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"
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;
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;
}
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,
#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"
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;
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);
glVisual, driContextPriv,
sharedContextPrivate)) {
FREE(rmesa);
+ *error = __DRI_CTX_ERROR_NO_MEMORY;
return GL_FALSE;
}
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;
}
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,
#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"
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;
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);
glVisual, driContextPriv,
sharedContextPrivate)) {
FREE(rmesa);
+ *error = __DRI_CTX_ERROR_NO_MEMORY;
return GL_FALSE;
}
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;
}
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);
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;
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;
/* basic context setup */
if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions, (void *) cPriv)) {
+ *error = __DRI_CTX_ERROR_NO_MEMORY;
goto context_fail;
}
break;
}
+ *error = __DRI_CTX_ERROR_SUCCESS;
return GL_TRUE;
context_fail: