[Mesa-dev] [PATCH v3 2/8] mesa: glGet: fix parameter lookup for apps using multiple APIs

Imre Deak imre.deak at intel.com
Mon Oct 1 03:37:59 PDT 2012


The glGet hash was initialized only once for a single GL API, even if
the application later created a context for a different API. This
resulted in glGet failing for otherwise valid parameters in a context
if that parameter was invalid in another context created earlier.

Fix this by using a separate hash table for each API.

Signed-off-by: Imre Deak <imre.deak at intel.com>
Reviewed-by: Brian Paul <brianp at vmware.com>
---
 src/mesa/main/context.c |    5 ++---
 src/mesa/main/get.c     |   44 +++++++++++++++++++++++++++++---------------
 src/mesa/main/mtypes.h  |    2 ++
 3 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index c50504d..bc1f42d 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -404,9 +404,6 @@ one_time_init( struct gl_context *ctx )
 
       _mesa_get_cpu_features();
 
-      /* context dependence is never a one-time thing... */
-      _mesa_init_get_hash(ctx);
-
       for (i = 0; i < 256; i++) {
          _mesa_ubyte_to_float_color_tab[i] = (float) i / 255.0F;
       }
@@ -425,6 +422,8 @@ one_time_init( struct gl_context *ctx )
 
    /* per-API one-time init */
    if (!(api_init_mask & (1 << ctx->API))) {
+      _mesa_init_get_hash(ctx);
+
       /*
        * This is fine as ES does not use the remap table, but it may not be
        * future-proof.  We cannot always initialize the remap table because
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index 1420850..b46492c 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -1385,29 +1385,37 @@ static const struct value_desc values[] = {
  * collisions for any enum (typical numbers).  And the code is very
  * simple, even though it feels a little magic. */
 
-static unsigned short table[1024];
+static unsigned short table[API_LAST + 1][1024];
 static const int prime_factor = 89, prime_step = 281;
 
 #ifdef GET_DEBUG
 static void
-print_table_stats(void)
+print_table_stats(int api)
 {
    int i, j, collisions[11], count, hash, mask;
    const struct value_desc *d;
-
+   const char *api_names[] = {
+      [API_OPENGL] = "GL",
+      [API_OPENGL_CORE] = "GL_CORE",
+      [API_OPENGLES] = "GLES",
+      [API_OPENGLES2] = "GLES2",
+   };
+   const char *api_name;
+
+   api_name = api < Elements(api_names) ? api_names[api] : "N/A";
    count = 0;
-   mask = Elements(table) - 1;
+   mask = Elements(table[api]) - 1;
    memset(collisions, 0, sizeof collisions);
 
-   for (i = 0; i < Elements(table); i++) {
-      if (!table[i])
+   for (i = 0; i < Elements(table[api]); i++) {
+      if (!table[api][i])
          continue;
       count++;
-      d = &values[table[i]];
+      d = &values[table[api][i]];
       hash = (d->pname * prime_factor);
       j = 0;
       while (1) {
-         if (values[table[hash & mask]].pname == d->pname)
+         if (values[table[api][hash & mask]].pname == d->pname)
             break;
          hash += prime_step;
          j++;
@@ -1419,7 +1427,8 @@ print_table_stats(void)
          collisions[10]++;
    }
 
-   printf("number of enums: %d (total %d)\n", count, Elements(values));
+   printf("number of enums for %s: %d (total %ld)\n",
+         api_name, count, Elements(values));
    for (i = 0; i < Elements(collisions) - 1; i++)
       if (collisions[i] > 0)
          printf("  %d enums with %d %scollisions\n",
@@ -1438,10 +1447,13 @@ print_table_stats(void)
 void _mesa_init_get_hash(struct gl_context *ctx)
 {
    int i, hash, index, mask;
+   int api;
    int api_mask = 0, api_bit;
 
-   mask = Elements(table) - 1;
-   api_bit = 1 << ctx->API;
+   api = ctx->API;
+
+   mask = Elements(table[api]) - 1;
+   api_bit = 1 << api;
 
    for (i = 0; i < Elements(values); i++) {
       if (values[i].type == TYPE_API_MASK) {
@@ -1454,8 +1466,8 @@ void _mesa_init_get_hash(struct gl_context *ctx)
       hash = (values[i].pname * prime_factor) & mask;
       while (1) {
          index = hash & mask;
-         if (!table[index]) {
-            table[index] = i;
+         if (!table[api][index]) {
+            table[api][index] = i;
             break;
          }
          hash += prime_step;
@@ -1986,11 +1998,13 @@ find_value(const char *func, GLenum pname, void **p, union value *v)
    struct gl_texture_unit *unit;
    int mask, hash;
    const struct value_desc *d;
+   int api;
 
-   mask = Elements(table) - 1;
+   api = ctx->API;
+   mask = Elements(table[api]) - 1;
    hash = (pname * prime_factor);
    while (1) {
-      d = &values[table[hash & mask]];
+      d = &values[table[api][hash & mask]];
 
       /* If the enum isn't valid, the hash walk ends with index 0,
        * which is the API mask entry at the beginning of values[]. */
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index ba43e57..f185ffd 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -3340,6 +3340,8 @@ typedef enum
    API_OPENGLES,
    API_OPENGLES2,
    API_OPENGL_CORE,
+
+   API_LAST = API_OPENGL_CORE,
 } gl_api;
 
 /**
-- 
1.7.9.5



More information about the mesa-dev mailing list