From 4531356817ec8383ac35932903773de67af92e37 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 10 Sep 2010 10:31:06 +0800 Subject: [PATCH] gallium: Add context profile support to st_api. 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. --- src/gallium/include/state_tracker/st_api.h | 63 +++++++++++++++- .../state_trackers/dri/common/dri_context.c | 10 ++- .../state_trackers/egl/common/egl_g3d_api.c | 24 +++++- src/gallium/state_trackers/glx/xlib/xm_api.c | 7 +- src/gallium/state_trackers/vega/vg_manager.c | 11 ++- src/gallium/state_trackers/wgl/stw_context.c | 7 +- src/mesa/main/version.c | 6 +- src/mesa/state_tracker/st_manager.c | 75 ++++++++++++++----- 8 files changed, 171 insertions(+), 32 deletions(-) diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h index 11424611881..9e87c8e0d40 100644 --- a/src/gallium/include/state_tracker/st_api.h +++ b/src/gallium/include/state_tracker/st_api.h @@ -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, diff --git a/src/gallium/state_trackers/dri/common/dri_context.c b/src/gallium/state_trackers/dri/common/dri_context.c index f9ebe1edcce..8948cfc2ccb 100644 --- a/src/gallium/state_trackers/dri/common/dri_context.c +++ b/src/gallium/state_trackers/dri/common/dri_context.c @@ -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; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c index 3ec53653f44..cda46b8c301 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -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; diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index eb4ce742669..36d63c30d6c 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -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; diff --git a/src/gallium/state_trackers/vega/vg_manager.c b/src/gallium/state_trackers/vega/vg_manager.c index c2aa98b231c..e7996741d14 100644 --- a/src/gallium/state_trackers/vega/vg_manager.c +++ b/src/gallium/state_trackers/vega/vg_manager.c @@ -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, diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c index a0e14b96016..85878b46730 100644 --- a/src/gallium/state_trackers/wgl/stw_context.c +++ b/src/gallium/state_trackers/wgl/stw_context.c @@ -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; diff --git a/src/mesa/main/version.c b/src/mesa/main/version.c index d833a160e9e..9e1f5f2a4fe 100644 --- a/src/mesa/main/version.c +++ b/src/mesa/main/version.c @@ -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); diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index ccce574c364..8acd0938bb8 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -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, -- 2.30.2