Am Mo, den 20.12.2004 schrieb Keith Whitwell um 16:54:
[snip]
> Hi Felix,
> 
> Your patch looks good to me.  If you're looking for ways to avoid the 
> indirect function call, probably the way to do it is to somehow try and 
> get onto the DO_FALLBACK path.  This is difficult for PTEX vertices as 
> there is no GL state to say 'OK, I'm going to do PTEX vertices now', it 
> is just based on what comes down the pipe, and we don't have a very good 
> set of triggers for that.
> 
> But, if you could find a way to detect that you were expecting PTEX 
> vertices, then the i915 driver (intel_tris.c, intel_atten_point()) might 
> be a model for how to do this.

I had thought about this once, but then I got lost trying to figure out
when and in which order some driver callbacks get called by Mesa. And
since there was no Mesa state for projective textures anyway I gave it
up and took the easy way first.

Your comment made me try a little harder and now it works. :) It's quite
a mess though. I first tried to detect projective textures in
savageRunPipeline, but that doesn't work because apparently the
dimension of tex coords can change in the pipeline. I had a case where
2D texcoords went in and 4D (projective) texcoords came out of the
pipeline.

So now I check for the ptexHack in savageStartRender, and if the
ptexHack state bit changes I call savageChooseRenderSate again. This
works. I hope this is the last patch (attached). I'm going to commit it
after some more testing, unless you find some problem I overlooked.

> 
> Keith

Cheers,
  Felix

-- 
| Felix K�hling <[EMAIL PROTECTED]>                     http://fxk.de.vu |
| PGP Fingerprint: 6A3C 9566 5B30 DDED 73C3  B152 151C 5CC1 D888 E595 |
? core.2742
? core.2751
? debugfallback.diff
? depend
? diff-20041215
? savage_mesa_20041019.diff
? savage_projtex.diff
? savage_projtex2.diff
? savage_projtex3.diff
? savage_texnorm.diff
? savagestate.diff
? savagetris.diff
? throttle_and_front.diff
Index: savagecontext.h
===================================================================
RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/savage/savagecontext.h,v
retrieving revision 1.11
diff -u -r1.11 savagecontext.h
--- savagecontext.h	17 Dec 2004 15:55:17 -0000	1.11
+++ savagecontext.h	21 Dec 2004 15:58:26 -0000
@@ -141,6 +141,7 @@
     /* Manage our own state */
     GLuint new_state; 
     GLuint new_gl_state;
+    GLboolean ptexHack;
 
     GLuint BCIBase;  
     GLuint MMIO_BASE;
@@ -179,6 +180,7 @@
    GLenum render_primitive;
 
    GLuint DrawPrimitiveCmd;
+   GLuint HwVertexSize;
 
    /* Fallback rasterization functions 
     */
