- Fake projective textures on a single texture unit. A fallback is only

needed if a second texture unit is enabled.
- Also worked around an application bug in Chromium B.S.U.: it sends 3D
  texture coordinates while only a 2D texture is enabled. This used to
  trigger a PTEX fallback. Now the 3rd coordinate is just ignored.
- Fixed the _savage_texnorm_stage to never normalize homogenous texture
  coordinates.
This commit is contained in:
Felix Kuehling
2004-12-22 00:21:32 +00:00
parent 8bdaa927eb
commit 80dd3c7917
3 changed files with 220 additions and 43 deletions
@@ -141,6 +141,7 @@ struct savage_context_t {
/* Manage our own state */
GLuint new_state;
GLuint new_gl_state;
GLboolean ptexHack;
GLuint BCIBase;
GLuint MMIO_BASE;
@@ -179,6 +180,7 @@ struct savage_context_t {
GLenum render_primitive;
GLuint DrawPrimitiveCmd;
GLuint HwVertexSize;
/* Fallback rasterization functions
*/
+2 -2
View File
@@ -312,8 +312,8 @@ static drmBuf vertex_buffer = {
};
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;
+216 -41
View File
@@ -77,14 +77,14 @@ static GLenum reduced_prim[GL_POLYGON+1] = {
***********************************************************************/
#if defined (USE_X86_ASM)
#define EMIT_VERT( j, vb, vertex_size, start, v ) \
do { int __tmp; \
vb += start; \
__asm__ __volatile__( "rep ; movsl" \
: "=%c" (j), "=D" (vb), "=S" (__tmp) \
: "0" (vertex_size-start), \
"D" ((long)vb), \
"S" ((long)&v->ui[start])); \
#define EMIT_VERT( j, vb, vertex_size, start, v ) \
do { int __tmp; \
vb += start; \
__asm__ __volatile__( "rep ; movsl" \
: "=%c" (j), "=D" (vb), "=S" (__tmp) \
: "0" (vertex_size-start), \
"D" ((long)vb), \
"S" ((long)&(v)->ui[start])); \
} while (0)
#else
#define EMIT_VERT( j, vb, vertex_size, start, v ) \
@@ -99,7 +99,7 @@ static void __inline__ savage_draw_triangle (savageContextPtr imesa,
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 @@ static void __inline__ savage_draw_quad (savageContextPtr imesa,
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 void __inline__ savage_draw_quad (savageContextPtr imesa,
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_point (savageContextPtr imesa,
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 @@ static __inline__ void savage_draw_line (savageContextPtr imesa,
*(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 @@ static void savageChooseRenderState(GLcontext *ctx)
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 @@ static void savageChooseRenderState(GLcontext *ctx)
/* 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,28 @@ static void savageRenderPrimitive( GLcontext *ctx, GLenum prim )
}
}
/* 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) && VB->TexCoordPtr[0]->size == 4) {
if ((index & _TNL_BITS_TEX_ANY) == _TNL_BIT_TEX(0))
return GL_TRUE; /* apply ptex hack */
else
FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
}
if ((index & _TNL_BIT_TEX(1)) && VB->TexCoordPtr[1]->size == 4)
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 +869,19 @@ do { \
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 +892,26 @@ static void savageRenderStart( GLcontext *ctx )
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 +942,22 @@ static void savageRenderStart( GLcontext *ctx )
}
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 == 4)
assert (0); /* should be caught by savageCheckPTexHack */
else if (VB->TexCoordPtr[0]->size >= 2)
/* The chromium menu emits some 3D tex coords even though no
* 3D texture is enabled. Ignore the 3rd coordinate. */
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 == 4)
/* 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 +975,23 @@ static void savageRenderStart( GLcontext *ctx )
imesa->SetupIndex = setupIndex;
imesa->DrawPrimitiveCmd = drawCmd;
imesa->HwVertexSize = imesa->vertex_size;
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);
}
if (!SAVAGE_CONTEXT(ctx)->Fallback) {
/* Update hardware state and get the lock */
savageDDRenderStart( ctx );
} else {
tnl->Driver.Render.Start(ctx);
}
/* Update hardware state and get the lock */
savageDDRenderStart( ctx );
}
static void savageRenderFinish( GLcontext *ctx )
@@ -959,7 +1132,9 @@ static GLboolean run_texnorm_stage( GLcontext *ctx,
return GL_TRUE;
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
if (!(stage->inputs & stage->changed_inputs & VERT_BIT_TEX(i)))
if (!(stage->inputs & stage->changed_inputs & VERT_BIT_TEX(i)) ||
VB->TexCoordPtr[i]->size == 4)
/* Never try to normalize homogenous tex coords! */
continue;
GLuint reallyEnabled = ctx->Texture.Unit[i]._ReallyEnabled;