Hi,

I'm trying to get projective textures working on hardware that doesn't
support homogenous texture coordinates with the new vertex setup code
(t_vertex.[ch]). The problem with this is that the W coordinate of the
hardware vertex must be computed from two vertex attributes, which is
why the new vertex setup code can't generated it directly.

The solution I'm proposing emits homogenous texture coordinates and then
calls a vertex post-processing hook in the driver that can compute W and
2D tex coords suitable for my crippled hardware from homogenous tex
coords.

I'm attaching two patches. The first one implements the
driver-independent functionality for hooking up a post-processing
function. The second one demonstrates the changes to the Savage driver
to support projective texturing using the post-processing hook.

I'd appreciate feedback (Keith?) if this is good for CVS or if there are
other/better ideas for solving the same problem.

Thanks,
  Felix

-- 
| Felix Kühling <[EMAIL PROTECTED]>                     http://fxk.de.vu |
| PGP Fingerprint: 6A3C 9566 5B30 DDED 73C3  B152 151C 5CC1 D888 E595 |
--- ./t_context.h.~1.64.~	2004-07-23 16:18:37.000000000 +0200
+++ ./t_context.h	2004-12-17 19:56:09.000000000 +0100
@@ -539,6 +539,10 @@
 			       GLuint start, 
 			       GLuint end, void *dest );
 
+typedef void (*tnl_postproc_func)( GLcontext *ctx,
+				   GLuint start,
+				   GLuint end, void *dest );
+
 
 /**
  * Describes how to convert/move a vertex attribute from a vertex array
@@ -631,6 +635,7 @@
    tnl_emit_func emit;
    tnl_interp_func interp;
    tnl_copy_pv_func copy_pv;
+   tnl_postproc_func postproc;
 
    struct tnl_clipspace_codegen codegen;
 };
--- ./t_vertex.c.~1.24.~	2004-10-27 11:12:58.000000000 +0200
+++ ./t_vertex.c	2004-12-17 20:07:30.000000000 +0100
@@ -1177,6 +1177,7 @@
    vtx->emit = 0;
    vtx->interp = choose_interp_func;
    vtx->copy_pv = choose_copy_pv_func;
+   vtx->postproc = 0;
    vtx->new_inputs = ~0;
 
    for (j = 0, i = 0; i < nr; i++) {
@@ -1225,6 +1226,12 @@
 }
 
 
+void _tnl_install_postproc( GLcontext *ctx, tnl_postproc_func func )
+{
+   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+   vtx->postproc = func;
+}
+
 
 void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs )
 {
@@ -1245,8 +1252,11 @@
    newinputs |= vtx->new_inputs;
    vtx->new_inputs = 0;
 
-   if (newinputs) 
+   if (newinputs) {
       do_emit( ctx, start, end, vDest );
+      if (vtx->postproc)
+	 vtx->postproc( ctx, start, end, vDest );
+   }
 }
 
 
--- ./t_vertex.h.~1.12.~	2004-10-27 11:12:58.000000000 +0200
+++ ./t_vertex.h	2004-12-17 20:07:15.000000000 +0100
@@ -103,6 +103,9 @@
 				  GLuint nr, const GLfloat *vp,
 				  GLuint unpacked_size );
 
+extern void _tnl_install_postproc( GLcontext *ctx,
+				   tnl_postproc_func func);
+
 
 
 
--- ./savagedma.c.~1.4.~	2004-12-15 16:37:19.000000000 +0100
+++ ./savagedma.c	2004-12-17 21:35:56.000000000 +0100
@@ -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;
--- ./savagecontext.h.~1.11.~	2004-12-17 16:06:50.000000000 +0100
+++ ./savagecontext.h	2004-12-17 20:35:19.000000000 +0100
@@ -179,6 +179,7 @@
    GLenum render_primitive;
 
    GLuint DrawPrimitiveCmd;
+   GLuint HwVertexSize;
 
    /* Fallback rasterization functions 
     */
--- ./savagetris.c.~1.16.~	2004-12-17 16:34:52.000000000 +0100
+++ ./savagetris.c	2004-12-17 21:57:58.000000000 +0100
@@ -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;
@@ -724,19 +724,35 @@
    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 savageFakePTex( GLcontext *ctx, GLuint start, GLuint end,
+			    void *dest ) {
+   savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+   GLfloat *vDest = (GLfloat *)dest;
+   GLuint size = imesa->vertex_size, i;
+
+   for (i = start; i < end; ++i, vDest += size) {
+      GLfloat rhw = 1.0 / vDest[size-1];
+      vDest[3] *= vDest[size-1];
+      vDest[size-3] *= rhw;
+      vDest[size-2] *= rhw;
+   }
+}
+
 static void savageRenderStart( GLcontext *ctx )
 {
    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
@@ -779,21 +795,22 @@
    }
 
    if (index & _TNL_BIT_TEX(0)) {
-      if (VB->TexCoordPtr[0]->size > 2) {
+      if (VB->TexCoordPtr[0]->size == 4 &&
+	  (index & _TNL_BITS_TEX_ANY) == _TNL_BIT_TEX(0))
+	 EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_HW_NO_UV0);
+      else 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)
+      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) {
+      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)
+      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,6 +828,12 @@
       imesa->SetupIndex = setupIndex;
 
       imesa->DrawPrimitiveCmd = drawCmd;
+      imesa->HwVertexSize = imesa->vertex_size;
+
+      if (imesa->SetupIndex & SAVAGE_EMIT_Q0) {
+	 _tnl_install_postproc( ctx, savageFakePTex );
+	 imesa->HwVertexSize--;
+      }
    }
 
    if (!SAVAGE_CONTEXT(ctx)->Fallback) {

Reply via email to