Merge branch 'master' of git+ssh://michal@git.freedesktop.org/git/mesa/mesa into...
[mesa.git] / src / mesa / shader / arbprogram.c
index 9cc5488b2b12b9894f0656c60e1fcec8f6d2ce83..4b5f63ef9207b15804a32806b3695d2171f5ce87 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  7.0
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,6 +36,7 @@
 #include "imports.h"
 #include "macros.h"
 #include "mtypes.h"
+#include "program.h"
 
 
 void GLAPIENTRY
@@ -51,8 +52,8 @@ _mesa_EnableVertexAttribArrayARB(GLuint index)
    }
 
    FLUSH_VERTICES(ctx, _NEW_ARRAY);
-   ctx->Array.VertexAttrib[index].Enabled = GL_TRUE;
-   ctx->Array._Enabled |= _NEW_ARRAY_ATTRIB(index);
+   ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE;
+   ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index);
    ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
 }
 
@@ -70,8 +71,8 @@ _mesa_DisableVertexAttribArrayARB(GLuint index)
    }
 
    FLUSH_VERTICES(ctx, _NEW_ARRAY);
-   ctx->Array.VertexAttrib[index].Enabled = GL_FALSE;
-   ctx->Array._Enabled &= ~_NEW_ARRAY_ATTRIB(index);
+   ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE;
+   ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index);
    ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
 }
 
@@ -101,28 +102,33 @@ _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   if (index == 0 || index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
+   if (index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribfvARB(index)");
       return;
    }
 
    switch (pname) {
       case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
-         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Enabled;
+         params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Enabled;
          break;
       case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
-         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Size;
+         params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size;
          break;
       case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
-         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Stride;
+         params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride;
          break;
       case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
-         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Type;
+         params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type;
          break;
       case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
-         params[0] = ctx->Array.VertexAttrib[index].Normalized;
+         params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Normalized;
          break;
       case GL_CURRENT_VERTEX_ATTRIB_ARB:
+         if (index == 0) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glGetVertexAttribfvARB(index==0)");
+            return;
+         }
          FLUSH_CURRENT(ctx, 0);
          COPY_4V(params, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]);
          break;
@@ -131,7 +137,8 @@ _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
             _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
             return;
          }
-         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].BufferObj->Name;
+         params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name;
+         break;
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
          return;
@@ -174,7 +181,32 @@ _mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
       return;
    }
 
-   *pointer = (GLvoid *) ctx->Array.VertexAttrib[index].Ptr;;
+   *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
+}
+
+
+/**
+ * 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
+ * \return GL_TRUE if id is a program, else GL_FALSE.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsProgramARB(GLuint id)
+{
+   struct gl_program *prog = NULL; 
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+   if (id == 0)
+      return GL_FALSE;
+
+   prog = _mesa_lookup_program(ctx, id);
+   if (prog && (prog != &_mesa_DummyProgram))
+      return GL_TRUE;
+   else
+      return GL_FALSE;
 }
 
 
@@ -194,7 +226,7 @@ _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
 
    if (target == GL_VERTEX_PROGRAM_ARB
        && ctx->Extensions.ARB_vertex_program) {
-      struct vertex_program *prog = ctx->VertexProgram.Current;
+      struct gl_vertex_program *prog = ctx->VertexProgram.Current;
       _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
       
       if (ctx->Driver.ProgramStringNotify)
@@ -202,7 +234,7 @@ _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
    }
    else if (target == GL_FRAGMENT_PROGRAM_ARB
             && ctx->Extensions.ARB_fragment_program) {
-      struct fragment_program *prog = ctx->FragmentProgram.Current;
+      struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
       _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
 
       if (ctx->Driver.ProgramStringNotify)
@@ -275,6 +307,50 @@ _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
 }
 
 
+void GLAPIENTRY
+_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
+                                const GLfloat *params)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLint i;
+   GLfloat * dest;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+   if (count <= 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
+   }
+
+   if (target == GL_FRAGMENT_PROGRAM_ARB
+       && ctx->Extensions.ARB_fragment_program) {
+      if ((index + count) > ctx->Const.FragmentProgram.MaxEnvParams) {
+         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
+         return;
+      }
+      dest = ctx->FragmentProgram.Parameters[index];
+   }
+   else if (target == GL_VERTEX_PROGRAM_ARB
+       && ctx->Extensions.ARB_vertex_program) {
+      if ((index + count) > ctx->Const.VertexProgram.MaxEnvParams) {
+         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
+         return;
+      }
+      dest = ctx->VertexProgram.Parameters[index];
+   }
+   else {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
+      return;
+   }
+
+   for ( i = 0 ; i < count ; i++ ) {
+      COPY_4V(dest, params);
+      params += 4;
+      dest += 4;
+   }
+}
+
+
 void GLAPIENTRY
 _mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
                                   GLdouble *params)
@@ -334,7 +410,7 @@ _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
                                  GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct program *prog;
+   struct gl_program *prog;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
@@ -382,6 +458,50 @@ _mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
 }
 
 
+void GLAPIENTRY
+_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
+                                  const GLfloat *params)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_program *prog;
+   GLint i;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+   if (count <= 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
+   }
+
+   if (target == GL_FRAGMENT_PROGRAM_ARB
+       && ctx->Extensions.ARB_fragment_program) {
+      if ((index + count) > ctx->Const.FragmentProgram.MaxLocalParams) {
+         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
+         return;
+      }
+      prog = &(ctx->FragmentProgram.Current->Base);
+   }
+   else if (target == GL_VERTEX_PROGRAM_ARB
+            && ctx->Extensions.ARB_vertex_program) {
+      if ((index + count) > ctx->Const.VertexProgram.MaxLocalParams) {
+         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
+         return;
+      }
+      prog = &(ctx->VertexProgram.Current->Base);
+   }
+   else {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)");
+      return;
+   }
+
+   for (i = 0; i < count; i++) {
+      ASSERT((index + i) < MAX_PROGRAM_LOCAL_PARAMS);
+      COPY_4V(prog->LocalParams[index + i], params);
+      params += 4;
+   }
+}
+
+
 /**
  * Note, this function is also used by the GL_NV_fragment_program extension.
  */
