glsl: remove duplicate frag input entry
[mesa.git] / src / mesa / shader / atifragshader.c
index 3117467c3cfb3b970679ddf25111d1afb5d2942d..ac087d415c5df2f829c5bf80bd8d8e946b978fa0 100644 (file)
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "glheader.h"
-#include "context.h"
-#include "hash.h"
-#include "imports.h"
-#include "macros.h"
-#include "enums.h"
-#include "mtypes.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/hash.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "main/mtypes.h"
 #include "atifragshader.h"
 
 #define MESA_DEBUG_ATI_FS 0
 
-extern struct program _mesa_DummyProgram;
+static struct ati_fragment_shader DummyShader;
+
+
+/**
+ * Allocate and initialize a new ATI fragment shader object.
+ */
+struct ati_fragment_shader *
+_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id)
+{
+   struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
+   (void) ctx;
+   if (s) {
+      s->Id = id;
+      s->RefCount = 1;
+   }
+   return s;
+}
+
+
+/**
+ * Delete the given ati fragment shader
+ */
+void
+_mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s)
+{
+   GLuint i;
+   for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
+      if (s->Instructions[i])
+         _mesa_free(s->Instructions[i]);
+      if (s->SetupInst[i])
+         _mesa_free(s->SetupInst[i]);
+   }
+   _mesa_free(s);
+}
+
+
 
 static void
 new_arith_inst(struct ati_fragment_shader *prog)
@@ -165,9 +200,9 @@ _mesa_GenFragmentShadersATI(GLuint range)
       return 0;
    }
 
-   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, range);
+   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
    for (i = 0; i < range; i++) {
-      _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
+      _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
    }
 
    return first;
@@ -176,9 +211,9 @@ _mesa_GenFragmentShadersATI(GLuint range)
 void GLAPIENTRY
 _mesa_BindFragmentShaderATI(GLuint id)
 {
-   struct program *prog;
    GET_CURRENT_CONTEXT(ctx);
    struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
+   struct ati_fragment_shader *newProg;
 
    if (ctx->ATIFragmentShader.Compiling) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
@@ -187,41 +222,43 @@ _mesa_BindFragmentShaderATI(GLuint id)
 
    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
-   if (curProg->Base.Id == id) {
+   if (curProg->Id == id) {
       return;
    }
 
-   if (curProg->Base.Id != 0) {
-      curProg->Base.RefCount--;
-      if (curProg->Base.RefCount <= 0) {
-        _mesa_HashRemove(ctx->Shared->Programs, id);
+   /* unbind current */
+   if (curProg->Id != 0) {
+      curProg->RefCount--;
+      if (curProg->RefCount <= 0) {
+        _mesa_HashRemove(ctx->Shared->ATIShaders, id);
       }
    }
 
-   /* Go bind */
+   /* find new shader */
    if (id == 0) {
-      prog = ctx->Shared->DefaultFragmentShader;
+      newProg = ctx->Shared->DefaultFragmentShader;
    }
    else {
-      prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id);
-      if (!prog || prog == &_mesa_DummyProgram) {
+      newProg = (struct ati_fragment_shader *)
+         _mesa_HashLookup(ctx->Shared->ATIShaders, id);
+      if (!newProg || newProg == &DummyShader) {
         /* allocate a new program now */
-        prog = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_SHADER_ATI, id);
-        if (!prog) {
+        newProg = _mesa_new_ati_fragment_shader(ctx, id);
+        if (!newProg) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
            return;
         }
-        _mesa_HashInsert(ctx->Shared->Programs, id, prog);
+        _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
       }
 
    }
 
    /* do actual bind */
-   ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) prog;
+   ctx->ATIFragmentShader.Current = newProg;
 
    ASSERT(ctx->ATIFragmentShader.Current);
-   if (prog)
-      prog->RefCount++;
+   if (newProg)
+      newProg->RefCount++;
 
    /*if (ctx->Driver.BindProgram)
       ctx->Driver.BindProgram(ctx, target, prog); */
@@ -238,37 +275,29 @@ _mesa_DeleteFragmentShaderATI(GLuint id)
    }
 
    if (id != 0) {
-      struct program *prog = (struct program *)
-        _mesa_HashLookup(ctx->Shared->Programs, id);
-      if (prog == &_mesa_DummyProgram) {
-        _mesa_HashRemove(ctx->Shared->Programs, id);
+      struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
+        _mesa_HashLookup(ctx->Shared->ATIShaders, id);
+      if (prog == &DummyShader) {
+        _mesa_HashRemove(ctx->Shared->ATIShaders, id);
       }
       else if (prog) {
         if (ctx->ATIFragmentShader.Current &&
-            ctx->ATIFragmentShader.Current->Base.Id == id) {
+            ctx->ATIFragmentShader.Current->Id == id) {
+            FLUSH_VERTICES(ctx, _NEW_PROGRAM);
            _mesa_BindFragmentShaderATI(0);
         }
       }
-#if 0
-      if (!prog->DeletePending) {
-        prog->DeletePending = GL_TRUE;
-        prog->RefCount--;
-      }
-      if (prog->RefCount <= 0) {
-        _mesa_HashRemove(ctx->Shared->Programs, id);
-        ctx->Driver.DeleteProgram(ctx, prog);
-      }
-#else
+
       /* The ID is immediately available for re-use now */
-      _mesa_HashRemove(ctx->Shared->Programs, id);
+      _mesa_HashRemove(ctx->Shared->ATIShaders, id);
       prog->RefCount--;
       if (prog->RefCount <= 0) {
-        ctx->Driver.DeleteProgram(ctx, prog);
+         _mesa_free(prog);
       }
-#endif
    }
 }
 
+
 void GLAPIENTRY
 _mesa_BeginFragmentShaderATI(void)
 {
@@ -280,6 +309,8 @@ _mesa_BeginFragmentShaderATI(void)
       return;
    }
 
+   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
    /* if the shader was already defined free instructions and get new ones
       (or, could use the same mem but would need to reinitialize) */
    /* no idea if it's allowed to redefine a shader */
@@ -304,7 +335,7 @@ _mesa_BeginFragmentShaderATI(void)
    }
 
 /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
