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) {