diff options
Diffstat (limited to 'src/mesa/drivers/dri/mga/mgastate.c')
-rw-r--r-- | src/mesa/drivers/dri/mga/mgastate.c | 1297 |
1 files changed, 722 insertions, 575 deletions
diff --git a/src/mesa/drivers/dri/mga/mgastate.c b/src/mesa/drivers/dri/mga/mgastate.c index 02b98fdb766..0d304966d7e 100644 --- a/src/mesa/drivers/dri/mga/mgastate.c +++ b/src/mesa/drivers/dri/mga/mgastate.c @@ -26,9 +26,9 @@ */ /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgastate.c,v 1.13 2002/10/30 12:51:36 alanh Exp $ */ -#include <stdio.h> #include "mtypes.h" +#include "colormac.h" #include "dd.h" #include "mm.h" @@ -40,19 +40,22 @@ #include "mgatris.h" #include "mgaioctl.h" #include "mgaregs.h" -#include "mgabuffers.h" #include "swrast/swrast.h" #include "array_cache/acache.h" #include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" #include "swrast_setup/swrast_setup.h" +static void updateSpecularLighting( GLcontext *ctx ); + /* Some outstanding problems with accelerating logic ops... */ #if defined(ACCEL_ROP) -static GLuint mgarop_NoBLK[16] = { +static const GLuint mgarop_NoBLK[16] = { DC_atype_rpl | 0x00000000, DC_atype_rstr | 0x00080000, DC_atype_rstr | 0x00040000, DC_atype_rpl | 0x000c0000, DC_atype_rstr | 0x00020000, DC_atype_rstr | 0x000a0000, @@ -65,221 +68,57 @@ static GLuint mgarop_NoBLK[16] = { #endif -static void mgaUpdateStencil(const GLcontext *ctx) -{ - mgaContextPtr mmesa = MGA_CONTEXT(ctx); - GLuint stencil = 0, stencilctl = 0; - - if (ctx->Stencil.Enabled) - { - stencil = ctx->Stencil.Ref[0] | - ( ctx->Stencil.ValueMask[0] << 8 ) | - ( ctx->Stencil.WriteMask[0] << 16 ); - - switch (ctx->Stencil.Function[0]) - { - case GL_NEVER: - MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_snever); - break; - case GL_LESS: - MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_slt); - break; - case GL_LEQUAL: - MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_slte); - break; - case GL_GREATER: - MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sgt); - break; - case GL_GEQUAL: - MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sgte); - break; - case GL_NOTEQUAL: - MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sne); - break; - case GL_EQUAL: - MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_se); - break; - case GL_ALWAYS: - MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_salways); - default: - break; - } - - switch (ctx->Stencil.FailFunc[0]) - { - case GL_KEEP: - MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_keep); - break; - case GL_ZERO: - MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_zero); - break; - case GL_REPLACE: - MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_replace); - break; - case GL_INCR: - MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_incrsat); - break; - case GL_DECR: - MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_decrsat); - break; - case GL_INVERT: - MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_invert); - break; - default: - break; - } - - switch (ctx->Stencil.ZFailFunc[0]) - { - case GL_KEEP: - MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_keep); - break; - case GL_ZERO: - MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_zero); - break; - case GL_REPLACE: - MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_replace); - break; - case GL_INCR: - MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_incrsat); - break; - case GL_DECR: - MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_decrsat); - break; - case GL_INVERT: - MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_invert); - break; - default: - break; - } - - switch (ctx->Stencil.ZPassFunc[0]) - { - case GL_KEEP: - MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_keep); - break; - case GL_ZERO: - MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_zero); - break; - case GL_REPLACE: - MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_replace); - break; - case GL_INCR: - MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_incrsat); - break; - case GL_DECR: - MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_decrsat); - break; - case GL_INVERT: - MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_invert); - break; - default: - break; - } - } - - mmesa->setup.stencil = stencil; - mmesa->setup.stencilctl = stencilctl; - mmesa->dirty |= MGA_UPLOAD_CONTEXT; -} - -static void mgaDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref, - GLuint mask) -{ - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL; -} - -static void mgaDDStencilMask(GLcontext *ctx, GLuint mask) -{ - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL; -} - -static void mgaDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail, - GLenum zpass) -{ - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL; -} +/* ============================================================= + * Alpha blending + */ -static void mgaDDClearDepth(GLcontext *ctx, GLclampd d) +static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLubyte refByte; + GLuint a; - /* KW: should the ~ be there? */ - switch (mmesa->setup.maccess & ~MA_zwidth_MASK) { - case MA_zwidth_16: mmesa->ClearDepth = d * 0x0000ffff; break; - case MA_zwidth_24: mmesa->ClearDepth = d * 0xffffff00; break; - case MA_zwidth_32: mmesa->ClearDepth = d * 0xffffffff; break; - default: return; - } -} - -static void mgaUpdateZMode(const GLcontext *ctx) -{ - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - int zmode = 0; - - if (ctx->Depth.Test) { - switch(ctx->Depth.Func) { - case GL_NEVER: - /* can't do this in h/w, we'll use a s/w fallback */ - zmode = DC_zmode_nozcmp; - break; - case GL_ALWAYS: - zmode = DC_zmode_nozcmp; break; - case GL_LESS: - zmode = DC_zmode_zlt; break; - case GL_LEQUAL: - zmode = DC_zmode_zlte; break; - case GL_EQUAL: - zmode = DC_zmode_ze; break; - case GL_GREATER: - zmode = DC_zmode_zgt; break; - case GL_GEQUAL: - zmode = DC_zmode_zgte; break; - case GL_NOTEQUAL: - zmode = DC_zmode_zne; break; - default: - break; - } + CLAMPED_FLOAT_TO_UBYTE(refByte, ref); - if (ctx->Depth.Mask) - zmode |= DC_atype_zi; - else - zmode |= DC_atype_i; - } - else { - zmode |= DC_zmode_nozcmp; - zmode |= DC_atype_i; /* don't write to zbuffer */ + switch ( func ) { + case GL_NEVER: + a = AC_atmode_alt; + refByte = 0; + break; + case GL_LESS: + a = AC_atmode_alt; + break; + case GL_GEQUAL: + a = AC_atmode_agte; + break; + case GL_LEQUAL: + a = AC_atmode_alte; + break; + case GL_GREATER: + a = AC_atmode_agt; + break; + case GL_NOTEQUAL: + a = AC_atmode_ane; + break; + case GL_EQUAL: + a = AC_atmode_ae; + break; + case GL_ALWAYS: + a = AC_atmode_noacmp; + break; + default: + a = 0; + break; } -#if defined(ACCEL_ROP) - mmesa->setup.dwgctl &= DC_bop_MASK; - if (ctx->Color.ColorLogicOpEnabled) - zmode |= mgarop_NoBLK[(ctx->Color.LogicOp)&0xf]; - else - zmode |= mgarop_NoBLK[GL_COPY & 0xf]; -#endif - - mmesa->setup.dwgctl &= DC_zmode_MASK & DC_atype_MASK; - mmesa->setup.dwgctl |= zmode; + FLUSH_BATCH( mmesa ); + mmesa->hw.alpha_func = a | MGA_FIELD( AC_atref, refByte ); mmesa->dirty |= MGA_UPLOAD_CONTEXT; } - -static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) -{ - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA; -} - - static void mgaDDBlendEquation(GLcontext *ctx, GLenum mode) { FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA; /* BlendEquation sets ColorLogicOpEnabled in an unexpected * manner. @@ -291,247 +130,169 @@ static void mgaDDBlendEquation(GLcontext *ctx, GLenum mode) static void mgaDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) { - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA; + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + mgaScreenPrivate *mgaScreen = mmesa->mgaScreen; + GLuint src; + GLuint dst; + + switch (ctx->Color.BlendSrcRGB) { + case GL_ZERO: + src = AC_src_zero; break; + case GL_SRC_ALPHA: + src = AC_src_src_alpha; break; + case GL_ONE: + default: /* never happens */ + src = AC_src_one; break; + case GL_DST_COLOR: + src = AC_src_dst_color; break; + case GL_ONE_MINUS_DST_COLOR: + src = AC_src_om_dst_color; break; + case GL_ONE_MINUS_SRC_ALPHA: + src = AC_src_om_src_alpha; break; + case GL_DST_ALPHA: + src = (mgaScreen->cpp == 4) + ? AC_src_dst_alpha : AC_src_one; + break; + case GL_ONE_MINUS_DST_ALPHA: + src = (mgaScreen->cpp == 4) + ? AC_src_om_dst_alpha : AC_src_zero; + break; + case GL_SRC_ALPHA_SATURATE: + src = (ctx->Visual.alphaBits > 0) + ? AC_src_src_alpha_sat : AC_src_zero; + break; + } + + switch (ctx->Color.BlendDstRGB) { + case GL_SRC_ALPHA: + dst = AC_dst_src_alpha; break; + case GL_ONE_MINUS_SRC_ALPHA: + dst = AC_dst_om_src_alpha; break; + default: /* never happens */ + case GL_ZERO: + dst = AC_dst_zero; break; + case GL_ONE: + dst = AC_dst_one; break; + case GL_SRC_COLOR: + dst = AC_dst_src_color; break; + case GL_ONE_MINUS_SRC_COLOR: + dst = AC_dst_om_src_color; break; + case GL_DST_ALPHA: + dst = (mgaScreen->cpp == 4) + ? AC_dst_dst_alpha : AC_dst_one; + break; + case GL_ONE_MINUS_DST_ALPHA: + dst = (mgaScreen->cpp == 4) + ? AC_dst_om_dst_alpha : AC_dst_zero; + break; + } + + FLUSH_BATCH( mmesa ); + mmesa->hw.blend_func = (src | dst); + mmesa->dirty |= MGA_UPLOAD_CONTEXT; } static void mgaDDBlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA ) { - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA; + mgaDDBlendFunc( ctx, sfactorRGB, dfactorRGB ); } +/* ============================================================= + * Depth testing + */ -static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname, - const GLfloat *param) +static void mgaDDDepthFunc(GLcontext *ctx, GLenum func) { - if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE; + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + int zmode; + + switch (func) { + case GL_NEVER: + /* can't do this in h/w, we'll use a s/w fallback */ + FALLBACK (ctx, MGA_FALLBACK_DEPTH, ctx->Depth.Test); + + /* FALLTHROUGH */ + case GL_ALWAYS: + zmode = DC_zmode_nozcmp; break; + case GL_LESS: + zmode = DC_zmode_zlt; break; + case GL_LEQUAL: + zmode = DC_zmode_zlte; break; + case GL_EQUAL: + zmode = DC_zmode_ze; break; + case GL_GREATER: + zmode = DC_zmode_zgt; break; + case GL_GEQUAL: + zmode = DC_zmode_zgte; break; + case GL_NOTEQUAL: + zmode = DC_zmode_zne; break; + default: + zmode = 0; break; } -} - -static void mgaDDShadeModel(GLcontext *ctx, GLenum mode) -{ - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE; -} - - -static void mgaDDDepthFunc(GLcontext *ctx, GLenum func) -{ - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH; + FLUSH_BATCH( mmesa ); + mmesa->hw.zmode &= DC_zmode_MASK; + mmesa->hw.zmode |= zmode; + mmesa->dirty |= MGA_UPLOAD_CONTEXT; } static void mgaDDDepthMask(GLcontext *ctx, GLboolean flag) { - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH; -} + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); -#if defined(ACCEL_ROP) -static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode ) -{ - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH; -} -#else -static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode ) -{ - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - FALLBACK( ctx, MGA_FALLBACK_LOGICOP, - (ctx->Color.ColorLogicOpEnabled && opcode != GL_COPY) ); -} -#endif + FLUSH_BATCH( mmesa ); + mmesa->hw.zmode &= DC_atype_MASK; + mmesa->hw.zmode |= (flag) ? DC_atype_zi : DC_atype_i; + mmesa->dirty |= MGA_UPLOAD_CONTEXT; +} -static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) +static void mgaDDClearDepth(GLcontext *ctx, GLclampd d) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); - if (pname == GL_FOG_COLOR) { - GLuint color = MGAPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F), - (GLubyte)(ctx->Fog.Color[1]*255.0F), - (GLubyte)(ctx->Fog.Color[2]*255.0F)); - - MGA_STATECHANGE(mmesa, MGA_UPLOAD_CONTEXT); - mmesa->setup.fogcolor = color; + /* Select the Z depth. The ~ is used because the _MASK values in the + * MGA driver are used to mask OFF the selected bits. In this case, + * we want to mask off everything except the MA_zwidth bits. + */ + switch (mmesa->setup.maccess & ~MA_zwidth_MASK) { + case MA_zwidth_16: mmesa->ClearDepth = d * 0x0000ffff; break; + case MA_zwidth_24: mmesa->ClearDepth = d * 0xffffff00; break; + case MA_zwidth_32: mmesa->ClearDepth = d * 0xffffffff; break; + default: return; } } - - /* ============================================================= - * Alpha blending + * Fog */ -static void mgaUpdateAlphaMode(GLcontext *ctx) +static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) { - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - mgaScreenPrivate *mgaScreen = mmesa->mgaScreen; - int a = 0; - - /* determine source of alpha for blending and testing */ - if ( !ctx->Texture.Unit[0]._ReallyEnabled ) { - a |= AC_alphasel_diffused; - } - else { - /* G400: Regardless of texture env mode, we use the alpha from the - * texture unit (AC_alphasel_fromtex) since it will have already - * been modulated by the incoming fragment color, if needed. - * We don't want (AC_alphasel_modulate) since that'll effectively - * do the modulation twice. - */ - if (MGA_IS_G400(mmesa)) { - a |= AC_alphasel_fromtex; - } - else { - /* G200 */ - switch (ctx->Texture.Unit[0].EnvMode) { - case GL_DECAL: - a |= AC_alphasel_diffused; - case GL_REPLACE: - a |= AC_alphasel_fromtex; - break; - case GL_BLEND: - case GL_MODULATE: - a |= AC_alphasel_modulated; - break; - default: - break; - } - } - } - - - /* alpha test control. - */ - if (ctx->Color.AlphaEnabled) { - GLubyte ref = ctx->Color.AlphaRef; - switch (ctx->Color.AlphaFunc) { - case GL_NEVER: - a |= AC_atmode_alt; - ref = 0; - break; - case GL_LESS: - a |= AC_atmode_alt; - break; - case GL_GEQUAL: - a |= AC_atmode_agte; - break; - case GL_LEQUAL: - a |= AC_atmode_alte; - break; - case GL_GREATER: - a |= AC_atmode_agt; - break; - case GL_NOTEQUAL: - a |= AC_atmode_ane; - break; - case GL_EQUAL: - a |= AC_atmode_ae; - break; - case GL_ALWAYS: - a |= AC_atmode_noacmp; - break; - default: - break; - } - a |= MGA_FIELD(AC_atref,ref); - } + mgaContextPtr mmesa = MGA_CONTEXT(ctx); - /* blending control */ - if (ctx->Color.BlendEnabled) { - switch (ctx->Color.BlendSrcRGB) { - case GL_ZERO: - a |= AC_src_zero; break; - case GL_SRC_ALPHA: - a |= AC_src_src_alpha; break; - case GL_ONE: - a |= AC_src_one; break; - case GL_DST_COLOR: - a |= AC_src_dst_color; break; - case GL_ONE_MINUS_DST_COLOR: - a |= AC_src_om_dst_color; break; - case GL_ONE_MINUS_SRC_ALPHA: - a |= AC_src_om_src_alpha; break; - case GL_DST_ALPHA: - if (mgaScreen->cpp == 4) - a |= AC_src_dst_alpha; - else - a |= AC_src_one; - break; - case GL_ONE_MINUS_DST_ALPHA: - if (mgaScreen->cpp == 4) - a |= AC_src_om_dst_alpha; - else - a |= AC_src_zero; - break; - case GL_SRC_ALPHA_SATURATE: - if (ctx->Visual.alphaBits > 0) - a |= AC_src_src_alpha_sat; - else - a |= AC_src_zero; - break; - default: /* never happens */ - break; - } + if (pname == GL_FOG_COLOR) { + GLuint color = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F), + (GLubyte)(ctx->Fog.Color[1]*255.0F), + (GLubyte)(ctx->Fog.Color[2]*255.0F)); - switch (ctx->Color.BlendDstRGB) { - case GL_SRC_ALPHA: - a |= AC_dst_src_alpha; break; - case GL_ONE_MINUS_SRC_ALPHA: - a |= AC_dst_om_src_alpha; break; - case GL_ZERO: - a |= AC_dst_zero; break; - case GL_ONE: - a |= AC_dst_one; break; - case GL_SRC_COLOR: - a |= AC_dst_src_color; break; - case GL_ONE_MINUS_SRC_COLOR: - a |= AC_dst_om_src_color; break; - case GL_DST_ALPHA: - if (mgaScreen->cpp == 4) - a |= AC_dst_dst_alpha; - else - a |= AC_dst_one; - break; - case GL_ONE_MINUS_DST_ALPHA: - if (mgaScreen->cpp == 4) - a |= AC_dst_om_dst_alpha; - else - a |= AC_dst_zero; - break; - default: /* never happens */ - break; - } - } else { - a |= AC_src_one|AC_dst_zero; + MGA_STATECHANGE(mmesa, MGA_UPLOAD_CONTEXT); + mmesa->setup.fogcolor = color; } - - mmesa->setup.alphactrl = (AC_amode_alpha_channel | - AC_astipple_disable | - AC_aten_disable | - AC_atmode_noacmp | - a); - - mmesa->dirty |= MGA_UPLOAD_CONTEXT; } - /* ============================================================= - * Hardware clipping + * Scissoring */ + void mgaUpdateClipping(const GLcontext *ctx) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); @@ -554,13 +315,6 @@ void mgaUpdateClipping(const GLcontext *ctx) mmesa->scissor_rect.x2 = x2; mmesa->scissor_rect.y2 = y2; - if (MGA_DEBUG&DEBUG_VERBOSE_2D) - fprintf(stderr, "SET SCISSOR %d,%d-%d,%d\n", - mmesa->scissor_rect.x1, - mmesa->scissor_rect.y1, - mmesa->scissor_rect.x2, - mmesa->scissor_rect.y2); - mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; } } @@ -569,19 +323,10 @@ void mgaUpdateClipping(const GLcontext *ctx) static void mgaDDScissor( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h ) { - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CLIP; -} - - -static void mgaDDClearColor(GLcontext *ctx, - const GLfloat color[4] ) -{ - mgaContextPtr mmesa = MGA_CONTEXT(ctx); - - mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp, - color[0], color[1], - color[2], color[3]); + if ( ctx->Scissor.Enabled ) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); /* don't pipeline cliprect changes */ + mgaUpdateClipping( ctx ); + } } @@ -589,46 +334,42 @@ static void mgaDDClearColor(GLcontext *ctx, * Culling */ + #define _CULL_DISABLE 0 #define _CULL_NEGATIVE ((1<<11)|(1<<5)|(1<<16)) #define _CULL_POSITIVE (1<<11) - -void mgaUpdateCull( GLcontext *ctx ) +static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum unused) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); - GLuint mode = _CULL_DISABLE; + + FLUSH_BATCH( mmesa ); if (ctx->Polygon.CullFlag && - mmesa->raster_primitive == GL_TRIANGLES && ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) { - mode = _CULL_NEGATIVE; + mmesa->hw.cull = _CULL_NEGATIVE; + if (ctx->Polygon.CullFaceMode == GL_FRONT) - mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE); + mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE); + if (ctx->Polygon.FrontFace != GL_CCW) - mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE); - if ((ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_2D_BIT) && - (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_2D_BIT)) - mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE); /* warp bug? */ + mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE); + + mmesa->hw.cull_dualtex = mmesa->hw.cull ^ + (_CULL_POSITIVE ^ _CULL_NEGATIVE); /* warp bug? */ + } + else { + mmesa->hw.cull = _CULL_DISABLE; + mmesa->hw.cull_dualtex = _CULL_DISABLE; } - mmesa->setup.wflag = mode; mmesa->dirty |= MGA_UPLOAD_CONTEXT; } -static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum mode) -{ - FLUSH_BATCH( MGA_CONTEXT(ctx) ); - MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CULL; -} - - - - /* ============================================================= - * Color masks + * Masks */ static void mgaDDColorMask(GLcontext *ctx, @@ -654,15 +395,11 @@ static void mgaDDColorMask(GLcontext *ctx, } } + /* ============================================================= - * Polygon stipple - * - * The mga supports a subset of possible 4x4 stipples natively, GL - * wants 32x32. Fortunately stipple is usually a repeating pattern. - * - * Note: the fully opaque pattern (0xffff) has been disabled in order - * to work around a conformance issue. + * Polygon state */ + static int mgaStipples[16] = { 0xffff1, /* See above note */ 0xa5a5, @@ -682,6 +419,17 @@ static int mgaStipples[16] = { 0x0000 }; +/** + * The MGA supports a subset of possible 4x4 stipples natively, GL + * wants 32x32. Fortunately stipple is usually a repeating pattern. + * + * \param ctx GL rendering context to be affected + * \param mask Pointer to the 32x32 stipple mask + * + * \note the fully opaque pattern (0xffff) has been disabled in order + * to work around a conformance issue. + */ + static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask ) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); @@ -730,93 +478,216 @@ static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask ) } } + /* ============================================================= + * Rendering attributes + * + * We really don't want to recalculate all this every time we bind a + * texture. These things shouldn't change all that often, so it makes + * sense to break them out of the core texture state update routines. */ -static void mgaDDPrintDirty( const char *msg, GLuint state ) +static void updateSpecularLighting( GLcontext *ctx ) { - fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s%s\n", - msg, - (unsigned int) state, - (state & MGA_WAIT_AGE) ? "wait-age, " : "", - (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img, " : "", - (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img, " : "", - (state & MGA_UPLOAD_CONTEXT) ? "upload-ctx, " : "", - (state & MGA_UPLOAD_TEX0) ? "upload-tex0, " : "", - (state & MGA_UPLOAD_TEX1) ? "upload-tex1, " : "", - (state & MGA_UPLOAD_PIPE) ? "upload-pipe, " : "" - ); + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + unsigned int specen; + + specen = (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR && + ctx->Light.Enabled) ? TMC_specen_enable : 0; + + if ( specen != mmesa->hw.specen ) { + mmesa->hw.specen = specen; + mmesa->dirty |= MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1; + + mgaChooseVertexState( ctx ); + } } -/* Push the state into the sarea and/or texture memory. + +/* ============================================================= + * Materials */ -void mgaEmitHwStateLocked( mgaContextPtr mmesa ) -{ - MGASAREAPrivPtr sarea = mmesa->sarea; - if (MGA_DEBUG & DEBUG_VERBOSE_MSG) - mgaDDPrintDirty( "mgaEmitHwStateLocked", mmesa->dirty ); - if ((mmesa->dirty & MGA_UPLOAD_TEX0IMAGE) && mmesa->CurrentTexObj[0]) - mgaUploadTexImages(mmesa, mmesa->CurrentTexObj[0]); +static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname, + const GLfloat *param) +{ + if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { + FLUSH_BATCH( MGA_CONTEXT(ctx) ); + updateSpecularLighting( ctx ); + } +} - if ((mmesa->dirty & MGA_UPLOAD_TEX1IMAGE) && mmesa->CurrentTexObj[1]) - mgaUploadTexImages(mmesa, mmesa->CurrentTexObj[1]); - if (mmesa->dirty & MGA_UPLOAD_CONTEXT) { - memcpy( &sarea->ContextState, &mmesa->setup, sizeof(mmesa->setup)); - } +static void mgaDDShadeModel(GLcontext *ctx, GLenum mode) +{ + /* FIXME: This used to FLUSH_BATCH and set MGA_NEW_TEXTURE in new_state, + * FIXME: so I'm not sure what to do here now. + */ +} - if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) { - memcpy(&sarea->TexState[0], - &mmesa->CurrentTexObj[0]->setup, - sizeof(sarea->TexState[0])); - } - if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) { - memcpy(&sarea->TexState[1], - &mmesa->CurrentTexObj[1]->setup, - sizeof(sarea->TexState[1])); - } +/* ============================================================= + * Stencil + */ - if (sarea->TexState[0].texctl2 != - sarea->TexState[1].texctl2) { - memcpy(&sarea->TexState[1], - &sarea->TexState[0], - sizeof(sarea->TexState[0])); - mmesa->dirty |= MGA_UPLOAD_TEX1|MGA_UPLOAD_TEX0; - } - if (mmesa->dirty & MGA_UPLOAD_PIPE) { -/* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */ - mmesa->sarea->WarpPipe = mmesa->vertex_format; - mmesa->sarea->vertsize = mmesa->vertex_size; +static void mgaDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref, + GLuint mask) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint stencil; + GLuint stencilctl; + + stencil = (ref << S_sref_SHIFT) | (mask << S_smsk_SHIFT); + switch (func) + { + case GL_NEVER: + stencilctl = SC_smode_snever; + break; + case GL_LESS: + stencilctl = SC_smode_slt; + break; + case GL_LEQUAL: + stencilctl = SC_smode_slte; + break; + case GL_GREATER: + stencilctl = SC_smode_sgt; + break; + case GL_GEQUAL: + stencilctl = SC_smode_sgte; + break; + case GL_NOTEQUAL: + stencilctl = SC_smode_sne; + break; + case GL_EQUAL: + stencilctl = SC_smode_se; + break; + case GL_ALWAYS: + default: + stencilctl = SC_smode_salways; + break; } - mmesa->sarea->dirty |= mmesa->dirty; + FLUSH_BATCH( mmesa ); + mmesa->hw.stencil &= (S_sref_MASK & S_smsk_MASK); + mmesa->hw.stencil |= stencil; + mmesa->hw.stencilctl &= SC_smode_MASK; + mmesa->hw.stencilctl |= stencilctl; + mmesa->dirty |= MGA_UPLOAD_CONTEXT; +} - mmesa->dirty &= (MGA_UPLOAD_CLIPRECTS|MGA_WAIT_AGE); +static void mgaDDStencilMask(GLcontext *ctx, GLuint mask) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); - /* This is a bit of a hack but seems to be the best place to ensure - * that separate specular is disabled when not needed. - */ - if (mmesa->glCtx->Texture.Unit[0]._ReallyEnabled == 0 || - !mmesa->glCtx->Light.Enabled || - mmesa->glCtx->Light.Model.ColorControl == GL_SINGLE_COLOR) { - sarea->TexState[0].texctl2 &= ~TMC_specen_enable; - sarea->TexState[1].texctl2 &= ~TMC_specen_enable; - } + FLUSH_BATCH( mmesa ); + mmesa->hw.stencil &= S_swtmsk_MASK; + mmesa->hw.stencil |= (mask << S_swtmsk_SHIFT); + mmesa->dirty |= MGA_UPLOAD_CONTEXT; } -/* Fallback to swrast for select and feedback. - */ -static void mgaRenderMode( GLcontext *ctx, GLenum mode ) +static void mgaDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail, + GLenum zpass) { - FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) ); + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + GLuint stencilctl; + + stencilctl = 0; + switch (ctx->Stencil.FailFunc[0]) + { + case GL_KEEP: + stencilctl |= SC_sfailop_keep; + break; + case GL_ZERO: + stencilctl |= SC_sfailop_zero; + break; + case GL_REPLACE: + stencilctl |= SC_sfailop_replace; + break; + case GL_INCR: + stencilctl |= SC_sfailop_incrsat; + break; + case GL_DECR: + stencilctl |= SC_sfailop_decrsat; + break; + case GL_INCR_WRAP: + stencilctl |= SC_sfailop_incr; + break; + case GL_DECR_WRAP: + stencilctl |= SC_sfailop_decr; + break; + case GL_INVERT: + stencilctl |= SC_sfailop_invert; + break; + default: + break; + } + + switch (ctx->Stencil.ZFailFunc[0]) + { + case GL_KEEP: + stencilctl |= SC_szfailop_keep; + break; + case GL_ZERO: + stencilctl |= SC_szfailop_zero; + break; + case GL_REPLACE: + stencilctl |= SC_szfailop_replace; + break; + case GL_INCR: + stencilctl |= SC_szfailop_incrsat; + break; + case GL_DECR: + stencilctl |= SC_szfailop_decrsat; + break; + case GL_INCR_WRAP: + stencilctl |= SC_szfailop_incr; + break; + case GL_DECR_WRAP: + stencilctl |= SC_szfailop_decr; + break; + case GL_INVERT: + stencilctl |= SC_szfailop_invert; + break; + default: + break; + } + + switch (ctx->Stencil.ZPassFunc[0]) + { + case GL_KEEP: + stencilctl |= SC_szpassop_keep; + break; + case GL_ZERO: + stencilctl |= SC_szpassop_zero; + break; + case GL_REPLACE: + stencilctl |= SC_szpassop_replace; + break; + case GL_INCR: + stencilctl |= SC_szpassop_incrsat; + break; + case GL_DECR: + stencilctl |= SC_szpassop_decrsat; + break; + case GL_INVERT: + stencilctl |= SC_szpassop_invert; + break; + default: + break; + } + + FLUSH_BATCH( mmesa ); + mmesa->hw.stencilctl &= (SC_sfailop_MASK & SC_szfailop_MASK + & SC_szpassop_MASK); + mmesa->hw.stencilctl |= stencilctl; + mmesa->dirty |= MGA_UPLOAD_CONTEXT; } /* ============================================================= + * Window position and viewport transformation */ void mgaCalcViewport( GLcontext *ctx ) @@ -850,8 +721,167 @@ static void mgaDepthRange( GLcontext *ctx, mgaCalcViewport( ctx ); } + /* ============================================================= + * Miscellaneous + */ + +static void mgaDDClearColor(GLcontext *ctx, + const GLfloat color[4] ) +{ + mgaContextPtr mmesa = MGA_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]); + + mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp, + c[0], c[1], c[2], c[3]); +} + + +/* Fallback to swrast for select and feedback. */ +static void mgaRenderMode( GLcontext *ctx, GLenum mode ) +{ + FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) ); +} + + +static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + + FLUSH_BATCH( mmesa ); +#if defined(ACCEL_ROP) + mmesa->hw.rop = mgarop_NoBLK[ opcode & 0x0f ]; + mmesa->dirty |= MGA_UPLOAD_CONTEXT; +#else + FALLBACK( ctx, MGA_FALLBACK_LOGICOP, + (ctx->Color.ColorLogicOpEnabled && opcode != GL_COPY) ); +#endif +} + + +static void mgaXMesaSetFrontClipRects( mgaContextPtr mmesa ) +{ + __DRIdrawablePrivate *driDrawable = mmesa->driDrawable; + + if (driDrawable->numClipRects == 0) { + static XF86DRIClipRectRec zeroareacliprect = {0,0,0,0}; + mmesa->numClipRects = 1; + mmesa->pClipRects = &zeroareacliprect; + } else { + mmesa->numClipRects = driDrawable->numClipRects; + mmesa->pClipRects = driDrawable->pClipRects; + } + mmesa->drawX = driDrawable->x; + mmesa->drawY = driDrawable->y; + + mmesa->setup.dstorg = mmesa->drawOffset; + mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS; +} + + +static void mgaXMesaSetBackClipRects( mgaContextPtr mmesa ) +{ + __DRIdrawablePrivate *driDrawable = mmesa->driDrawable; + + if (driDrawable->numBackClipRects == 0) + { + if (driDrawable->numClipRects == 0) { + static XF86DRIClipRectRec zeroareacliprect = {0,0,0,0}; + mmesa->numClipRects = 1; + mmesa->pClipRects = &zeroareacliprect; + } else { + mmesa->numClipRects = driDrawable->numClipRects; + mmesa->pClipRects = driDrawable->pClipRects; + } + mmesa->drawX = driDrawable->x; + mmesa->drawY = driDrawable->y; + } else { + mmesa->numClipRects = driDrawable->numBackClipRects; + mmesa->pClipRects = driDrawable->pBackClipRects; + mmesa->drawX = driDrawable->backX; + mmesa->drawY = driDrawable->backY; + } + + mmesa->setup.dstorg = mmesa->drawOffset; + mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS; +} + + +void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers ) +{ + __DRIdrawablePrivate *driDrawable = mmesa->driDrawable; + MGASAREAPrivPtr sarea = mmesa->sarea; + + + DRI_VALIDATE_DRAWABLE_INFO(mmesa->driScreen, driDrawable); + mmesa->dirty_cliprects = 0; + + if (mmesa->draw_buffer == MGA_FRONT) + mgaXMesaSetFrontClipRects( mmesa ); + else + mgaXMesaSetBackClipRects( mmesa ); + + sarea->req_draw_buffer = mmesa->draw_buffer; + + mgaUpdateClipping( mmesa->glCtx ); + mgaCalcViewport( mmesa->glCtx ); + + mmesa->dirty |= MGA_UPLOAD_CLIPRECTS; +} + + +static void mgaDDDrawBuffer(GLcontext *ctx, GLenum mode ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + FLUSH_BATCH( mmesa ); + + /* + * _DrawDestMask is easier to cope with than <mode>. + */ + switch ( ctx->Color._DrawDestMask ) { + case FRONT_LEFT_BIT: + mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset; + mmesa->dirty |= MGA_UPLOAD_CONTEXT; + mmesa->draw_buffer = MGA_FRONT; + mgaXMesaSetFrontClipRects( mmesa ); + FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE ); + break; + case BACK_LEFT_BIT: + mmesa->setup.dstorg = mmesa->mgaScreen->backOffset; + mmesa->draw_buffer = MGA_BACK; + mmesa->dirty |= MGA_UPLOAD_CONTEXT; + mgaXMesaSetBackClipRects( mmesa ); + FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE ); + break; + default: + /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */ + FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE ); + return; + } + + /* We want to update the s/w rast state too so that r200SetBuffer() + * gets called. + */ + _swrast_DrawBuffer(ctx, mode); +} + + +static void mgaDDReadBuffer(GLcontext *ctx, GLenum mode ) +{ + /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ +} + + +/* ============================================================= + * State enable/disable + */ + static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) { @@ -860,11 +890,11 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) switch(cap) { case GL_ALPHA_TEST: FLUSH_BATCH( mmesa ); - mmesa->new_state |= MGA_NEW_ALPHA; + mmesa->hw.alpha_func_enable = (state) ? ~0 : 0; break; case GL_BLEND: FLUSH_BATCH( mmesa ); - mmesa->new_state |= MGA_NEW_ALPHA; + mmesa->hw.blend_func_enable = (state) ? ~0 : 0; /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled. */ @@ -874,31 +904,31 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) break; case GL_DEPTH_TEST: FLUSH_BATCH( mmesa ); - mmesa->new_state |= MGA_NEW_DEPTH; FALLBACK (ctx, MGA_FALLBACK_DEPTH, ctx->Depth.Func == GL_NEVER && ctx->Depth.Test); break; + case GL_SCISSOR_TEST: FLUSH_BATCH( mmesa ); mmesa->scissor = state; - mmesa->new_state |= MGA_NEW_CLIP; + mgaUpdateClipping( ctx ); break; + case GL_FOG: MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); if (ctx->Fog.Enabled) mmesa->setup.maccess |= MA_fogen_enable; else mmesa->setup.maccess &= ~MA_fogen_enable; + + mgaChooseVertexState( ctx ); break; case GL_CULL_FACE: - FLUSH_BATCH( mmesa ); - mmesa->new_state |= MGA_NEW_CULL; + mgaDDCullFaceFrontFace( ctx, 0 ); break; case GL_TEXTURE_1D: case GL_TEXTURE_2D: case GL_TEXTURE_3D: - FLUSH_BATCH( mmesa ); - mmesa->new_state |= (MGA_NEW_TEXTURE|MGA_NEW_ALPHA); break; case GL_POLYGON_STIPPLE: if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) { @@ -914,16 +944,16 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) #if !defined(ACCEL_ROP) FALLBACK( ctx, MGA_FALLBACK_LOGICOP, (state && ctx->Color.LogicOp != GL_COPY)); -#else - mmesa->new_state |= MGA_NEW_DEPTH; #endif break; case GL_STENCIL_TEST: FLUSH_BATCH( mmesa ); - if (mmesa->hw_stencil) - mmesa->new_state |= MGA_NEW_STENCIL; - else + if (mmesa->hw_stencil) { + mmesa->hw.stencil_enable = ( state ) ? ~0 : 0; + } + else { FALLBACK( ctx, MGA_FALLBACK_STENCIL, state ); + } default: break; } @@ -933,56 +963,150 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) /* ============================================================= */ - - -/* ============================================================= - */ - -static void mgaDDPrintState( const char *msg, GLuint state ) +static void mgaDDPrintDirty( const char *msg, GLuint state ) { - fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s\n", + fprintf(stderr, "%s (0x%03x): %s%s%s%s%s%s%s\n", msg, - state, - (state & MGA_NEW_DEPTH) ? "depth, " : "", - (state & MGA_NEW_ALPHA) ? "alpha, " : "", - (state & MGA_NEW_CLIP) ? "clip, " : "", - (state & MGA_NEW_CULL) ? "cull, " : "", - (state & MGA_NEW_TEXTURE) ? "texture, " : "", - (state & MGA_NEW_CONTEXT) ? "context, " : ""); + (unsigned int) state, + (state & MGA_WAIT_AGE) ? "wait-age " : "", + (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img " : "", + (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img " : "", + (state & MGA_UPLOAD_CONTEXT) ? "upload-ctx " : "", + (state & MGA_UPLOAD_TEX0) ? "upload-tex0 " : "", + (state & MGA_UPLOAD_TEX1) ? "upload-tex1 " : "", + (state & MGA_UPLOAD_PIPE) ? "upload-pipe " : "" + ); } -void mgaDDUpdateHwState( GLcontext *ctx ) +/* Push the state into the sarea and/or texture memory. + */ +void mgaEmitHwStateLocked( mgaContextPtr mmesa ) { - mgaContextPtr mmesa = MGA_CONTEXT( ctx ); - int new_state = mmesa->new_state; + MGASAREAPrivPtr sarea = mmesa->sarea; + GLcontext * ctx = mmesa->glCtx; - if (new_state) - { - FLUSH_BATCH( mmesa ); + if (MGA_DEBUG & DEBUG_VERBOSE_MSG) + mgaDDPrintDirty( __FUNCTION__, mmesa->dirty ); - mmesa->new_state = 0; + if (mmesa->dirty & MGA_UPLOAD_CONTEXT) { + mmesa->setup.wflag = _CULL_DISABLE; + if (mmesa->raster_primitive == GL_TRIANGLES) { + if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT && + ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) { + mmesa->setup.wflag = mmesa->hw.cull_dualtex; + } + else { + mmesa->setup.wflag = mmesa->hw.cull; + } + } - if (MESA_VERBOSE&VERBOSE_DRIVER) - mgaDDPrintState("UpdateHwState", new_state); + mmesa->setup.stencil = mmesa->hw.stencil + & mmesa->hw.stencil_enable; + mmesa->setup.stencilctl = mmesa->hw.stencilctl + & mmesa->hw.stencil_enable; - if (new_state & MGA_NEW_DEPTH) - mgaUpdateZMode(ctx); + /* If depth testing is not enabled, then use the no Z-compare / no + * Z-write mode. Otherwise, use whatever is set in hw.zmode. + */ + mmesa->setup.dwgctl &= (DC_zmode_MASK & DC_atype_MASK); + mmesa->setup.dwgctl |= (ctx->Depth.Test) + ? mmesa->hw.zmode : (DC_zmode_nozcmp | DC_atype_i); - if (new_state & MGA_NEW_ALPHA) - mgaUpdateAlphaMode(ctx); +#if defined(ACCEL_ROP) + mmesa->setup.dwgctl &= DC_bop_MASK; + mmesa->setup.dwgctl |= (ctx->Color.ColorLogicOpEnabled) + ? mmesa->hw.rop : mgarop_NoBLK[ GL_COPY & 0x0f ]; +#endif - if (new_state & MGA_NEW_CLIP) - mgaUpdateClipping(ctx); + mmesa->setup.alphactrl &= AC_src_MASK & AC_dst_MASK & AC_atmode_MASK + & AC_atref_MASK & AC_alphasel_MASK; + mmesa->setup.alphactrl |= + ((mmesa->hw.alpha_func & mmesa->hw.alpha_func_enable) + | ((mmesa->hw.blend_func & mmesa->hw.blend_func_enable) + | ((AC_src_one | AC_dst_zero) & ~mmesa->hw.blend_func_enable)) + | mmesa->hw.alpha_sel + | (AC_amode_alpha_channel + | AC_astipple_disable + | AC_aten_disable + | AC_atmode_noacmp)); - if (new_state & MGA_NEW_STENCIL) - mgaUpdateStencil(ctx); + memcpy( &sarea->ContextState, &mmesa->setup, sizeof(mmesa->setup)); + } - if (new_state & (MGA_NEW_WARP|MGA_NEW_CULL)) - mgaUpdateCull(ctx); + if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) { + mmesa->CurrentTexObj[0]->setup.texctl2 &= ~TMC_specen_enable; + mmesa->CurrentTexObj[0]->setup.texctl2 |= mmesa->hw.specen; - if (new_state & (MGA_NEW_WARP|MGA_NEW_TEXTURE)) - mgaUpdateTextureState(ctx); + memcpy(&sarea->TexState[0], + &mmesa->CurrentTexObj[0]->setup, + sizeof(sarea->TexState[0])); } + + if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) { + mmesa->CurrentTexObj[1]->setup.texctl2 &= ~TMC_specen_enable; + mmesa->CurrentTexObj[1]->setup.texctl2 |= mmesa->hw.specen; + + memcpy(&sarea->TexState[1], + &mmesa->CurrentTexObj[1]->setup, + sizeof(sarea->TexState[1])); + } + + if ( (sarea->TexState[0].texctl2 & TMC_borderen_MASK) != + (sarea->TexState[1].texctl2 & TMC_borderen_MASK) ) { + const int borderen = sarea->TexState[1].texctl2 & ~TMC_borderen_MASK; + + memcpy( &sarea->TexState[1], &sarea->TexState[0], + sizeof(sarea->TexState[0]) ); + sarea->TexState[1].texctl2 |= borderen; + mmesa->dirty |= MGA_UPLOAD_TEX1|MGA_UPLOAD_TEX0; + } + + if (mmesa->dirty & MGA_UPLOAD_PIPE) { +/* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */ + mmesa->sarea->WarpPipe = mmesa->vertex_format; + mmesa->sarea->vertsize = mmesa->vertex_size; + } + + mmesa->sarea->dirty |= mmesa->dirty; + mmesa->dirty &= MGA_UPLOAD_CLIPRECTS; + + /* This is a bit of a hack but seems to be the best place to ensure + * that separate specular is disabled when not needed. + */ + if (ctx->Texture._EnabledUnits == 0 || + !ctx->Light.Enabled || + ctx->Light.Model.ColorControl == GL_SINGLE_COLOR) { + sarea->TexState[0].texctl2 &= ~TMC_specen_enable; + sarea->TexState[1].texctl2 &= ~TMC_specen_enable; + } +} + + +/* ============================================================= + */ + + +static void mgaDDValidateState( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT( ctx ); + int new_state = mmesa->NewGLState; + + + FLUSH_BATCH( mmesa ); + + if (mmesa->NewGLState & _MGA_NEW_RASTERSETUP) { + mgaChooseVertexState( ctx ); + } + + if (mmesa->NewGLState & _MGA_NEW_RENDERSTATE) { + mgaChooseRenderState( ctx ); + } + + if (new_state & _NEW_TEXTURE) { + mgaUpdateTextureState(ctx); + } + + mmesa->NewGLState = 0; } @@ -992,25 +1116,40 @@ static void mgaDDInvalidateState( GLcontext *ctx, GLuint new_state ) _swsetup_InvalidateState( ctx, new_state ); _ac_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); - MGA_CONTEXT(ctx)->new_gl_state |= new_state; + MGA_CONTEXT(ctx)->NewGLState |= new_state; } +static void mgaRunPipeline( GLcontext *ctx ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + + if (mmesa->NewGLState) { + mgaDDValidateState( ctx ); + } + + if (mmesa->dirty) { + mgaEmitHwStateLocked( mmesa ); + } + + _tnl_run_pipeline( ctx ); +} + void mgaInitState( mgaContextPtr mmesa ) { mgaScreenPrivate *mgaScreen = mmesa->mgaScreen; GLcontext *ctx = mmesa->glCtx; - if (ctx->Color._DrawDestMask == BACK_LEFT_BIT) { + if (ctx->Visual.doubleBufferMode) { + /* use back buffer by default */ mmesa->draw_buffer = MGA_BACK; - mmesa->read_buffer = MGA_BACK; mmesa->drawOffset = mmesa->mgaScreen->backOffset; mmesa->readOffset = mmesa->mgaScreen->backOffset; mmesa->setup.dstorg = mgaScreen->backOffset; } else { + /* use front buffer by default */ mmesa->draw_buffer = MGA_FRONT; - mmesa->read_buffer = MGA_FRONT; mmesa->drawOffset = mmesa->mgaScreen->frontOffset; mmesa->readOffset = mmesa->mgaScreen->frontOffset; mmesa->setup.dstorg = mgaScreen->frontOffset; @@ -1043,14 +1182,21 @@ void mgaInitState( mgaContextPtr mmesa ) mmesa->setup.maccess |= MA_zwidth_24; break; case 32: - mmesa->setup.maccess |= MA_pwidth_32; + mmesa->setup.maccess |= MA_zwidth_32; break; } + mmesa->hw.zmode = DC_zmode_zlt | DC_atype_zi; + mmesa->hw.stencil = (0x0ff << S_smsk_SHIFT) | (0x0ff << S_swtmsk_SHIFT); + mmesa->hw.stencilctl = SC_smode_salways | SC_sfailop_keep + | SC_szfailop_keep | SC_szpassop_keep; + mmesa->hw.stencil_enable = 0; + mmesa->hw.cull = _CULL_NEGATIVE; + mmesa->hw.cull_dualtex = _CULL_POSITIVE; + mmesa->hw.specen = 0; + mmesa->setup.dwgctl = (DC_opcod_trap | - DC_atype_i | DC_linear_xy | - DC_zmode_nozcmp | DC_solid_disable | DC_arzero_disable | DC_sgnzero_disable | @@ -1072,16 +1218,15 @@ void mgaInitState( mgaContextPtr mmesa ) AC_atmode_noacmp | AC_alphasel_fromtex ); - mmesa->setup.fogcolor = - MGAPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F), - (GLubyte)(ctx->Fog.Color[1]*255.0F), - (GLubyte)(ctx->Fog.Color[2]*255.0F)); + mmesa->setup.fogcolor = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F), + (GLubyte)(ctx->Fog.Color[1]*255.0F), + (GLubyte)(ctx->Fog.Color[2]*255.0F)); mmesa->setup.wflag = 0; mmesa->setup.tdualstage0 = 0; mmesa->setup.tdualstage1 = 0; mmesa->setup.fcol = 0; - mmesa->new_state = ~0; + mmesa->dirty |= MGA_UPLOAD_CONTEXT; } @@ -1103,8 +1248,8 @@ void mgaDDInitStateFuncs( GLcontext *ctx ) ctx->Driver.FrontFace = mgaDDCullFaceFrontFace; ctx->Driver.ColorMask = mgaDDColorMask; - ctx->Driver.DrawBuffer = mgaDDSetDrawBuffer; - ctx->Driver.ReadBuffer = mgaDDSetReadBuffer; + ctx->Driver.DrawBuffer = mgaDDDrawBuffer; + ctx->Driver.ReadBuffer = mgaDDReadBuffer; ctx->Driver.ClearColor = mgaDDClearColor; ctx->Driver.ClearDepth = mgaDDClearDepth; ctx->Driver.LogicOpcode = mgaDDLogicOp; @@ -1128,4 +1273,6 @@ void mgaDDInitStateFuncs( GLcontext *ctx ) ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; + + TNL_CONTEXT(ctx)->Driver.RunPipeline = mgaRunPipeline; } |