On 10/16/2011 04:37 PM, vlj wrote:
---
  src/mesa/main/bufferobj.c |    2 +
  src/mesa/main/uniforms.c  |  187 +++++++++++++++++++++++++++++++++++++++++++++
  src/mesa/main/uniforms.h  |   15 ++++
  3 files changed, 204 insertions(+), 0 deletions(-)

diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index c453f9c..cddb0b4 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -98,6 +98,8 @@ get_buffer_target(struct gl_context *ctx, GLenum target)
           return&ctx->Texture.BufferObject;
        }
        break;
+   case GL_UNIFORM_BUFFER:
+      return&ctx->UniformBufferObject.UniformObj;

We should have an extension check here as with some of the other cases:

case GL_UNIFORM_BUFFER:
   if (ctx->Extensions.ARB_uniform_buffer_object)
      return &ctx->UniformBufferObject.UniformObj;
   }



     default:
        return NULL;
     }
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index fe1ce6d..253e5cf 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c


I'm thinking this new code should go into a new file (ubo.c) because uniforms.c is rather large already and on the surface it doesn't look like there's a lot of code sharing with what's in uniforms.c


@@ -45,12 +45,14 @@
  #include "main/shaderapi.h"
  #include "main/shaderobj.h"
  #include "main/uniforms.h"
+#include "main/hash.h"
  #include "program/prog_parameter.h"
  #include "program/prog_statevars.h"
  #include "program/prog_uniform.h"
  #include "program/prog_instruction.h"


+
  static GLenum
  base_uniform_type(GLenum type)
  {
@@ -1064,6 +1066,121 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct 
gl_shader_program *shProg,
     uniform->Initialized = GL_TRUE;
  }

+static void
+_mesa_query_ubo_general(struct gl_context *ctx, struct gl_shader_program 
*shProg, GLint ubo_index,
+                        GLenum query, int* data)
+{
+   if(ubo_index>  shProg->UBOCount || ubo_index<  0)
+      _mesa_error(ctx, GL_INVALID_VALUE, 
"glGetActiveUniformBlock(uniformBlockIndex)");

'return' after generating the error.


+
+   struct ubo current_ubo = *(shProg->UniformBufferObject[ubo_index]);
+
+   switch(query)
+   {
+   case GL_UNIFORM_BLOCK_BINDING:
+      *data = current_ubo.BoundBuffer;
+      break;
+   case GL_UNIFORM_BLOCK_DATA_SIZE:
+      *data = 0;
+      break;
+   case GL_UNIFORM_BLOCK_NAME_LENGTH:
+      *data = strlen(current_ubo.Name);
+      break;
+   case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+      *data = current_ubo.NumberOfVariables;
+      break;
+   case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+   case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
+   case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+      *data = 0;
+      break;
+   default:
+      break;

I suspect we should generate a GL_INVALID_ENUM error for the default case here.


+   }
+}
+
+/**
+ * TODO : Switch to hash table
+ */
+static GLuint
+getIndices(const struct gl_shader_program* prog, const char* name)

get_indices(const struct gl_shader_program *prog, const char *name)


+{
+   unsigned i,k;
+   for (k = 0; k<  prog->Uniforms->Size; k++)
+   {
+      struct gl_uniform* current_uniform =&(prog->Uniforms->Uniforms[k]);
+      if(strcmp(name,current_uniform->Name)==0)
+      {
+         return k;
+      }
+   }
+   for (i = 0;i<  prog->UBOVariableCount; i++)
+   {
+      struct UBOVariableInfo* var = prog->IndexedUniformsInUBO[i];
+      if(strcmp(name,var->Name)==0)
+      {
+         return i + prog->Uniforms->Size;
+      }
+   }
+   return GL_INVALID_INDEX;
+}
+
+static void
+_mesa_get_ubo_name(struct gl_context *ctx, struct gl_shader_program *shProg, 
GLint index,
+                   GLsizei bufsize, GLsizei* length, char* buffer)
+{
+   if(index>= shProg->UBOCount || index<  0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, 
"GetActiveUniformBlockName(uniformBlockIndex)");
+      return;
+   }
+
+   struct ubo current_ubo = *(shProg->UniformBufferObject[index]);
+   GLsizei temp_length = strlen(current_ubo.Name);

We need to put declarations before code so we can compile with MSVC. So put these var decls at the top of the function.


+   if(bufsize - 1<  temp_length) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "GetActiveUniformBlockName(bufSize)");
+      return;
+   }
+
+   memcpy(buffer,current_ubo.Name,temp_length);
+   buffer[temp_length] = '\0';
+   if(length != NULL)
+      *length = temp_length;
+}
+
+static void
+_mesa_link_buffer_uniform(struct gl_context* ctx,struct gl_shader_program 
*shProg, GLint ubo_index,
+                          GLint buffer_index)
+{
+   if(ubo_index>  shProg->UBOCount || ubo_index<  0)
+      _mesa_error(ctx, GL_INVALID_VALUE, 
"UniformBlockBinding(uniformBlockIndex)");
+
+   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
+
+   shProg->UniformBufferObject[ubo_index]->BoundBuffer = buffer_index;
+}
+
+static
+GLint GetLoneUniformInfo(struct gl_shader_program* sh, GLuint index, GLenum 
pname) {
+   uint n = sh->Uniforms->Size;
+   if(index>= n) {
+      struct UBOVariableInfo *var = sh->IndexedUniformsInUBO[index - n];
+      switch(pname) {
+      case GL_UNIFORM_TYPE:
+         return var->Type;
+      case GL_UNIFORM_SIZE:
+      case GL_UNIFORM_BLOCK_NAME_LENGTH:
+      case GL_UNIFORM_BLOCK_INDEX:
+         return var->UBO->Index;
+      case GL_UNIFORM_OFFSET:
+         return var->Offset;
+      case GL_UNIFORM_ARRAY_STRIDE:
+      case GL_UNIFORM_MATRIX_STRIDE:
+         return var->Stride;
+      case GL_UNIFORM_IS_ROW_MAJOR:
+         return sh->UniformBufferObject[var->UBO->Index]->MatrixLayout == 
rowmajor;
+      }

Add default case to raise GL_INVALID_ENUM?


+   }
+}

  void GLAPIENTRY
  _mesa_Uniform1fARB(GLint location, GLfloat v0)
