added GL_X_RENDERABLE to glXChooseFBConfig (bug 4181)
[mesa.git] / src / mesa / tnl / t_vtx_api.c
index 9f67c6cee731659d0f3aa05e4e1b23cd0bb8942d..fa9e04ad336f52c38e994abff940248f477b87ee 100644 (file)
@@ -43,10 +43,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "t_vtx_api.h"
 #include "simple_list.h"
 
+#include "dispatch.h"
+
 static void reset_attrfv( TNLcontext *tnl );
 
-static attrfv_func choose[_TNL_MAX_ATTR_CODEGEN+1][4]; /* +1 for ERROR_ATTRIB */
-static attrfv_func generic_attr_func[_TNL_MAX_ATTR_CODEGEN][4];
+static tnl_attrfv_func choose[_TNL_MAX_ATTR_CODEGEN+1][4]; /* +1 for ERROR_ATTRIB */
+static tnl_attrfv_func generic_attr_func[_TNL_MAX_ATTR_CODEGEN][4];
 
 
 /* Close off the last primitive, execute the buffer, restart the
@@ -64,7 +66,7 @@ static void _tnl_wrap_buffers( GLcontext *ctx )
    }
    else {
       GLuint last_prim = tnl->vtx.prim[tnl->vtx.prim_count-1].mode;
-      GLuint last_count = tnl->vtx.prim[tnl->vtx.prim_count-1].count;
+      GLuint last_count;
 
       if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
         GLint i = tnl->vtx.prim_count - 1;
@@ -74,6 +76,8 @@ static void _tnl_wrap_buffers( GLcontext *ctx )
                                   tnl->vtx.prim[i].start);
       }
 
+      last_count = tnl->vtx.prim[tnl->vtx.prim_count-1].count;
+
       /* Execute the buffer and save copied vertices.
        */
       if (tnl->vtx.counter != tnl->vtx.initial_counter)
@@ -102,8 +106,10 @@ static void _tnl_wrap_buffers( GLcontext *ctx )
 
 /* Deal with buffer wrapping where provoked by the vertex buffer
  * filling up, as opposed to upgrade_vertex().
+ *
+ * Make it GLAPIENTRY, so we can tail from the codegen'ed Vertex*fv
  */
-void _tnl_wrap_filled_vertex( GLcontext *ctx )
+void GLAPIENTRY _tnl_wrap_filled_vertex( GLcontext *ctx )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    GLfloat *data = tnl->vtx.copied.buffer;
@@ -138,23 +144,30 @@ static void _tnl_copy_to_current( GLcontext *ctx )
    TNLcontext *tnl = TNL_CONTEXT(ctx); 
    GLuint i;
 
-   for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++)
+   for (i = _TNL_ATTRIB_POS+1 ; i < _TNL_ATTRIB_INDEX ; i++) {
       if (tnl->vtx.attrsz[i]) {
          /* Note: the tnl->vtx.current[i] pointers points to
           * the ctx->Current fields.  The first 16 or so, anyway.
           */
-        ASSIGN_4V( tnl->vtx.current[i], 0, 0, 0, 1 );
-        COPY_SZ_4V(tnl->vtx.current[i], 
+        COPY_CLEAN_4V(tnl->vtx.current[i], 
                    tnl->vtx.attrsz[i], 
                    tnl->vtx.attrptr[i]);
       }
+   }
 
-   /* Edgeflag requires special treatment:
+   /* color index is special (it's not a float[4] so COPY_CLEAN_4V above
+    * will trash adjacent memory!)
     */
-   if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) 
-      ctx->Current.EdgeFlag = 
-        (tnl->vtx.attrptr[_TNL_ATTRIB_EDGEFLAG][0] == 1.0);
+   if (tnl->vtx.attrsz[_TNL_ATTRIB_INDEX]) {
+      ctx->Current.Index = tnl->vtx.attrptr[_TNL_ATTRIB_INDEX][0];
+   }
 
