diff options
author | Alan Hourihane <[email protected]> | 2003-09-30 11:28:16 +0000 |
---|---|---|
committer | Alan Hourihane <[email protected]> | 2003-09-30 11:28:16 +0000 |
commit | e508f7f08e6fa4292136a377150fc058c041fbc0 (patch) | |
tree | a012bb2a36fc4858d03e3b6af9a6fe714000f10b /src/mesa/drivers/dri/gamma/gamma_state.c | |
parent | 0f2e1869263ef04b3bc47d9817278a555201bda8 (diff) |
add gamma driver - no kernel driver yet
(build tested, not physically tested)
Diffstat (limited to 'src/mesa/drivers/dri/gamma/gamma_state.c')
-rw-r--r-- | src/mesa/drivers/dri/gamma/gamma_state.c | 1734 |
1 files changed, 1734 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/gamma/gamma_state.c b/src/mesa/drivers/dri/gamma/gamma_state.c new file mode 100644 index 00000000000..8a767206782 --- /dev/null +++ b/src/mesa/drivers/dri/gamma/gamma_state.c @@ -0,0 +1,1734 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/gamma/gamma_state.c,v 1.5 2002/11/05 17:46:07 tsi Exp $ */ +/* + * Copyright 2001 by Alan Hourihane. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, <[email protected]> + * + * 3DLabs Gamma driver + */ + +#include "gamma_context.h" +#include "gamma_macros.h" +#include "macros.h" +#include "glint_dri.h" +#include "colormac.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" + +#define ENABLELIGHTING 0 + +/* ============================================================= + * Alpha blending + */ + +static void gammaUpdateAlphaMode( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 a = gmesa->AlphaTestMode; + CARD32 b = gmesa->AlphaBlendMode; + CARD32 f = gmesa->AB_FBReadMode_Save = 0; + GLubyte refByte = (GLint) (ctx->Color.AlphaRef * 255.0); + + a &= ~(AT_CompareMask | AT_RefValueMask); + b &= ~(AB_SrcBlendMask | AB_DstBlendMask); + + a |= refByte << 4; + + switch ( ctx->Color.AlphaFunc ) { + case GL_NEVER: + a |= AT_Never; + break; + case GL_LESS: + a |= AT_Less; + break; + case GL_EQUAL: + a |= AT_Equal; + break; + case GL_LEQUAL: + a |= AT_LessEqual; + break; + case GL_GEQUAL: + a |= AT_GreaterEqual; + break; + case GL_GREATER: + a |= AT_Greater; + break; + case GL_NOTEQUAL: + a |= AT_NotEqual; + break; + case GL_ALWAYS: + a |= AT_Always; + break; + } + + if ( ctx->Color.AlphaEnabled ) { + f |= FBReadDstEnable; + a |= AlphaTestModeEnable; + } else { + a &= ~AlphaTestModeEnable; + } + + switch ( ctx->Color.BlendSrcRGB ) { + case GL_ZERO: + b |= AB_Src_Zero; + break; + case GL_ONE: + b |= AB_Src_One; + break; + case GL_DST_COLOR: + b |= AB_Src_DstColor; + break; + case GL_ONE_MINUS_DST_COLOR: + b |= AB_Src_OneMinusDstColor; + break; + case GL_SRC_ALPHA: + b |= AB_Src_SrcAlpha; + break; + case GL_ONE_MINUS_SRC_ALPHA: + b |= AB_Src_OneMinusSrcAlpha; + break; + case GL_DST_ALPHA: + b |= AB_Src_DstAlpha; + f |= FBReadSrcEnable; + break; + case GL_ONE_MINUS_DST_ALPHA: + b |= AB_Src_OneMinusDstAlpha; + f |= FBReadSrcEnable; + break; + case GL_SRC_ALPHA_SATURATE: + b |= AB_Src_SrcAlphaSaturate; + break; + } + + switch ( ctx->Color.BlendDstRGB ) { + case GL_ZERO: + b |= AB_Dst_Zero; + break; + case GL_ONE: + b |= AB_Dst_One; + break; + case GL_SRC_COLOR: + b |= AB_Dst_SrcColor; + break; + case GL_ONE_MINUS_SRC_COLOR: + b |= AB_Dst_OneMinusSrcColor; + break; + case GL_SRC_ALPHA: + b |= AB_Dst_SrcAlpha; + break; + case GL_ONE_MINUS_SRC_ALPHA: + b |= AB_Dst_OneMinusSrcAlpha; + break; + case GL_DST_ALPHA: + b |= AB_Dst_DstAlpha; + f |= FBReadSrcEnable; + break; + case GL_ONE_MINUS_DST_ALPHA: + b |= AB_Dst_OneMinusDstAlpha; + f |= FBReadSrcEnable; + break; + } + + if ( ctx->Color.BlendEnabled ) { + f |= FBReadDstEnable; + b |= AlphaBlendModeEnable; + } else { + b &= ~AlphaBlendModeEnable; + } + + if ( gmesa->AlphaTestMode != a ) { + gmesa->AlphaTestMode = a; + gmesa->dirty |= GAMMA_UPLOAD_ALPHA; + } + if ( gmesa->AlphaBlendMode != b) { + gmesa->AlphaBlendMode = b; + gmesa->dirty |= GAMMA_UPLOAD_BLEND; + } + gmesa->AB_FBReadMode_Save = f; +} + +static void gammaDDAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + (void) ref; + + FLUSH_BATCH( gmesa ); + + gmesa->new_state |= GAMMA_NEW_ALPHA; +} + +static void gammaDDBlendEquation( GLcontext *ctx, GLenum mode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + gmesa->new_state |= GAMMA_NEW_ALPHA; +} + +static void gammaDDBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + gmesa->new_state |= GAMMA_NEW_ALPHA; +} + +static void gammaDDBlendFuncSeparate( GLcontext *ctx, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + gmesa->new_state |= GAMMA_NEW_ALPHA; +} + + +/* ================================================================ + * Buffer clear + */ + +static void gammaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + GLINTDRIPtr gDRIPriv = (GLINTDRIPtr)gmesa->driScreen->pDevPriv; + GLuint temp = 0; + + FLUSH_BATCH( gmesa ); + + /* Update and emit any new state. We need to do this here to catch + * changes to the masks. + * FIXME: Just update the masks? + */ + if ( gmesa->new_state ) + gammaDDUpdateHWState( ctx ); + +#ifdef DO_VALIDATE + /* Flush any partially filled buffers */ + FLUSH_DMA_BUFFER(gmesa); + + DRM_SPINLOCK(&gmesa->driScreen->pSAREA->drawable_lock, + gmesa->driScreen->drawLockID); + VALIDATE_DRAWABLE_INFO_NO_LOCK(gmesa); +#endif + + if (mask & DD_DEPTH_BIT) { + /* Turn off writes the FB */ + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, FBWriteMode, FBWriteModeDisable); + + mask &= ~DD_DEPTH_BIT; + + /* + * Turn Rectangle2DControl off when the window is not clipped + * (i.e., the GID tests are not necessary). This dramatically + * increases the performance of the depth clears. + */ + if (!gmesa->NotClipped) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, Rectangle2DControl, 1); + } + + temp = (gmesa->LBReadMode & LBPartialProdMask) | LBWindowOriginBot; + if (gDRIPriv->numMultiDevices == 2) temp |= LBScanLineInt2; + + CHECK_DMA_BUFFER(gmesa, 5); + WRITE(gmesa->buf, LBReadMode, temp); + WRITE(gmesa->buf, DeltaMode, DM_DepthEnable); + WRITE(gmesa->buf, DepthMode, (DepthModeEnable | + DM_Always | + DM_SourceDepthRegister | + DM_WriteMask)); + WRITE(gmesa->buf, GLINTDepth, gmesa->ClearDepth); + + /* Increment the frame count */ + gmesa->FrameCount++; +#ifdef FAST_CLEAR_4 + gmesa->FrameCount &= 0x0f; +#else + gmesa->FrameCount &= 0xff; +#endif + + /* Force FCP to be written */ + WRITE(gmesa->buf, GLINTWindow, (WindowEnable | + W_PassIfEqual | + (gmesa->Window & W_GIDMask) | + W_DepthFCP | + W_LBUpdateFromRegisters | + W_OverrideWriteFiltering | + (gmesa->FrameCount << 9))); + + /* Clear part of the depth and FCP buffers */ + { + int y = gmesa->driScreen->fbHeight - gmesa->driDrawable->y - gmesa->driDrawable->h; + int x = gmesa->driDrawable->x; + int w = gmesa->driDrawable->w; + int h = gmesa->driDrawable->h; +#ifndef TURN_OFF_FCP + float hsub = h; + + if (gmesa->WindowChanged) { + gmesa->WindowChanged = GL_FALSE; + } else { +#ifdef FAST_CLEAR_4 + hsub /= 16; +#else + hsub /= 256; +#endif + + /* Handle the case where the height < # of FCPs */ + if (hsub < 1.0) { + if (gmesa->FrameCount > h) + gmesa->FrameCount = 0; + h = 1; + y += gmesa->FrameCount; + } else { + h = (gmesa->FrameCount+1)*hsub; + h -= (int)(gmesa->FrameCount*hsub); + y += gmesa->FrameCount*hsub; + } + } +#endif + if (h && w) { +#if 0 + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, Rectangle2DMode, ((h & 0xfff)<<12) | + (w & 0xfff) ); + WRITE(gmesa->buf, DrawRectangle2D, ((y & 0xffff)<<16) | + (x & 0xffff) ); +#else + CHECK_DMA_BUFFER(gmesa, 8); + WRITE(gmesa->buf, StartXDom, x<<16); + WRITE(gmesa->buf, StartY, y<<16); + WRITE(gmesa->buf, StartXSub, (x+w)<<16); + WRITE(gmesa->buf, GLINTCount, h); + WRITE(gmesa->buf, dY, 1<<16); + WRITE(gmesa->buf, dXDom, 0<<16); + WRITE(gmesa->buf, dXSub, 0<<16); + WRITE(gmesa->buf, Render, 0x00000040); /* NOT_DONE */ +#endif + } + } + + CHECK_DMA_BUFFER(gmesa, 6); + WRITE(gmesa->buf, DepthMode, gmesa->DepthMode); + WRITE(gmesa->buf, DeltaMode, gmesa->DeltaMode); + WRITE(gmesa->buf, LBReadMode, gmesa->LBReadMode); + WRITE(gmesa->buf, GLINTWindow, gmesa->Window); + WRITE(gmesa->buf, FastClearDepth, gmesa->ClearDepth); + WRITE(gmesa->buf, FBWriteMode, FBWriteModeEnable); + + /* Turn on Depth FCP */ + if (gmesa->Window & W_DepthFCP) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, WindowOr, (gmesa->FrameCount << 9)); + } + + /* Turn off GID clipping if window is not clipped */ + if (gmesa->NotClipped) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, Rectangle2DControl, 0); + } + } + + if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) { + int y = gmesa->driScreen->fbHeight - gmesa->driDrawable->y - gmesa->driDrawable->h; + int x = gmesa->driDrawable->x; + int w = gmesa->driDrawable->w; + int h = gmesa->driDrawable->h; + + mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT); + + if (x < 0) { w -= -x; x = 0; } + + /* Turn on GID clipping if window is clipped */ + if (!gmesa->NotClipped) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, Rectangle2DControl, 1); + } + + CHECK_DMA_BUFFER(gmesa, 18); + WRITE(gmesa->buf, FBBlockColor, gmesa->ClearColor); + WRITE(gmesa->buf, ColorDDAMode, ColorDDADisable); + WRITE(gmesa->buf, FBWriteMode, FBWriteModeEnable); + WRITE(gmesa->buf, DepthMode, 0); + WRITE(gmesa->buf, DeltaMode, 0); + WRITE(gmesa->buf, AlphaBlendMode, 0); +#if 1 + WRITE(gmesa->buf, dY, 1<<16); + WRITE(gmesa->buf, dXDom, 0<<16); + WRITE(gmesa->buf, dXSub, 0<<16); + WRITE(gmesa->buf, StartXSub, (x+w)<<16); + WRITE(gmesa->buf, GLINTCount, h); + WRITE(gmesa->buf, StartXDom, x<<16); + WRITE(gmesa->buf, StartY, y<<16); + WRITE(gmesa->buf, Render, 0x00000048); /* NOT_DONE */ +#else + WRITE(gmesa->buf, Rectangle2DMode, (((h & 0xfff)<<12) | + (w & 0xfff))); + WRITE(gmesa->buf, DrawRectangle2D, (((y & 0xffff)<<16) | + (x & 0xffff))); +#endif + WRITE(gmesa->buf, DepthMode, gmesa->DepthMode); + WRITE(gmesa->buf, DeltaMode, gmesa->DeltaMode); + WRITE(gmesa->buf, AlphaBlendMode, gmesa->AlphaBlendMode); + WRITE(gmesa->buf, ColorDDAMode, gmesa->ColorDDAMode); + + /* Turn off GID clipping if window is clipped */ + if (gmesa->NotClipped) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, Rectangle2DControl, 0); + } + } + +#ifdef DO_VALIDATE + PROCESS_DMA_BUFFER_TOP_HALF(gmesa); + + DRM_SPINUNLOCK(&gmesa->driScreen->pSAREA->drawable_lock, + gmesa->driScreen->drawLockID); + VALIDATE_DRAWABLE_INFO_NO_LOCK_POST(gmesa); + + PROCESS_DMA_BUFFER_BOTTOM_HALF(gmesa); +#endif + + if ( mask ) + _swrast_Clear( ctx, mask, all, cx, cy, cw, ch ); +} + +/* ============================================================= + * Depth testing + */ + +static void gammaUpdateZMode( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 z = gmesa->DepthMode; + CARD32 delta = gmesa->DeltaMode; + CARD32 window = gmesa->Window; + CARD32 lbread = gmesa->LBReadMode; + + z &= ~DM_CompareMask; + + switch ( ctx->Depth.Func ) { + case GL_NEVER: + z |= DM_Never; + break; + case GL_ALWAYS: + z |= DM_Always; + break; + case GL_LESS: + z |= DM_Less; + break; + case GL_LEQUAL: + z |= DM_LessEqual; + break; + case GL_EQUAL: + z |= DM_Equal; + break; + case GL_GEQUAL: + z |= DM_GreaterEqual; + break; + case GL_GREATER: + z |= DM_Greater; + break; + case GL_NOTEQUAL: + z |= DM_NotEqual; + break; + } + + if ( ctx->Depth.Test ) { + z |= DepthModeEnable; + delta |= DM_DepthEnable; + window |= W_DepthFCP; + lbread |= LBReadDstEnable; + } else { + z &= ~DepthModeEnable; + delta &= ~DM_DepthEnable; + window &= ~W_DepthFCP; + lbread &= ~LBReadDstEnable; + } + + if ( ctx->Depth.Mask ) { + z |= DM_WriteMask; + } else { + z &= ~DM_WriteMask; + } + +#if 0 + if ( gmesa->DepthMode != z ){ +#endif + gmesa->DepthMode = z; + gmesa->DeltaMode = delta; + gmesa->Window = window; + gmesa->LBReadMode = lbread; + gmesa->dirty |= GAMMA_UPLOAD_DEPTH; +#if 0 + } +#endif +} + +static void gammaDDDepthFunc( GLcontext *ctx, GLenum func ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_DEPTH; +} + +static void gammaDDDepthMask( GLcontext *ctx, GLboolean flag ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_DEPTH; +} + +static void gammaDDClearDepth( GLcontext *ctx, GLclampd d ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + switch ( gmesa->DepthSize ) { + case 16: + gmesa->ClearDepth = d * 0x0000ffff; + break; + case 24: + gmesa->ClearDepth = d * 0x00ffffff; + break; + case 32: + gmesa->ClearDepth = d * 0xffffffff; + break; + } +} + +static void gammaDDFinish( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_DMA_BUFFER(gmesa); +} + +static void gammaDDFlush( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_DMA_BUFFER(gmesa); +} + +/* ============================================================= + * Fog + */ + +static void gammaUpdateFogAttrib( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 f = gmesa->FogMode; + CARD32 g = gmesa->GeometryMode; + CARD32 d = gmesa->DeltaMode; + + if (ctx->Fog.Enabled) { + f |= FogModeEnable; + g |= GM_FogEnable; + d |= DM_FogEnable; + } else { + f &= ~FogModeEnable; + g &= ~GM_FogEnable; + d &= ~DM_FogEnable; + } + + g &= ~GM_FogMask; + + switch (ctx->Fog.Mode) { + case GL_LINEAR: + g |= GM_FogLinear; + break; + case GL_EXP: + g |= GM_FogExp; + break; + case GL_EXP2: + g |= GM_FogExpSquared; + break; + } + + if ( gmesa->FogMode != f ) { + gmesa->FogMode = f; + gmesa->dirty |= GAMMA_UPLOAD_FOG; + } + + if ( gmesa->GeometryMode != g ) { + gmesa->GeometryMode = g; + gmesa->dirty |= GAMMA_UPLOAD_GEOMETRY; + } + + if ( gmesa->DeltaMode != d ) { + gmesa->DeltaMode = d; + gmesa->dirty |= GAMMA_UPLOAD_DEPTH; + } +} + +static void gammaDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_FOG; +} + +/* ============================================================= + * Lines + */ +static void gammaDDLineWidth( GLcontext *ctx, GLfloat width ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + CHECK_DMA_BUFFER(gmesa, 3); + WRITE(gmesa->buf, LineWidth, (GLuint)width); + WRITEF(gmesa->buf, AAlineWidth, width); + WRITE(gmesa->buf, LineWidthOffset, (GLuint)(width-1)/2); +} + +static void gammaDDLineStipple( GLcontext *ctx, GLint factor, GLushort pattern ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + gmesa->LineMode &= ~(LM_StippleMask | LM_RepeatFactorMask); + gmesa->LineMode |= ((GLuint)(factor - 1) << 1) | ((GLuint)pattern << 10); + + gmesa->dirty |= GAMMA_UPLOAD_LINEMODE; +} + + + +/* ============================================================= + * Points + */ +static void gammaDDPointSize( GLcontext *ctx, GLfloat size ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, PointSize, (GLuint)size); + WRITEF(gmesa->buf, AApointSize, size); +} + +/* ============================================================= + * Polygon + */ + +static void gammaUpdatePolygon( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 g = gmesa->GeometryMode; + + g &= ~(GM_PolyOffsetFillEnable | GM_PolyOffsetPointEnable | + GM_PolyOffsetLineEnable); + + if (ctx->Polygon.OffsetFill) g |= GM_PolyOffsetFillEnable; + if (ctx->Polygon.OffsetPoint) g |= GM_PolyOffsetPointEnable; + if (ctx->Polygon.OffsetLine) g |= GM_PolyOffsetLineEnable; + + g &= ~GM_FB_PolyMask; + + switch (ctx->Polygon.FrontMode) { + case GL_FILL: + g |= GM_FrontPolyFill; + break; + case GL_LINE: + g |= GM_FrontPolyLine; + break; + case GL_POINT: + g |= GM_FrontPolyPoint; + break; + } + + switch (ctx->Polygon.BackMode) { + case GL_FILL: + g |= GM_BackPolyFill; + break; + case GL_LINE: + g |= GM_BackPolyLine; + break; + case GL_POINT: + g |= GM_BackPolyPoint; + break; + } + + if ( gmesa->GeometryMode != g ) { + gmesa->GeometryMode = g; + gmesa->dirty |= GAMMA_UPLOAD_GEOMETRY; + } + + gmesa->dirty |= GAMMA_UPLOAD_POLYGON; +} + +static void gammaDDPolygonMode( GLcontext *ctx, GLenum face, GLenum mode) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + gmesa->new_state |= GAMMA_NEW_POLYGON; +} + +static void gammaUpdateStipple( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + if (ctx->Polygon.StippleFlag) { + gmesa->AreaStippleMode |= AreaStippleModeEnable/* | ASM_X32 | ASM_Y32*/; + } else { + gmesa->AreaStippleMode &= ~AreaStippleModeEnable; + } + + gmesa->dirty |= GAMMA_UPLOAD_STIPPLE; +} + +static void gammaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_STIPPLE; +} + +/* ============================================================= + * Clipping + */ + +static void gammaUpdateClipping( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + GLint x1, y1, x2, y2; + + if ( gmesa->driDrawable ) { + x1 = gmesa->driDrawable->x + ctx->Scissor.X; + y1 = gmesa->driScreen->fbHeight - + (gmesa->driDrawable->y + + gmesa->driDrawable->h) + ctx->Scissor.Y; + x2 = x1 + ctx->Scissor.Width; + y2 = y1 + ctx->Scissor.Height; + + gmesa->ScissorMinXY = x1 | (y1 << 16); + gmesa->ScissorMaxXY = x2 | (y2 << 16); + if (ctx->Scissor.Enabled) + gmesa->ScissorMode |= UserScissorEnable; + else + gmesa->ScissorMode &= ~UserScissorEnable; + + gmesa->dirty |= GAMMA_UPLOAD_CLIP; + } +} + +static void gammaDDScissor( GLcontext *ctx, + GLint x, GLint y, GLsizei w, GLsizei h ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_CLIP; +} + +/* ============================================================= + * Culling + */ + +static void gammaUpdateCull( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 g = gmesa->GeometryMode; + + g &= ~(GM_PolyCullMask | GM_FFMask); + + if (ctx->Polygon.FrontFace == GL_CCW) { + g |= GM_FrontFaceCCW; + } else { + g |= GM_FrontFaceCW; + } + + switch ( ctx->Polygon.CullFaceMode ) { + case GL_FRONT: + g |= GM_PolyCullFront; + break; + case GL_BACK: + g |= GM_PolyCullBack; + break; + case GL_FRONT_AND_BACK: + g |= GM_PolyCullBoth; + break; + } + + if ( ctx->Polygon.CullFlag ) { + g |= GM_PolyCullEnable; + } else { + g &= ~GM_PolyCullEnable; + } + + if ( gmesa->GeometryMode != g ) { + gmesa->GeometryMode = g; + gmesa->dirty |= GAMMA_UPLOAD_GEOMETRY; + } +} + +static void gammaDDCullFace( GLcontext *ctx, GLenum mode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_CULL; +} + +static void gammaDDFrontFace( GLcontext *ctx, GLenum mode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_CULL; +} + +/* ============================================================= + * Masks + */ + +static void gammaUpdateMasks( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + + GLuint mask = gammaPackColor( gmesa->gammaScreen->cpp, + ctx->Color.ColorMask[RCOMP], + ctx->Color.ColorMask[GCOMP], + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP] ); + + if (gmesa->gammaScreen->cpp == 2) mask |= mask << 16; + + if ( gmesa->FBHardwareWriteMask != mask ) { + gmesa->FBHardwareWriteMask = mask; + gmesa->dirty |= GAMMA_UPLOAD_MASKS; + } +} + +static void gammaDDColorMask( GLcontext *ctx, GLboolean r, GLboolean g, + GLboolean b, GLboolean a) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_MASKS; +} + +/* ============================================================= + * 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. + */ + +#if ENABLELIGHTING +static void gammaDDLightfv(GLcontext *ctx, GLenum light, GLenum pname, + const GLfloat *params, GLint nParams) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + GLfloat l,x,y,z,w; + + switch(light) { + case GL_LIGHT0: + switch (pname) { + case GL_AMBIENT: + CHECK_DMA_BUFFER(gmesa, 3); + /* We don't do alpha */ + WRITEF(gmesa->buf, Light0AmbientIntensityBlue, params[2]); + WRITEF(gmesa->buf, Light0AmbientIntensityGreen, params[1]); + WRITEF(gmesa->buf, Light0AmbientIntensityRed, params[0]); + break; + case GL_DIFFUSE: + CHECK_DMA_BUFFER(gmesa, 3); + /* We don't do alpha */ + WRITEF(gmesa->buf, Light0DiffuseIntensityBlue, params[2]); + WRITEF(gmesa->buf, Light0DiffuseIntensityGreen, params[1]); + WRITEF(gmesa->buf, Light0DiffuseIntensityRed, params[0]); + break; + case GL_SPECULAR: + CHECK_DMA_BUFFER(gmesa, 3); + /* We don't do alpha */ + WRITEF(gmesa->buf, Light0SpecularIntensityBlue, params[2]); + WRITEF(gmesa->buf, Light0SpecularIntensityGreen, params[1]); + WRITEF(gmesa->buf, Light0SpecularIntensityRed, params[0]); + break; + case GL_POSITION: + /* Normalize <x,y,z> */ + x = params[0]; y = params[1]; z = params[2]; w = params[3]; + l = sqrt(x*x + y*y + z*z + w*w); + w /= l; + x /= l; + y /= l; + z /= l; + if (params[3] != 0.0) { + gmesa->Light0Mode |= Light0ModeAttenuation; + gmesa->Light0Mode |= Light0ModeLocal; + } else { + gmesa->Light0Mode &= ~Light0ModeAttenuation; + gmesa->Light0Mode &= ~Light0ModeLocal; + } + CHECK_DMA_BUFFER(gmesa, 5); + WRITE(gmesa->buf, Light0Mode, gmesa->Light0Mode); + WRITEF(gmesa->buf, Light0PositionW, w); + WRITEF(gmesa->buf, Light0PositionZ, z); + WRITEF(gmesa->buf, Light0PositionY, y); + WRITEF(gmesa->buf, Light0PositionX, x); + break; + case GL_SPOT_DIRECTION: + CHECK_DMA_BUFFER(gmesa, 3); + /* WRITEF(gmesa->buf, Light0SpotlightDirectionW, params[3]); */ + WRITEF(gmesa->buf, Light0SpotlightDirectionZ, params[2]); + WRITEF(gmesa->buf, Light0SpotlightDirectionY, params[1]); + WRITEF(gmesa->buf, Light0SpotlightDirectionX, params[0]); + break; + case GL_SPOT_EXPONENT: + CHECK_DMA_BUFFER(gmesa, 1); + WRITEF(gmesa->buf, Light0SpotlightExponent, params[0]); + break; + case GL_SPOT_CUTOFF: + if (params[0] != 180.0) + gmesa->Light0Mode |= Light0ModeSpotLight; + else + gmesa->Light0Mode &= ~Light0ModeSpotLight; + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, Light0Mode, gmesa->Light0Mode); + WRITEF(gmesa->buf, Light0CosSpotlightCutoffAngle, cos(params[0]*DEG2RAD)); + break; + case GL_CONSTANT_ATTENUATION: + CHECK_DMA_BUFFER(gmesa, 1); + WRITEF(gmesa->buf, Light0ConstantAttenuation, params[0]); + break; + case GL_LINEAR_ATTENUATION: + CHECK_DMA_BUFFER(gmesa, 1); + WRITEF(gmesa->buf, Light0LinearAttenuation, params[0]); + break; + case GL_QUADRATIC_ATTENUATION: + CHECK_DMA_BUFFER(gmesa, 1); + WRITEF(gmesa->buf, Light0QuadraticAttenuation, params[0]); + break; + } + break; + } +} + +static void gammaDDLightModelfv( GLcontext *ctx, GLenum pname, + const GLfloat *params ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + CHECK_DMA_BUFFER(gmesa, 3); + /* We don't do alpha */ + WRITEF(gmesa->buf, SceneAmbientColorBlue, params[2]); + WRITEF(gmesa->buf, SceneAmbientColorGreen, params[1]); + WRITEF(gmesa->buf, SceneAmbientColorRed, params[0]); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + if (params[0] != 0.0) + gmesa->LightingMode |= LightingModeLocalViewer; + else + gmesa->LightingMode &= ~LightingModeLocalViewer; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, LightingMode, gmesa->LightingMode); + break; + case GL_LIGHT_MODEL_TWO_SIDE: + if (params[0] == 1.0f) { + gmesa->LightingMode |= LightingModeTwoSides; + gmesa->MaterialMode |= MaterialModeTwoSides; + } else { + gmesa->LightingMode &= ~LightingModeTwoSides; + gmesa->MaterialMode &= ~MaterialModeTwoSides; + } + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, LightingMode, gmesa->LightingMode); + WRITE(gmesa->buf, MaterialMode, gmesa->MaterialMode); + break; + } +} +#endif + +static void gammaDDShadeModel( GLcontext *ctx, GLenum mode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + CARD32 g = gmesa->GeometryMode; + CARD32 c = gmesa->ColorDDAMode; + + g &= ~GM_ShadingMask; + c &= ~ColorDDAShadingMask; + + switch ( mode ) { + case GL_FLAT: + g |= GM_FlatShading; + c |= ColorDDAFlat; + break; + case GL_SMOOTH: + g |= GM_GouraudShading; + c |= ColorDDAGouraud; + break; + default: + return; + } + + if ( gmesa->ColorDDAMode != c ) { + FLUSH_BATCH( gmesa ); + gmesa->ColorDDAMode = c; + + gmesa->dirty |= GAMMA_UPLOAD_SHADE; + } + + if ( gmesa->GeometryMode != g ) { + FLUSH_BATCH( gmesa ); + gmesa->GeometryMode = g; + + gmesa->dirty |= GAMMA_UPLOAD_GEOMETRY; + } +} + +/* ============================================================= + * Miscellaneous + */ + +static void gammaDDClearColor( GLcontext *ctx, const GLfloat color[4]) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + GLubyte c[4]; + UNCLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); + UNCLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); + UNCLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); + UNCLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); + + gmesa->ClearColor = gammaPackColor( gmesa->gammaScreen->cpp, + c[0], c[1], c[2], c[3] ); + + if (gmesa->gammaScreen->cpp == 2) gmesa->ClearColor |= gmesa->ClearColor<<16; +} + + +static void gammaDDLogicalOpcode( GLcontext *ctx, GLenum opcode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + if ( ctx->Color.ColorLogicOpEnabled ) { + gmesa->LogicalOpMode = opcode << 1 | LogicalOpModeEnable; + } else { + gmesa->LogicalOpMode = LogicalOpModeDisable; + } + + gmesa->dirty |= GAMMA_UPLOAD_LOGICOP; +} + +static void gammaDDDrawBuffer( GLcontext *ctx, GLenum mode ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + FLUSH_BATCH( gmesa ); + + switch ( mode ) { + case GL_FRONT_LEFT: + gmesa->drawOffset = gmesa->readOffset = 0; + break; + case GL_BACK_LEFT: + gmesa->drawOffset = gmesa->readOffset = gmesa->driScreen->fbHeight * gmesa->driScreen->fbWidth * gmesa->gammaScreen->cpp; + break; + } +} + +static void gammaDDReadBuffer( GLcontext *ctx, GLenum mode ) +{ + /* XXX anything? */ +} + +/* ============================================================= + * Window position and viewport transformation + */ + +void gammaUpdateWindow( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = gmesa->driDrawable; + GLfloat xoffset = (GLfloat)dPriv->x; + GLfloat yoffset = gmesa->driScreen->fbHeight - (GLfloat)dPriv->y - dPriv->h; + const GLfloat *v = ctx->Viewport._WindowMap.m; + + GLfloat sx = v[MAT_SX]; + GLfloat tx = v[MAT_TX] + xoffset; + GLfloat sy = v[MAT_SY]; + GLfloat ty = v[MAT_TY] + yoffset; + GLfloat sz = v[MAT_SZ] * gmesa->depth_scale; + GLfloat tz = v[MAT_TZ] * gmesa->depth_scale; + + gmesa->dirty |= GAMMA_UPLOAD_VIEWPORT; + + gmesa->ViewportScaleX = sx; + gmesa->ViewportScaleY = sy; + gmesa->ViewportScaleZ = sz; + gmesa->ViewportOffsetX = tx; + gmesa->ViewportOffsetY = ty; + gmesa->ViewportOffsetZ = tz; +} + + + +static void gammaDDViewport( GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height ) +{ + gammaUpdateWindow( ctx ); +} + +static void gammaDDDepthRange( GLcontext *ctx, GLclampd nearval, + GLclampd farval ) +{ + gammaUpdateWindow( ctx ); +} + +void gammaUpdateViewportOffset( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = gmesa->driDrawable; + GLfloat xoffset = (GLfloat)dPriv->x; + GLfloat yoffset = gmesa->driScreen->fbHeight - (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 ( gmesa->ViewportOffsetX != tx || + gmesa->ViewportOffsetY != ty ) + { + gmesa->ViewportOffsetX = tx; + gmesa->ViewportOffsetY = ty; + + gmesa->new_state |= GAMMA_NEW_WINDOW; + } + + gmesa->new_state |= GAMMA_NEW_CLIP; +} + +#if 0 +/* + * Matrix + */ + +static void gammaLoadHWMatrix(GLcontext *ctx) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + const GLfloat *m; + + gmesa->TransformMode &= ~XM_XformTexture; + + switch (ctx->Transform.MatrixMode) { + case GL_MODELVIEW: + gmesa->TransformMode |= XM_UseModelViewMatrix; + m = ctx->ModelviewMatrixStack.Top->m; + CHECK_DMA_BUFFER(gmesa, 16); + WRITEF(gmesa->buf, ModelViewMatrix0, m[0]); + WRITEF(gmesa->buf, ModelViewMatrix1, m[1]); + WRITEF(gmesa->buf, ModelViewMatrix2, m[2]); + WRITEF(gmesa->buf, ModelViewMatrix3, m[3]); + WRITEF(gmesa->buf, ModelViewMatrix4, m[4]); + WRITEF(gmesa->buf, ModelViewMatrix5, m[5]); + WRITEF(gmesa->buf, ModelViewMatrix6, m[6]); + WRITEF(gmesa->buf, ModelViewMatrix7, m[7]); + WRITEF(gmesa->buf, ModelViewMatrix8, m[8]); + WRITEF(gmesa->buf, ModelViewMatrix9, m[9]); + WRITEF(gmesa->buf, ModelViewMatrix10, m[10]); + WRITEF(gmesa->buf, ModelViewMatrix11, m[11]); + WRITEF(gmesa->buf, ModelViewMatrix12, m[12]); + WRITEF(gmesa->buf, ModelViewMatrix13, m[13]); + WRITEF(gmesa->buf, ModelViewMatrix14, m[14]); + WRITEF(gmesa->buf, ModelViewMatrix15, m[15]); + break; + case GL_PROJECTION: + m = ctx->ProjectionMatrixStack.Top->m; + CHECK_DMA_BUFFER(gmesa, 16); + WRITEF(gmesa->buf, ModelViewProjectionMatrix0, m[0]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix1, m[1]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix2, m[2]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix3, m[3]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix4, m[4]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix5, m[5]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix6, m[6]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix7, m[7]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix8, m[8]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix9, m[9]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix10, m[10]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix11, m[11]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix12, m[12]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix13, m[13]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix14, m[14]); + WRITEF(gmesa->buf, ModelViewProjectionMatrix15, m[15]); + break; + case GL_TEXTURE: + m = ctx->TextureMatrixStack[0].Top->m; + CHECK_DMA_BUFFER(gmesa, 16); + gmesa->TransformMode |= XM_XformTexture; + WRITEF(gmesa->buf, TextureMatrix0, m[0]); + WRITEF(gmesa->buf, TextureMatrix1, m[1]); + WRITEF(gmesa->buf, TextureMatrix2, m[2]); + WRITEF(gmesa->buf, TextureMatrix3, m[3]); + WRITEF(gmesa->buf, TextureMatrix4, m[4]); + WRITEF(gmesa->buf, TextureMatrix5, m[5]); + WRITEF(gmesa->buf, TextureMatrix6, m[6]); + WRITEF(gmesa->buf, TextureMatrix7, m[7]); + WRITEF(gmesa->buf, TextureMatrix8, m[8]); + WRITEF(gmesa->buf, TextureMatrix9, m[9]); + WRITEF(gmesa->buf, TextureMatrix10, m[10]); + WRITEF(gmesa->buf, TextureMatrix11, m[11]); + WRITEF(gmesa->buf, TextureMatrix12, m[12]); + WRITEF(gmesa->buf, TextureMatrix13, m[13]); + WRITEF(gmesa->buf, TextureMatrix14, m[14]); + WRITEF(gmesa->buf, TextureMatrix15, m[15]); + break; + + default: + /* ERROR!!! -- how did this happen? */ + break; + } + + gmesa->dirty |= GAMMA_UPLOAD_TRANSFORM; +} +#endif + +/* ============================================================= + * State enable/disable + */ + +static void gammaDDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + + switch ( cap ) { + case GL_ALPHA_TEST: + case GL_BLEND: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_ALPHA; + break; + + case GL_CULL_FACE: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_CULL; + break; + + case GL_DEPTH_TEST: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_DEPTH; + break; + + case GL_DITHER: + do { + CARD32 d = gmesa->DitherMode; + FLUSH_BATCH( gmesa ); + + if ( state ) { + d |= DM_DitherEnable; + } else { + d &= ~DM_DitherEnable; + } + + if ( gmesa->DitherMode != d ) { + gmesa->DitherMode = d; + gmesa->dirty |= GAMMA_UPLOAD_DITHER; + } + } while (0); + break; + +#if 0 + case GL_FOG: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_FOG; + break; +#endif + + case GL_INDEX_LOGIC_OP: + case GL_COLOR_LOGIC_OP: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_LOGICOP; + break; + +#if ENABLELIGHTING + case GL_LIGHTING: + do { + CARD32 l = gmesa->LightingMode; + FLUSH_BATCH( gmesa ); + + if ( state ) { + l |= LightingModeEnable; + } else { + l &= ~LightingModeEnable; + } + + if ( gmesa->LightingMode != l ) { + gmesa->LightingMode = l; + gmesa->dirty |= GAMMA_UPLOAD_LIGHT; + } + } while (0); + break; + + case GL_COLOR_MATERIAL: + do { + CARD32 m = gmesa->MaterialMode; + FLUSH_BATCH( gmesa ); + + if ( state ) { + m |= MaterialModeEnable; + } else { + m &= ~MaterialModeEnable; + } + + if ( gmesa->MaterialMode != m ) { + gmesa->MaterialMode = m; + gmesa->dirty |= GAMMA_UPLOAD_LIGHT; + } + } while (0); + break; +#endif + + case GL_LINE_SMOOTH: + FLUSH_BATCH( gmesa ); + if ( state ) { + gmesa->AntialiasMode |= AntialiasModeEnable; + gmesa->LineMode |= LM_AntialiasEnable; + } else { + gmesa->AntialiasMode &= ~AntialiasModeEnable; + gmesa->LineMode &= ~LM_AntialiasEnable; + } + gmesa->dirty |= GAMMA_UPLOAD_LINEMODE; + break; + + case GL_POINT_SMOOTH: + FLUSH_BATCH( gmesa ); + if ( state ) { + gmesa->AntialiasMode |= AntialiasModeEnable; + gmesa->PointMode |= PM_AntialiasEnable; + } else { + gmesa->AntialiasMode &= ~AntialiasModeEnable; + gmesa->PointMode &= ~PM_AntialiasEnable; + } + gmesa->dirty |= GAMMA_UPLOAD_POINTMODE; + break; + + case GL_POLYGON_SMOOTH: + FLUSH_BATCH( gmesa ); + if ( state ) { + gmesa->AntialiasMode |= AntialiasModeEnable; + gmesa->TriangleMode |= TM_AntialiasEnable; + } else { + gmesa->AntialiasMode &= ~AntialiasModeEnable; + gmesa->TriangleMode &= ~TM_AntialiasEnable; + } + gmesa->dirty |= GAMMA_UPLOAD_TRIMODE; + break; + + case GL_SCISSOR_TEST: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_CLIP; + break; + + case GL_POLYGON_OFFSET_FILL: + case GL_POLYGON_OFFSET_POINT: + case GL_POLYGON_OFFSET_LINE: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_POLYGON; + break; + + case GL_LINE_STIPPLE: + FLUSH_BATCH( gmesa ); + if ( state ) + gmesa->LineMode |= LM_StippleEnable; + else + gmesa->LineMode &= ~LM_StippleEnable; + gmesa->dirty |= GAMMA_UPLOAD_LINEMODE; + break; + + case GL_POLYGON_STIPPLE: + FLUSH_BATCH( gmesa ); + gmesa->new_state |= GAMMA_NEW_STIPPLE; + break; + + default: + return; + } +} + +/* ============================================================= + * State initialization, management + */ + + +/* + * Load the current context's state into the hardware. + * + * NOTE: Be VERY careful about ensuring the context state is marked for + * upload, the only place it shouldn't be uploaded is when the setup + * state has changed in ReducedPrimitiveChange as this comes right after + * a state update. + * + * Blits of any type should always upload the context and masks after + * they are done. + */ +void gammaEmitHwState( gammaContextPtr gmesa ) +{ + if (!gmesa->driDrawable) return; + + if (!gmesa->dirty) return; + +#ifdef DO_VALIDATE + /* Flush any partially filled buffers */ + FLUSH_DMA_BUFFER(gmesa); + + DRM_SPINLOCK(&gmesa->driScreen->pSAREA->drawable_lock, + gmesa->driScreen->drawLockID); + VALIDATE_DRAWABLE_INFO_NO_LOCK(gmesa); +#endif + + if (gmesa->dirty & GAMMA_UPLOAD_VIEWPORT) { + gmesa->dirty &= ~GAMMA_UPLOAD_VIEWPORT; + CHECK_DMA_BUFFER(gmesa, 6); + WRITEF(gmesa->buf, ViewPortOffsetX, gmesa->ViewportOffsetX); + WRITEF(gmesa->buf, ViewPortOffsetY, gmesa->ViewportOffsetY); + WRITEF(gmesa->buf, ViewPortOffsetZ, gmesa->ViewportOffsetZ); + WRITEF(gmesa->buf, ViewPortScaleX, gmesa->ViewportScaleX); + WRITEF(gmesa->buf, ViewPortScaleY, gmesa->ViewportScaleY); + WRITEF(gmesa->buf, ViewPortScaleZ, gmesa->ViewportScaleZ); + } + if ( (gmesa->dirty & GAMMA_UPLOAD_POINTMODE) || + (gmesa->dirty & GAMMA_UPLOAD_LINEMODE) || + (gmesa->dirty & GAMMA_UPLOAD_TRIMODE) ) { + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, AntialiasMode, gmesa->AntialiasMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_POINTMODE) { + gmesa->dirty &= ~GAMMA_UPLOAD_POINTMODE; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, PointMode, gmesa->PointMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_LINEMODE) { + gmesa->dirty &= ~GAMMA_UPLOAD_LINEMODE; + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, LineMode, gmesa->LineMode); + WRITE(gmesa->buf, LineStippleMode, gmesa->LineMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_TRIMODE) { + gmesa->dirty &= ~GAMMA_UPLOAD_TRIMODE; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, TriangleMode, gmesa->TriangleMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_FOG) { + GLchan c[3], col; + UNCLAMPED_FLOAT_TO_RGB_CHAN( c, gmesa->glCtx->Fog.Color ); + col = gammaPackColor(4, c[0], c[1], c[2], 0); + gmesa->dirty &= ~GAMMA_UPLOAD_FOG; + CHECK_DMA_BUFFER(gmesa, 5); +#if 0 + WRITE(gmesa->buf, FogMode, gmesa->FogMode); + WRITE(gmesa->buf, FogColor, col); + WRITEF(gmesa->buf, FStart, gmesa->glCtx->Fog.Start); +#endif + WRITEF(gmesa->buf, FogEnd, gmesa->glCtx->Fog.End); + WRITEF(gmesa->buf, FogDensity, gmesa->glCtx->Fog.Density); + WRITEF(gmesa->buf, FogScale, + 1.0f/(gmesa->glCtx->Fog.End - gmesa->glCtx->Fog.Start)); + } + if (gmesa->dirty & GAMMA_UPLOAD_DITHER) { + gmesa->dirty &= ~GAMMA_UPLOAD_DITHER; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, DitherMode, gmesa->DitherMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_LOGICOP) { + gmesa->dirty &= ~GAMMA_UPLOAD_LOGICOP; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, LogicalOpMode, gmesa->LogicalOpMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_CLIP) { + gmesa->dirty &= ~GAMMA_UPLOAD_CLIP; + CHECK_DMA_BUFFER(gmesa, 3); + WRITE(gmesa->buf, ScissorMinXY, gmesa->ScissorMinXY); + WRITE(gmesa->buf, ScissorMaxXY, gmesa->ScissorMaxXY); + WRITE(gmesa->buf, ScissorMode, gmesa->ScissorMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_MASKS) { + gmesa->dirty &= ~GAMMA_UPLOAD_MASKS; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, FBHardwareWriteMask, gmesa->FBHardwareWriteMask); + } + if (gmesa->dirty & GAMMA_UPLOAD_ALPHA) { + gmesa->dirty &= ~GAMMA_UPLOAD_ALPHA; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, AlphaTestMode, gmesa->AlphaTestMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_BLEND) { + gmesa->dirty &= ~GAMMA_UPLOAD_BLEND; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, AlphaBlendMode, gmesa->AlphaBlendMode); + } + CHECK_DMA_BUFFER(gmesa, 1); + if (gmesa->glCtx->Color.BlendEnabled || gmesa->glCtx->Color.AlphaEnabled) { + WRITE(gmesa->buf, FBReadMode, gmesa->FBReadMode | gmesa->AB_FBReadMode_Save); + } else { + WRITE(gmesa->buf, FBReadMode, gmesa->FBReadMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_LIGHT) { + gmesa->dirty &= ~GAMMA_UPLOAD_LIGHT; + CHECK_DMA_BUFFER(gmesa, 2); + WRITE(gmesa->buf, LightingMode, gmesa->LightingMode); + WRITE(gmesa->buf, MaterialMode, gmesa->MaterialMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_SHADE) { + gmesa->dirty &= ~GAMMA_UPLOAD_SHADE; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, ColorDDAMode, gmesa->ColorDDAMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_POLYGON) { + gmesa->dirty &= ~GAMMA_UPLOAD_POLYGON; + CHECK_DMA_BUFFER(gmesa, 2); + WRITEF(gmesa->buf, PolygonOffsetBias, gmesa->glCtx->Polygon.OffsetUnits); + WRITEF(gmesa->buf, PolygonOffsetFactor, gmesa->glCtx->Polygon.OffsetFactor); + } + if (gmesa->dirty & GAMMA_UPLOAD_STIPPLE) { + gmesa->dirty &= ~GAMMA_UPLOAD_STIPPLE; + CHECK_DMA_BUFFER(gmesa, 33); + WRITE(gmesa->buf, AreaStippleMode, gmesa->AreaStippleMode); + WRITE(gmesa->buf, AreaStipplePattern0, gmesa->glCtx->PolygonStipple[0]); + WRITE(gmesa->buf, AreaStipplePattern1, gmesa->glCtx->PolygonStipple[1]); + WRITE(gmesa->buf, AreaStipplePattern2, gmesa->glCtx->PolygonStipple[2]); + WRITE(gmesa->buf, AreaStipplePattern3, gmesa->glCtx->PolygonStipple[3]); + WRITE(gmesa->buf, AreaStipplePattern4, gmesa->glCtx->PolygonStipple[4]); + WRITE(gmesa->buf, AreaStipplePattern5, gmesa->glCtx->PolygonStipple[5]); + WRITE(gmesa->buf, AreaStipplePattern6, gmesa->glCtx->PolygonStipple[6]); + WRITE(gmesa->buf, AreaStipplePattern7, gmesa->glCtx->PolygonStipple[7]); + WRITE(gmesa->buf, AreaStipplePattern8, gmesa->glCtx->PolygonStipple[8]); + WRITE(gmesa->buf, AreaStipplePattern9, gmesa->glCtx->PolygonStipple[9]); + WRITE(gmesa->buf, AreaStipplePattern10, gmesa->glCtx->PolygonStipple[10]); + WRITE(gmesa->buf, AreaStipplePattern11, gmesa->glCtx->PolygonStipple[11]); + WRITE(gmesa->buf, AreaStipplePattern12, gmesa->glCtx->PolygonStipple[12]); + WRITE(gmesa->buf, AreaStipplePattern13, gmesa->glCtx->PolygonStipple[13]); + WRITE(gmesa->buf, AreaStipplePattern14, gmesa->glCtx->PolygonStipple[14]); + WRITE(gmesa->buf, AreaStipplePattern15, gmesa->glCtx->PolygonStipple[15]); + WRITE(gmesa->buf, AreaStipplePattern16, gmesa->glCtx->PolygonStipple[16]); + WRITE(gmesa->buf, AreaStipplePattern17, gmesa->glCtx->PolygonStipple[17]); + WRITE(gmesa->buf, AreaStipplePattern18, gmesa->glCtx->PolygonStipple[18]); + WRITE(gmesa->buf, AreaStipplePattern19, gmesa->glCtx->PolygonStipple[19]); + WRITE(gmesa->buf, AreaStipplePattern20, gmesa->glCtx->PolygonStipple[20]); + WRITE(gmesa->buf, AreaStipplePattern21, gmesa->glCtx->PolygonStipple[21]); + WRITE(gmesa->buf, AreaStipplePattern22, gmesa->glCtx->PolygonStipple[22]); + WRITE(gmesa->buf, AreaStipplePattern23, gmesa->glCtx->PolygonStipple[23]); + WRITE(gmesa->buf, AreaStipplePattern24, gmesa->glCtx->PolygonStipple[24]); + WRITE(gmesa->buf, AreaStipplePattern25, gmesa->glCtx->PolygonStipple[25]); + WRITE(gmesa->buf, AreaStipplePattern26, gmesa->glCtx->PolygonStipple[26]); + WRITE(gmesa->buf, AreaStipplePattern27, gmesa->glCtx->PolygonStipple[27]); + WRITE(gmesa->buf, AreaStipplePattern28, gmesa->glCtx->PolygonStipple[28]); + WRITE(gmesa->buf, AreaStipplePattern29, gmesa->glCtx->PolygonStipple[29]); + WRITE(gmesa->buf, AreaStipplePattern30, gmesa->glCtx->PolygonStipple[30]); + WRITE(gmesa->buf, AreaStipplePattern31, gmesa->glCtx->PolygonStipple[31]); + } + if (gmesa->dirty & GAMMA_UPLOAD_DEPTH) { + gmesa->dirty &= ~GAMMA_UPLOAD_DEPTH; + CHECK_DMA_BUFFER(gmesa, 4); + WRITE(gmesa->buf, DepthMode, gmesa->DepthMode); + WRITE(gmesa->buf, DeltaMode, gmesa->DeltaMode); + WRITE(gmesa->buf, GLINTWindow,gmesa->Window | (gmesa->FrameCount << 9)); + WRITE(gmesa->buf, LBReadMode, gmesa->LBReadMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_GEOMETRY) { + gmesa->dirty &= ~GAMMA_UPLOAD_GEOMETRY; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, GeometryMode, gmesa->GeometryMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_TRANSFORM) { + gmesa->dirty &= ~GAMMA_UPLOAD_TRANSFORM; + CHECK_DMA_BUFFER(gmesa, 1); + WRITE(gmesa->buf, TransformMode, gmesa->TransformMode); + } + if (gmesa->dirty & GAMMA_UPLOAD_TEX0) { + gammaTextureObjectPtr curTex = gmesa->CurrentTexObj[0]; + gmesa->dirty &= ~GAMMA_UPLOAD_TEX0; + if (curTex) { + CHECK_DMA_BUFFER(gmesa, 21); + WRITE(gmesa->buf, GeometryMode, gmesa->GeometryMode | GM_TextureEnable); + WRITE(gmesa->buf, DeltaMode, gmesa->DeltaMode | DM_TextureEnable); + WRITE(gmesa->buf, TextureAddressMode, curTex->TextureAddressMode); + WRITE(gmesa->buf, TextureReadMode, curTex->TextureReadMode); + WRITE(gmesa->buf, TextureColorMode, curTex->TextureColorMode); + WRITE(gmesa->buf, TextureFilterMode, curTex->TextureFilterMode); + WRITE(gmesa->buf, TextureFormat, curTex->TextureFormat); + WRITE(gmesa->buf, GLINTBorderColor, curTex->TextureBorderColor); + WRITE(gmesa->buf, TxBaseAddr0, curTex->TextureBaseAddr[0]); + WRITE(gmesa->buf, TxBaseAddr1, curTex->TextureBaseAddr[1]); + WRITE(gmesa->buf, TxBaseAddr2, curTex->TextureBaseAddr[2]); + WRITE(gmesa->buf, TxBaseAddr3, curTex->TextureBaseAddr[3]); + WRITE(gmesa->buf, TxBaseAddr4, curTex->TextureBaseAddr[4]); + WRITE(gmesa->buf, TxBaseAddr5, curTex->TextureBaseAddr[5]); + WRITE(gmesa->buf, TxBaseAddr6, curTex->TextureBaseAddr[6]); + WRITE(gmesa->buf, TxBaseAddr7, curTex->TextureBaseAddr[7]); + WRITE(gmesa->buf, TxBaseAddr8, curTex->TextureBaseAddr[8]); + WRITE(gmesa->buf, TxBaseAddr9, curTex->TextureBaseAddr[9]); + WRITE(gmesa->buf, TxBaseAddr10, curTex->TextureBaseAddr[10]); + WRITE(gmesa->buf, TxBaseAddr11, curTex->TextureBaseAddr[11]); + WRITE(gmesa->buf, TxBaseAddr12, curTex->TextureBaseAddr[12]); + WRITE(gmesa->buf, TextureCacheControl, (TCC_Enable | TCC_Invalidate)); + } else { + CHECK_DMA_BUFFER(gmesa, 6); + WRITE(gmesa->buf, GeometryMode, gmesa->GeometryMode); + WRITE(gmesa->buf, DeltaMode, gmesa->DeltaMode); + WRITE(gmesa->buf, TextureAddressMode, TextureAddressModeDisable); + WRITE(gmesa->buf, TextureReadMode, TextureReadModeDisable); + WRITE(gmesa->buf, TextureFilterMode, TextureFilterModeDisable); + WRITE(gmesa->buf, TextureColorMode, TextureColorModeDisable); + } + } +#ifdef DO_VALIDATE + PROCESS_DMA_BUFFER_TOP_HALF(gmesa); + + DRM_SPINUNLOCK(&gmesa->driScreen->pSAREA->drawable_lock, + gmesa->driScreen->drawLockID); + VALIDATE_DRAWABLE_INFO_NO_LOCK_POST(gmesa); + + PROCESS_DMA_BUFFER_BOTTOM_HALF(gmesa); +#endif +} + +void gammaDDUpdateHWState( GLcontext *ctx ) +{ + gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); + int new_state = gmesa->new_state; + + if ( new_state ) + { + FLUSH_BATCH( gmesa ); + + gmesa->new_state = 0; + + /* Update the various parts of the context's state. + */ + if ( new_state & GAMMA_NEW_ALPHA ) + gammaUpdateAlphaMode( ctx ); + + if ( new_state & GAMMA_NEW_DEPTH ) + gammaUpdateZMode( ctx ); + + if ( new_state & GAMMA_NEW_FOG ) + gammaUpdateFogAttrib( ctx ); + + if ( new_state & GAMMA_NEW_CLIP ) + gammaUpdateClipping( ctx ); + + if ( new_state & GAMMA_NEW_POLYGON ) + gammaUpdatePolygon( ctx ); + + if ( new_state & GAMMA_NEW_CULL ) + gammaUpdateCull( ctx ); + + if ( new_state & GAMMA_NEW_MASKS ) + gammaUpdateMasks( ctx ); + + if ( new_state & GAMMA_NEW_WINDOW ) + gammaUpdateWindow( ctx ); + + if ( new_state & GAMMA_NEW_STIPPLE ) + gammaUpdateStipple( ctx ); + } + + /* HACK ! */ + + gammaEmitHwState( gmesa ); +} + + +static void gammaDDUpdateState( 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 ); + GAMMA_CONTEXT(ctx)->new_gl_state |= new_state; +} + + +/* Initialize the context's hardware state. + */ +void gammaDDInitState( gammaContextPtr gmesa ) +{ + gmesa->new_state = 0; +} + +/* Initialize the driver's state functions. + */ +void gammaDDInitStateFuncs( GLcontext *ctx ) +{ + ctx->Driver.UpdateState = gammaDDUpdateState; + + ctx->Driver.Clear = gammaDDClear; + ctx->Driver.ClearIndex = NULL; + ctx->Driver.ClearColor = gammaDDClearColor; + ctx->Driver.DrawBuffer = gammaDDDrawBuffer; + ctx->Driver.ReadBuffer = gammaDDReadBuffer; + + ctx->Driver.IndexMask = NULL; + ctx->Driver.ColorMask = gammaDDColorMask; + + ctx->Driver.AlphaFunc = gammaDDAlphaFunc; + ctx->Driver.BlendEquation = gammaDDBlendEquation; + ctx->Driver.BlendFunc = gammaDDBlendFunc; + ctx->Driver.BlendFuncSeparate = gammaDDBlendFuncSeparate; + ctx->Driver.ClearDepth = gammaDDClearDepth; + ctx->Driver.CullFace = gammaDDCullFace; + ctx->Driver.FrontFace = gammaDDFrontFace; + ctx->Driver.DepthFunc = gammaDDDepthFunc; + ctx->Driver.DepthMask = gammaDDDepthMask; + ctx->Driver.DepthRange = gammaDDDepthRange; + ctx->Driver.Enable = gammaDDEnable; + ctx->Driver.Finish = gammaDDFinish; + ctx->Driver.Flush = gammaDDFlush; +#if 0 + ctx->Driver.Fogfv = gammaDDFogfv; +#endif + ctx->Driver.Hint = NULL; + ctx->Driver.LineWidth = gammaDDLineWidth; + ctx->Driver.LineStipple = gammaDDLineStipple; +#if ENABLELIGHTING + ctx->Driver.Lightfv = gammaDDLightfv; + ctx->Driver.LightModelfv = gammaDDLightModelfv; +#endif + ctx->Driver.LogicOpcode = gammaDDLogicalOpcode; + ctx->Driver.PointSize = gammaDDPointSize; + ctx->Driver.PolygonMode = gammaDDPolygonMode; + ctx->Driver.PolygonStipple = gammaDDPolygonStipple; + ctx->Driver.Scissor = gammaDDScissor; + ctx->Driver.ShadeModel = gammaDDShadeModel; + ctx->Driver.ClearStencil = NULL; + ctx->Driver.StencilFunc = NULL; + ctx->Driver.StencilMask = NULL; + ctx->Driver.StencilOp = NULL; + ctx->Driver.Viewport = gammaDDViewport; +} |