mesa/sso: Add pipeline container/state
authorGregory Hainaut <gregory.hainaut@gmail.com>
Fri, 28 Jun 2013 20:54:06 +0000 (13:54 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 21 Feb 2014 23:41:02 +0000 (15:41 -0800)
V1:
* Extend gl_shader_state as pipeline object state
* Add a new container gl_pipeline_shader_state that contains
   binding point of the previous object
* Update mesa init/free shader state due to the extension of
   the attibute
* Add an init/free pipeline function for the context

V2:
* Rename gl_shader_state to gl_pipeline_object
* Rename Pipeline.PipelineObj to Pipeline.Current
* Formatting improvement

V3 (idr):
* Split out from previous uber patch.
* Remove '#if 0' debug printfs.

V4 (idr):
* Fix some errors in comments.  Suggested by Jordan.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
src/mesa/main/context.c
src/mesa/main/mtypes.h
src/mesa/main/pipelineobj.c
src/mesa/main/pipelineobj.h

index 3910b7541a0f24925698055b23bba87b66a225bf..85119c3a0eca1aad8fc1e9195ca6bb766d132b02 100644 (file)
 #include "matrix.h"
 #include "multisample.h"
 #include "performance_monitor.h"
+#include "pipelineobj.h"
 #include "pixel.h"
 #include "pixelstore.h"
 #include "points.h"
@@ -811,6 +812,7 @@ init_attrib_groups(struct gl_context *ctx)
    _mesa_init_matrix( ctx );
    _mesa_init_multisample( ctx );
    _mesa_init_performance_monitors( ctx );
+   _mesa_init_pipeline( ctx );
    _mesa_init_pixel( ctx );
    _mesa_init_pixelstore( ctx );
    _mesa_init_point( ctx );
@@ -1216,6 +1218,7 @@ _mesa_free_context_data( struct gl_context *ctx )
    _mesa_free_texture_data( ctx );
    _mesa_free_matrix_data( ctx );
    _mesa_free_viewport_data( ctx );
+   _mesa_free_pipeline_data(ctx);
    _mesa_free_program_data(ctx);
    _mesa_free_shader_state(ctx);
    _mesa_free_queryobj_data(ctx);
index 48ae519ed57b808d6a96e7f4c0a913e793ba81c4..90f71a72761f5ed97fefe8398680bc1be8ba976c 100644 (file)
@@ -2757,9 +2757,15 @@ struct gl_shader_program
 
 /**
  * Context state for GLSL vertex/fragment shaders.
+ * Extended to support pipeline object
  */
-struct gl_shader_state
+struct gl_pipeline_object
 {
+   /** Name of the pipeline object as received from glGenProgramPipelines.
+    * It would be 0 for shaders without separate shader objects.
+    */
+   GLuint Name;
+
    GLint RefCount;
 
    _glthread_Mutex Mutex;
@@ -2785,6 +2791,17 @@ struct gl_shader_state
    GLbitfield Flags;                    /**< Mask of GLSL_x flags */
 };
 
+/**
+ * Context state for GLSL pipeline shaders.
+ */
+struct gl_pipeline_shader_state
+{
+   /** Currently bound pipeline object. See _mesa_BindProgramPipeline() */
+   struct gl_pipeline_object *Current;
+
+   /** Pipeline objects */
+   struct _mesa_HashTable *Objects;
+};
 
 /**
  * Compiler options for a single GLSL shaders type
@@ -4085,7 +4102,8 @@ struct gl_context
    struct gl_geometry_program_state GeometryProgram;
    struct gl_ati_fragment_shader_state ATIFragmentShader;
 
-   struct gl_shader_state Shader; /**< GLSL shader object state */
+   struct gl_pipeline_shader_state Pipeline; /**< GLSL pipeline shader object state */
+   struct gl_pipeline_object Shader; /**< GLSL shader object state */
    struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES];
 
    struct gl_query_state Query;  /**< occlusion, timer queries */
index 74546197ae8e1e0d321abdce9ee333f1f7952cc7..d50214cf1ace714f3d98961039f254dae1dbec4c 100644 (file)
@@ -29,7 +29,6 @@
  *
  * Implementation of pipeline object related API functions. Based on
  * GL_ARB_separate_shader_objects extension.
- *
  */
 
 #include "main/glheader.h"
 #include "../glsl/glsl_parser_extras.h"
 #include "../glsl/ir_uniform.h"
 
