diff options
Diffstat (limited to 'xc/lib/GL/mesa/src/drv/radeon/radeon_state.c')
-rw-r--r-- | xc/lib/GL/mesa/src/drv/radeon/radeon_state.c | 1648 |
1 files changed, 1232 insertions, 416 deletions
diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c index 9077ee43f..5c46fc902 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c @@ -25,16 +25,12 @@ * * Authors: * Gareth Hughes <gareth@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> */ -#include "radeon_context.h" -#include "radeon_state.h" -#include "radeon_ioctl.h" -#include "radeon_tris.h" -#include "radeon_vb.h" -#include "radeon_tex.h" - +#include "glheader.h" +#include "imports.h" +#include "api_arrayelt.h" #include "mmath.h" #include "enums.h" #include "colormac.h" @@ -46,62 +42,83 @@ #include "swrast_setup/swrast_setup.h" +#include "radeon_context.h" +#include "radeon_ioctl.h" +#include "radeon_state.h" +#include "radeon_tcl.h" +#include "radeon_tex.h" +#include "radeon_swtcl.h" +#include "radeon_vtxfmt.h" + + +#define MODEL_PROJ 0 +#define MODEL 1 +#define MODEL_IT 2 +#define TEXMAT_0 3 +#define TEXMAT_1 4 +#define TEXMAT_2 5 + + /* ============================================================= * Alpha blending */ -static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLchan ref ) +static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC]; + GLubyte refByte; + + CLAMPED_FLOAT_TO_UBYTE(refByte, ref); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); - rmesa->state.hw.context.pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | - RADEON_REF_ALPHA_MASK); + pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | RADEON_REF_ALPHA_MASK); + pp_misc |= (refByte & RADEON_REF_ALPHA_MASK); switch ( func ) { case GL_NEVER: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_FAIL; + pp_misc |= RADEON_ALPHA_TEST_FAIL; break; case GL_LESS: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_LESS; + pp_misc |= RADEON_ALPHA_TEST_LESS; break; case GL_EQUAL: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_EQUAL; + pp_misc |= RADEON_ALPHA_TEST_EQUAL; break; case GL_LEQUAL: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_LEQUAL; + pp_misc |= RADEON_ALPHA_TEST_LEQUAL; break; case GL_GREATER: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_GREATER; + pp_misc |= RADEON_ALPHA_TEST_GREATER; break; case GL_NOTEQUAL: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_NEQUAL; + pp_misc |= RADEON_ALPHA_TEST_NEQUAL; break; case GL_GEQUAL: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_GEQUAL; + pp_misc |= RADEON_ALPHA_TEST_GEQUAL; break; case GL_ALWAYS: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_PASS; + pp_misc |= RADEON_ALPHA_TEST_PASS; break; } - rmesa->state.hw.context.pp_misc |= (ref & RADEON_REF_ALPHA_MASK); + rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc; } static void radeonBlendEquation( GLcontext *ctx, GLenum mode ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint b = rmesa->state.hw.context.rb3d_blendcntl & ~RADEON_COMB_FCN_MASK; + GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK; GLboolean fallback = GL_FALSE; switch ( mode ) { - case GL_FUNC_ADD_EXT: + case GL_FUNC_ADD: case GL_LOGIC_OP: b |= RADEON_COMB_FCN_ADD_CLAMP; break; - case GL_FUNC_SUBTRACT_EXT: + case GL_FUNC_SUBTRACT: b |= RADEON_COMB_FCN_SUB_CLAMP; break; @@ -112,12 +129,12 @@ static void radeonBlendEquation( GLcontext *ctx, GLenum mode ) FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, fallback ); if ( !fallback ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_blendcntl = b; + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b; if ( ctx->Color.ColorLogicOpEnabled ) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; } } } @@ -125,8 +142,8 @@ static void radeonBlendEquation( GLcontext *ctx, GLenum mode ) static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint b = rmesa->state.hw.context.rb3d_blendcntl & ~(RADEON_SRC_BLEND_MASK | - RADEON_DST_BLEND_MASK); + GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & + ~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK); GLboolean fallback = GL_FALSE; switch ( ctx->Color.BlendSrcRGB ) { @@ -142,6 +159,12 @@ static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) case GL_ONE_MINUS_DST_COLOR: b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR; break; + case GL_SRC_COLOR: + b |= RADEON_SRC_BLEND_GL_SRC_COLOR; + break; + case GL_ONE_MINUS_SRC_COLOR: + b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR; + break; case GL_SRC_ALPHA: b |= RADEON_SRC_BLEND_GL_SRC_ALPHA; break; @@ -184,6 +207,12 @@ static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) case GL_ONE_MINUS_SRC_ALPHA: b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA; break; + case GL_DST_COLOR: + b |= RADEON_DST_BLEND_GL_DST_COLOR; + break; + case GL_ONE_MINUS_DST_COLOR: + b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR; + break; case GL_DST_ALPHA: b |= RADEON_DST_BLEND_GL_DST_ALPHA; break; @@ -200,8 +229,8 @@ static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, fallback ); if ( !fallback ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_blendcntl = b; + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b; } } @@ -221,33 +250,33 @@ static void radeonDepthFunc( GLcontext *ctx, GLenum func ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_zstencilcntl &= ~RADEON_Z_TEST_MASK; + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK; switch ( ctx->Depth.Func ) { case GL_NEVER: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_NEVER; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEVER; break; case GL_LESS: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_LESS; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LESS; break; case GL_EQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_EQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_EQUAL; break; case GL_LEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_LEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LEQUAL; break; case GL_GREATER: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_GREATER; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GREATER; break; case GL_NOTEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_NEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEQUAL; break; case GL_GEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_GEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GEQUAL; break; case GL_ALWAYS: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_ALWAYS; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_ALWAYS; break; } } @@ -256,19 +285,19 @@ static void radeonDepthFunc( GLcontext *ctx, GLenum func ) static void radeonDepthMask( GLcontext *ctx, GLboolean flag ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( ctx->Depth.Mask ) { - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_WRITE_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_WRITE_ENABLE; } else { - rmesa->state.hw.context.rb3d_zstencilcntl &= ~RADEON_Z_WRITE_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_WRITE_ENABLE; } } static void radeonClearDepth( GLcontext *ctx, GLclampd d ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint format = (rmesa->state.hw.context.rb3d_zstencilcntl & + GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] & RADEON_DEPTH_FORMAT_MASK); switch ( format ) { @@ -286,22 +315,156 @@ static void radeonClearDepth( GLcontext *ctx, GLclampd d ) * Fog */ + static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLchan c[4]; + union { int i; float f; } c, d; + GLchan col[4]; + + c.i = rmesa->hw.fog.cmd[FOG_C]; + d.i = rmesa->hw.fog.cmd[FOG_D]; + + switch (pname) { + case GL_FOG_MODE: + if (!ctx->Fog.Enabled) + return; + RADEON_STATECHANGE(rmesa, tcl); + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK; + switch (ctx->Fog.Mode) { + case GL_LINEAR: + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR; + if (ctx->Fog.Start == ctx->Fog.End) { + c.f = 1.0F; + d.f = 1.0F; + } + else { + c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); + d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start); + } + break; + case GL_EXP: + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP; + c.f = 0.0; + d.f = ctx->Fog.Density; + break; + case GL_EXP2: + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2; + c.f = 0.0; + d.f = -(ctx->Fog.Density * ctx->Fog.Density); + break; + default: + return; + } + break; + case GL_FOG_DENSITY: + switch (ctx->Fog.Mode) { + case GL_EXP: + c.f = 0.0; + d.f = ctx->Fog.Density; + break; + case GL_EXP2: + c.f = 0.0; + d.f = -(ctx->Fog.Density * ctx->Fog.Density); + break; + default: + break; + } + break; + case GL_FOG_START: + case GL_FOG_END: + if (ctx->Fog.Mode == GL_LINEAR) { + if (ctx->Fog.Start == ctx->Fog.End) { + c.f = 1.0F; + d.f = 1.0F; + } else { + c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); + d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start); + } + } + break; + case GL_FOG_COLOR: + RADEON_STATECHANGE( rmesa, ctx ); + UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color ); + rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = + radeonPackColor( 4, col[0], col[1], col[2], 0 ); + break; + case GL_FOG_COORDINATE_SOURCE_EXT: + /* What to do? + */ + break; + default: + return; + } - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - UNCLAMPED_FLOAT_TO_RGB_CHAN( c, ctx->Fog.Color ); - rmesa->state.hw.context.pp_fog_color = - radeonPackColor( 4, c[0], c[1], c[2], 0 ); + if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) { + RADEON_STATECHANGE( rmesa, fog ); + rmesa->hw.fog.cmd[FOG_C] = c.i; + rmesa->hw.fog.cmd[FOG_D] = d.i; + } } /* ============================================================= - * Clipping + * Scissoring */ + +static GLboolean intersect_rect( XF86DRIClipRectPtr out, + XF86DRIClipRectPtr a, + XF86DRIClipRectPtr b ) +{ + *out = *a; + if ( b->x1 > out->x1 ) out->x1 = b->x1; + if ( b->y1 > out->y1 ) out->y1 = b->y1; + if ( b->x2 < out->x2 ) out->x2 = b->x2; + if ( b->y2 < out->y2 ) out->y2 = b->y2; + if ( out->x1 >= out->x2 ) return GL_FALSE; + if ( out->y1 >= out->y2 ) return GL_FALSE; + return GL_TRUE; +} + + +void radeonRecalcScissorRects( radeonContextPtr rmesa ) +{ + XF86DRIClipRectPtr out; + int i; + + /* Grow cliprect store? + */ + if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) { + while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) { + rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */ + rmesa->state.scissor.numAllocedClipRects *= 2; + } + + if (rmesa->state.scissor.pClipRects) + FREE(rmesa->state.scissor.pClipRects); + + rmesa->state.scissor.pClipRects = + MALLOC( rmesa->state.scissor.numAllocedClipRects * + sizeof(XF86DRIClipRectRec) ); + + if ( rmesa->state.scissor.pClipRects == NULL ) { + rmesa->state.scissor.numAllocedClipRects = 0; + return; + } + } + + out = rmesa->state.scissor.pClipRects; + rmesa->state.scissor.numClipRects = 0; + + for ( i = 0 ; i < rmesa->numClipRects ; i++ ) { + if ( intersect_rect( out, + &rmesa->pClipRects[i], + &rmesa->state.scissor.rect ) ) { + rmesa->state.scissor.numClipRects++; + out++; + } + } +} + + static void radeonUpdateScissor( GLcontext *ctx ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); @@ -319,8 +482,7 @@ static void radeonUpdateScissor( GLcontext *ctx ) rmesa->state.scissor.rect.x2 = w + dPriv->x + 1; rmesa->state.scissor.rect.y2 = h + dPriv->y + 1; - if ( ctx->Scissor.Enabled ) - rmesa->upload_cliprects = 1; + radeonRecalcScissorRects( rmesa ); } } @@ -330,10 +492,11 @@ static void radeonScissor( GLcontext *ctx, { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - if ( ctx->Scissor.Enabled ) + if ( ctx->Scissor.Enabled ) { RADEON_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */ + radeonUpdateScissor( ctx ); + } - radeonUpdateScissor( ctx ); } @@ -344,27 +507,37 @@ static void radeonScissor( GLcontext *ctx, static void radeonCullFace( GLcontext *ctx, GLenum unused ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint s = rmesa->state.hw.setup1.se_cntl; + GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; + GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL]; s |= RADEON_FFACE_SOLID | RADEON_BFACE_SOLID; + t &= ~(RADEON_CULL_FRONT | RADEON_CULL_BACK); if ( ctx->Polygon.CullFlag ) { switch ( ctx->Polygon.CullFaceMode ) { case GL_FRONT: s &= ~RADEON_FFACE_SOLID; + t |= RADEON_CULL_FRONT; break; case GL_BACK: s &= ~RADEON_BFACE_SOLID; + t |= RADEON_CULL_BACK; break; case GL_FRONT_AND_BACK: s &= ~(RADEON_FFACE_SOLID | RADEON_BFACE_SOLID); + t |= (RADEON_CULL_FRONT | RADEON_CULL_BACK); break; } } - if ( rmesa->state.hw.setup1.se_cntl != s ) { - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_SETUP); - rmesa->state.hw.setup1.se_cntl = s; + if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { + RADEON_STATECHANGE(rmesa, set ); + rmesa->hw.set.cmd[SET_SE_CNTL] = s; + } + + if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) { + RADEON_STATECHANGE(rmesa, tcl ); + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t; } } @@ -372,15 +545,19 @@ static void radeonFrontFace( GLcontext *ctx, GLenum mode ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_SETUP ); - rmesa->state.hw.setup1.se_cntl &= ~RADEON_FFACE_CULL_DIR_MASK; + RADEON_STATECHANGE( rmesa, set ); + rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK; + + RADEON_STATECHANGE( rmesa, tcl ); + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_CULL_FRONT_IS_CCW; switch ( mode ) { case GL_CW: - rmesa->state.hw.setup1.se_cntl |= RADEON_FFACE_CULL_CW; + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CW; break; case GL_CCW: - rmesa->state.hw.setup1.se_cntl |= RADEON_FFACE_CULL_CCW; + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CCW; + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_CULL_FRONT_IS_CCW; break; } } @@ -393,15 +570,16 @@ static void radeonLineWidth( GLcontext *ctx, GLfloat widthf ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_LINE | RADEON_UPLOAD_SETUP ); + RADEON_STATECHANGE( rmesa, lin ); + RADEON_STATECHANGE( rmesa, set ); /* Line width is stored in U6.4 format. */ - rmesa->state.hw.line.se_line_width = (GLuint)(widthf * 16.0); + rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (GLuint)(widthf * 16.0); if ( widthf > 1.0 ) { - rmesa->state.hw.setup1.se_cntl |= RADEON_WIDELINE_ENABLE; + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_WIDELINE_ENABLE; } else { - rmesa->state.hw.setup1.se_cntl &= ~RADEON_WIDELINE_ENABLE; + rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_WIDELINE_ENABLE; } } @@ -409,10 +587,9 @@ static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_LINE ); - - rmesa->state.hw.line.re_line_pattern = ((((GLuint)factor & 0xff) << 16) | - ((GLuint)pattern)); + RADEON_STATECHANGE( rmesa, lin ); + rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = + ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern)); } @@ -430,9 +607,9 @@ static void radeonColorMask( GLcontext *ctx, ctx->Color.ColorMask[BCOMP], ctx->Color.ColorMask[ACOMP] ); - if ( rmesa->state.hw.mask.rb3d_planemask != mask ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_MASKS ); - rmesa->state.hw.mask.rb3d_planemask = mask; + if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) { + RADEON_STATECHANGE( rmesa, msk ); + rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask; } } @@ -447,15 +624,16 @@ static void radeonPolygonOffset( GLcontext *ctx, radeonContextPtr rmesa = RADEON_CONTEXT(ctx); GLfloat constant = units * rmesa->state.depth.scale; - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_ZBIAS ); - rmesa->state.hw.zbias.se_zbias_factor = *(GLuint *)&factor; - rmesa->state.hw.zbias.se_zbias_constant = *(GLuint *)&constant; + RADEON_STATECHANGE( rmesa, zbs ); + rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = *(GLuint *)&factor; + rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = *(GLuint *)&constant; } static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); GLuint i; + drmRadeonStipple stipple; /* Must flip pattern upside down. */ @@ -463,15 +641,34 @@ static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask ) rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i]; } + /* TODO: push this into cmd mechanism + */ RADEON_FIREVERTICES( rmesa ); LOCK_HARDWARE( rmesa ); /* FIXME: Use window x,y offsets into stipple RAM. */ - drmRadeonPolygonStipple( rmesa->dri.fd, rmesa->state.stipple.mask ); + stipple.mask = rmesa->state.stipple.mask; + drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE, + &stipple, sizeof(drmRadeonStipple) ); UNLOCK_HARDWARE( rmesa ); } +static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0; + + /* Can't generally do unfilled via tcl, but some good special + * cases work. + */ + TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag); + if (rmesa->TclFallback) { + radeonChooseRenderState( ctx ); + radeonChooseVertexState( ctx ); + } +} + /* ============================================================= * Rendering attributes @@ -487,34 +684,478 @@ static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask ) static void radeonUpdateSpecular( GLcontext *ctx ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - CARD32 p = rmesa->state.hw.context.pp_cntl; + CARD32 p = rmesa->hw.ctx.cmd[CTX_PP_CNTL]; - if ( ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR && - ctx->Light.Enabled) { + if ( ctx->_TriangleCaps & DD_SEPARATE_SPECULAR ) { p |= RADEON_SPECULAR_ENABLE; } else { p &= ~RADEON_SPECULAR_ENABLE; } - if ( rmesa->state.hw.context.pp_cntl != p ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.pp_cntl = p; + if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) { + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p; + } + + /* Bizzare: have to leave lighting enabled to get fog. + */ + RADEON_STATECHANGE( rmesa, tcl ); + if ((ctx->Light.Enabled && + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; + } + else if (ctx->Fog.Enabled) { + if (ctx->Light.Enabled) { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; + } else { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; + } + } + else if (ctx->Light.Enabled) { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; + } else if (ctx->Fog.ColorSumEnabled ) { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE; + } else { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE; + } + + /* Update vertex/render formats + */ + if (rmesa->TclFallback) { + radeonChooseRenderState( ctx ); + radeonChooseVertexState( ctx ); } } +/* ============================================================= + * Materials + */ + + +/* Update on colormaterial, material emmissive/ambient, + * lightmodel.globalambient + */ +static void update_global_ambient( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + float *fcmd = (float *)RADEON_DB_STATE( glt ); + + /* Need to do more if both emmissive & ambient are PREMULT: + */ + if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] & + ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) | + (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0) + { + COPY_3V( &fcmd[GLT_RED], + ctx->Light.Material[0].Emission); + ACC_SCALE_3V( &fcmd[GLT_RED], + ctx->Light.Model.Ambient, + ctx->Light.Material[0].Ambient); + } + else + { + COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient ); + } + + RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt); +} + +/* Update on change to + * - light[p].colors + * - light[p].enabled + * - material, + * - colormaterial enabled + * - colormaterial bitmask + */ +static void update_light_colors( GLcontext *ctx, GLuint p ) +{ + struct gl_light *l = &ctx->Light.Light[p]; + +/* fprintf(stderr, "%s\n", __FUNCTION__); */ + + if (l->Enabled) { + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + float *fcmd = (float *)RADEON_DB_STATE( lit[p] ); + GLuint bitmask = ctx->Light.ColorMaterialBitmask; + struct gl_material *mat = &ctx->Light.Material[0]; + + COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient ); + COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse ); + COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular ); + + if (!ctx->Light.ColorMaterialEnabled) + bitmask = 0; + + if ((bitmask & FRONT_AMBIENT_BIT) == 0) + SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat->Ambient ); + + if ((bitmask & FRONT_DIFFUSE_BIT) == 0) + SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat->Diffuse ); + + if ((bitmask & FRONT_SPECULAR_BIT) == 0) + SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat->Specular ); + + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); + } +} + +/* Also fallback for asym colormaterial mode in twoside lighting... + */ +static void check_twoside_fallback( GLcontext *ctx ) +{ + GLboolean fallback = GL_FALSE; + + if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) { + if (memcmp( &ctx->Light.Material[0], + &ctx->Light.Material[1], + sizeof(struct gl_material)) != 0) + fallback = GL_TRUE; + else if (ctx->Light.ColorMaterialEnabled && + (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) != + ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1)) + fallback = GL_TRUE; + } + + TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback ); +} + +static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode ) +{ + if (ctx->Light.ColorMaterialEnabled) { + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint light_model_ctl = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]; + GLuint mask = ctx->Light.ColorMaterialBitmask; + + /* Default to PREMULT: + */ + light_model_ctl &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) | + (3 << RADEON_AMBIENT_SOURCE_SHIFT) | + (3 << RADEON_DIFFUSE_SOURCE_SHIFT) | + (3 << RADEON_SPECULAR_SOURCE_SHIFT)); + + if (mask & FRONT_EMISSION_BIT) { + light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << + RADEON_EMISSIVE_SOURCE_SHIFT); + } + + if (mask & FRONT_AMBIENT_BIT) { + light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << + RADEON_AMBIENT_SOURCE_SHIFT); + } + + if (mask & FRONT_DIFFUSE_BIT) { + light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << + RADEON_DIFFUSE_SOURCE_SHIFT); + } + + if (mask & FRONT_SPECULAR_BIT) { + light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << + RADEON_SPECULAR_SOURCE_SHIFT); + } + + if (light_model_ctl != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) { + GLuint p; + + RADEON_STATECHANGE( rmesa, tcl ); + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl; + + for (p = 0 ; p < MAX_LIGHTS; p++) + update_light_colors( ctx, p ); + update_global_ambient( ctx ); + } + } + + check_twoside_fallback( ctx ); +} + +void radeonUpdateMaterial( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl ); + GLuint p; + GLuint mask = ~0; + + if (ctx->Light.ColorMaterialEnabled) + mask &= ~ctx->Light.ColorMaterialBitmask; + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s\n", __FUNCTION__); + + + if (mask & FRONT_EMISSION_BIT) { + fcmd[MTL_EMMISSIVE_RED] = ctx->Light.Material[0].Emission[0]; + fcmd[MTL_EMMISSIVE_GREEN] = ctx->Light.Material[0].Emission[1]; + fcmd[MTL_EMMISSIVE_BLUE] = ctx->Light.Material[0].Emission[2]; + fcmd[MTL_EMMISSIVE_ALPHA] = ctx->Light.Material[0].Emission[3]; + } + if (mask & FRONT_AMBIENT_BIT) { + fcmd[MTL_AMBIENT_RED] = ctx->Light.Material[0].Ambient[0]; + fcmd[MTL_AMBIENT_GREEN] = ctx->Light.Material[0].Ambient[1]; + fcmd[MTL_AMBIENT_BLUE] = ctx->Light.Material[0].Ambient[2]; + fcmd[MTL_AMBIENT_ALPHA] = ctx->Light.Material[0].Ambient[3]; + } + if (mask & FRONT_DIFFUSE_BIT) { + fcmd[MTL_DIFFUSE_RED] = ctx->Light.Material[0].Diffuse[0]; + fcmd[MTL_DIFFUSE_GREEN] = ctx->Light.Material[0].Diffuse[1]; + fcmd[MTL_DIFFUSE_BLUE] = ctx->Light.Material[0].Diffuse[2]; + fcmd[MTL_DIFFUSE_ALPHA] = ctx->Light.Material[0].Diffuse[3]; + } + if (mask & FRONT_SPECULAR_BIT) { + fcmd[MTL_SPECULAR_RED] = ctx->Light.Material[0].Specular[0]; + fcmd[MTL_SPECULAR_GREEN] = ctx->Light.Material[0].Specular[1]; + fcmd[MTL_SPECULAR_BLUE] = ctx->Light.Material[0].Specular[2]; + fcmd[MTL_SPECULAR_ALPHA] = ctx->Light.Material[0].Specular[3]; + } + if (mask & FRONT_SHININESS_BIT) { + fcmd[MTL_SHININESS] = ctx->Light.Material[0].Shininess; + } + + if (RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl )) { + for (p = 0 ; p < MAX_LIGHTS; p++) + update_light_colors( ctx, p ); + + check_twoside_fallback( ctx ); + update_global_ambient( ctx ); + } + else if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_STATE)) + fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__); +} + +/* _NEW_LIGHT + * _NEW_MODELVIEW + * _MESA_NEW_NEED_EYE_COORDS + * + * Uses derived state from mesa: + * _VP_inf_norm + * _h_inf_norm + * _Position + * _NormDirection + * _ModelViewInvScale + * _NeedEyeCoords + * _EyeZDir + * + * which are calculated in light.c and are correct for the current + * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW + * and _MESA_NEW_NEED_EYE_COORDS. + */ +static void update_light( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + /* Have to check these, or have an automatic shortcircuit mechanism + * to remove noop statechanges. (Or just do a better job on the + * front end). + */ + { + GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]; + + if (ctx->_NeedEyeCoords) + tmp &= ~RADEON_LIGHT_IN_MODELSPACE; + else + tmp |= RADEON_LIGHT_IN_MODELSPACE; + + + /* Leave this test disabled: (unexplained q3 lockup) (even with + new packets) + */ + if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) + { + RADEON_STATECHANGE( rmesa, tcl ); + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp; + } + } + + { + GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye ); + fcmd[EYE_X] = ctx->_EyeZDir[0]; + fcmd[EYE_Y] = ctx->_EyeZDir[1]; + fcmd[EYE_Z] = - ctx->_EyeZDir[2]; + fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale; + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye ); + } + + +/* RADEON_STATECHANGE( rmesa, glt ); */ + + if (ctx->Light.Enabled) { + GLint p; + for (p = 0 ; p < MAX_LIGHTS; p++) { + if (ctx->Light.Light[p].Enabled) { + struct gl_light *l = &ctx->Light.Light[p]; + GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] ); + + if (l->EyePosition[3] == 0.0) { + COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm ); + COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm ); + fcmd[LIT_POSITION_W] = 0; + fcmd[LIT_DIRECTION_W] = 0; + } else { + COPY_4V( &fcmd[LIT_POSITION_X], l->_Position ); + fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0]; + fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1]; + fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2]; + fcmd[LIT_DIRECTION_W] = 0; + } + + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); + } + } + } +} + +static void radeonLightfv( GLcontext *ctx, GLenum light, + GLenum pname, const GLfloat *params ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLint p = light - GL_LIGHT0; + struct gl_light *l = &ctx->Light.Light[p]; + GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd; + + + switch (pname) { + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + update_light_colors( ctx, p ); + break; + + case GL_SPOT_DIRECTION: + /* picked up in update_light */ + break; + + case GL_POSITION: { + /* positions picked up in update_light, but can do flag here */ + GLuint flag = (p&1)? RADEON_LIGHT_1_IS_LOCAL : RADEON_LIGHT_0_IS_LOCAL; + GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; + + RADEON_STATECHANGE(rmesa, tcl); + if (l->EyePosition[3] != 0.0F) + rmesa->hw.tcl.cmd[idx] |= flag; + else + rmesa->hw.tcl.cmd[idx] &= ~flag; + break; + } + + case GL_SPOT_EXPONENT: + RADEON_STATECHANGE(rmesa, lit[p]); + fcmd[LIT_SPOT_EXPONENT] = params[0]; + break; + + case GL_SPOT_CUTOFF: { + GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT; + GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; + + RADEON_STATECHANGE(rmesa, lit[p]); + fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff; + + RADEON_STATECHANGE(rmesa, tcl); + if (l->SpotCutoff != 180.0F) + rmesa->hw.tcl.cmd[idx] |= flag; + else + rmesa->hw.tcl.cmd[idx] &= ~flag; + break; + } + + case GL_CONSTANT_ATTENUATION: + RADEON_STATECHANGE(rmesa, lit[p]); + fcmd[LIT_ATTEN_CONST] = params[0]; + break; + case GL_LINEAR_ATTENUATION: + RADEON_STATECHANGE(rmesa, lit[p]); + fcmd[LIT_ATTEN_LINEAR] = params[0]; + break; + case GL_QUADRATIC_ATTENUATION: + RADEON_STATECHANGE(rmesa, lit[p]); + fcmd[LIT_ATTEN_QUADRATIC] = params[0]; + break; + default: + return; + } + +} + + + + static void radeonLightModelfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) { - if ( pname == GL_LIGHT_MODEL_COLOR_CONTROL ) { - radeonUpdateSpecular(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + update_global_ambient( ctx ); + break; + + case GL_LIGHT_MODEL_LOCAL_VIEWER: + RADEON_STATECHANGE( rmesa, tcl ); + if (ctx->Light.Model.LocalViewer) + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER; + else + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER; + break; + + case GL_LIGHT_MODEL_TWO_SIDE: + RADEON_STATECHANGE( rmesa, tcl ); + if (ctx->Light.Model.TwoSide) + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE; + else + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE; + + check_twoside_fallback( ctx ); + + if (rmesa->TclFallback) { + radeonChooseRenderState( ctx ); + radeonChooseVertexState( ctx ); + } + break; + + case GL_LIGHT_MODEL_COLOR_CONTROL: + radeonUpdateSpecular(ctx); + + RADEON_STATECHANGE( rmesa, tcl ); + if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= + ~RADEON_DIFFUSE_SPECULAR_COMBINE; + else + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= + RADEON_DIFFUSE_SPECULAR_COMBINE; + break; + + default: + break; } } static void radeonShadeModel( GLcontext *ctx, GLenum mode ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint s = rmesa->state.hw.setup1.se_cntl; + GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; s &= ~(RADEON_DIFFUSE_SHADE_MASK | RADEON_ALPHA_SHADE_MASK | @@ -538,9 +1179,45 @@ static void radeonShadeModel( GLcontext *ctx, GLenum mode ) return; } - if ( rmesa->state.hw.setup1.se_cntl != s ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_SETUP ); - rmesa->state.hw.setup1.se_cntl = s; + if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { + RADEON_STATECHANGE( rmesa, set ); + rmesa->hw.set.cmd[SET_SE_CNTL] = s; + } +} + + +/* ============================================================= + * User clip planes + */ + +static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq ) +{ + GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; + + RADEON_STATECHANGE( rmesa, ucp[p] ); + rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; + rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; + rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; + rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; +} + +static void radeonUpdateClipPlanes( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint p; + + for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { + if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { + GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; + + RADEON_STATECHANGE( rmesa, ucp[p] ); + rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; + rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; + rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; + rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; + } } } @@ -553,54 +1230,54 @@ static void radeonStencilFunc( GLcontext *ctx, GLenum func, GLint ref, GLuint mask ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint refmask = ((ctx->Stencil.Ref << RADEON_STENCIL_REF_SHIFT) | - (ctx->Stencil.ValueMask << RADEON_STENCIL_MASK_SHIFT)); + GLuint refmask = ((ctx->Stencil.Ref[0] << RADEON_STENCIL_REF_SHIFT) | + (ctx->Stencil.ValueMask[0] << RADEON_STENCIL_MASK_SHIFT)); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_MASKS ); + RADEON_STATECHANGE( rmesa, ctx ); + RADEON_STATECHANGE( rmesa, msk ); - rmesa->state.hw.context.rb3d_zstencilcntl &= ~RADEON_STENCIL_TEST_MASK; - rmesa->state.hw.mask.rb3d_stencilrefmask &= ~(RADEON_STENCIL_REF_MASK| - RADEON_STENCIL_VALUE_MASK); + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_STENCIL_TEST_MASK; + rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(RADEON_STENCIL_REF_MASK| + RADEON_STENCIL_VALUE_MASK); - switch ( ctx->Stencil.Function ) { + switch ( ctx->Stencil.Function[0] ) { case GL_NEVER: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_NEVER; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER; break; case GL_LESS: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_LESS; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS; break; case GL_EQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_EQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL; break; case GL_LEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_LEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL; break; case GL_GREATER: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_GREATER; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER; break; case GL_NOTEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_NEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL; break; case GL_GEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_GEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL; break; case GL_ALWAYS: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_ALWAYS; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS; break; } - rmesa->state.hw.mask.rb3d_stencilrefmask |= refmask; + rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask; } static void radeonStencilMask( GLcontext *ctx, GLuint mask ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_MASKS ); - rmesa->state.hw.mask.rb3d_stencilrefmask &= ~RADEON_STENCIL_WRITE_MASK; - - rmesa->state.hw.mask.rb3d_stencilrefmask |= - (ctx->Stencil.WriteMask << RADEON_STENCIL_WRITEMASK_SHIFT); + RADEON_STATECHANGE( rmesa, msk ); + rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK; + rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= + (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT); } static void radeonStencilOp( GLcontext *ctx, GLenum fail, @@ -608,71 +1285,71 @@ static void radeonStencilOp( GLcontext *ctx, GLenum fail, { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_zstencilcntl &= ~(RADEON_STENCIL_FAIL_MASK | + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK | RADEON_STENCIL_ZFAIL_MASK | RADEON_STENCIL_ZPASS_MASK); - switch ( ctx->Stencil.FailFunc ) { + switch ( ctx->Stencil.FailFunc[0] ) { case GL_KEEP: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_KEEP; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP; break; case GL_ZERO: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_ZERO; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO; break; case GL_REPLACE: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_REPLACE; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE; break; case GL_INCR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_INC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC; break; case GL_DECR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_DEC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC; break; case GL_INVERT: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_INVERT; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT; break; } - switch ( ctx->Stencil.ZFailFunc ) { + switch ( ctx->Stencil.ZFailFunc[0] ) { case GL_KEEP: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_KEEP; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP; break; case GL_ZERO: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_ZERO; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO; break; case GL_REPLACE: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_REPLACE; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE; break; case GL_INCR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_INC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC; break; case GL_DECR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_DEC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC; break; case GL_INVERT: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_INVERT; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT; break; } - switch ( ctx->Stencil.ZPassFunc ) { + switch ( ctx->Stencil.ZPassFunc[0] ) { case GL_KEEP: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_KEEP; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP; break; case GL_ZERO: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_ZERO; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO; break; case GL_REPLACE: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_REPLACE; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE; break; case GL_INCR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_INC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC; break; case GL_DECR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_DEC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC; break; case GL_INVERT: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_INVERT; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT; break; } } @@ -681,9 +1358,10 @@ static void radeonClearStencil( GLcontext *ctx, GLint s ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - rmesa->state.stencil.clear = ((GLuint) ctx->Stencil.Clear | - (0xff << RADEON_STENCIL_MASK_SHIFT) | - (ctx->Stencil.WriteMask << RADEON_STENCIL_WRITEMASK_SHIFT)); + rmesa->state.stencil.clear = + ((GLuint) ctx->Stencil.Clear | + (0xff << RADEON_STENCIL_MASK_SHIFT) | + (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT)); } @@ -695,6 +1373,7 @@ static void radeonClearStencil( GLcontext *ctx, GLint s ) * To correctly position primitives: */ #define SUBPIXEL_X 0.125 +#define SUBPIXEL_Y 0.125 void radeonUpdateWindow( GLcontext *ctx ) { @@ -707,20 +1386,18 @@ void radeonUpdateWindow( GLcontext *ctx ) GLfloat sx = v[MAT_SX]; GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X; GLfloat sy = - v[MAT_SY]; - GLfloat ty = (- v[MAT_TY]) + yoffset; + GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y; GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale; GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale; - -/* fprintf(stderr, "radeonUpdateWindow %d,%d %dx%d\n", */ -/* dPriv->x, dPriv->y, dPriv->w, dPriv->h); */ - - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_VIEWPORT); - rmesa->state.hw.viewport.se_vport_xscale = *(GLuint *)&sx; - rmesa->state.hw.viewport.se_vport_xoffset = *(GLuint *)&tx; - rmesa->state.hw.viewport.se_vport_yscale = *(GLuint *)&sy; - rmesa->state.hw.viewport.se_vport_yoffset = *(GLuint *)&ty; - rmesa->state.hw.viewport.se_vport_zscale = *(GLuint *)&sz; - rmesa->state.hw.viewport.se_vport_zoffset = *(GLuint *)&tz; + RADEON_FIREVERTICES( rmesa ); + RADEON_STATECHANGE( rmesa, vpt ); + + rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = *(GLuint *)&sx; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = *(GLuint *)&sy; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = *(GLuint *)&sz; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz; } @@ -753,29 +1430,19 @@ void radeonUpdateViewportOffset( GLcontext *ctx ) GLfloat tx = v[MAT_TX] + xoffset; GLfloat ty = (- v[MAT_TY]) + yoffset; - if ( rmesa->state.hw.viewport.se_vport_xoffset != tx || - rmesa->state.hw.viewport.se_vport_yoffset != ty ) + if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx || + rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty ) { - rmesa->state.hw.viewport.se_vport_xoffset = *(GLuint *)&tx; - rmesa->state.hw.viewport.se_vport_yoffset = *(GLuint *)&ty; - - if (rmesa->store.statenr) { - int i; - rmesa->store.state[0].dirty |= RADEON_UPLOAD_VIEWPORT; - /* Note: assume vport x/yoffset are constant over the buffer: - */ - for (i = 0 ; i < rmesa->store.statenr ; i++) { - rmesa->store.state[i].viewport.se_vport_xoffset = *(GLuint *)&tx; - rmesa->store.state[i].viewport.se_vport_yoffset = *(GLuint *)&ty; - } - } else { - rmesa->state.hw.dirty |= RADEON_UPLOAD_VIEWPORT; - } - + /* Note: this should also modify whatever data the context reset + * code uses... + */ + rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty; + /* update polygon stipple x/y screen offset */ { GLuint stx, sty; - GLuint m = rmesa->state.hw.misc.re_misc; + GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC]; m &= ~(RADEON_STIPPLE_X_OFFSET_MASK | RADEON_STIPPLE_Y_OFFSET_MASK); @@ -788,9 +1455,9 @@ void radeonUpdateViewportOffset( GLcontext *ctx ) m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) | (sty << RADEON_STIPPLE_Y_OFFSET_SHIFT)); - if ( rmesa->state.hw.misc.re_misc != m ) { - rmesa->state.hw.misc.re_misc = m; - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_MISC); + if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) { + RADEON_STATECHANGE( rmesa, msc ); + rmesa->hw.msc.cmd[MSC_RE_MISC] = m; } } } @@ -804,9 +1471,14 @@ void radeonUpdateViewportOffset( GLcontext *ctx ) * Miscellaneous */ -static void radeonClearColor( GLcontext *ctx, const GLchan c[4] ) +static void radeonClearColor( GLcontext *ctx, const GLfloat color[4] ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLubyte c[4]; + CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); + CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); + CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); + CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); rmesa->state.color.clear = radeonPackColor( rmesa->radeonScreen->cpp, c[0], c[1], c[2], c[3] ); } @@ -845,8 +1517,8 @@ static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode ) ASSERT( rop < 16 ); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_MASKS ); - rmesa->state.hw.mask.rb3d_ropcntl = radeon_rop_tab[rop]; + RADEON_STATECHANGE( rmesa, msk ); + rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop]; } @@ -860,7 +1532,9 @@ void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode ) rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects; break; case GL_BACK_LEFT: - if ( dPriv->numBackClipRects == 0 ) { + /* Can't ignore 2d windows if we are page flipping. + */ + if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) { rmesa->numClipRects = dPriv->numClipRects; rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects; } @@ -870,41 +1544,57 @@ void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode ) } break; default: + fprintf(stderr, "bad mode in radeonSetCliprects\n"); return; } - rmesa->upload_cliprects = 1; + if (rmesa->state.scissor.enabled) + radeonRecalcScissorRects( rmesa ); } -static void radeonSetDrawBuffer( GLcontext *ctx, GLenum mode ) +static void radeonDrawBuffer( GLcontext *ctx, GLenum mode ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s %s\n", __FUNCTION__, + _mesa_lookup_enum_by_nr( mode )); + RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */ - switch ( mode ) { - case GL_FRONT_LEFT: + /* + * _DrawDestMask is easier to cope with than <mode>. + */ + switch ( ctx->Color._DrawDestMask ) { + case FRONT_LEFT_BIT: FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE ); - rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; - rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; radeonSetCliprects( rmesa, GL_FRONT_LEFT ); break; - case GL_BACK_LEFT: + case BACK_LEFT_BIT: FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE ); - rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; - rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; radeonSetCliprects( rmesa, GL_BACK_LEFT ); break; default: + /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */ FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE ); return; } - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_coloroffset = (rmesa->state.color.drawOffset & + /* We want to update the s/w rast state too so that r200SetBuffer() + * gets called. + */ + _swrast_DrawBuffer(ctx, mode); + + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset & RADEON_COLOROFFSET_MASK); - rmesa->state.hw.context.rb3d_colorpitch = rmesa->state.color.drawPitch; + rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch; +} + +static void radeonReadBuffer( GLcontext *ctx, GLenum mode ) +{ + /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ } @@ -915,9 +1605,10 @@ static void radeonSetDrawBuffer( GLcontext *ctx, GLenum mode ) static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint p, flag; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) - fprintf( stderr, "%s( %s = %s )\n",__FUNCTION__, + if ( RADEON_DEBUG & DEBUG_STATE ) + fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__, _mesa_lookup_enum_by_nr( cap ), state ? "GL_TRUE" : "GL_FALSE" ); @@ -930,371 +1621,490 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state ) break; case GL_ALPHA_TEST: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE( rmesa, ctx ); if (state) { - rmesa->state.hw.context.pp_cntl |= RADEON_ALPHA_TEST_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE; } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_ALPHA_TEST_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE; } break; case GL_BLEND: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE( rmesa, ctx ); if (state) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_ALPHA_BLEND_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ALPHA_BLEND_ENABLE; + } else { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE; + } + if ( ctx->Color.ColorLogicOpEnabled ) { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_ALPHA_BLEND_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; + } + break; + + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + p = cap-GL_CLIP_PLANE0; + RADEON_STATECHANGE( rmesa, tcl ); + if (state) { + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p); + radeonClipPlane( ctx, cap, NULL ); + } + else { + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p); } break; + case GL_COLOR_MATERIAL: + radeonColorMaterial( ctx, 0, 0 ); + if (!state) + radeonUpdateMaterial( ctx ); + break; + case GL_CULL_FACE: radeonCullFace( ctx, 0 ); break; case GL_DEPTH_TEST: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE(rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_Z_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_Z_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_Z_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE; } break; case GL_DITHER: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE(rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_DITHER_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_DITHER_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE; } break; case GL_FOG: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE(rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.pp_cntl |= RADEON_FOG_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE; + radeonFogfv( ctx, GL_FOG_MODE, 0 ); } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_FOG_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE; + RADEON_STATECHANGE(rmesa, tcl); + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK; } + radeonUpdateSpecular( ctx ); /* for PK_SPEC */ + if (rmesa->TclFallback) + radeonChooseVertexState( ctx ); + break; + + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + RADEON_STATECHANGE(rmesa, tcl); + p = cap - GL_LIGHT0; + if (p&1) + flag = (RADEON_LIGHT_1_ENABLE | + RADEON_LIGHT_1_ENABLE_AMBIENT | + RADEON_LIGHT_1_ENABLE_SPECULAR); + else + flag = (RADEON_LIGHT_0_ENABLE | + RADEON_LIGHT_0_ENABLE_AMBIENT | + RADEON_LIGHT_0_ENABLE_SPECULAR); + + if (state) + rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag; + else + rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag; + + /* + */ + update_light_colors( ctx, p ); break; case GL_LIGHTING: + RADEON_STATECHANGE(rmesa, tcl); + if (state) { +/* rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; */ +/* rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; */ + } + else { +/* rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE; */ +/* rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE; */ + } radeonUpdateSpecular(ctx); + check_twoside_fallback( ctx ); break; case GL_LINE_SMOOTH: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.pp_cntl |= RADEON_ANTI_ALIAS_LINE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_LINE; } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_ANTI_ALIAS_LINE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE; } break; case GL_LINE_STIPPLE: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.pp_cntl |= RADEON_PATTERN_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_PATTERN_ENABLE; } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_PATTERN_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE; } break; case GL_COLOR_LOGIC_OP: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; } break; - - case GL_POLYGON_OFFSET_POINT: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_SETUP ); + + case GL_NORMALIZE: + RADEON_STATECHANGE( rmesa, tcl ); if ( state ) { - rmesa->state.hw.setup1.se_cntl |= RADEON_ZBIAS_ENABLE_POINT; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_NORMALIZE_NORMALS; } else { - rmesa->state.hw.setup1.se_cntl &= ~RADEON_ZBIAS_ENABLE_POINT; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS; + } + break; + + case GL_POLYGON_OFFSET_POINT: + if (rmesa->dri.drmMinor == 1) { + radeonChooseRenderState( ctx ); + } + else { + RADEON_STATECHANGE( rmesa, set ); + if ( state ) { + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_POINT; + } else { + rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT; + } } break; case GL_POLYGON_OFFSET_LINE: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_SETUP ); - if ( state ) { - rmesa->state.hw.setup1.se_cntl |= RADEON_ZBIAS_ENABLE_LINE; - } else { - rmesa->state.hw.setup1.se_cntl &= ~RADEON_ZBIAS_ENABLE_LINE; + if (rmesa->dri.drmMinor == 1) { + radeonChooseRenderState( ctx ); + } + else { + RADEON_STATECHANGE( rmesa, set ); + if ( state ) { + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_LINE; + } else { + rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE; + } } break; case GL_POLYGON_OFFSET_FILL: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_SETUP ); - if ( state ) { - rmesa->state.hw.setup1.se_cntl |= RADEON_ZBIAS_ENABLE_TRI; - } else { - rmesa->state.hw.setup1.se_cntl &= ~RADEON_ZBIAS_ENABLE_TRI; + if (rmesa->dri.drmMinor == 1) { + radeonChooseRenderState( ctx ); + } + else { + RADEON_STATECHANGE( rmesa, set ); + if ( state ) { + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_TRI; + } else { + rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI; + } } break; case GL_POLYGON_SMOOTH: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.pp_cntl |= RADEON_ANTI_ALIAS_POLY; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_POLY; } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_ANTI_ALIAS_POLY; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY; } break; case GL_POLYGON_STIPPLE: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE(rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.pp_cntl |= RADEON_STIPPLE_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_STIPPLE_ENABLE; + } else { + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE; + } + break; + + case GL_RESCALE_NORMAL_EXT: { + GLboolean tmp = ctx->_NeedEyeCoords ? state : !state; + RADEON_STATECHANGE( rmesa, tcl ); + if ( tmp ) { + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS; } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_STIPPLE_ENABLE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS; } break; + } case GL_SCISSOR_TEST: RADEON_FIREVERTICES( rmesa ); rmesa->state.scissor.enabled = state; - rmesa->upload_cliprects = 1; + radeonUpdateScissor( ctx ); break; case GL_STENCIL_TEST: if ( rmesa->state.stencil.hwBuffer ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_STENCIL_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_STENCIL_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE; } } else { FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state ); } break; + case GL_TEXTURE_GEN_Q: + case GL_TEXTURE_GEN_R: + case GL_TEXTURE_GEN_S: + case GL_TEXTURE_GEN_T: + /* Picked up in radeonUpdateTextureState. + */ + rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE; + break; + + case GL_COLOR_SUM_EXT: + radeonUpdateSpecular ( ctx ); + break; + default: return; } } +static void radeonLightingSpaceChange( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLboolean tmp; + RADEON_STATECHANGE( rmesa, tcl ); + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s %d\n", __FUNCTION__, ctx->_NeedEyeCoords); + + if (ctx->_NeedEyeCoords) + tmp = ctx->Transform.RescaleNormals; + else + tmp = !ctx->Transform.RescaleNormals; + + if ( tmp ) { + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS; + } else { + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS; + } +} + /* ============================================================= - * State initialization, management + * Deferred state management - matrices, textures, other? */ -void radeonPrintDirty( const char *msg, GLuint state ) -{ - fprintf( stderr, - "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s\n", - msg, - state, - (state & RADEON_UPLOAD_CONTEXT) ? "context, " : "", - (state & RADEON_UPLOAD_LINE) ? "line, " : "", - (state & RADEON_UPLOAD_BUMPMAP) ? "bumpmap, " : "", - (state & RADEON_UPLOAD_MASKS) ? "masks, " : "", - (state & RADEON_UPLOAD_VIEWPORT) ? "viewport, " : "", - (state & RADEON_UPLOAD_SETUP) ? "setup, " : "", - (state & RADEON_UPLOAD_TCL) ? "tcl, " : "", - (state & RADEON_UPLOAD_MISC) ? "misc, " : "", - (state & RADEON_UPLOAD_TEX0) ? "tex0, " : "", - (state & RADEON_UPLOAD_TEX1) ? "tex1, " : "", - (state & RADEON_UPLOAD_TEX2) ? "tex2, " : ""); -} +static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx ) +{ + float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0; + int i; + + for (i = 0 ; i < 4 ; i++) { + *dest++ = src[i]; + *dest++ = src[i+4]; + *dest++ = src[i+8]; + *dest++ = src[i+12]; + } -static void radeonInvalidateState( GLcontext *ctx, GLuint new_state ) + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); +} + +static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx ) { - _swrast_InvalidateState( ctx, new_state ); - _swsetup_InvalidateState( ctx, new_state ); - _ac_InvalidateState( ctx, new_state ); - _tnl_InvalidateState( ctx, new_state ); - RADEON_CONTEXT(ctx)->NewGLState |= new_state; + float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0; + memcpy(dest, src, 16*sizeof(float)); + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); } +static void update_texturematrix( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL]; + GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]; + int unit; + rmesa->TexMatEnabled = 0; -/* Initialize the context's hardware state. - */ -void radeonInitState( radeonContextPtr rmesa ) -{ - GLcontext *ctx = rmesa->glCtx; - GLuint color_fmt, depth_fmt; + for (unit = 0 ; unit < 2; unit++) { + if (!ctx->Texture.Unit[unit]._ReallyEnabled) { + } + else if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) { + GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4; + + rmesa->TexMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE| + RADEON_TEXMAT_0_ENABLE) << unit; + + if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) { + /* Need to preconcatenate any active texgen + * obj/eyeplane matrices: + */ + _math_matrix_mul_matrix( &rmesa->tmpmat, + &rmesa->TexGenMatrix[unit], + ctx->TextureMatrixStack[unit].Top ); + upload_matrix( rmesa, rmesa->tmpmat.m, TEXMAT_0+unit ); + } + else { + rmesa->TexMatEnabled |= + (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift; + upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m, + TEXMAT_0+unit ); + } + } + else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) { + upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m, + TEXMAT_0+unit ); + } + } - switch ( rmesa->radeonScreen->cpp ) { - case 2: - color_fmt = RADEON_COLOR_FORMAT_RGB565; - break; - case 4: - color_fmt = RADEON_COLOR_FORMAT_ARGB8888; - break; - default: - fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" ); - exit( -1 ); + + tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled); + + vs &= ~((0xf << RADEON_TCL_TEX_0_OUTPUT_SHIFT) | + (0xf << RADEON_TCL_TEX_1_OUTPUT_SHIFT)); + + if (tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE) + vs |= RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT; + else + vs |= RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT; + + if (tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE) + vs |= RADEON_TCL_TEX_COMPUTED_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT; + else + vs |= RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT; + + if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] || + vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) { + + RADEON_STATECHANGE(rmesa, tcl); + rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs; } +} - rmesa->state.color.clear = 0x00000000; - switch ( ctx->Visual.depthBits ) { - case 16: - rmesa->state.depth.clear = 0x0000ffff; - rmesa->state.depth.scale = 1.0 / (GLfloat)0xffff; - depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; - rmesa->state.stencil.clear = 0x00000000; - break; - case 24: - rmesa->state.depth.clear = 0x00ffffff; - rmesa->state.depth.scale = 1.0 / (GLfloat)0xffffff; - depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; - rmesa->state.stencil.clear = 0xffff0000; - break; - default: - fprintf( stderr, "Error: Unsupported depth %d... exiting\n", - ctx->Visual.depthBits ); - exit( -1 ); + +void radeonValidateState( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint new_state = rmesa->NewGLState; + + if (new_state & _NEW_TEXTURE) { + radeonUpdateTextureState( ctx ); + new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */ } - /* Only have hw stencil when depth buffer is 24 bits deep */ - rmesa->state.stencil.hwBuffer = ( ctx->Visual.stencilBits > 0 && - ctx->Visual.depthBits == 24 ); + /* Need an event driven matrix update? + */ + if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) + upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ ); - rmesa->RenderIndex = ~0; - rmesa->Fallback = 0; - rmesa->render_primitive = GL_TRIANGLES; - rmesa->hw_primitive = RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST; + /* Need these for lighting (shouldn't upload otherwise) + */ + if (new_state & (_NEW_MODELVIEW)) { + upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL ); + upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT ); + } - if ( ctx->Visual.doubleBufferMode ) { - rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; - rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; - } else { - rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; - rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + /* Does this need to be triggered on eg. modelview for + * texgen-derived objplane/eyeplane matrices? + */ + if (new_state & _NEW_TEXTURE_MATRIX) { + update_texturematrix( ctx ); + } + + if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) { + update_light( ctx ); } - rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset; - rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch; - /* Harware state: + /* emit all active clip planes if projection matrix changes. */ - rmesa->state.hw.context.pp_misc = (RADEON_ALPHA_TEST_PASS | - RADEON_CHROMA_FUNC_FAIL | - RADEON_CHROMA_KEY_NEAREST | - RADEON_SHADOW_FUNC_EQUAL | - RADEON_SHADOW_PASS_1 | - RADEON_RIGHT_HAND_CUBE_OGL); + if (new_state & (_NEW_PROJECTION)) { + if (ctx->Transform.ClipPlanesEnabled) + radeonUpdateClipPlanes( ctx ); + } - rmesa->state.hw.context.pp_fog_color = ((0x00000000 & RADEON_FOG_COLOR_MASK) | - RADEON_FOG_VERTEX | - RADEON_FOG_USE_DEPTH); - rmesa->state.hw.context.re_solid_color = 0x00000000; + rmesa->NewGLState = 0; +} - rmesa->state.hw.context.rb3d_blendcntl = (RADEON_COMB_FCN_ADD_CLAMP | - RADEON_SRC_BLEND_GL_ONE | - RADEON_DST_BLEND_GL_ZERO ); - rmesa->state.hw.context.rb3d_depthoffset = rmesa->radeonScreen->depthOffset; +static void radeonInvalidateState( GLcontext *ctx, GLuint new_state ) +{ + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + _ae_invalidate_state( ctx, new_state ); + RADEON_CONTEXT(ctx)->NewGLState |= new_state; + radeonVtxfmtInvalidate( ctx ); +} - rmesa->state.hw.context.rb3d_depthpitch = ((rmesa->radeonScreen->depthPitch & - RADEON_DEPTHPITCH_MASK) | - RADEON_DEPTH_ENDIAN_NO_SWAP); +static void radeonWrapRunPipeline( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); - rmesa->state.hw.context.rb3d_zstencilcntl = (depth_fmt | - RADEON_Z_TEST_LESS | - RADEON_STENCIL_TEST_ALWAYS | - RADEON_STENCIL_FAIL_KEEP | - RADEON_STENCIL_ZPASS_KEEP | - RADEON_STENCIL_ZFAIL_KEEP | - RADEON_Z_WRITE_ENABLE); + if (0) + fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState); - rmesa->state.hw.context.pp_cntl = (RADEON_SCISSOR_ENABLE | - RADEON_ANTI_ALIAS_NONE); + /* Validate state: + */ + if (rmesa->NewGLState) + radeonValidateState( ctx ); - rmesa->state.hw.context.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE | - color_fmt | - RADEON_ZBLOCK16); + if (tnl->vb.Material) { + TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE ); + } - rmesa->state.hw.context.rb3d_coloroffset = (rmesa->state.color.drawOffset & - RADEON_COLOROFFSET_MASK); + /* Run the pipeline. + */ + _tnl_run_pipeline( ctx ); - rmesa->state.hw.context.re_width_height = ((0x7ff << RADEON_RE_WIDTH_SHIFT) | - (0x7ff << RADEON_RE_HEIGHT_SHIFT)); - - rmesa->state.hw.context.rb3d_colorpitch = ((rmesa->state.color.drawPitch & - RADEON_COLORPITCH_MASK) | - RADEON_COLOR_ENDIAN_NO_SWAP); - - rmesa->state.hw.setup1.se_cntl = (RADEON_FFACE_CULL_CCW | - RADEON_BFACE_SOLID | - RADEON_FFACE_SOLID | - RADEON_FLAT_SHADE_VTX_LAST | - RADEON_DIFFUSE_SHADE_GOURAUD | - RADEON_ALPHA_SHADE_GOURAUD | - RADEON_SPECULAR_SHADE_GOURAUD | - RADEON_FOG_SHADE_GOURAUD | - RADEON_VPORT_XY_XFORM_ENABLE | - RADEON_VPORT_Z_XFORM_ENABLE | - RADEON_VTX_PIX_CENTER_OGL | - RADEON_ROUND_MODE_TRUNC | - RADEON_ROUND_PREC_8TH_PIX); - - rmesa->state.hw.vertex.se_coord_fmt = ( -#if 1 - RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | - RADEON_VTX_Z_PRE_MULT_1_OVER_W0 | -#else - RADEON_VTX_W0_IS_NOT_1_OVER_W0 | -#endif - RADEON_TEX1_W_ROUTING_USE_Q1); - - rmesa->state.hw.setup2.se_cntl_status = (RADEON_VC_NO_SWAP | - RADEON_TCL_BYPASS); - - rmesa->state.hw.line.re_line_pattern = ((0x0000 & RADEON_LINE_PATTERN_MASK) | - (0 << RADEON_LINE_REPEAT_COUNT_SHIFT) | - (0 << RADEON_LINE_PATTERN_START_SHIFT) | - RADEON_LINE_PATTERN_LITTLE_BIT_ORDER); - - rmesa->state.hw.line.re_line_state = ((0 << RADEON_LINE_CURRENT_PTR_SHIFT) | - (1 << RADEON_LINE_CURRENT_COUNT_SHIFT)); - - rmesa->state.hw.line.se_line_width = (1 << 4); - - rmesa->state.hw.bumpmap.pp_lum_matrix = 0x00000000; - rmesa->state.hw.bumpmap.pp_rot_matrix_0 = 0x00000000; - rmesa->state.hw.bumpmap.pp_rot_matrix_1 = 0x00000000; - - rmesa->state.hw.mask.rb3d_stencilrefmask = ((0x00 << RADEON_STENCIL_REF_SHIFT) | - (0xff << RADEON_STENCIL_MASK_SHIFT) | - (0xff << RADEON_STENCIL_WRITEMASK_SHIFT)); - - rmesa->state.hw.mask.rb3d_ropcntl = RADEON_ROP_COPY; - rmesa->state.hw.mask.rb3d_planemask = 0xffffffff; - - rmesa->state.hw.viewport.se_vport_xscale = 0x00000000; - rmesa->state.hw.viewport.se_vport_xoffset = 0x00000000; - rmesa->state.hw.viewport.se_vport_yscale = 0x00000000; - rmesa->state.hw.viewport.se_vport_yoffset = 0x00000000; - rmesa->state.hw.viewport.se_vport_zscale = 0x00000000; - rmesa->state.hw.viewport.se_vport_zoffset = 0x00000000; - - rmesa->state.hw.misc.re_misc = ((0 << RADEON_STIPPLE_X_OFFSET_SHIFT) | - (0 << RADEON_STIPPLE_Y_OFFSET_SHIFT) | - RADEON_STIPPLE_BIG_BIT_ORDER); - - rmesa->state.hw.dirty = RADEON_UPLOAD_CONTEXT_ALL; + if (tnl->vb.Material) { + TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE ); + radeonUpdateMaterial( ctx ); /* not needed any more? */ + } } + + + /* Initialize the driver's state functions. */ void radeonInitStateFuncs( GLcontext *ctx ) { ctx->Driver.UpdateState = radeonInvalidateState; + ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange; - ctx->Driver.SetDrawBuffer = radeonSetDrawBuffer; + ctx->Driver.DrawBuffer = radeonDrawBuffer; + ctx->Driver.ReadBuffer = radeonReadBuffer; ctx->Driver.AlphaFunc = radeonAlphaFunc; ctx->Driver.BlendEquation = radeonBlendEquation; @@ -1304,6 +2114,7 @@ void radeonInitStateFuncs( GLcontext *ctx ) ctx->Driver.ClearDepth = radeonClearDepth; ctx->Driver.ClearIndex = NULL; ctx->Driver.ClearStencil = radeonClearStencil; + ctx->Driver.ClipPlane = radeonClipPlane; ctx->Driver.ColorMask = radeonColorMask; ctx->Driver.CullFace = radeonCullFace; ctx->Driver.DepthFunc = radeonDepthFunc; @@ -1315,12 +2126,15 @@ void radeonInitStateFuncs( GLcontext *ctx ) ctx->Driver.Hint = NULL; ctx->Driver.IndexMask = NULL; ctx->Driver.LightModelfv = radeonLightModelfv; - ctx->Driver.Lightfv = NULL; + ctx->Driver.Lightfv = radeonLightfv; ctx->Driver.LineStipple = radeonLineStipple; ctx->Driver.LineWidth = radeonLineWidth; ctx->Driver.LogicOpcode = radeonLogicOpCode; - ctx->Driver.PolygonMode = NULL; - ctx->Driver.PolygonOffset = radeonPolygonOffset; + ctx->Driver.PolygonMode = radeonPolygonMode; + + if (RADEON_CONTEXT(ctx)->dri.drmMinor > 1) + ctx->Driver.PolygonOffset = radeonPolygonOffset; + ctx->Driver.PolygonStipple = radeonPolygonStipple; ctx->Driver.RenderMode = radeonRenderMode; ctx->Driver.Scissor = radeonScissor; @@ -1337,7 +2151,6 @@ void radeonInitStateFuncs( GLcontext *ctx ) ctx->Driver.CopyPixels = _swrast_CopyPixels; ctx->Driver.DrawPixels = _swrast_DrawPixels; ctx->Driver.ReadPixels = _swrast_ReadPixels; - ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; /* Swrast hooks for imaging extensions: */ @@ -1345,4 +2158,7 @@ void radeonInitStateFuncs( GLcontext *ctx ) ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; + + TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial; + TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline; } |