Index: savagedma.c
===================================================================
RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/savage/savagedma.c,v
retrieving revision 1.4
diff -u -r1.4 savagedma.c
--- savagedma.c	14 Dec 2004 22:37:46 -0000	1.4
+++ savagedma.c	21 Dec 2004 15:58:26 -0000
@@ -312,8 +312,8 @@
 };
 
 void savageFakeVertices (savageContextPtr imesa, drmBufPtr buffer) {
-    GLuint vertexStride = imesa->vertex_size; /* stride in dwords */
-    GLuint vertexSize = imesa->vertex_size; /* the real vertex size in dwords */
+    GLuint vertexStride = imesa->HwVertexSize; /* stride in dwords */
+    GLuint vertexSize = imesa->HwVertexSize; /* the real vertex size in dwords */
     GLuint nVertices = buffer->used / (vertexStride*4);
     u_int32_t *data = (u_int32_t*)buffer->address;
     u_int32_t vertexFormat = imesa->DrawPrimitiveCmd & SAVAGE_HW_SKIPFLAGS;
Index: savagetris.c
===================================================================
RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/savage/savagetris.c,v
retrieving revision 1.16
diff -u -r1.16 savagetris.c
--- savagetris.c	17 Dec 2004 15:55:17 -0000	1.16
+++ savagetris.c	21 Dec 2004 15:58:26 -0000
@@ -79,11 +79,11 @@
 #if defined (USE_X86_ASM)
 #define EMIT_VERT( j, vb, vertex_size, start, v )	\
 do {	int __tmp;					\
-        vb += start;					\
+	 vb += start;					\
 	__asm__ __volatile__( "rep ; movsl"		\
 			 : "=%c" (j), "=D" (vb), "=S" (__tmp)		\
 			 : "0" (vertex_size-start),	\
-			   "D" ((long)vb), 		\
+			   "D" ((long)vb),		\
 			   "S" ((long)&v->ui[start]));	\
 } while (0)
 #else
@@ -99,7 +99,7 @@
 					     savageVertexPtr v0,
 					     savageVertexPtr v1,
 					     savageVertexPtr v2) {
-   GLuint vertsize = imesa->vertex_size;
+   GLuint vertsize = imesa->HwVertexSize;
    u_int32_t *vb = savageAllocDmaLow (imesa, 3*4*vertsize);
    GLuint j;
 
@@ -113,7 +113,7 @@
 					 savageVertexPtr v1,
 					 savageVertexPtr v2,
 					 savageVertexPtr v3) {
-   GLuint vertsize = imesa->vertex_size;
+   GLuint vertsize = imesa->HwVertexSize;
    u_int32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
    GLuint j;
 
@@ -127,7 +127,7 @@
 
 static __inline__ void savage_draw_point (savageContextPtr imesa,
 					  savageVertexPtr tmp) {
-   GLuint vertsize = imesa->vertex_size;
+   GLuint vertsize = imesa->HwVertexSize;
    u_int32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
    const GLfloat x = tmp->v.x;
    const GLfloat y = tmp->v.y;
@@ -162,7 +162,7 @@
 static __inline__ void savage_draw_line (savageContextPtr imesa,
 					 savageVertexPtr v0,
 					 savageVertexPtr v1 ) {
-   GLuint vertsize = imesa->vertex_size;
+   GLuint vertsize = imesa->HwVertexSize;
    u_int32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
    GLfloat width = imesa->glCtx->Line._Width;
    GLfloat dx, dy, ix, iy;
@@ -200,6 +200,117 @@
    *(float *)&vb[1] = v1->v.y + iy;
    EMIT_VERT (j, vb, vertsize, 2, v1);
 } 
+
+/* Fallback drawing functions for the ptex hack. Code duplication
+ * (especially lines and points) isn't beautiful, but I didn't feel
+ * like inventing yet another template. :-/
+ */
+#define PTEX_VERTEX( j, tmp, vertex_size, start, v)	\
+do {							\
+   GLfloat rhw = 1.0 / v->f[vertex_size];		\
+   for ( j = start ; j < vertex_size ; j++ )		\
+      tmp.f[j] = v->f[j];				\
+   tmp.f[3] *= v->f[vertex_size];			\
+   tmp.f[vertex_size-2] *= rhw;				\
+   tmp.f[vertex_size-1] *= rhw;				\
+} while (0)
+
+static void __inline__ savage_ptex_tri (savageContextPtr imesa,
+					savageVertexPtr v0,
+					savageVertexPtr v1,
+					savageVertexPtr v2) {
+   GLuint vertsize = imesa->HwVertexSize;
+   u_int32_t *vb = savageAllocDmaLow (imesa, 3*4*vertsize);
+   savageVertex tmp;
+   GLuint j;
+
+   PTEX_VERTEX (j, tmp, vertsize, 0, v0); EMIT_VERT (j, vb, vertsize, 0, &tmp);
+   PTEX_VERTEX (j, tmp, vertsize, 0, v1); EMIT_VERT (j, vb, vertsize, 0, &tmp);
+   PTEX_VERTEX (j, tmp, vertsize, 0, v2); EMIT_VERT (j, vb, vertsize, 0, &tmp);
+}
+
+static __inline__ void savage_ptex_line (savageContextPtr imesa,
+					 savageVertexPtr v0,
+					 savageVertexPtr v1 ) {
+   GLuint vertsize = imesa->HwVertexSize;
+   u_int32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
+   GLfloat width = imesa->glCtx->Line._Width;
+   GLfloat dx, dy, ix, iy;
+   savageVertex tmp0, tmp1;
+   GLuint j;
+
+   PTEX_VERTEX (j, tmp0, vertsize, 2, v0);
+   PTEX_VERTEX (j, tmp1, vertsize, 2, v1);
+
+   dx = v0->v.x - v1->v.x;
+   dy = v0->v.y - v1->v.y;
+
+   ix = width * .5; iy = 0;
+   if (dx * dx > dy * dy) {
+      iy = ix; ix = 0;
+   }
+
+   *(float *)&vb[0] = v0->v.x - ix;
+   *(float *)&vb[1] = v0->v.y - iy;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp0);
+
+   *(float *)&vb[0] = v1->v.x + ix;
+   *(float *)&vb[1] = v1->v.y + iy;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp1);
+
+   *(float *)&vb[0] = v0->v.x + ix;
+   *(float *)&vb[1] = v0->v.y + iy;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp0);
+
+   *(float *)&vb[0] = v0->v.x - ix;
+   *(float *)&vb[1] = v0->v.y - iy;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp0);
+
+   *(float *)&vb[0] = v1->v.x - ix;
+   *(float *)&vb[1] = v1->v.y - iy;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp1);
+
+   *(float *)&vb[0] = v1->v.x + ix;
+   *(float *)&vb[1] = v1->v.y + iy;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp1);
+} 
+
+static __inline__ void savage_ptex_point (savageContextPtr imesa,
+					  savageVertexPtr v0) {
+   GLuint vertsize = imesa->HwVertexSize;
+   u_int32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
+   const GLfloat x = v0->v.x;
+   const GLfloat y = v0->v.y;
+   const GLfloat sz = imesa->glCtx->Point._Size * .5;
+   savageVertex tmp;
+   GLuint j;
+
+   PTEX_VERTEX (j, tmp, vertsize, 2, v0);
+
+   *(float *)&vb[0] = x - sz;
+   *(float *)&vb[1] = y - sz;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp);
+
+   *(float *)&vb[0] = x + sz;
+   *(float *)&vb[1] = y - sz;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp);
+
+   *(float *)&vb[0] = x + sz;
+   *(float *)&vb[1] = y + sz;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp);
+
+   *(float *)&vb[0] = x + sz;
+   *(float *)&vb[1] = y + sz;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp);
+
+   *(float *)&vb[0] = x - sz;
+   *(float *)&vb[1] = y + sz;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp);
+
+   *(float *)&vb[0] = x - sz;
+   *(float *)&vb[1] = y - sz;
+   EMIT_VERT (j, vb, vertsize, 2, &tmp);
+}
  
 /***********************************************************************
  *          Macros for t_dd_tritmp.h to draw basic primitives          *
@@ -591,6 +702,18 @@
    GLuint flags = ctx->_TriangleCaps;
    GLuint index = 0;
 
+   /* Hook in fallback functions for the ptex hack. Do this first, so
+    * that a real fallback will overwrite them with the respective
+    * savage_fallback_... function.
+    */
+   if (imesa->ptexHack) {
+      /* Do textures make sense with points? */
+      imesa->draw_point = savage_ptex_point;
+      imesa->draw_line = savage_ptex_line;
+      imesa->draw_tri = savage_ptex_tri;
+      index |= SAVAGE_FALLBACK_BIT;
+   }
+
    if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
       imesa->draw_point = savage_draw_point;
       imesa->draw_line = savage_draw_line;
