Make it easier for drivers to create "subclasses" of the existing
authorKeith Whitwell <keith@tungstengraphics.com>
Sat, 14 Feb 2004 15:00:42 +0000 (15:00 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Sat, 14 Feb 2004 15:00:42 +0000 (15:00 +0000)
program struct hierarchy.

Add driver callbacks to enable the above and make it possible to track
more changes to program objects.

src/mesa/main/arbprogram.c
src/mesa/main/dd.h
src/mesa/main/program.c
src/mesa/main/program.h

index ab27e086770ab781334941d7d9d81af2056a31bd..f6d16b5547f7b9d72100d422f598226a59c4c1b8 100644 (file)
@@ -202,6 +202,9 @@ _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
       }
       _mesa_parse_arb_vertex_program(ctx, target, (const GLubyte *) string,
                                      len, prog);
+      
+      if (ctx->Driver.ProgramStringNotify)
+        ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
    }
    else if (target == GL_FRAGMENT_PROGRAM_ARB
             && ctx->Extensions.ARB_fragment_program) {
@@ -212,9 +215,13 @@ _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
       }
       _mesa_parse_arb_fragment_program(ctx, target, (const GLubyte *) string,
                                        len, prog);
+
+      if (ctx->Driver.ProgramStringNotify)
+        ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
    }
    else {
       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
+      return;
    }
 }
 
@@ -618,8 +625,10 @@ _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
             *params = ctx->Const.MaxFragmentProgramEnvParams;
          break;
       case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
-         /* XXX ok? */
-         *params = GL_TRUE;
+        if (ctx->Driver.IsProgramNative) 
+           *params = ctx->Driver.IsProgramNative( ctx, target, prog );
+        else
+           *params = GL_TRUE;
          break;
 
       /*
index f9fdd3b92b65228fcc4de039c6fd71629fba7796..f1b49b7a300e80eecef9837c24a16dc0d08a9dbe 100644 (file)
@@ -572,7 +572,17 @@ struct dd_function_table {
    /** Allocate a new program */
    struct program * (*NewProgram)(GLcontext *ctx, GLenum target, GLuint id);
    /** Delete a program */
-   void (*DeleteProgram)(GLcontext *ctx, struct program *prog);
+   void (*DeleteProgram)(GLcontext *ctx, struct program *prog);   
+   /** Notify driver that a program string has been specified. */
+   void (*ProgramStringNotify)(GLcontext *ctx, GLenum target, 
+                              struct program *prog);
+   
+
+
+   /** Query if program can be loaded onto hardware */
+   GLboolean (*IsProgramNative)(GLcontext *ctx, GLenum target, 
+                               struct program *prog);
+   
    /*@}*/
 
 
index e32e8a3b1aced79aa8b0717ebb664d0147e7946d..fe536566304a01b9846162b7a2fda1b6870377d2 100644 (file)
@@ -138,12 +138,49 @@ _mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
 }
 
 
