comment-out some unused code to silence warnings
[mesa.git] / src / mesa / shader / program.c
index daec9252fff20b31b68f4dd95f79bf101f865a50..0ccc741dd0c860a53de3dfcc3d25d4b5474d0db0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.1
+ * Version:  6.2
  *
  * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
@@ -39,6 +39,7 @@
 #include "nvfragparse.h"
 #include "nvfragprog.h"
 #include "nvvertparse.h"
+#include "nvvertprog.h"
 
 
 /**********************************************************************/
 /**********************************************************************/
 
 
+/* A pointer to this dummy program is put into the hash table when
+ * glGenPrograms is called.
+ */
+struct program _mesa_DummyProgram;
+
+
 /**
  * Init context's vertex/fragment program state
  */
@@ -76,6 +83,13 @@ _mesa_init_program(GLcontext *ctx)
    assert(ctx->FragmentProgram.Current);
    ctx->FragmentProgram.Current->Base.RefCount++;
 #endif
+
+#if FEATURE_ATI_fragment_shader
+   ctx->ATIFragmentShader.Enabled = GL_FALSE;
+   ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
+   assert(ctx->ATIFragmentShader.Current);
+   ctx->ATIFragmentShader.Current->Base.RefCount++;
+#endif
 }
 
 
@@ -98,6 +112,13 @@ _mesa_free_program_data(GLcontext *ctx)
       if (ctx->FragmentProgram.Current->Base.RefCount <= 0)
          ctx->Driver.DeleteProgram(ctx, &(ctx->FragmentProgram.Current->Base));
    }
+#endif
+#if FEATURE_ATI_fragment_shader
+   if (ctx->ATIFragmentShader.Current) {
+      ctx->ATIFragmentShader.Current->Base.RefCount--;
+      if (ctx->ATIFragmentShader.Current->Base.RefCount <= 0)
+       ctx->Driver.DeleteProgram(ctx, &(ctx->ATIFragmentShader.Current->Base));
+   }
 #endif
    _mesa_free((void *) ctx->Program.ErrorString);
 }
@@ -163,10 +184,14 @@ _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)
+/**
+ * Initialize a new vertex/fragment program object.
+ */
+static struct program *
+_mesa_init_program_struct( GLcontext *ctx, struct program *prog,
+                           GLenum target, GLuint id)
 {
+   (void) ctx;
    if (prog) {
       prog->Id = id;
       prog->Target = target;
@@ -177,9 +202,13 @@ static struct program * _mesa_init_program_struct( GLcontext *ctx,
    return prog;
 }
 
-struct program * _mesa_init_fragment_program( GLcontext *ctx, 
-                                             struct fragment_program *prog,
-                                             GLenum target, GLuint id)
+
+/**
+ * Initialize a new fragment program object.
+ */
+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 );
@@ -187,9 +216,13 @@ struct program * _mesa_init_fragment_program( GLcontext *ctx,
       return NULL;
 }
 
-struct program * _mesa_init_vertex_program( GLcontext *ctx, 
-                                           struct vertex_program *prog,
-                                           GLenum target, GLuint id)
+
+/**
+ * Initialize a new vertex program object.
+ */
+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 );
@@ -197,6 +230,21 @@ struct program * _mesa_init_vertex_program( GLcontext *ctx,
       return NULL;
 }
 
+/**
+ * Initialize a new ATI fragment shader object.
+ */
+struct program *
+_mesa_init_ati_fragment_shader( GLcontext *ctx,
+                                struct ati_fragment_shader *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
@@ -217,11 +265,13 @@ _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id)
    case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
       return _mesa_init_vertex_program( ctx, CALLOC_STRUCT(vertex_program),
                                        target, id );
-
    case GL_FRAGMENT_PROGRAM_NV:
    case GL_FRAGMENT_PROGRAM_ARB:
       return _mesa_init_fragment_program( ctx, CALLOC_STRUCT(fragment_program),
                                          target, id );
+   case GL_FRAGMENT_SHADER_ATI:
+      return _mesa_init_ati_fragment_shader( ctx, CALLOC_STRUCT(ati_fragment_shader),
+                                         target, id );
 
    default:
       _mesa_problem(ctx, "bad target in _mesa_new_program");
