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 )