@@ -1452,6 +1569,69 @@ _mesa_GetActiveUniformARB(GLhandleARB program, GLuint 
index,
                              type, name);
  }

+void GLAPIENTRY
+_mesa_GetActiveUniformBlockInfo(GLuint program,GLuint ubo_index,GLenum pname, 
GLint* params)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, program, "GetActiveUniformBlockiv");
+   _mesa_query_ubo_general(ctx,shProg,ubo_index,pname,params);
+}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformBlockName(GLuint program,GLuint ubo_index,GLsizei 
bufsize, GLint* length, char* name)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, program, 
"GetActiveUniformBlockName");
+   _mesa_get_ubo_name(ctx,shProg,ubo_index,bufsize,length,name);
+}
+
+/* Note : location and index are the same */
+void GLAPIENTRY
+_mesa_GetUniformIndices(GLuint program, GLsizei number_of_variables, const 
char** names, GLuint* indices)
+{
+   unsigned i;
+   GET_CURRENT_CONTEXT(ctx);
+
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, program, "GetUniformIndices");
+   for (i=0; i<  number_of_variables; i++)
+   {
+      indices[i] = getIndices(shProg,names[i]);
+   }
+}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformName(GLuint program, GLuint index, GLsizei bufsize, 
GLsizei* length, char* uniformName)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, program, "GetActiveUniformName");
+   const char* name = shProg->Uniforms->Uniforms[index].Name;

We need to check for shProg==NULL (in case 'program' is invalid) and we need to check that 'index' isn't out of bounds (and raise GL_INVALID_VALUE, probably).

It looks like quite a bit of error checking is missing in this file, actually. The "Errors" section of the extension spec should list everything you need to check.


+   unsigned n = strlen(name);
+   if(n + 1<= bufsize) {
+      memcpy(uniformName,name,n);
+      uniformName[n]='\0';
+   }
+   if(length) {
+      *length = n;
+   }
+}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* 
uniformIndices, GLenum pname, GLint* param)
+{
+   unsigned k;
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, program, "GetActiveUniformsiv");
+
+
+   for(k = 0; k<  uniformCount; k++) {
+      param[k] = GetLoneUniformInfo(shProg,uniformIndices[k],pname);
+   }
+}

  /**
   * Plug in shader uniform-related functions into API dispatch table.
@@ -1510,5 +1690,12 @@ _mesa_init_shader_uniform_dispatch(struct _glapi_table 
*exec)
     SET_GetnUniformuivARB(exec, _mesa_GetnUniformuivARB);
     SET_GetnUniformdvARB(exec, _mesa_GetnUniformdvARB); /* GL 4.0 */

+   /* GL_ARB_Uniform_Buffer_Object */
+   SET_GetActiveUniformBlockiv(exec, _mesa_GetActiveUniformBlockInfo);
+   SET_GetActiveUniformBlockName(exec, _mesa_GetActiveUniformBlockName);
+   SET_GetUniformIndices(exec, _mesa_GetUniformIndices);
+   SET_GetActiveUniformName(exec, _mesa_GetActiveUniformName);
+   SET_GetActiveUniformsiv(exec,_mesa_GetActiveUniformsiv);
+
  #endif /* FEATURE_GL */
  }
diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h
index b024cb3..dfcf16b 100644
--- a/src/mesa/main/uniforms.h
+++ b/src/mesa/main/uniforms.h
@@ -169,6 +169,21 @@ _mesa_GetnUniformdvARB(GLhandleARB, GLint, GLsizei, 
GLdouble *);
  extern GLint GLAPIENTRY
  _mesa_GetUniformLocationARB(GLhandleARB, const GLcharARB *);

+void GLAPIENTRY
+_mesa_GetActiveUniformBlockInfo(GLuint, GLuint, GLenum, GLint *);
+
+extern void GLAPIENTRY
+_mesa_GetActiveUniformBlockName(GLuint, GLuint, GLsizei, GLint *, char *);
+
+extern void GLAPIENTRY
+_mesa_GetUniformIndices(GLuint, GLsizei, const char **, GLuint *);
+
+extern void GLAPIENTRY
+_mesa_GetActiveUniformName(GLuint, GLuint, GLsizei, GLsizei*, char*);
+
+void GLAPIENTRY
+_mesa_GetActiveUniformsiv(GLuint, GLsizei, const GLuint*, GLenum, GLint*);
+
  GLint
  _mesa_get_uniform_location(struct gl_context *ctx, struct gl_shader_program 
*shProg,
                           const GLchar *name);

After putting this code into a new ubo.c file, run 'indent' on it per the "Development Notes" on the website to fix the formatting. Thanks.

-Brian
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to