@@ -239,6 +289,7 @@ _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id)
 void
 _mesa_delete_program(GLcontext *ctx, struct program *prog)
 {
+   (void) ctx;
    ASSERT(prog);
 
    if (prog->String)
@@ -246,19 +297,37 @@ _mesa_delete_program(GLcontext *ctx, struct program *prog)
    if (prog->Target == GL_VERTEX_PROGRAM_NV ||
        prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
       struct vertex_program *vprog = (struct vertex_program *) prog;
-      if (vprog->Instructions)
+      if (vprog->Instructions) {
+         GLuint i;
+         for (i = 0; i < vprog->Base.NumInstructions; i++) {
+            if (vprog->Instructions[i].Data)
+               _mesa_free(vprog->Instructions[i].Data);
+         }
          _mesa_free(vprog->Instructions);
+      }
       if (vprog->Parameters)
          _mesa_free_parameter_list(vprog->Parameters);
    }
    else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
             prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
       struct fragment_program *fprog = (struct fragment_program *) prog;
-      if (fprog->Instructions)
+      if (fprog->Instructions) {
+         GLuint i;
+         for (i = 0; i < fprog->Base.NumInstructions; i++) {
+            if (fprog->Instructions[i].Data)
+               _mesa_free(fprog->Instructions[i].Data);
+         }
          _mesa_free(fprog->Instructions);
+      }
       if (fprog->Parameters)
          _mesa_free_parameter_list(fprog->Parameters);
    }
+   else if (prog->Target == GL_FRAGMENT_SHADER_ATI) {
+      struct ati_fragment_shader *atifs = (struct ati_fragment_shader *)prog;
+      if (atifs->Instructions)
+        _mesa_free(atifs->Instructions);
+   }
+
    _mesa_free(prog);
 }
 
@@ -283,6 +352,9 @@ void
 _mesa_free_parameter_list(struct program_parameter_list *paramList)
 {
    _mesa_free_parameters(paramList);
+   _mesa_free(paramList->Parameters);
+   if (paramList->ParameterValues)
+      ALIGN_FREE(paramList->ParameterValues);
    _mesa_free(paramList);
 }
 
@@ -296,11 +368,10 @@ _mesa_free_parameters(struct program_parameter_list *paramList)
 {
    GLuint i;
    for (i = 0; i < paramList->NumParameters; i++) {
-      _mesa_free((void *) paramList->Parameters[i].Name);
+      if (paramList->Parameters[i].Name)
+        _mesa_free((void *) paramList->Parameters[i].Name);
    }
-   _mesa_free(paramList->Parameters);
    paramList->NumParameters = 0;
-   paramList->Parameters = NULL;
 }
 
 
