Add struct st_context_attribs to describe context profiles and attributes. Modify st_api::create_context to take the new struct instead of an st_visual. st_context_attribs can be used to support GLX_ARB_create_context_profile and GLX_EXT_create_context_es2_profile in the future. But the motivation for doing it now is to be able to replace ST_API_OPENGL_ES1 and ST_API_OPENGL_ES2 by profiles. Having 3 st_api's to provide OpenGL, OpenGL ES 1.1, and OpenGL ES 2.0 is not a sane abstraction, since all of them share glapi for current context/dispatch management.tags/mesa-7.9-rc1
@@ -54,6 +54,23 @@ enum st_api_type { | |||
ST_API_COUNT | |||
}; | |||
/** | |||
* The profile of a context. | |||
*/ | |||
enum st_profile_type | |||
{ | |||
ST_PROFILE_DEFAULT, | |||
ST_PROFILE_OPENGL_CORE, | |||
ST_PROFILE_OPENGL_ES1, | |||
ST_PROFILE_OPENGL_ES2 | |||
}; | |||
/* for profile_mask in st_api */ | |||
#define ST_PROFILE_DEFAULT_MASK (1 << ST_PROFILE_DEFAULT) | |||
#define ST_PROFILE_OPENGL_CORE_MASK (1 << ST_PROFILE_OPENGL_CORE) | |||
#define ST_PROFILE_OPENGL_ES1_MASK (1 << ST_PROFILE_OPENGL_ES1) | |||
#define ST_PROFILE_OPENGL_ES2_MASK (1 << ST_PROFILE_OPENGL_ES2) | |||
/** | |||
* Used in st_context_iface->teximage. | |||
*/ | |||
@@ -179,6 +196,37 @@ struct st_visual | |||
enum st_attachment_type render_buffer; | |||
}; | |||
/** | |||
* Represent the attributes of a context. | |||
*/ | |||
struct st_context_attribs | |||
{ | |||
/** | |||
* The profile and minimal version to support. | |||
* | |||
* The valid profiles and versions are rendering API dependent. The latest | |||
* version satisfying the request should be returned, unless | |||
* forward_compatiible is true. | |||
*/ | |||
enum st_profile_type profile; | |||
int major, minor; | |||
/** | |||
* Enable debugging. | |||
*/ | |||
boolean debug; | |||
/** | |||
* Return the exact version and disallow the use of deprecated features. | |||
*/ | |||
boolean forward_compatible; | |||
/** | |||
* The visual of the framebuffers the context will be bound to. | |||
*/ | |||
struct st_visual visual; | |||
}; | |||
/** | |||
* Represent a windowing system drawable. | |||
* | |||
@@ -356,6 +404,16 @@ struct st_manager | |||
*/ | |||
struct st_api | |||
{ | |||
/** | |||
* The supported rendering API. | |||
*/ | |||
enum st_api_type api; | |||
/** | |||
* The supported profiles. Tested with ST_PROFILE_*_MASK. | |||
*/ | |||
unsigned profile_mask; | |||
/** | |||
* Destroy the API. | |||
*/ | |||
@@ -373,13 +431,14 @@ struct st_api | |||
*/ | |||
struct st_context_iface *(*create_context)(struct st_api *stapi, | |||
struct st_manager *smapi, | |||
const struct st_visual *visual, | |||
const struct st_context_attribs *attribs, | |||
struct st_context_iface *stsharei); | |||
/** | |||
* Bind the context to the calling thread with draw and read as drawables. | |||
* | |||
* The framebuffers might have different visuals than the context does. | |||
* The framebuffers might be NULL, or might have different visuals than the | |||
* context does. | |||
*/ | |||
boolean (*make_current)(struct st_api *stapi, | |||
struct st_context_iface *stctxi, |
@@ -57,17 +57,21 @@ dri_create_context(gl_api api, const __GLcontextModes * visual, | |||
struct st_api *stapi; | |||
struct dri_context *ctx = NULL; | |||
struct st_context_iface *st_share = NULL; | |||
struct st_visual stvis; | |||
struct st_context_attribs attribs; | |||
memset(&attribs, 0, sizeof(attribs)); | |||
switch (api) { | |||
case API_OPENGL: | |||
stapi = screen->st_api[ST_API_OPENGL]; | |||
attribs.profile = ST_PROFILE_DEFAULT; | |||
break; | |||
case API_OPENGLES: | |||
stapi = screen->st_api[ST_API_OPENGL_ES1]; | |||
attribs.profile = ST_PROFILE_OPENGL_ES1; | |||
break; | |||
case API_OPENGLES2: | |||
stapi = screen->st_api[ST_API_OPENGL_ES2]; | |||
attribs.profile = ST_PROFILE_OPENGL_ES2; | |||
break; | |||
default: | |||
stapi = NULL; | |||
@@ -92,8 +96,8 @@ dri_create_context(gl_api api, const __GLcontextModes * visual, | |||
driParseConfigFiles(&ctx->optionCache, | |||
&screen->optionCache, sPriv->myNum, "dri"); | |||
dri_fill_st_visual(&stvis, screen, visual); | |||
ctx->st = stapi->create_context(stapi, &screen->base, &stvis, st_share); | |||
dri_fill_st_visual(&attribs.visual, screen, visual); | |||
ctx->st = stapi->create_context(stapi, &screen->base, &attribs, st_share); | |||
if (ctx->st == NULL) | |||
goto fail; | |||
ctx->st->st_manager_private = (void *) ctx; |
@@ -43,7 +43,8 @@ | |||
* Return the state tracker for the given context. | |||
*/ | |||
static struct st_api * | |||
egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) | |||
egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx, | |||
enum st_profile_type *profile) | |||
{ | |||
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); | |||
EGLint idx = -1; | |||
@@ -74,6 +75,18 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) | |||
break; | |||
} | |||
switch (idx) { | |||
case ST_API_OPENGL_ES1: | |||
*profile = ST_PROFILE_OPENGL_ES1; | |||
break; | |||
case ST_API_OPENGL_ES2: | |||
*profile = ST_PROFILE_OPENGL_ES2; | |||
break; | |||
default: | |||
*profile = ST_PROFILE_DEFAULT; | |||
break; | |||
} | |||
return (idx >= 0) ? gdrv->loader->get_st_api(idx) : NULL; | |||
} | |||
@@ -85,6 +98,7 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, | |||
struct egl_g3d_context *gshare = egl_g3d_context(share); | |||
struct egl_g3d_config *gconf = egl_g3d_config(conf); | |||
struct egl_g3d_context *gctx; | |||
struct st_context_attribs stattribs; | |||
gctx = CALLOC_STRUCT(egl_g3d_context); | |||
if (!gctx) { | |||
@@ -97,14 +111,18 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, | |||
return NULL; | |||
} | |||
gctx->stapi = egl_g3d_choose_st(drv, &gctx->base); | |||
memset(&stattribs, 0, sizeof(stattribs)); | |||
if (gconf) | |||
stattribs.visual = gconf->stvis; | |||
gctx->stapi = egl_g3d_choose_st(drv, &gctx->base, &stattribs.profile); | |||
if (!gctx->stapi) { | |||
FREE(gctx); | |||
return NULL; | |||
} | |||
gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi, | |||
(gconf) ? &gconf->stvis : NULL, (gshare) ? gshare->stctxi : NULL); | |||
&stattribs, (gshare) ? gshare->stctxi : NULL); | |||
if (!gctx->stctxi) { | |||
FREE(gctx); | |||
return NULL; |
@@ -849,6 +849,7 @@ PUBLIC | |||
XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) | |||
{ | |||
XMesaDisplay xmdpy = xmesa_init_display(v->display); | |||
struct st_context_attribs attribs; | |||
XMesaContext c; | |||
if (!xmdpy) | |||
@@ -863,8 +864,12 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) | |||
c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ | |||
c->xm_read_buffer = NULL; | |||
memset(&attribs, 0, sizeof(attribs)); | |||
attribs.profile = ST_PROFILE_DEFAULT; | |||
attribs.visual = v->stvis; | |||
c->st = stapi->create_context(stapi, xmdpy->smapi, | |||
&v->stvis, (share_list) ? share_list->st : NULL); | |||
&attribs, (share_list) ? share_list->st : NULL); | |||
if (c->st == NULL) | |||
goto fail; | |||
@@ -341,13 +341,20 @@ vg_context_destroy(struct st_context_iface *stctxi) | |||
static struct st_context_iface * | |||
vg_api_create_context(struct st_api *stapi, struct st_manager *smapi, | |||
const struct st_visual *visual, | |||
const struct st_context_attribs *attribs, | |||
struct st_context_iface *shared_stctxi) | |||
{ | |||
struct vg_context *shared_ctx = (struct vg_context *) shared_stctxi; | |||
struct vg_context *ctx; | |||
struct pipe_context *pipe; | |||
if (!(stapi->profile_mask & (1 << attribs->profile))) | |||
return NULL; | |||
/* only 1.0 is supported */ | |||
if (attribs->major != 1 || attribs->minor > 0) | |||
return NULL; | |||
pipe = smapi->screen->context_create(smapi->screen, NULL); | |||
if (!pipe) | |||
return NULL; | |||
@@ -528,6 +535,8 @@ vg_api_destroy(struct st_api *stapi) | |||
} | |||
static const struct st_api vg_api = { | |||
ST_API_OPENVG, | |||
ST_PROFILE_DEFAULT_MASK, | |||
vg_api_destroy, | |||
vg_api_get_proc_address, | |||
vg_api_create_context, |
@@ -129,6 +129,7 @@ DrvCreateLayerContext( | |||
{ | |||
int iPixelFormat; | |||
const struct stw_pixelformat_info *pfi; | |||
struct st_context_attribs attribs; | |||
struct stw_context *ctx = NULL; | |||
if(!stw_dev) | |||
@@ -150,8 +151,12 @@ DrvCreateLayerContext( | |||
ctx->hdc = hdc; | |||
ctx->iPixelFormat = iPixelFormat; | |||
memset(&attribs, 0, sizeof(attribs)); | |||
attribs.profile = ST_PROFILE_DEFAULT; | |||
attribs.visual = pfi->stvis; | |||
ctx->st = stw_dev->stapi->create_context(stw_dev->stapi, | |||
stw_dev->smapi, &pfi->stvis, NULL); | |||
stw_dev->smapi, &attribs, NULL); | |||
if (ctx->st == NULL) | |||
goto no_st_ctx; | |||
@@ -260,11 +260,15 @@ compute_version_es2(GLcontext *ctx) | |||
/** | |||
* Set the context's VersionMajor, VersionMinor, VersionString fields. | |||
* This should only be called once as part of context initialization. | |||
* This should only be called once as part of context initialization | |||
* or to perform version check for GLX_ARB_create_context_profile. | |||
*/ | |||
void | |||
_mesa_compute_version(GLcontext *ctx) | |||
{ | |||
if (ctx->VersionMajor) | |||
return; | |||
switch (ctx->API) { | |||
case API_OPENGL: | |||
compute_version(ctx); |
@@ -44,6 +44,7 @@ | |||
#include "main/framebuffer.h" | |||
#include "main/fbobject.h" | |||
#include "main/renderbuffer.h" | |||
#include "main/version.h" | |||
#include "st_texture.h" | |||
#include "st_context.h" | |||
@@ -303,10 +304,6 @@ st_visual_to_context_mode(const struct st_visual *visual, | |||
{ | |||
memset(mode, 0, sizeof(*mode)); | |||
/* FBO-only context */ | |||
if (!visual) | |||
return; | |||
if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK)) | |||
mode->doubleBufferMode = GL_TRUE; | |||
if (st_visual_have_buffers(visual, | |||
@@ -612,26 +609,57 @@ st_context_destroy(struct st_context_iface *stctxi) | |||
} | |||
static struct st_context_iface * | |||
create_context(gl_api api, struct st_manager *smapi, | |||
const struct st_visual *visual, | |||
struct st_context_iface *shared_stctxi) | |||
st_api_create_context(struct st_api *stapi, struct st_manager *smapi, | |||
const struct st_context_attribs *attribs, | |||
struct st_context_iface *shared_stctxi) | |||
{ | |||
struct st_context *shared_ctx = (struct st_context *) shared_stctxi; | |||
struct st_context *st; | |||
struct pipe_context *pipe; | |||
__GLcontextModes mode; | |||
gl_api api; | |||
if (!(stapi->profile_mask & (1 << attribs->profile))) | |||
return NULL; | |||
switch (attribs->profile) { | |||
case ST_PROFILE_DEFAULT: | |||
api = API_OPENGL; | |||
break; | |||
case ST_PROFILE_OPENGL_ES1: | |||
api = API_OPENGLES; | |||
break; | |||
case ST_PROFILE_OPENGL_ES2: | |||
api = API_OPENGLES2; | |||
break; | |||
case ST_PROFILE_OPENGL_CORE: | |||
default: | |||
return NULL; | |||
break; | |||
} | |||
pipe = smapi->screen->context_create(smapi->screen, NULL); | |||
if (!pipe) | |||
return NULL; | |||
st_visual_to_context_mode(visual, &mode); | |||
st_visual_to_context_mode(&attribs->visual, &mode); | |||
st = st_create_context(api, pipe, &mode, shared_ctx); | |||
if (!st) { | |||
pipe->destroy(pipe); | |||
return NULL; | |||
} | |||
/* need to perform version check */ | |||
if (attribs->major > 1 || attribs->minor > 0) { | |||
_mesa_compute_version(st->ctx); | |||
if (st->ctx->VersionMajor < attribs->major || | |||
st->ctx->VersionMajor < attribs->minor) { | |||
st_destroy_context(st); | |||
return NULL; | |||
} | |||
} | |||
st->invalidate_on_gl_viewport = | |||
smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE); | |||
@@ -646,28 +674,20 @@ create_context(gl_api api, struct st_manager *smapi, | |||
return &st->iface; | |||
} | |||
static struct st_context_iface * | |||
st_api_create_context(struct st_api *stapi, struct st_manager *smapi, | |||
const struct st_visual *visual, | |||
struct st_context_iface *shared_stctxi) | |||
{ | |||
return create_context(API_OPENGL, smapi, visual, shared_stctxi); | |||
} | |||
static struct st_context_iface * | |||
st_api_create_context_es1(struct st_api *stapi, struct st_manager *smapi, | |||
const struct st_visual *visual, | |||
const struct st_context_attribs *attribs, | |||
struct st_context_iface *shared_stctxi) | |||
{ | |||
return create_context(API_OPENGLES, smapi, visual, shared_stctxi); | |||
return st_api_create_context(stapi, smapi, attribs, shared_stctxi); | |||
} | |||
static struct st_context_iface * | |||
st_api_create_context_es2(struct st_api *stapi, struct st_manager *smapi, | |||
const struct st_visual *visual, | |||
const struct st_context_attribs *attribs, | |||
struct st_context_iface *shared_stctxi) | |||
{ | |||
return create_context(API_OPENGLES2, smapi, visual, shared_stctxi); | |||
return st_api_create_context(stapi, smapi, attribs, shared_stctxi); | |||
} | |||
static boolean | |||
@@ -852,6 +872,17 @@ st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb, | |||
} | |||
static const struct st_api st_gl_api = { | |||
ST_API_OPENGL, | |||
#if FEATURE_GL | |||
ST_PROFILE_DEFAULT_MASK | | |||
#endif | |||
#if FEATURE_ES1 | |||
ST_PROFILE_OPENGL_ES1_MASK | | |||
#endif | |||
#if FEATURE_ES2 | |||
ST_PROFILE_OPENGL_ES2_MASK | | |||
#endif | |||
0, | |||
st_api_destroy, | |||
st_api_get_proc_address, | |||
st_api_create_context, | |||
@@ -860,6 +891,8 @@ static const struct st_api st_gl_api = { | |||
}; | |||
static const struct st_api st_gl_api_es1 = { | |||
ST_API_OPENGL_ES1, | |||
ST_PROFILE_OPENGL_ES1_MASK, | |||
st_api_destroy, | |||
st_api_get_proc_address, | |||
st_api_create_context_es1, | |||
@@ -868,6 +901,8 @@ static const struct st_api st_gl_api_es1 = { | |||
}; | |||
static const struct st_api st_gl_api_es2 = { | |||
ST_API_OPENGL_ES2, | |||
ST_PROFILE_OPENGL_ES2_MASK, | |||
st_api_destroy, | |||
st_api_get_proc_address, | |||
st_api_create_context_es2, |