-   ctx->ATIFragmentShader.Current->localConstDef = 0;
+   ctx->ATIFragmentShader.Current->LocalConstDef = 0;
    ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
    ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
    ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
@@ -369,6 +400,8 @@ _mesa_EndFragmentShaderATI(void)
       }
    }
 #endif
+   if (ctx->Driver.ProgramStringNotify)
+      ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_SHADER_ATI, NULL );
 }
 
 void GLAPIENTRY
@@ -392,13 +425,14 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
       return;
    }
-   if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
+   if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
+      ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
       return;
    }
    if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
-       ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE5_ARB))) {
-   /* is this texture5 or texture7? spec is a bit unclear there */
+       ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
+       ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
       return;
    }
@@ -406,7 +440,7 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
       return;
    }
-   if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
+   if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
       return;
    }
@@ -414,13 +448,14 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
       return;
    }
-   if (coord <= GL_TEXTURE5) {
-      if ((((curProg->swizzlerq >> (coord * 2)) & 3) != 0) &&
-          (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (coord * 2)) & 3))) {
+   if (coord <= GL_TEXTURE7_ARB) {
+      GLuint tmp = coord - GL_TEXTURE0_ARB;
+      if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
+          (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
         return;
       } else {
-        curProg->swizzlerq |= (((swizzle & 1) + 1) << (coord * 2));
+        curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
       }
    }
 
@@ -462,12 +497,14 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
       return;
    }
-   if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
+   if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
+      ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
       return;
    }
    if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
-       ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE5_ARB))) {
+       ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
+       ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
    /* is this texture5 or texture7? spec is a bit unclear there */
       _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
       return;
@@ -476,7 +513,7 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
       return;
    }
-   if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) {
+   if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
       return;
    }
@@ -484,13 +521,14 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
       return;
    }
-   if (interp <= GL_TEXTURE5) {
-      if ((((curProg->swizzlerq >> (interp * 2)) & 3) != 0) &&
-          (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (interp * 2)) & 3))) {
+   if (interp <= GL_TEXTURE7_ARB) {
+      GLuint tmp = interp - GL_TEXTURE0_ARB;
+      if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
+          (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
         return;
       } else {
-        curProg->swizzlerq |= (((swizzle & 1) + 1) << (interp * 2));
+        curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
       }
    }
 
@@ -712,9 +750,10 @@ _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
    if (ctx->ATIFragmentShader.Compiling) {
       struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
       COPY_4V(curProg->Constants[dstindex], value);
-      curProg->localConstDef |= 1 << dstindex;
+      curProg->LocalConstDef |= 1 << dstindex;
    }
    else {
-      COPY_4V(ctx->ATIFragmentShader.globalConstants[dstindex], value);
+      FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+      COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
    }
 }