+static struct program * _mesa_init_program_struct( GLcontext *ctx, 
+                                                  struct program *prog,
+                                                  GLenum target, GLuint id)
+{
+   if (prog) {
+      prog->Id = id;
+      prog->Target = target;
+      prog->Resident = GL_TRUE;
+      prog->RefCount = 1;
+   }
+
+   fprintf(stderr, "%s %x %x\n", __FUNCTION__, target, prog);
+   return prog;
+}
+
+struct program * _mesa_init_fragment_program( GLcontext *ctx, 
+                                             struct fragment_program *prog,
+                                             GLenum target, GLuint id)
+{
+   if (prog) 
+      return _mesa_init_program_struct( ctx, &prog->Base, target, id );
+   else
+      return NULL;
+}
+
+struct program * _mesa_init_vertex_program( GLcontext *ctx, 
+                                           struct vertex_program *prog,
+                                           GLenum target, GLuint id)
+{
+   if (prog) 
+      return _mesa_init_program_struct( ctx, &prog->Base, target, id );
+   else
+      return NULL;
+}
+
 
 /**
- * Allocate and initialize a new fragment/vertex program object but don't
- * put it into the program hash table.
- * Called via ctx->Driver.NewProgram.  May be wrapped (OO deriviation)
- * by a device driver function.
+ * Allocate and initialize a new fragment/vertex program object but
+ * don't put it into the program hash table.  Called via
+ * ctx->Driver.NewProgram.  May be overridden (ie. replaced) by a
+ * device driver function to implement OO deriviation with additional
+ * types not understood by this function.
+ * 
  * \param ctx  context
  * \param id   program id/number
  * \param target  program target/type
@@ -152,33 +189,21 @@ _mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
 struct program *
 _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id)
 {
-   struct program *prog;
+   fprintf(stderr, "%s\n", __FUNCTION__);
+   switch (target) {
+   case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
+      return _mesa_init_vertex_program( ctx, CALLOC_STRUCT(vertex_program),
+                                       target, id );
 
-   if (target == GL_VERTEX_PROGRAM_NV
-       || target == GL_VERTEX_PROGRAM_ARB) {
-      struct vertex_program *vprog = CALLOC_STRUCT(vertex_program);
-      if (!vprog) {
-         return NULL;
-      }
-      prog = &(vprog->Base);
-   }
-   else if (target == GL_FRAGMENT_PROGRAM_NV
-            || target == GL_FRAGMENT_PROGRAM_ARB) {
-      struct fragment_program *fprog = CALLOC_STRUCT(fragment_program);
-      if (!fprog) {
-         return NULL;
-      }
-      prog = &(fprog->Base);
-   }
-   else {
+   case GL_FRAGMENT_PROGRAM_NV:
+   case GL_FRAGMENT_PROGRAM_ARB:
+      return _mesa_init_fragment_program( ctx, CALLOC_STRUCT(fragment_program),
+                                         target, id );
+
+   default:
       _mesa_problem(ctx, "bad target in _mesa_new_program");
       return NULL;
    }
-   prog->Id = id;
-   prog->Target = target;
-   prog->Resident = GL_TRUE;
-   prog->RefCount = 1;
-   return prog;
 }
 
 
@@ -946,6 +971,14 @@ _mesa_DeletePrograms(GLsizei n, const GLuint *ids)
                ctx->Driver.DeleteProgram(ctx, prog);
             }
          }
+        else {
+           /* This is necessary as we can't tell from HashLookup
+            * whether the entry exists with data == 0, or if it
+            * doesn't exist at all.  As GenPrograms creates the first
+            * case below, need to call Remove() to avoid memory leak:
+            */
+            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
+        }
       }
    }
 }
@@ -975,16 +1008,7 @@ _mesa_GenPrograms(GLsizei n, GLuint *ids)
    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
 
    for (i = 0; i < (GLuint) n; i++) {
-      const int bytes = MAX2(sizeof(struct vertex_program),
-                             sizeof(struct fragment_program));
-      struct program *prog = (struct program *) _mesa_calloc(bytes);
-      if (!prog) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenPrograms");
-         return;
-      }
-      prog->RefCount = 1;
-      prog->Id = first + i;
-      _mesa_HashInsert(ctx->Shared->Programs, first + i, prog);
+      _mesa_HashInsert(ctx->Shared->Programs, first + i, 0);
    }
 
    /* Return the program names */
@@ -1004,15 +1028,13 @@ _mesa_GenPrograms(GLsizei n, GLuint *ids)
 GLboolean GLAPIENTRY
 _mesa_IsProgram(GLuint id)
 {
-   struct program *prog;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
 
    if (id == 0)
       return GL_FALSE;
 
-   prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
-   if (prog && prog->Target)
+   if (_mesa_HashLookup(ctx->Shared->Programs, id))
       return GL_TRUE;
    else
       return GL_FALSE;
index 0217a00487dd04b18fa28e30f2b78b55bb613530..f71b46f1f70aeefbe131369f71a4a29c2b2d90eb 100644 (file)
@@ -58,6 +58,19 @@ extern const GLubyte *
 _mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
                        GLint *line, GLint *col);
 
+
+extern struct program * 
+_mesa_init_vertex_program( GLcontext *ctx, 
+                          struct vertex_program *prog, 
+                          GLenum target,
+                          GLuint id );
+
+extern struct program * 
+_mesa_init_fragment_program( GLcontext *ctx, 
+                            struct fragment_program *prog,
+                            GLenum target, 
+                            GLuint id );
+
 extern struct program *
 _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id);