summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/mga/mgastate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/mga/mgastate.c')
-rw-r--r--src/mesa/drivers/dri/mga/mgastate.c1131
1 files changed, 1131 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/mga/mgastate.c b/src/mesa/drivers/dri/mga/mgastate.c
new file mode 100644
index 00000000000..02b98fdb766
--- /dev/null
+++ b/src/mesa/drivers/dri/mga/mgastate.c
@@ -0,0 +1,1131 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+/* $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 "dd.h"
+
+#include "mm.h"
+#include "mgacontext.h"
+#include "mgadd.h"
+#include "mgastate.h"
+#include "mgatex.h"
+#include "mgavb.h"
+#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 "swrast_setup/swrast_setup.h"
+
+
+
+/* Some outstanding problems with accelerating logic ops...
+ */
+#if defined(ACCEL_ROP)
+static 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,
+ DC_atype_rstr | 0x00060000, DC_atype_rstr | 0x000e0000,
+ DC_atype_rstr | 0x00010000, DC_atype_rstr | 0x00090000,
+ DC_atype_rstr | 0x00050000, DC_atype_rstr | 0x000d0000,
+ DC_atype_rpl | 0x00030000, DC_atype_rstr | 0x000b0000,
+ DC_atype_rstr | 0x00070000, DC_atype_rpl | 0x000f0000
+};
+#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;
+}
+
+static void mgaDDClearDepth(GLcontext *ctx, GLclampd d)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ /* 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;
+ }
+
+ 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 */
+ }
+
+#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;
+ 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.
+ */
+ FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
+ (ctx->Color.ColorLogicOpEnabled &&
+ ctx->Color.LogicOp != GL_COPY));
+}
+
+static void mgaDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
+{
+ FLUSH_BATCH( MGA_CONTEXT(ctx) );
+ MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
+}
+
+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;
+}
+
+
+
+static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname,
+ const GLfloat *param)
+{
+ if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
+ FLUSH_BATCH( MGA_CONTEXT(ctx) );
+ MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE;
+ }
+}
+
+
+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;
+}
+
+static void mgaDDDepthMask(GLcontext *ctx, GLboolean flag)
+{
+ FLUSH_BATCH( MGA_CONTEXT(ctx) );
+ MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH;
+}
+
+#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
+
+
+
+static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
+{
+ 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;
+ }
+}
+
+
+
+
+/* =============================================================
+ * Alpha blending
+ */
+
+
+static void mgaUpdateAlphaMode(GLcontext *ctx)
+{
+ 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);
+ }
+
+ /* 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;
+ }
+
+ 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;
+ }
+
+ mmesa->setup.alphactrl = (AC_amode_alpha_channel |
+ AC_astipple_disable |
+ AC_aten_disable |
+ AC_atmode_noacmp |
+ a);
+
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+}
+
+
+
+/* =============================================================
+ * Hardware clipping
+ */
+
+void mgaUpdateClipping(const GLcontext *ctx)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ if (mmesa->driDrawable)
+ {
+ int x1 = mmesa->driDrawable->x + ctx->Scissor.X;
+ int y1 = mmesa->driDrawable->y + mmesa->driDrawable->h
+ - (ctx->Scissor.Y + ctx->Scissor.Height);
+ int x2 = x1 + ctx->Scissor.Width - 1;
+ int y2 = y1 + ctx->Scissor.Height - 1;
+
+ if (x1 < 0) x1 = 0;
+ if (y1 < 0) y1 = 0;
+ if (x2 < 0) x2 = 0;
+ if (y2 < 0) y2 = 0;
+
+ mmesa->scissor_rect.x1 = x1;
+ mmesa->scissor_rect.y1 = y1;
+ 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;
+ }
+}
+
+
+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]);
+}
+
+
+/* =============================================================
+ * Culling
+ */
+
+#define _CULL_DISABLE 0
+#define _CULL_NEGATIVE ((1<<11)|(1<<5)|(1<<16))
+#define _CULL_POSITIVE (1<<11)
+
+
+void mgaUpdateCull( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint mode = _CULL_DISABLE;
+
+ if (ctx->Polygon.CullFlag &&
+ mmesa->raster_primitive == GL_TRIANGLES &&
+ ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK)
+ {
+ mode = _CULL_NEGATIVE;
+ if (ctx->Polygon.CullFaceMode == GL_FRONT)
+ mode ^= (_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->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
+ */
+
+static void mgaDDColorMask(GLcontext *ctx,
+ GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
+
+
+ GLuint mask = mgaPackColor(mgaScreen->cpp,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP]);
+
+ if (mgaScreen->cpp == 2)
+ mask = mask | (mask << 16);
+
+ if (mmesa->setup.plnwt != mask) {
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->setup.plnwt = mask;
+ }
+}
+
+/* =============================================================
+ * 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.
+ */
+static int mgaStipples[16] = {
+ 0xffff1, /* See above note */
+ 0xa5a5,
+ 0x5a5a,
+ 0xa0a0,
+ 0x5050,
+ 0x0a0a,
+ 0x0505,
+ 0x8020,
+ 0x0401,
+ 0x1040,
+ 0x0208,
+ 0x0802,
+ 0x4010,
+ 0x0104,
+ 0x2080,
+ 0x0000
+};
+
+static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ const GLubyte *m = mask;
+ GLubyte p[4];
+ int i,j,k;
+ int active = (ctx->Polygon.StippleFlag &&
+ mmesa->raster_primitive == GL_TRIANGLES);
+ GLuint stipple;
+
+ FLUSH_BATCH(mmesa);
+ mmesa->haveHwStipple = 0;
+
+ if (active) {
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+ mmesa->setup.dwgctl &= ~(0xf<<20);
+ }
+
+ p[0] = mask[0] & 0xf; p[0] |= p[0] << 4;
+ p[1] = mask[4] & 0xf; p[1] |= p[1] << 4;
+ p[2] = mask[8] & 0xf; p[2] |= p[2] << 4;
+ p[3] = mask[12] & 0xf; p[3] |= p[3] << 4;
+
+ for (k = 0 ; k < 8 ; k++)
+ for (j = 0 ; j < 4; j++)
+ for (i = 0 ; i < 4 ; i++)
+ if (*m++ != p[j]) {
+ return;
+ }
+
+ stipple = ( ((p[0] & 0xf) << 0) |
+ ((p[1] & 0xf) << 4) |
+ ((p[2] & 0xf) << 8) |
+ ((p[3] & 0xf) << 12) );
+
+ for (i = 0 ; i < 16 ; i++)
+ if (mgaStipples[i] == stipple) {
+ mmesa->poly_stipple = i<<20;
+ mmesa->haveHwStipple = 1;
+ break;
+ }
+
+ if (active) {
+ mmesa->setup.dwgctl &= ~(0xf<<20);
+ mmesa->setup.dwgctl |= mmesa->poly_stipple;
+ }
+}
+
+/* =============================================================
+ */
+
+static void mgaDDPrintDirty( const char *msg, GLuint state )
+{
+ 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, " : ""
+ );
+}
+
+/* Push the state into the sarea and/or texture memory.
+ */
+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]);
+
+ 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));
+ }
+
+ 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]));
+ }
+
+ 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;
+ }
+
+ mmesa->sarea->dirty |= mmesa->dirty;
+
+ mmesa->dirty &= (MGA_UPLOAD_CLIPRECTS|MGA_WAIT_AGE);
+
+ /* 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;
+ }
+}
+
+/* Fallback to swrast for select and feedback.
+ */
+static void mgaRenderMode( GLcontext *ctx, GLenum mode )
+{
+ FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
+}
+
+
+/* =============================================================
+ */
+
+void mgaCalcViewport( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+ GLfloat *m = mmesa->hw_viewport;
+
+ /* See also mga_translate_vertex.
+ */
+ m[MAT_SX] = v[MAT_SX];
+ m[MAT_TX] = v[MAT_TX] + mmesa->drawX + SUBPIXEL_X;
+ m[MAT_SY] = - v[MAT_SY];
+ m[MAT_TY] = - v[MAT_TY] + mmesa->driDrawable->h + mmesa->drawY + SUBPIXEL_Y;
+ m[MAT_SZ] = v[MAT_SZ] * mmesa->depth_scale;
+ m[MAT_TZ] = v[MAT_TZ] * mmesa->depth_scale;
+
+ mmesa->SetupNewInputs = ~0;
+}
+
+static void mgaViewport( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height )
+{
+ mgaCalcViewport( ctx );
+}
+
+static void mgaDepthRange( GLcontext *ctx,
+ GLclampd nearval, GLclampd farval )
+{
+ mgaCalcViewport( ctx );
+}
+
+/* =============================================================
+ */
+
+static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+
+ switch(cap) {
+ case GL_ALPHA_TEST:
+ FLUSH_BATCH( mmesa );
+ mmesa->new_state |= MGA_NEW_ALPHA;
+ break;
+ case GL_BLEND:
+ FLUSH_BATCH( mmesa );
+ mmesa->new_state |= MGA_NEW_ALPHA;
+
+ /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
+ */
+ FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
+ (ctx->Color.ColorLogicOpEnabled &&
+ ctx->Color.LogicOp != GL_COPY));
+ 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;
+ 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;
+ break;
+ case GL_CULL_FACE:
+ FLUSH_BATCH( mmesa );
+ mmesa->new_state |= MGA_NEW_CULL;
+ 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) {
+ FLUSH_BATCH(mmesa);
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+ mmesa->setup.dwgctl &= ~(0xf<<20);
+ if (state)
+ mmesa->setup.dwgctl |= mmesa->poly_stipple;
+ }
+ break;
+ case GL_COLOR_LOGIC_OP:
+ FLUSH_BATCH( mmesa );
+#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
+ FALLBACK( ctx, MGA_FALLBACK_STENCIL, state );
+ default:
+ break;
+ }
+}
+
+
+/* =============================================================
+ */
+
+
+
+/* =============================================================
+ */
+
+static void mgaDDPrintState( const char *msg, GLuint state )
+{
+ fprintf(stderr, "%s (0x%x): %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, " : "");
+}
+
+void mgaDDUpdateHwState( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ int new_state = mmesa->new_state;
+
+ if (new_state)
+ {
+ FLUSH_BATCH( mmesa );
+
+ mmesa->new_state = 0;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER)
+ mgaDDPrintState("UpdateHwState", new_state);
+
+ if (new_state & MGA_NEW_DEPTH)
+ mgaUpdateZMode(ctx);
+
+ if (new_state & MGA_NEW_ALPHA)
+ mgaUpdateAlphaMode(ctx);
+
+ if (new_state & MGA_NEW_CLIP)
+ mgaUpdateClipping(ctx);
+
+ if (new_state & MGA_NEW_STENCIL)
+ mgaUpdateStencil(ctx);
+
+ if (new_state & (MGA_NEW_WARP|MGA_NEW_CULL))
+ mgaUpdateCull(ctx);
+
+ if (new_state & (MGA_NEW_WARP|MGA_NEW_TEXTURE))
+ mgaUpdateTextureState(ctx);
+ }
+}
+
+
+static void mgaDDInvalidateState( 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 );
+ MGA_CONTEXT(ctx)->new_gl_state |= new_state;
+}
+
+
+
+void mgaInitState( mgaContextPtr mmesa )
+{
+ mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
+ GLcontext *ctx = mmesa->glCtx;
+
+ if (ctx->Color._DrawDestMask == BACK_LEFT_BIT) {
+ 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 {
+ 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;
+ }
+
+ mmesa->setup.maccess = (MA_memreset_disable |
+ MA_fogen_disable |
+ MA_tlutload_disable |
+ MA_nodither_disable |
+ MA_dit555_disable);
+
+ switch (mmesa->mgaScreen->cpp) {
+ case 2:
+ mmesa->setup.maccess |= MA_pwidth_16;
+ break;
+ case 4:
+ mmesa->setup.maccess |= MA_pwidth_32;
+ break;
+ default:
+ fprintf( stderr, "Error: unknown cpp %d, exiting...\n",
+ mmesa->mgaScreen->cpp );
+ exit( 1 );
+ }
+
+ switch (mmesa->glCtx->Visual.depthBits) {
+ case 16:
+ mmesa->setup.maccess |= MA_zwidth_16;
+ break;
+ case 24:
+ mmesa->setup.maccess |= MA_zwidth_24;
+ break;
+ case 32:
+ mmesa->setup.maccess |= MA_pwidth_32;
+ break;
+ }
+
+ mmesa->setup.dwgctl = (DC_opcod_trap |
+ DC_atype_i |
+ DC_linear_xy |
+ DC_zmode_nozcmp |
+ DC_solid_disable |
+ DC_arzero_disable |
+ DC_sgnzero_disable |
+ DC_shftzero_enable |
+ (0xC << DC_bop_SHIFT) |
+ (0x0 << DC_trans_SHIFT) |
+ DC_bltmod_bmonolef |
+ DC_pattern_disable |
+ DC_transc_disable |
+ DC_clipdis_disable);
+
+
+ mmesa->setup.plnwt = ~0;
+ mmesa->setup.alphactrl = ( AC_src_one |
+ AC_dst_zero |
+ AC_amode_FCOL |
+ AC_astipple_disable |
+ AC_aten_disable |
+ 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.wflag = 0;
+ mmesa->setup.tdualstage0 = 0;
+ mmesa->setup.tdualstage1 = 0;
+ mmesa->setup.fcol = 0;
+ mmesa->new_state = ~0;
+}
+
+
+void mgaDDInitStateFuncs( GLcontext *ctx )
+{
+ ctx->Driver.UpdateState = mgaDDInvalidateState;
+ ctx->Driver.Enable = mgaDDEnable;
+ ctx->Driver.LightModelfv = mgaDDLightModelfv;
+ ctx->Driver.AlphaFunc = mgaDDAlphaFunc;
+ ctx->Driver.BlendEquation = mgaDDBlendEquation;
+ ctx->Driver.BlendFunc = mgaDDBlendFunc;
+ ctx->Driver.BlendFuncSeparate = mgaDDBlendFuncSeparate;
+ ctx->Driver.DepthFunc = mgaDDDepthFunc;
+ ctx->Driver.DepthMask = mgaDDDepthMask;
+ ctx->Driver.Fogfv = mgaDDFogfv;
+ ctx->Driver.Scissor = mgaDDScissor;
+ ctx->Driver.ShadeModel = mgaDDShadeModel;
+ ctx->Driver.CullFace = mgaDDCullFaceFrontFace;
+ ctx->Driver.FrontFace = mgaDDCullFaceFrontFace;
+ ctx->Driver.ColorMask = mgaDDColorMask;
+
+ ctx->Driver.DrawBuffer = mgaDDSetDrawBuffer;
+ ctx->Driver.ReadBuffer = mgaDDSetReadBuffer;
+ ctx->Driver.ClearColor = mgaDDClearColor;
+ ctx->Driver.ClearDepth = mgaDDClearDepth;
+ ctx->Driver.LogicOpcode = mgaDDLogicOp;
+
+ ctx->Driver.PolygonStipple = mgaDDPolygonStipple;
+
+ ctx->Driver.StencilFunc = mgaDDStencilFunc;
+ ctx->Driver.StencilMask = mgaDDStencilMask;
+ ctx->Driver.StencilOp = mgaDDStencilOp;
+
+ ctx->Driver.DepthRange = mgaDepthRange;
+ ctx->Driver.Viewport = mgaViewport;
+ ctx->Driver.RenderMode = mgaRenderMode;
+
+ ctx->Driver.ClearIndex = 0;
+ ctx->Driver.IndexMask = 0;
+
+ /* Swrast hooks for imaging extensions:
+ */
+ ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+ ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+ ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+}