Mesa (master): gallium: Add context profile support to st_api.

Chia-I Wu olv at kemper.freedesktop.org
Fri Sep 10 07:47:39 UTC 2010


Module: Mesa
Branch: master
Commit: 4531356817ec8383ac35932903773de67af92e37
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4531356817ec8383ac35932903773de67af92e37

Author: Chia-I Wu <olv at lunarg.com>
Date:   Fri Sep 10 10:31:06 2010 +0800

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 1142461..9e87c8e 100644
--- a/src/gallium/include/state_tracker/st_api.h
+++ b/src/gallium/include/state_tracker/st_api.h
@@ -55,6 +55,23 @@ enum st_api_type {
 };
 
 /**
+ * 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.
  */
 enum st_texture_type {
@@ -180,6 +197,37 @@ struct st_visual
 };
 
 /**
+ * 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.
  *
  * The framebuffer is implemented by the state tracker manager and
@@ -357,6 +405,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.
     */
    void (*destroy)(struct st_api *stapi);
@@ -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 f9ebe1e..8948cfc 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 3ec5365..cda46b8 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 eb4ce74..36d63c3 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 c2aa98b..e799674 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 a0e14b9..85878b4 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 d833a16..9e1f5f2 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 ccce574..8acd093 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);
 
@@ -647,27 +675,19 @@ create_context(gl_api api, struct st_manager *smapi,
 }
 
 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,




More information about the mesa-commit mailing list