@@ -314,21 +385,44 @@ add_parameter(struct program_parameter_list *paramList,
 {
    const GLuint n = paramList->NumParameters;
 
-   paramList->Parameters = (struct program_parameter *)
-      _mesa_realloc(paramList->Parameters,
-                    n * sizeof(struct program_parameter),
-                    (n + 1) * sizeof(struct program_parameter));
-   if (!paramList->Parameters) {
+   if (n == paramList->Size) {
+      GLfloat (*tmp)[4];
+
+      paramList->Size *= 2;
+      if (!paramList->Size)
+        paramList->Size = 8;
+
+      paramList->Parameters = (struct program_parameter *)
+        _mesa_realloc(paramList->Parameters,
+                      n * sizeof(struct program_parameter),
+                      paramList->Size * sizeof(struct program_parameter));
+
+      tmp = paramList->ParameterValues;
+      paramList->ParameterValues = ALIGN_MALLOC(paramList->Size * 4 * sizeof(GLfloat), 16);
+      if (tmp) {
+        _mesa_memcpy(paramList->ParameterValues, tmp, 
+                     n * 4 * sizeof(GLfloat));
+        ALIGN_FREE(tmp);
+      }
+   }
+
+   if (!paramList->Parameters ||
+       !paramList->ParameterValues) {
       /* out of memory */
       paramList->NumParameters = 0;
+      paramList->Size = 0;
       return -1;
    }
    else {
       paramList->NumParameters = n + 1;
-      paramList->Parameters[n].Name = _mesa_strdup(name);
+
+      _mesa_memset(&paramList->Parameters[n], 0, 
+                  sizeof(struct program_parameter));
+
+      paramList->Parameters[n].Name = name ? _mesa_strdup(name) : NULL;
       paramList->Parameters[n].Type = type;
       if (values)
-         COPY_4V(paramList->Parameters[n].Values, values);
+         COPY_4V(paramList->ParameterValues[n], values);
       return (GLint) n;
    }
 }
@@ -370,13 +464,7 @@ GLint
 _mesa_add_unnamed_constant(struct program_parameter_list *paramList,
                            const GLfloat values[4])
 {
-   /* generate a new dummy name */
-   static GLuint n = 0;
-   char name[20];
-   _mesa_sprintf(name, "constant%d", n);
-   n++;
-   /* store it */
-   return add_parameter(paramList, name, values, CONSTANT);
+   return add_parameter(paramList, NULL, values, CONSTANT);
 }
 
 
@@ -396,7 +484,7 @@ _mesa_add_state_reference(struct program_parameter_list *paramList,
     */
    GLint a, idx;
 
-   idx = add_parameter(paramList, "Some State", NULL, STATE);
+   idx = add_parameter(paramList, NULL, NULL, STATE);
        
    for (a=0; a<6; a++)
       paramList->Parameters[idx].StateIndexes[a] = (enum state_index) stateTokens[a];
@@ -421,16 +509,18 @@ _mesa_lookup_parameter_value(struct program_parameter_list *paramList,
    if (nameLen == -1) {
       /* name is null-terminated */
       for (i = 0; i < paramList->NumParameters; i++) {
-         if (_mesa_strcmp(paramList->Parameters[i].Name, name) == 0)
-            return paramList->Parameters[i].Values;
+         if (paramList->Parameters[i].Name &&
+            _mesa_strcmp(paramList->Parameters[i].Name, name) == 0)
+            return paramList->ParameterValues[i];
       }
    }
    else {
       /* name is not null-terminated, use nameLen */
       for (i = 0; i < paramList->NumParameters; i++) {
-         if (_mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
+         if (paramList->Parameters[i].Name &&
+            _mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
              && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen)
-            return paramList->Parameters[i].Values;
+            return paramList->ParameterValues[i];
       }
    }
    return NULL;
@@ -453,14 +543,16 @@ _mesa_lookup_parameter_index(struct program_parameter_list *paramList,
    if (nameLen == -1) {
       /* name is null-terminated */
       for (i = 0; i < (GLint) paramList->NumParameters; i++) {
-         if (_mesa_strcmp(paramList->Parameters[i].Name, name) == 0)
+         if (paramList->Parameters[i].Name &&
+            _mesa_strcmp(paramList->Parameters[i].Name, name) == 0)
             return i;
       }
    }
    else {
       /* name is not null-terminated, use nameLen */
       for (i = 0; i < (GLint) paramList->NumParameters; i++) {
-         if (_mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
+         if (paramList->Parameters[i].Name &&
+            _mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
              && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen)
             return i;
       }
@@ -524,8 +616,7 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[],
             _mesa_problem(ctx, "Invalid material state in fetch_state");
             return;
          }
-      };
-      return;
+      }
    case STATE_LIGHT:
       {
          /* state[1] is the light number */
@@ -551,7 +642,8 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[],
             value[3] = ctx->Light.Light[ln].SpotExponent;
             return;
          case STATE_SPOT_DIRECTION:
-            COPY_4V(value, ctx->Light.Light[ln].EyeDirection);
+            COPY_3V(value, ctx->Light.Light[ln].EyeDirection);
+            value[3] = ctx->Light.Light[ln]._CosCutoff;
             return;
          case STATE_HALF:
             {
@@ -560,20 +652,23 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[],
                /* Compute infinite half angle vector:
                 *   half-vector = light_position + (0, 0, 1) 
                 * and then normalize.  w = 0
-                                        *
-                                        * light.EyePosition.w should be 0 for infinite lights.
+               *
+               * light.EyePosition.w should be 0 for infinite lights.
                 */
-                                       ADD_3V(value, eye_z, ctx->Light.Light[ln].EyePosition);
-                                       NORMALIZE_3FV(value);
-                                       value[3] = 0;
+              ADD_3V(value, eye_z, ctx->Light.Light[ln].EyePosition);
+              NORMALIZE_3FV(value);
+              value[3] = 0;
             }                                            
             return;
+        case STATE_POSITION_NORMALIZED:
+            COPY_4V(value, ctx->Light.Light[ln].EyePosition);
+           NORMALIZE_3FV( value );
+            return;
          default:
             _mesa_problem(ctx, "Invalid light state in fetch_state");
             return;
          }
       }
-      return;
    case STATE_LIGHTMODEL_AMBIENT:
       COPY_4V(value, ctx->Light.Model.Ambient);
       return;
@@ -581,20 +676,22 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[],
       if (state[1] == 0) {
          /* front */
          GLint i;
-         for (i = 0; i < 4; i++) {
+         for (i = 0; i < 3; i++) {
             value[i] = ctx->Light.Model.Ambient[i]
                * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i]
                + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i];
          }
+        value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
       }
       else {
          /* back */
          GLint i;
-         for (i = 0; i < 4; i++) {
+         for (i = 0; i < 3; i++) {
             value[i] = ctx->Light.Model.Ambient[i]
                * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i]
                + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i];
          }
+        value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
       }
       return;
    case STATE_LIGHTPROD:
@@ -633,7 +730,6 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[],
                return;
          }
       }