@@ -415,7 +535,7 @@ void GLAPIENTRY
 _mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
                                     GLfloat *params)
 {
-   const struct program *prog;
+   const struct gl_program *prog;
    GLuint maxParams;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -473,7 +593,7 @@ void GLAPIENTRY
 _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
 {
    const struct gl_program_constants *limits;
-   struct program *prog;
+   struct gl_program *prog;
    GET_CURRENT_CONTEXT(ctx);
 
    if (!ctx->_CurrentProgram)
@@ -583,10 +703,18 @@ _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
           * The spec says that even if this query returns true, there's
           * no guarantee that the program will run in hardware.
           */
-        if (ctx->Driver.IsProgramNative) 
+         if (prog->Id == 0) {
+            /* default/null program */
+            *params = GL_FALSE;
+         }
+        else if (ctx->Driver.IsProgramNative) {
+            /* ask the driver */
            *params = ctx->Driver.IsProgramNative( ctx, target, prog );
-        else
+         }
+        else {
+            /* probably running in software */
            *params = GL_TRUE;
+         }
          return;
       default:
          /* continue with fragment-program only queries below */
@@ -597,25 +725,25 @@ _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
     * The following apply to fragment programs only (at this time)
     */
    if (target == GL_FRAGMENT_PROGRAM_ARB) {
-      const struct fragment_program *fp = ctx->FragmentProgram.Current;
+      const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
       switch (pname) {
          case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
-            *params = fp->NumNativeAluInstructions;
+            *params = fp->Base.NumNativeAluInstructions;
             return;
          case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
-            *params = fp->NumAluInstructions;
+            *params = fp->Base.NumAluInstructions;
             return;
          case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
-            *params = fp->NumTexInstructions;
+            *params = fp->Base.NumTexInstructions;
             return;
          case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
-            *params = fp->NumNativeTexInstructions;
+            *params = fp->Base.NumNativeTexInstructions;
             return;
          case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
-            *params = fp->NumTexIndirections;
+            *params = fp->Base.NumTexIndirections;
             return;
          case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
-            *params = fp->NumNativeTexIndirections;
+            *params = fp->Base.NumNativeTexIndirections;
             return;
          case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
             *params = limits->MaxAluInstructions;
@@ -646,7 +774,8 @@ _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
 void GLAPIENTRY
 _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
 {
-   const struct program *prog;
+   const struct gl_program *prog;
+   char *dst = (char *) string;
    GET_CURRENT_CONTEXT(ctx);
 
    if (!ctx->_CurrentProgram)
@@ -670,5 +799,8 @@ _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
       return;
    }
 
-   _mesa_memcpy(string, prog->String, _mesa_strlen((char *) prog->String));
+   if (prog->String)
+      _mesa_memcpy(dst, prog->String, _mesa_strlen((char *) prog->String));
+   else
+      *dst = '\0';
 }