+   /* Edgeflag requires additional treatment:
+    */
+   if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) {
+      ctx->Current.EdgeFlag = 
+        (tnl->vtx.CurrentFloatEdgeFlag == 1.0);
+   }
 
    /* Colormaterial -- this kindof sucks.
     */
@@ -176,7 +189,12 @@ static void _tnl_copy_from_current( GLcontext *ctx )
    TNLcontext *tnl = TNL_CONTEXT(ctx); 
    GLint i;
 
-   for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) 
+   /* Edgeflag requires additional treatment:
+    */
+   tnl->vtx.CurrentFloatEdgeFlag = 
+      (GLfloat)ctx->Current.EdgeFlag;
+   
+   for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_MAX ; i++) 
       switch (tnl->vtx.attrsz[i]) {
       case 4: tnl->vtx.attrptr[i][3] = tnl->vtx.current[i][3];
       case 3: tnl->vtx.attrptr[i][2] = tnl->vtx.current[i][2];
@@ -185,13 +203,6 @@ static void _tnl_copy_from_current( GLcontext *ctx )
         break;
       }
 
-   /* Edgeflag requires special treatment:
-    */
-   if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) 
-      tnl->vtx.attrptr[_TNL_ATTRIB_EDGEFLAG][0] = 
-        (GLfloat)ctx->Current.EdgeFlag;
-
-
    ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
 }
 
@@ -251,7 +262,7 @@ static void _tnl_wrap_upgrade_vertex( GLcontext *ctx,
         tmp += tnl->vtx.attrsz[i];
       }
       else 
-        tnl->vtx.attrptr[i] = 0; /* will not be dereferenced */
+        tnl->vtx.attrptr[i] = NULL; /* will not be dereferenced */
    }
 
    /* Copy from current to repopulate the vertex with correct values.
@@ -273,10 +284,14 @@ static void _tnl_wrap_upgrade_vertex( GLcontext *ctx,
         for (j = 0 ; j < _TNL_ATTRIB_MAX ; j++) {
            if (tnl->vtx.attrsz[j]) {
               if (j == attr) {
-                 COPY_SZ_4V( dest, newsz, tnl->vtx.current[j] );
-                 COPY_SZ_4V( dest, oldsz, data );
-                 data += oldsz;
-                 dest += newsz;
+                 if (oldsz) {
+                    COPY_CLEAN_4V( dest, oldsz, data );
+                    data += oldsz;
+                    dest += newsz;
+                 } else {
+                    COPY_SZ_4V( dest, newsz, tnl->vtx.current[j] );
+                    dest += newsz;
+                 }
               }
               else {
                  GLuint sz = tnl->vtx.attrsz[j];
@@ -327,8 +342,18 @@ static void _tnl_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz )
       for (i = sz ; i <= tnl->vtx.attrsz[attr] ; i++)
         tnl->vtx.attrptr[attr][i-1] = id[i-1];
    }
+
+   /* Does setting NeedFlush belong here?  Necessitates resetting
+    * vtxfmt on each flush (otherwise flags won't get reset
+    * afterwards).
+    */
+   if (attr == 0) 
+      ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+   else 
+      ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
 }
 
+#ifdef USE_X86_ASM
 
 static struct _tnl_dynfn *lookup( struct _tnl_dynfn *l, GLuint key )
 {
@@ -339,14 +364,14 @@ static struct _tnl_dynfn *lookup( struct _tnl_dynfn *l, GLuint key )
         return f;
    }
 
-   return 0;
+   return NULL;
 }
 
 
-static attrfv_func do_codegen( GLcontext *ctx, GLuint attr, GLuint sz )
+static tnl_attrfv_func do_codegen( GLcontext *ctx, GLuint attr, GLuint sz )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx); 
-   struct _tnl_dynfn *dfn = 0;
+   struct _tnl_dynfn *dfn = NULL;
 
    if (attr == 0) {
       GLuint key = tnl->vtx.vertex_size;
@@ -366,16 +391,18 @@ static attrfv_func do_codegen( GLcontext *ctx, GLuint attr, GLuint sz )
    }
 
    if (dfn) 
-      return (attrfv_func) dfn->code;
+      return *(tnl_attrfv_func *) &dfn->code;
    else