-      return;
    case STATE_TEXGEN:
       {
          /* state[1] is the texture unit */
@@ -669,7 +765,6 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[],
             return;
          }
       }
-      return;
    case STATE_TEXENV_COLOR:
       {                
          /* state[1] is the texture unit */
@@ -741,7 +836,9 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[],
          }
          if (modifier == STATE_MATRIX_INVERSE ||
              modifier == STATE_MATRIX_INVTRANS) {
-            /* XXX be sure inverse is up to date */
+            /* Be sure inverse is up to date:
+            */
+           _math_matrix_analyse( (GLmatrix*) matrix );
             m = matrix->inv;
          }
          else {
@@ -809,6 +906,20 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[],
          }
       }
       return;
+
+   case STATE_INTERNAL:
+      {
+         switch (state[1]) {
+           case STATE_NORMAL_SCALE:
+               ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1);
+               break;
+           default:
+               _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
+               return;
+         }
+      }
+      return;
+
    default:
       _mesa_problem(ctx, "Invalid state in _mesa_fetch_state");
       return;
@@ -833,8 +944,9 @@ _mesa_load_state_parameters(GLcontext *ctx,
 
    for (i = 0; i < paramList->NumParameters; i++) {
       if (paramList->Parameters[i].Type == STATE) {
-         _mesa_fetch_state(ctx, paramList->Parameters[i].StateIndexes,
-                           paramList->Parameters[i].Values);
+         _mesa_fetch_state(ctx, 
+                          paramList->Parameters[i].StateIndexes,
+                           paramList->ParameterValues[i]);
       }
    }
 }