@@ -604,7 +727,7 @@
 
       /* Hook in fallbacks for specific primitives.
        */
-      if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
+      if (flags & ANY_FALLBACK_FLAGS) {
 	 if (flags & POINT_FALLBACK) imesa->draw_point = savage_fallback_point;
 	 if (flags & LINE_FALLBACK)  imesa->draw_line = savage_fallback_line;
 	 if (flags & TRI_FALLBACK)   imesa->draw_tri = savage_fallback_tri;
@@ -706,6 +829,29 @@
    }
 }
 
+/* Check if projective texture coordinates are used and if we can fake
+ * them. Fallback to swrast we can't. Returns GL_TRUE if projective
+ * texture coordinates must be faked, GL_FALSE otherwise.
+ */
+static GLboolean savageCheckPTexHack( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint index = tnl->render_inputs;
+
+   if (index & _TNL_BIT_TEX(0)) {
+      if (VB->TexCoordPtr[0]->size == 4 &&
+	  (index & _TNL_BITS_TEX_ANY) == _TNL_BIT_TEX(0)) {
+	 return GL_TRUE; /* apply ptex hack */
+      } else if (VB->TexCoordPtr[0]->size > 2)
+	 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
+   }
+   if ((index & _TNL_BIT_TEX(1)) && VB->TexCoordPtr[1]->size > 2)
+      FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
+
+   return GL_FALSE; /* don't apply ptex hack */
+}
+
 
 #define EMIT_ATTR( ATTR, STYLE, INDEX, SKIP )				\
 do {									\
@@ -724,17 +870,19 @@
    imesa->vertex_attr_count++;						\
 } while (0)
 
-#define SAVAGE_EMIT_XYZ 0x0001
-#define SAVAGE_EMIT_W   0x0002
-#define SAVAGE_EMIT_C0  0x0004
-#define SAVAGE_EMIT_C1  0x0008
-#define SAVAGE_EMIT_FOG 0x0010
-#define SAVAGE_EMIT_S0  0x0020
-#define SAVAGE_EMIT_T0  0x0040
-#define SAVAGE_EMIT_ST0 0x0060
-#define SAVAGE_EMIT_S1  0x0080
-#define SAVAGE_EMIT_T1  0x0100
-#define SAVAGE_EMIT_ST1 0x0180
+#define SAVAGE_EMIT_XYZ  0x0001
+#define SAVAGE_EMIT_W    0x0002
+#define SAVAGE_EMIT_C0   0x0004
+#define SAVAGE_EMIT_C1   0x0008
+#define SAVAGE_EMIT_FOG  0x0010
+#define SAVAGE_EMIT_S0   0x0020
+#define SAVAGE_EMIT_T0   0x0040
+#define SAVAGE_EMIT_Q0   0x0080
+#define SAVAGE_EMIT_ST0  0x0060
+#define SAVAGE_EMIT_STQ0 0x00e0
+#define SAVAGE_EMIT_S1   0x0100
+#define SAVAGE_EMIT_T1   0x0200
+#define SAVAGE_EMIT_ST1  0x0300
 
 
 static void savageRenderStart( GLcontext *ctx )