-      return 0;
+      return NULL;
 }
 
+#endif /* USE_X86_ASM */
+
 /* Helper function for 'CHOOSE' macro.  Do what's necessary when an
  * entrypoint is called for the first time.
  */
 
-static attrfv_func do_choose( GLuint attr, GLuint sz )
+static tnl_attrfv_func do_choose( GLuint attr, GLuint sz )
 { 
    GET_CURRENT_CONTEXT( ctx ); 
    TNLcontext *tnl = TNL_CONTEXT(ctx); 
@@ -391,23 +418,17 @@ static attrfv_func do_choose( GLuint attr, GLuint sz )
    
       _tnl_fixup_vertex( ctx, attr, sz );
  
-      /* Does setting NeedFlush belong here?  Necessitates resetting
-       * vtxfmt on each flush (otherwise flags won't get reset
-       * afterwards).
-       */
-      if (attr == 0) 
-        ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
-      else 
-        ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
    }
 
 
    /* Try to use codegen:
-    */   
+    */
+#ifdef USE_X86_ASM
    if (tnl->AllowCodegen)
       tnl->vtx.tabfv[attr][sz-1] = do_codegen( ctx, attr, sz );
    else
-      tnl->vtx.tabfv[attr][sz-1] = 0;
+#endif
+      tnl->vtx.tabfv[attr][sz-1] = NULL;
 
    /* Else use generic version:
     */
@@ -422,7 +443,7 @@ static attrfv_func do_choose( GLuint attr, GLuint sz )
 #define CHOOSE( ATTR, N )                              \
 static void choose_##ATTR##_##N( const GLfloat *v )    \
 {                                                      \
-   attrfv_func f = do_choose(ATTR, N);                 \
+   tnl_attrfv_func f = do_choose(ATTR, N);                     \
    f( v );                                             \
 }
 
@@ -471,11 +492,15 @@ static void reset_attrfv( TNLcontext *tnl )
 
    for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++) 
       if (tnl->vtx.attrsz[i]) {
-        GLuint j = tnl->vtx.attrsz[i] - 1;
+        GLint j = tnl->vtx.attrsz[i] - 1;
         tnl->vtx.attrsz[i] = 0;
 
-        if (i < _TNL_MAX_ATTR_CODEGEN)
-           tnl->vtx.tabfv[i][j] = choose[i][j];
+        if (i < _TNL_MAX_ATTR_CODEGEN) {
+            while (j >= 0) {
+              tnl->vtx.tabfv[i][j] = choose[i][j];
+               j--;
+            }
+         }
       }
 
    tnl->vtx.vertex_size = 0;
@@ -509,7 +534,6 @@ do {                                                        \
       if (N>1) dest[1] = (params)[1];                  \
       if (N>2) dest[2] = (params)[2];                  \
       if (N>3) dest[3] = (params)[3];                  \
-      ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;   \
    }                                                   \
 } while (0)
 
@@ -623,7 +647,7 @@ static void GLAPIENTRY _tnl_EvalCoord1f( GLfloat u )
 
       for (i = 0 ; i <= _TNL_ATTRIB_INDEX ; i++) {
         if (tnl->vtx.eval.map1[i].map) 
-           if (tnl->vtx.attrsz[i] < tnl->vtx.eval.map1[i].sz)
+           if (tnl->vtx.attrsz[i] != tnl->vtx.eval.map1[i].sz)
               _tnl_fixup_vertex( ctx, i, tnl->vtx.eval.map1[i].sz );
       }
    }
@@ -651,12 +675,12 @@ static void GLAPIENTRY _tnl_EvalCoord2f( GLfloat u, GLfloat v )
 
       for (i = 0 ; i <= _TNL_ATTRIB_INDEX ; i++) {
         if (tnl->vtx.eval.map2[i].map) 
-           if (tnl->vtx.attrsz[i] < tnl->vtx.eval.map2[i].sz)
+           if (tnl->vtx.attrsz[i] != tnl->vtx.eval.map2[i].sz)
               _tnl_fixup_vertex( ctx, i, tnl->vtx.eval.map2[i].sz );
       }
 
       if (ctx->Eval.AutoNormal) 