+/**
+ * Delete a pipeline object.
+ */
+void
+_mesa_delete_pipeline_object(struct gl_context *ctx,
+                             struct gl_pipeline_object *obj)
+{
+   unsinged i;
+
+   _mesa_reference_shader_program(ctx, &obj->_CurrentFragmentProgram, NULL);
+
+   for (i = 0; i < MESA_SHADER_STAGES; i++)
+      _mesa_reference_shader_program(ctx, &obj->CurrentProgram[i], NULL);
+
+   _mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL);
+   _glthread_DESTROY_MUTEX(obj->Mutex);
+   ralloc_free(obj);
+}
+
+/**
+ * Allocate and initialize a new pipeline object.
+ */
+static struct gl_pipeline_object *
+_mesa_new_pipeline_object(struct gl_context *ctx, GLuint name)
+{
+   struct gl_pipeline_object *obj = rzalloc(NULL, struct gl_pipeline_object);
+   if (obj) {
+      obj->Name = name;
+      _glthread_INIT_MUTEX(obj->Mutex);
+      obj->RefCount = 1;
+      obj->Flags = _mesa_get_shader_flags();
+   }
+
+   return obj;
+}
+
+/**
+ * Initialize pipeline object state for given context.
+ */
+void
+_mesa_init_pipeline(struct gl_context *ctx)
+{
+   ctx->Pipeline.Objects = _mesa_NewHashTable();
+
+   ctx->Pipeline.Current = NULL;
+}
+
+
+/**
+ * Callback for deleting a pipeline object.  Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_pipelineobj_cb(GLuint id, void *data, void *userData)
+{
+   struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data;
+   struct gl_context *ctx = (struct gl_context *) userData;
+   _mesa_delete_pipeline_object(ctx, obj);
+}
+
+
+/**
+ * Free pipeline state for given context.
+ */
+void
+_mesa_free_pipeline_data(struct gl_context *ctx)
+{
+   _mesa_HashDeleteAll(ctx->Pipeline.Objects, delete_pipelineobj_cb, ctx);
+   _mesa_DeleteHashTable(ctx->Pipeline.Objects);
+}
+
+/**
+ * Look up the pipeline object for the given ID.
+ *
+ * \returns
+ * Either a pointer to the pipeline object with the specified ID or \c NULL for
+ * a non-existent ID.  The spec defines ID 0 as being technically
+ * non-existent.
+ */
+static inline struct gl_pipeline_object *
+lookup_pipeline_object(struct gl_context *ctx, GLuint id)
+{
+   if (id == 0)
+      return NULL;
+   else
+      return (struct gl_pipeline_object *)
+         _mesa_HashLookup(ctx->Pipeline.Objects, id);
+}
+
+/**
+ * Add the given pipeline object to the pipeline object pool.
+ */
+static void
+save_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
+{
+   if (obj->Name > 0) {
+      _mesa_HashInsert(ctx->Pipeline.Objects, obj->Name, obj);
+   }
+}
+
+/**
+ * Remove the given pipeline object from the pipeline object pool.
+ * Do not deallocate the pipeline object though.
+ */
+static void
+remove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj)
+{
+   if (obj->Name > 0) {
+      _mesa_HashRemove(ctx->Pipeline.Objects, obj->Name);
+   }
+}
+
+/**
+ * Set ptr to obj w/ reference counting.
+ * Note: this should only be called from the _mesa_reference_pipeline_object()
+ * inline function.
+ */
+void
+_mesa_reference_pipeline_object_(struct gl_context *ctx,
+                                 struct gl_pipeline_object **ptr,
+                                 struct gl_pipeline_object *obj)
+{
+   assert(*ptr != obj);
+
+   if (*ptr) {
+      /* Unreference the old pipeline object */
+      GLboolean deleteFlag = GL_FALSE;
+      struct gl_pipeline_object *oldObj = *ptr;
+
+      _glthread_LOCK_MUTEX(oldObj->Mutex);
+      ASSERT(oldObj->RefCount > 0);
+      oldObj->RefCount--;
+      deleteFlag = (oldObj->RefCount == 0);
+      _glthread_UNLOCK_MUTEX(oldObj->Mutex);
+
+      if (deleteFlag) {
+         _mesa_delete_pipeline_object(ctx, oldObj);
+      }
+
+      *ptr = NULL;
+   }
+   ASSERT(!*ptr);
+
+   if (obj) {
+      /* reference new pipeline object */
+      _glthread_LOCK_MUTEX(obj->Mutex);
+      if (obj->RefCount == 0) {
+         /* this pipeline's being deleted (look just above) */
+         /* Not sure this can ever really happen.  Warn if it does. */
+         _mesa_problem(NULL, "referencing deleted pipeline object");
+         *ptr = NULL;
+      }
+      else {
+         obj->RefCount++;
+         *ptr = obj;
+      }
+      _glthread_UNLOCK_MUTEX(obj->Mutex);
+   }
+}
 
 /**
  * Bound program to severals stages of the pipeline
index 56d32ccef742b1f7ea751c95d92d0520509fc833..46d5fab4230a5fc168f08235afa1f1c41c33c6f4 100644 (file)
@@ -34,6 +34,31 @@ extern "C" {
 
 struct _glapi_table;
 struct gl_context;
+struct gl_pipeline_object;
+
+extern void
+_mesa_delete_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj);
+
+extern void
+_mesa_init_pipeline(struct gl_context *ctx);
+
+extern void
+_mesa_free_pipeline_data(struct gl_context *ctx);
+
+extern void
+_mesa_reference_pipeline_object_(struct gl_context *ctx,
+                                 struct gl_pipeline_object **ptr,
+                                 struct gl_pipeline_object *obj);
+
+static inline void
+_mesa_reference_pipeline_object(struct gl_context *ctx,
+                                struct gl_pipeline_object **ptr,
+                                struct gl_pipeline_object *obj)
+{
+   if (*ptr != obj)
+      _mesa_reference_pipeline_object_(ctx, ptr, obj);
+}
+
 
 extern void GLAPIENTRY
 _mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program);