@@ -864,16 +976,19 @@ _mesa_BindProgram(GLenum target, GLuint id)
         && ctx->Extensions.NV_vertex_program) ||
        (target == GL_VERTEX_PROGRAM_ARB
         && ctx->Extensions.ARB_vertex_program)) {
-      if (ctx->VertexProgram.Current &&
-          ctx->VertexProgram.Current->Base.Id == id)
+      /*** Vertex program binding ***/
+      struct vertex_program *curProg = ctx->VertexProgram.Current;
+      if (curProg->Base.Id == id) {
+         /* binding same program - no change */
          return;
-      /* decrement refcount on previously bound vertex program */
-      if (ctx->VertexProgram.Current) {
-         ctx->VertexProgram.Current->Base.RefCount--;
+      }
+      if (curProg->Base.Id != 0) {
+         /* decrement refcount on previously bound vertex program */
+         curProg->Base.RefCount--;
          /* and delete if refcount goes below one */
-         if (ctx->VertexProgram.Current->Base.RefCount <= 0) {
-            ctx->Driver.DeleteProgram(ctx, &(ctx->VertexProgram.Current->Base));
-            _mesa_HashRemove(ctx->Shared->Programs, id);
+         if (curProg->Base.RefCount <= 0) {
+            /* the program ID was already removed from the hash table */
+            ctx->Driver.DeleteProgram(ctx, &(curProg->Base));
          }
       }
    }
@@ -881,16 +996,19 @@ _mesa_BindProgram(GLenum target, GLuint id)
              && ctx->Extensions.NV_fragment_program) ||
             (target == GL_FRAGMENT_PROGRAM_ARB
              && ctx->Extensions.ARB_fragment_program)) {
-      if (ctx->FragmentProgram.Current &&
-          ctx->FragmentProgram.Current->Base.Id == id)
+      /*** Fragment program binding ***/
+      struct fragment_program *curProg = ctx->FragmentProgram.Current;
+      if (curProg->Base.Id == id) {
+         /* binding same program - no change */
          return;
-      /* decrement refcount on previously bound fragment program */
-      if (ctx->FragmentProgram.Current) {
-         ctx->FragmentProgram.Current->Base.RefCount--;
+      }
+      if (curProg->Base.Id != 0) {
+         /* decrement refcount on previously bound fragment program */
+         curProg->Base.RefCount--;
          /* and delete if refcount goes below one */
-         if (ctx->FragmentProgram.Current->Base.RefCount <= 0) {
-            ctx->Driver.DeleteProgram(ctx, &(ctx->FragmentProgram.Current->Base));
-            _mesa_HashRemove(ctx->Shared->Programs, id);
+         if (curProg->Base.RefCount <= 0) {
+            /* the program ID was already removed from the hash table */
+            ctx->Driver.DeleteProgram(ctx, &(curProg->Base));
          }
       }
    }
@@ -903,7 +1021,7 @@ _mesa_BindProgram(GLenum target, GLuint id)
     * That's supposed to be caught in glBegin.
     */
    if (id == 0) {
-      /* default program */
+      /* Bind default program */
       prog = NULL;
       if (target == GL_VERTEX_PROGRAM_NV || target == GL_VERTEX_PROGRAM_ARB)
          prog = ctx->Shared->DefaultVertexProgram;
@@ -911,19 +1029,9 @@ _mesa_BindProgram(GLenum target, GLuint id)
          prog = ctx->Shared->DefaultFragmentProgram;
    }
    else {
+      /* Bind user program */
       prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
-      if (prog) {
-         if (prog->Target == 0) {
-            /* prog was allocated with glGenProgramsNV */
-            prog->Target = target;
-         }
-         else if (prog->Target != target) {
-            _mesa_error(ctx, GL_INVALID_OPERATION,
-                        "glBindProgramNV/ARB(target mismatch)");
-            return;
-         }
-      }
-      else {
+      if (!prog || prog == &_mesa_DummyProgram) {
          /* allocate a new program now */
          prog = ctx->Driver.NewProgram(ctx, target, id);
          if (!prog) {
@@ -932,6 +1040,11 @@ _mesa_BindProgram(GLenum target, GLuint id)
          }
          _mesa_HashInsert(ctx->Shared->Programs, id, prog);
       }
+      else if (prog->Target != target) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glBindProgramNV/ARB(target mismatch)");
+         return;
+      }
    }
 
    /* bind now */
@@ -942,6 +1055,10 @@ _mesa_BindProgram(GLenum target, GLuint id)
       ctx->FragmentProgram.Current = (struct fragment_program *) prog;
    }
 
+   /* Never null pointers */
+   ASSERT(ctx->VertexProgram.Current);
+   ASSERT(ctx->FragmentProgram.Current);
+
    if (prog)
       prog->RefCount++;
 
@@ -971,7 +1088,11 @@ _mesa_DeletePrograms(GLsizei n, const GLuint *ids)
       if (ids[i] != 0) {
          struct program *prog = (struct program *)
             _mesa_HashLookup(ctx->Shared->Programs, ids[i]);
-         if (prog) {
+         if (prog == &_mesa_DummyProgram) {
+            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
+         }
+         else if (prog) {
+            /* Unbind program if necessary */
             if (prog->Target == GL_VERTEX_PROGRAM_NV ||
                 prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
                if (ctx->VertexProgram.Current &&
@@ -992,18 +1113,13 @@ _mesa_DeletePrograms(GLsizei n, const GLuint *ids)
                _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
                return;
             }
+            /* The ID is immediately available for re-use now */
+            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
             prog->RefCount--;
             if (prog->RefCount <= 0) {
                ctx->Driver.DeleteProgram(ctx, prog);
             }
          }
-         /* Always remove entry from hash table.
-          * 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]);
       }
    }
 }
@@ -1032,8 +1148,9 @@ _mesa_GenPrograms(GLsizei n, GLuint *ids)
 
    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
 
+   /* Insert pointer to dummy program as placeholder */
    for (i = 0; i < (GLuint) n; i++) {
-      _mesa_HashInsert(ctx->Shared->Programs, first + i, 0);
+      _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
    }
 
    /* Return the program names */
@@ -1044,7 +1161,7 @@ _mesa_GenPrograms(GLsizei n, GLuint *ids)
 
 
 /**
- * Determine if id names a program.
+ * Determine if id names a vertex or fragment program.
  * \note Not compiled into display lists.
  * \note Called from both glIsProgramNV and glIsProgramARB.
  * \param id is the program identifier
@@ -1073,7 +1190,7 @@ _mesa_IsProgram(GLuint id)
 
 
 /* XXX temporary */
-void
+GLAPI void GLAPIENTRY
 glProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
                       GLvoid *data)
 {
@@ -1121,7 +1238,7 @@ _mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
 
 
 /* XXX temporary */
-void
+GLAPI void GLAPIENTRY
 glGetProgramRegisterfvMESA(GLenum target,
                            GLsizei len, const GLubyte *registerName,
                            GLfloat *v)