-        if (tnl->vtx.attrsz[_TNL_ATTRIB_NORMAL] < 3)
+        if (tnl->vtx.attrsz[_TNL_ATTRIB_NORMAL] != 3)
            _tnl_fixup_vertex( ctx, _TNL_ATTRIB_NORMAL, 3 );
    }
 
@@ -711,24 +735,23 @@ static void GLAPIENTRY _tnl_Begin( GLenum mode )
 {
    GET_CURRENT_CONTEXT( ctx ); 
 
-   if ((ctx->VertexProgram.Enabled
-        && !ctx->VertexProgram.Current->Instructions) ||
-       (ctx->FragmentProgram.Enabled
-        && !ctx->FragmentProgram.Current->Instructions)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glBegin (invalid vertex/fragment program)");
-      return;
-   }
-
    if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
       TNLcontext *tnl = TNL_CONTEXT(ctx); 
       int i;
 
       if (ctx->NewState) {
         _mesa_update_state( ctx );
+
+         if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
+            (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glBegin (invalid vertex/fragment program)");
+            return;
+         }
+
         if (!(tnl->Driver.NotifyBegin && 
               tnl->Driver.NotifyBegin( ctx, mode )))
-            ctx->Exec->Begin(mode);
+            CALL_Begin(ctx->Exec, (mode));
         return;
       }
 
@@ -812,6 +835,7 @@ static void _tnl_exec_vtxfmt_init( GLcontext *ctx )
 void _tnl_FlushVertices( GLcontext *ctx, GLuint flags )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
+   (void) flags;
 
    if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
       return;
@@ -844,11 +868,13 @@ static void _tnl_current_init( GLcontext *ctx )
         ctx->Light.Material.Attrib[i];
 
    tnl->vtx.current[_TNL_ATTRIB_INDEX] = &ctx->Current.Index;
+   tnl->vtx.current[_TNL_ATTRIB_EDGEFLAG] = &tnl->vtx.CurrentFloatEdgeFlag;
 }
 
 static struct _tnl_dynfn *no_codegen( GLcontext *ctx, int key )
 {
-   return 0;
+   (void) ctx; (void) key;
+   return NULL;
 }
 
 void _tnl_vtx_init( GLcontext *ctx )
@@ -883,15 +909,17 @@ void _tnl_vtx_init( GLcontext *ctx )
       choose[ERROR_ATTRIB][2] = error_attrib;
       choose[ERROR_ATTRIB][3] = error_attrib;
 
+#ifdef USE_X86_ASM
       if (tnl->AllowCodegen) {
          _tnl_x86choosers(choose, do_choose); /* x86 INIT_CHOOSERS */
       }
+#endif
 
       _tnl_generic_attr_table_init( generic_attr_func );
    }
 
    for (i = 0; i < _TNL_ATTRIB_INDEX; i++)
-      _mesa_vector4f_init( &tmp->Attribs[i], 0, 0);
+      _mesa_vector4f_init( &tmp->Attribs[i], 0, NULL);
 
    for (i = 0; i < 4; i++) {
       make_empty_list( &tnl->vtx.cache.Vertex[i] );
@@ -900,14 +928,18 @@ void _tnl_vtx_init( GLcontext *ctx )
       tnl->vtx.gen.Attribute[i] = no_codegen;
    }
 
+#ifdef USE_X86_ASM
    _tnl_InitX86Codegen( &tnl->vtx.gen );
+#endif
 
    _tnl_current_init( ctx );
    _tnl_exec_vtxfmt_init( ctx );
    _tnl_generic_exec_vtxfmt_init( ctx );
+#ifdef USE_X86_ASM
    if (tnl->AllowCodegen) {
       _tnl_x86_exec_vtxfmt_init( ctx ); /* x86 DISPATCH_ATTRFV */
    }
+#endif
 
    _mesa_install_exec_vtxfmt( ctx, &tnl->exec_vtxfmt );