gallium: Add context profile support to st_api.
authorChia-I Wu <olv@lunarg.com>
Fri, 10 Sep 2010 02:31:06 +0000 (10:31 +0800)
committerChia-I Wu <olv@lunarg.com>
Fri, 10 Sep 2010 07:37:43 +0000 (15:37 +0800)
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
src/gallium/state_trackers/dri/common/dri_context.c
src/gallium/state_trackers/egl/common/egl_g3d_api.c
src/gallium/state_trackers/glx/xlib/xm_api.c
src/gallium/state_trackers/vega/vg_manager.c
src/gallium/state_trackers/wgl/stw_context.c
src/mesa/main/version.c
src/mesa/state_tracker/st_manager.c

index 114246118814a43c1a1e625318f9573fce4721b7..9e87c8e0d409cfea466b171183ba727cff2af42b 100644 (file)
@@ -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,
index f9ebe1edcce0e9ed5588774843181b26ccb967a3..8948cfc2ccb8a4cc888af053d0729c0beaa9dbd4 100644 (file)
@@ -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;
index 3ec53653f449502194f99866eb6c2d6ae539114e..cda46b8c301496da9c5e2589d81ca95eb0a74c1c 100644 (file)
@@ -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;
index eb4ce742669e75e122f727dfe0e1a67c0ff163af..36d63c30d6c043cde9c24d171dba928859bc1c8e 100644 (file)
@@ -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;
 
index c2aa98b231cdece13b8fface160462914879f001..e7996741d147d395aae0b652959dd9dba36b8f9e 100644 (file)
@@ -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,
index a0e14b96016c7c9af67986dc66faa8d45fb5da4e..85878b467305bb08af2b11b71e706d57ffdad280 100644 (file)
@@ -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;
 
index d833a160e9e55da858deec64703e48be9bbcbb76..9e1f5f2a4fe7eeeed6aea29b84a7e8bfaafec14f 100644 (file)
@@ -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);
index ccce574c36460da69e94aaa7804efee5424bf609..8acd0938bb8e393388c0e48a81ddd59374649433 100644 (file)
@@ -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,