@@ -745,10 +893,26 @@
    GLuint index = tnl->render_inputs;
    GLuint setupIndex = SAVAGE_EMIT_XYZ;
    GLuint drawCmd = SAVAGE_HW_SKIPFLAGS;
+   GLboolean ptexHack;
    if (imesa->savageScreen->chipset < S3_SAVAGE4)
       drawCmd &= ~SAVAGE_HW_NO_UV1;
    drawCmd &= ~SAVAGE_HW_NO_Z; /* all mesa vertices have a z coordinate */
 
+   /* Check if we need to apply the ptex hack. Choose a new render
+    * state if necessary. (Note: this can't be done in
+    * savageRunPipeline, since the number of vertex coordinates can
+    * change in the pipeline. texmat or texgen or both?) */
+   ptexHack = savageCheckPTexHack( ctx );
+   if (ptexHack != imesa->ptexHack) {
+      imesa->ptexHack = ptexHack;
+      savageChooseRenderState (ctx);
+   }
+   /* Handle fallback cases identified in savageCheckPTexHack. */
+   if (SAVAGE_CONTEXT(ctx)->Fallback) {
+      tnl->Driver.Render.Start(ctx);
+      return;
+   }
+
    /* Important:
     */
    VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
@@ -779,21 +943,20 @@
    }
 
    if (index & _TNL_BIT_TEX(0)) {
-      if (VB->TexCoordPtr[0]->size > 2) {
-	 /* projective textures are not supported by the hardware */
-	 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
-      }
-      if (VB->TexCoordPtr[0]->size == 2)
+      if (ptexHack)
+	 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_HW_NO_UV0);
+      else if (VB->TexCoordPtr[0]->size > 2)
+	 assert (0); /* should be caught by savageCheckPTexHack */
+      else if (VB->TexCoordPtr[0]->size == 2)
 	 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, SAVAGE_EMIT_ST0, SAVAGE_HW_NO_UV0 );
       else
 	 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F, SAVAGE_EMIT_S0, SAVAGE_HW_NO_U0 );
    }
    if (index & _TNL_BIT_TEX(1)) {
-      if (VB->TexCoordPtr[1]->size > 2) {
-	 /* projective textures are not supported by the hardware */
-	 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
-      }
-      if (VB->TexCoordPtr[1]->size == 2)
+      if (VB->TexCoordPtr[1]->size > 2)
+	 /* Projective textures are not supported by the hardware */
+	 assert (0); /* should be caught by savageCheckPTexHack */
+      else if (VB->TexCoordPtr[1]->size == 2)
 	 EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, SAVAGE_EMIT_ST1, SAVAGE_HW_NO_UV1 );
       else
 	 EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_1F, SAVAGE_EMIT_S1, SAVAGE_HW_NO_U1 );
@@ -811,14 +974,23 @@
       imesa->SetupIndex = setupIndex;
 
       imesa->DrawPrimitiveCmd = drawCmd;
-   }
+      imesa->HwVertexSize = imesa->vertex_size;
 
-   if (!SAVAGE_CONTEXT(ctx)->Fallback) {
-      /* Update hardware state and get the lock */
-      savageDDRenderStart( ctx );
-   } else {
-      tnl->Driver.Render.Start(ctx);
+      if (setupIndex & SAVAGE_EMIT_Q0) {
+	 /* The vertex setup code emits homogenous texture
+	  * coordinates. They are converted to normal 2D coords by
+	  * savage_ptex_tri/line/point. Now we have two different
+	  * vertex sizes. Functions that emit vertices to the hardware
+	  * need to use HwVertexSize, anything that manipulates the
+	  * vertices generated by t_vertex uses vertex_size. */
+	 imesa->HwVertexSize--;
+	 assert (imesa->ptexHack);
+      } else
+	 assert (!imesa->ptexHack);
    }
+
+   /* Update hardware state and get the lock */
+   savageDDRenderStart( ctx );
 }
 
 static void savageRenderFinish( GLcontext *ctx )

Reply via email to