#include "glheader.h"
#include "imports.h"
#include "api_arrayelt.h"
#include "enums.h"
#include "colormac.h"
#include "state.h"
#include "swrast/swrast.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#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"
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, ctx );
pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | RADEON_REF_ALPHA_MASK);
pp_misc |= (refByte & RADEON_REF_ALPHA_MASK);
switch ( func ) {
case GL_NEVER:
pp_misc |= RADEON_ALPHA_TEST_FAIL;
break;
case GL_LESS:
pp_misc |= RADEON_ALPHA_TEST_LESS;
break;
case GL_EQUAL:
pp_misc |= RADEON_ALPHA_TEST_EQUAL;
break;
case GL_LEQUAL:
pp_misc |= RADEON_ALPHA_TEST_LEQUAL;
break;
case GL_GREATER:
pp_misc |= RADEON_ALPHA_TEST_GREATER;
break;
case GL_NOTEQUAL:
pp_misc |= RADEON_ALPHA_TEST_NEQUAL;
break;
case GL_GEQUAL:
pp_misc |= RADEON_ALPHA_TEST_GEQUAL;
break;
case GL_ALWAYS:
pp_misc |= RADEON_ALPHA_TEST_PASS;
break;
}
rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
}
static void radeonBlendEquation( GLcontext *ctx, GLenum mode )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK;
GLboolean fallback = GL_FALSE;
switch ( mode ) {
case GL_FUNC_ADD:
case GL_LOGIC_OP:
b |= RADEON_COMB_FCN_ADD_CLAMP;
break;
case GL_FUNC_SUBTRACT:
b |= RADEON_COMB_FCN_SUB_CLAMP;
break;
default:
if (ctx->Color.BlendEnabled)
fallback = GL_TRUE;
else
b |= RADEON_COMB_FCN_ADD_CLAMP;
break;
}
FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, fallback );
if ( !fallback ) {
RADEON_STATECHANGE( rmesa, ctx );
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
if ( ctx->Color.ColorLogicOpEnabled ) {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
} else {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
}
}
}
static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
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 ) {
case GL_ZERO:
b |= RADEON_SRC_BLEND_GL_ZERO;
break;
case GL_ONE:
b |= RADEON_SRC_BLEND_GL_ONE;
break;
case GL_DST_COLOR:
b |= RADEON_SRC_BLEND_GL_DST_COLOR;
break;
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;
case GL_ONE_MINUS_SRC_ALPHA:
b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
break;
case GL_DST_ALPHA:
b |= RADEON_SRC_BLEND_GL_DST_ALPHA;
break;
case GL_ONE_MINUS_DST_ALPHA:
b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
break;
case GL_SRC_ALPHA_SATURATE:
b |= RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
break;
case GL_CONSTANT_COLOR:
case GL_ONE_MINUS_CONSTANT_COLOR:
case GL_CONSTANT_ALPHA:
case GL_ONE_MINUS_CONSTANT_ALPHA:
if (ctx->Color.BlendEnabled)
fallback = GL_TRUE;
else
b |= RADEON_SRC_BLEND_GL_ONE;
break;
default:
break;
}
switch ( ctx->Color.BlendDstRGB ) {
case GL_ZERO:
b |= RADEON_DST_BLEND_GL_ZERO;
break;
case GL_ONE:
b |= RADEON_DST_BLEND_GL_ONE;
break;
case GL_SRC_COLOR:
b |= RADEON_DST_BLEND_GL_SRC_COLOR;
break;
case GL_ONE_MINUS_SRC_COLOR:
b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR;
break;
case GL_SRC_ALPHA:
b |= RADEON_DST_BLEND_GL_SRC_ALPHA;
break;
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;
case GL_ONE_MINUS_DST_ALPHA:
b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA;
break;
case GL_CONSTANT_COLOR:
case GL_ONE_MINUS_CONSTANT_COLOR:
case GL_CONSTANT_ALPHA:
case GL_ONE_MINUS_CONSTANT_ALPHA:
if (ctx->Color.BlendEnabled)
fallback = GL_TRUE;
else
b |= RADEON_DST_BLEND_GL_ZERO;
break;
default:
break;
}
FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, fallback );
if ( !fallback ) {
RADEON_STATECHANGE( rmesa, ctx );
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
}
}
static void radeonBlendFuncSeparate( GLcontext *ctx,
GLenum sfactorRGB, GLenum dfactorRGB,
GLenum sfactorA, GLenum dfactorA )
{
radeonBlendFunc( ctx, sfactorRGB, dfactorRGB );
}
static void radeonDepthFunc( GLcontext *ctx, GLenum func )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, ctx );
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK;
switch ( ctx->Depth.Func ) {
case GL_NEVER:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEVER;
break;
case GL_LESS:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LESS;
break;
case GL_EQUAL:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_EQUAL;
break;
case GL_LEQUAL:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LEQUAL;
break;
case GL_GREATER:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GREATER;
break;
case GL_NOTEQUAL:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEQUAL;
break;
case GL_GEQUAL:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GEQUAL;
break;
case GL_ALWAYS:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_ALWAYS;
break;
}
}
static void radeonDepthMask( GLcontext *ctx, GLboolean flag )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, ctx );
if ( ctx->Depth.Mask ) {
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_WRITE_ENABLE;
} else {
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->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
RADEON_DEPTH_FORMAT_MASK);
switch ( format ) {
case RADEON_DEPTH_FORMAT_16BIT_INT_Z:
rmesa->state.depth.clear = d * 0x0000ffff;
break;
case RADEON_DEPTH_FORMAT_24BIT_INT_Z:
rmesa->state.depth.clear = d * 0x00ffffff;
break;
}
}
static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
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:
break;
default:
return;
}
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;
}
}
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;
if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
rmesa->state.scissor.numAllocedClipRects += 1;
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);
if ( rmesa->dri.drawable ) {
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
int x = ctx->Scissor.X;
int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
int h = dPriv->h - ctx->Scissor.Y - 1;
rmesa->state.scissor.rect.x1 = x + dPriv->x;
rmesa->state.scissor.rect.y1 = y + dPriv->y;
rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
radeonRecalcScissorRects( rmesa );
}
}
static void radeonScissor( GLcontext *ctx,
GLint x, GLint y, GLsizei w, GLsizei h )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if ( ctx->Scissor.Enabled ) {
RADEON_FIREVERTICES( rmesa );
radeonUpdateScissor( ctx );
}
}
static void radeonCullFace( GLcontext *ctx, GLenum unused )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
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->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;
}
}
static void radeonFrontFace( GLcontext *ctx, GLenum mode )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
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->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CW;
break;
case GL_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;
}
}
static void radeonLineWidth( GLcontext *ctx, GLfloat widthf )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, lin );
RADEON_STATECHANGE( rmesa, set );
rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (GLuint)(widthf * 16.0);
if ( widthf > 1.0 ) {
rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_WIDELINE_ENABLE;
} else {
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_WIDELINE_ENABLE;
}
}
static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, lin );
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
}
static void radeonColorMask( GLcontext *ctx,
GLboolean r, GLboolean g,
GLboolean b, GLboolean a )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint mask = radeonPackColor( rmesa->radeonScreen->cpp,
ctx->Color.ColorMask[RCOMP],
ctx->Color.ColorMask[GCOMP],
ctx->Color.ColorMask[BCOMP],
ctx->Color.ColorMask[ACOMP] );
if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
RADEON_STATECHANGE( rmesa, msk );
rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
}
}
static void radeonPolygonOffset( GLcontext *ctx,
GLfloat factor, GLfloat units )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLfloat constant = units * rmesa->state.depth.scale;
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;
for ( i = 0 ; i < 32 ; i++ ) {
rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
}
RADEON_FIREVERTICES( rmesa );
LOCK_HARDWARE( rmesa );
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;
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag);
if (rmesa->TclFallback) {
radeonChooseRenderState( ctx );
radeonChooseVertexState( ctx );
}
}
static void radeonUpdateSpecular( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
CARD32 p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
RADEON_STATECHANGE( rmesa, tcl );
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;
p &= ~RADEON_SPECULAR_ENABLE;
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_DIFFUSE_SPECULAR_COMBINE;
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;
p |= RADEON_SPECULAR_ENABLE;
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &=
~RADEON_DIFFUSE_SPECULAR_COMBINE;
}
else if (ctx->Light.Enabled) {
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
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_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
p |= RADEON_SPECULAR_ENABLE;
} else {
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
}
if (ctx->Fog.Enabled) {
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
}
if ( ctx->_TriangleCaps & DD_SEPARATE_SPECULAR ) {
assert( (p & RADEON_SPECULAR_ENABLE) != 0 );
} else {
assert( (p & RADEON_SPECULAR_ENABLE) == 0 );
}
if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
RADEON_STATECHANGE( rmesa, ctx );
rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
}
if (rmesa->TclFallback) {
radeonChooseRenderState( ctx );
radeonChooseVertexState( ctx );
}
}
static void update_global_ambient( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
float *fcmd = (float *)RADEON_DB_STATE( glt );
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);
}
static void update_light_colors( GLcontext *ctx, GLuint p )
{
struct gl_light *l = &ctx->Light.Light[p];
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] );
}
}
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;
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__);
}
static void update_light( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
{
GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
if (ctx->_NeedEyeCoords)
tmp &= ~RADEON_LIGHT_IN_MODELSPACE;
else
tmp |= RADEON_LIGHT_IN_MODELSPACE;
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 );
}
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:
break;
case GL_POSITION: {
GLuint flag;
GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
if (p&1)
flag = RADEON_LIGHT_1_IS_LOCAL;
else
flag = RADEON_LIGHT_0_IS_LOCAL;
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;
}
switch (pname) {
case GL_POSITION:
case GL_LINEAR_ATTENUATION:
case GL_QUADRATIC_ATTENUATION:
{
GLuint flag;
GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
if (p&1)
flag = RADEON_LIGHT_1_ENABLE_RANGE_ATTEN;
else
flag = RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
RADEON_STATECHANGE(rmesa, tcl);
if (l->EyePosition[3] != 0.0F &&
(l->LinearAttenuation != 0.0F || l->QuadraticAttenuation != 0.0F))
rmesa->hw.tcl.cmd[idx] |= flag;
else
rmesa->hw.tcl.cmd[idx] &= ~flag;
break;
}
default:
break;
}
}
static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
const GLfloat *param )
{
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);
break;
default:
break;
}
}
static void radeonShadeModel( GLcontext *ctx, GLenum mode )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
s &= ~(RADEON_DIFFUSE_SHADE_MASK |
RADEON_ALPHA_SHADE_MASK |
RADEON_SPECULAR_SHADE_MASK |
RADEON_FOG_SHADE_MASK);
switch ( mode ) {
case GL_FLAT:
s |= (RADEON_DIFFUSE_SHADE_FLAT |
RADEON_ALPHA_SHADE_FLAT |
RADEON_SPECULAR_SHADE_FLAT |
RADEON_FOG_SHADE_FLAT);
break;
case GL_SMOOTH:
s |= (RADEON_DIFFUSE_SHADE_GOURAUD |
RADEON_ALPHA_SHADE_GOURAUD |
RADEON_SPECULAR_SHADE_GOURAUD |
RADEON_FOG_SHADE_GOURAUD);
break;
default:
return;
}
if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
RADEON_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_SE_CNTL] = s;
}
}
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];
}
}
}
static void radeonStencilFunc( GLcontext *ctx, GLenum func,
GLint ref, GLuint mask )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint refmask = ((ctx->Stencil.Ref[0] << RADEON_STENCIL_REF_SHIFT) |
(ctx->Stencil.ValueMask[0] << RADEON_STENCIL_MASK_SHIFT));
RADEON_STATECHANGE( rmesa, ctx );
RADEON_STATECHANGE( rmesa, msk );
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[0] ) {
case GL_NEVER:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER;
break;
case GL_LESS:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS;
break;
case GL_EQUAL:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL;
break;
case GL_LEQUAL:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL;
break;
case GL_GREATER:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER;
break;
case GL_NOTEQUAL:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL;
break;
case GL_GEQUAL:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL;
break;
case GL_ALWAYS:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS;
break;
}
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
}
static void radeonStencilMask( GLcontext *ctx, GLuint mask )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
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,
GLenum zfail, GLenum zpass )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
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[0] ) {
case GL_KEEP:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP;
break;
case GL_ZERO:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO;
break;
case GL_REPLACE:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE;
break;
case GL_INCR:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC;
break;
case GL_DECR:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC;
break;
case GL_INVERT:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT;
break;
}
switch ( ctx->Stencil.ZFailFunc[0] ) {
case GL_KEEP:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP;
break;
case GL_ZERO:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO;
break;
case GL_REPLACE:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE;
break;
case GL_INCR:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC;
break;
case GL_DECR:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC;
break;
case GL_INVERT:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT;
break;
}
switch ( ctx->Stencil.ZPassFunc[0] ) {
case GL_KEEP:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP;
break;
case GL_ZERO:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO;
break;
case GL_REPLACE:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE;
break;
case GL_INCR:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC;
break;
case GL_DECR:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC;
break;
case GL_INVERT:
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT;
break;
}
}
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[0] << RADEON_STENCIL_WRITEMASK_SHIFT));
}
#define SUBPIXEL_X 0.125
#define SUBPIXEL_Y 0.125
void radeonUpdateWindow( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
GLfloat xoffset = (GLfloat)dPriv->x;
GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
const GLfloat *v = ctx->Viewport._WindowMap.m;
GLfloat sx = v[MAT_SX];
GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
GLfloat sy = - v[MAT_SY];
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;
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;
}
static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height )
{
RADEON_FIREVERTICES( RADEON_CONTEXT(ctx) );
radeonUpdateWindow( ctx );
}
static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
GLclampd farval )
{
radeonUpdateWindow( ctx );
}
void radeonUpdateViewportOffset( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
GLfloat xoffset = (GLfloat)dPriv->x;
GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
const GLfloat *v = ctx->Viewport._WindowMap.m;
GLfloat tx = v[MAT_TX] + xoffset;
GLfloat ty = (- v[MAT_TY]) + yoffset;
if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
{
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
{
GLuint stx, sty;
GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
m &= ~(RADEON_STIPPLE_X_OFFSET_MASK |
RADEON_STIPPLE_Y_OFFSET_MASK);
stx = 31 - ((rmesa->dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK);
sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
& RADEON_STIPPLE_COORD_MASK);
m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) |
(sty << RADEON_STIPPLE_Y_OFFSET_SHIFT));
if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
RADEON_STATECHANGE( rmesa, msc );
rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
}
}
}
radeonUpdateScissor( ctx );
}
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] );
}
static void radeonRenderMode( GLcontext *ctx, GLenum mode )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
}
static GLuint radeon_rop_tab[] = {
RADEON_ROP_CLEAR,
RADEON_ROP_AND,
RADEON_ROP_AND_REVERSE,
RADEON_ROP_COPY,
RADEON_ROP_AND_INVERTED,
RADEON_ROP_NOOP,
RADEON_ROP_XOR,
RADEON_ROP_OR,
RADEON_ROP_NOR,
RADEON_ROP_EQUIV,
RADEON_ROP_INVERT,
RADEON_ROP_OR_REVERSE,
RADEON_ROP_COPY_INVERTED,
RADEON_ROP_OR_INVERTED,
RADEON_ROP_NAND,
RADEON_ROP_SET,
};
static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
GLuint rop = (GLuint)opcode - GL_CLEAR;
ASSERT( rop < 16 );
RADEON_STATECHANGE( rmesa, msk );
rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop];
}
void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode )
{
__DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
switch ( mode ) {
case GL_FRONT_LEFT:
rmesa->numClipRects = dPriv->numClipRects;
rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
break;
case GL_BACK_LEFT:
if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
rmesa->numClipRects = dPriv->numClipRects;
rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
}
else {
rmesa->numClipRects = dPriv->numBackClipRects;
rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pBackClipRects;
}
break;
default:
fprintf(stderr, "bad mode in radeonSetCliprects\n");
return;
}
if (rmesa->state.scissor.enabled)
radeonRecalcScissorRects( rmesa );
}
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);
switch ( ctx->Color._DrawDestMask ) {
case FRONT_LEFT_BIT:
FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
radeonSetCliprects( rmesa, GL_FRONT_LEFT );
break;
case BACK_LEFT_BIT:
FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
radeonSetCliprects( rmesa, GL_BACK_LEFT );
break;
default:
FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
return;
}
_swrast_DrawBuffer(ctx, mode);
RADEON_STATECHANGE( rmesa, ctx );
rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((rmesa->state.color.drawOffset +
rmesa->radeonScreen->fbLocation)
& RADEON_COLOROFFSET_MASK);
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
}
static void radeonReadBuffer( 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_STATE )
fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
_mesa_lookup_enum_by_nr( cap ),
state ? "GL_TRUE" : "GL_FALSE" );
switch ( cap ) {
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
break;
case GL_ALPHA_TEST:
RADEON_STATECHANGE( rmesa, ctx );
if (state) {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE;
} else {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE;
}
break;
case GL_BLEND:
RADEON_STATECHANGE( rmesa, ctx );
if (state) {
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->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
}
if (state) {
ctx->Driver.BlendEquation( ctx, ctx->Color.BlendEquation );
ctx->Driver.BlendFunc( ctx, ctx->Color.BlendSrcRGB,
ctx->Color.BlendDstRGB );
}
else {
FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE );
FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, GL_FALSE );
}
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, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_Z_ENABLE;
} else {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE;
}
break;
case GL_DITHER:
RADEON_STATECHANGE(rmesa, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
} else {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE;
}
break;
case GL_FOG:
RADEON_STATECHANGE(rmesa, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE;
radeonFogfv( ctx, GL_FOG_MODE, 0 );
} else {
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 );
if (rmesa->TclFallback)
radeonChooseVertexState( ctx );
_mesa_allow_light_in_model( ctx, !state );
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);
radeonUpdateSpecular(ctx);
check_twoside_fallback( ctx );
break;
case GL_LINE_SMOOTH:
RADEON_STATECHANGE( rmesa, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_LINE;
} else {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE;
}
break;
case GL_LINE_STIPPLE:
RADEON_STATECHANGE( rmesa, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_PATTERN_ENABLE;
} else {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE;
}
break;
case GL_COLOR_LOGIC_OP:
RADEON_STATECHANGE( rmesa, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
} else {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
}
break;
case GL_NORMALIZE:
RADEON_STATECHANGE( rmesa, tcl );
if ( state ) {
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_NORMALIZE_NORMALS;
} else {
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS;
}
break;
case GL_POLYGON_OFFSET_POINT:
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, 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, 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, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_POLY;
} else {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY;
}
break;
case GL_POLYGON_STIPPLE:
RADEON_STATECHANGE(rmesa, ctx );
if ( state ) {
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->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
}
break;
}
case GL_SCISSOR_TEST:
RADEON_FIREVERTICES( rmesa );
rmesa->state.scissor.enabled = state;
radeonUpdateScissor( ctx );
break;
case GL_STENCIL_TEST:
if ( rmesa->state.stencil.hwBuffer ) {
RADEON_STATECHANGE( rmesa, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE;
} else {
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:
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 BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
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;
}
if (RADEON_DEBUG & DEBUG_STATE)
fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
}
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];
}
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
}
static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
{
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;
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)) {
_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 );
}
}
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;
}
}
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;
}
if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
if (new_state & (_NEW_MODELVIEW)) {
upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL );
upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT );
}
if (new_state & _NEW_TEXTURE_MATRIX) {
update_texturematrix( ctx );
}
if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
update_light( ctx );
}
if (new_state & (_NEW_PROJECTION)) {
if (ctx->Transform.ClipPlanesEnabled)
radeonUpdateClipPlanes( ctx );
}
rmesa->NewGLState = 0;
}
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 );
}
static void radeonWrapRunPipeline( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
if (0)
fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
if (rmesa->NewGLState)
radeonValidateState( ctx );
if (tnl->vb.Material) {
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE );
}
_tnl_run_pipeline( ctx );
if (tnl->vb.Material) {
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE );
radeonUpdateMaterial( ctx );
}
}
void radeonInitStateFuncs( GLcontext *ctx )
{
ctx->Driver.UpdateState = radeonInvalidateState;
ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange;
ctx->Driver.DrawBuffer = radeonDrawBuffer;
ctx->Driver.ReadBuffer = radeonReadBuffer;
ctx->Driver.AlphaFunc = radeonAlphaFunc;
ctx->Driver.BlendEquation = radeonBlendEquation;
ctx->Driver.BlendFunc = radeonBlendFunc;
ctx->Driver.BlendFuncSeparate = radeonBlendFuncSeparate;
ctx->Driver.ClearColor = radeonClearColor;
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;
ctx->Driver.DepthMask = radeonDepthMask;
ctx->Driver.DepthRange = radeonDepthRange;
ctx->Driver.Enable = radeonEnable;
ctx->Driver.Fogfv = radeonFogfv;
ctx->Driver.FrontFace = radeonFrontFace;
ctx->Driver.Hint = NULL;
ctx->Driver.IndexMask = NULL;
ctx->Driver.LightModelfv = radeonLightModelfv;
ctx->Driver.Lightfv = radeonLightfv;
ctx->Driver.LineStipple = radeonLineStipple;
ctx->Driver.LineWidth = radeonLineWidth;
ctx->Driver.LogicOpcode = radeonLogicOpCode;
ctx->Driver.PolygonMode = radeonPolygonMode;
ctx->Driver.PolygonOffset = radeonPolygonOffset;
ctx->Driver.PolygonStipple = radeonPolygonStipple;
ctx->Driver.RenderMode = radeonRenderMode;
ctx->Driver.Scissor = radeonScissor;
ctx->Driver.ShadeModel = radeonShadeModel;
ctx->Driver.StencilFunc = radeonStencilFunc;
ctx->Driver.StencilMask = radeonStencilMask;
ctx->Driver.StencilOp = radeonStencilOp;
ctx->Driver.Viewport = radeonViewport;
ctx->Driver.Accum = _swrast_Accum;
ctx->Driver.Bitmap = _swrast_Bitmap;
ctx->Driver.CopyPixels = _swrast_CopyPixels;
ctx->Driver.DrawPixels = _swrast_DrawPixels;
ctx->Driver.ReadPixels = _swrast_ReadPixels;
ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
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;
}