| /* |
| * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. |
| * Copyright 2001-2003 S3 Graphics, 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 |
| * 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 |
| * VIA, S3 GRAPHICS, 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. |
| */ |
| |
| |
| #include <stdio.h> |
| |
| #include "main/mtypes.h" |
| #include "main/enums.h" |
| #include "main/macros.h" |
| #include "main/dd.h" |
| |
| #include "main/mm.h" |
| #include "savagedd.h" |
| #include "savagecontext.h" |
| |
| #include "savagestate.h" |
| #include "savagetex.h" |
| #include "savagetris.h" |
| #include "savageioctl.h" |
| #include "savage_bci.h" |
| |
| #include "swrast/swrast.h" |
| #include "vbo/vbo.h" |
| #include "tnl/tnl.h" |
| #include "swrast_setup/swrast_setup.h" |
| |
| #include "xmlpool.h" |
| |
| /* Savage4, ProSavage[DDR], SuperSavage watermarks */ |
| #define S4_ZRLO 24 |
| #define S4_ZRHI 24 |
| #define S4_ZWLO 0 |
| #define S4_ZWHI 0 |
| |
| #define S4_DRLO 0 |
| #define S4_DRHI 0 |
| #define S4_DWLO 0 |
| #define S4_DWHI 0 |
| |
| #define S4_TR 15 |
| |
| /* Savage3D/MX/IX watermarks */ |
| #define S3D_ZRLO 8 |
| #define S3D_ZRHI 24 |
| #define S3D_ZWLO 0 |
| #define S3D_ZWHI 24 |
| |
| #define S3D_DRLO 0 |
| #define S3D_DRHI 0 |
| #define S3D_DWLO 0 |
| #define S3D_DWHI 0 |
| |
| #define S3D_TR 15 |
| |
| static void savageBlendFunc_s4(struct gl_context *); |
| static void savageBlendFunc_s3d(struct gl_context *); |
| |
| static INLINE GLuint savagePackColor(GLuint format, |
| GLubyte r, GLubyte g, |
| GLubyte b, GLubyte a) |
| { |
| switch (format) { |
| case DV_PF_8888: |
| return SAVAGEPACKCOLOR8888(r,g,b,a); |
| case DV_PF_565: |
| return SAVAGEPACKCOLOR565(r,g,b); |
| default: |
| |
| return 0; |
| } |
| } |
| |
| |
| static void savageDDAlphaFunc_s4(struct gl_context *ctx, GLenum func, GLfloat ref) |
| { |
| savageBlendFunc_s4(ctx); |
| } |
| static void savageDDAlphaFunc_s3d(struct gl_context *ctx, GLenum func, GLfloat ref) |
| { |
| savageBlendFunc_s3d(ctx); |
| } |
| |
| static void savageDDBlendEquationSeparate(struct gl_context *ctx, |
| GLenum modeRGB, GLenum modeA) |
| { |
| assert( modeRGB == modeA ); |
| |
| /* BlendEquation sets ColorLogicOpEnabled in an unexpected |
| * manner. |
| */ |
| FALLBACK( ctx, SAVAGE_FALLBACK_LOGICOP, |
| (ctx->Color.ColorLogicOpEnabled && |
| ctx->Color.LogicOp != GL_COPY)); |
| |
| /* Can only do blend addition, not min, max, subtract, etc. */ |
| FALLBACK( ctx, SAVAGE_FALLBACK_BLEND_EQ, |
| modeRGB != GL_FUNC_ADD); |
| } |
| |
| |
| static void savageBlendFunc_s4(struct gl_context *ctx) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| uint32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui; |
| uint32_t drawCtrl0 = imesa->regs.s4.drawCtrl0.ui; |
| uint32_t drawCtrl1 = imesa->regs.s4.drawCtrl1.ui; |
| |
| /* set up draw control register (including blending, alpha |
| * test, and shading model) |
| */ |
| |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_FALSE; |
| |
| /* |
| * blend modes |
| */ |
| if(ctx->Color.BlendEnabled){ |
| switch (ctx->Color.BlendDstRGB) |
| { |
| case GL_ZERO: |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero; |
| break; |
| |
| case GL_ONE: |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_One; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_SRC_COLOR: |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_SrcClr; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_ONE_MINUS_SRC_COLOR: |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_1SrcClr; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_SRC_ALPHA: |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_SrcAlpha; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_ONE_MINUS_SRC_ALPHA: |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_1SrcAlpha; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_DST_ALPHA: |
| if (imesa->glCtx->Visual.alphaBits == 0) |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_One; |
| } |
| else |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode= DAM_DstAlpha; |
| } |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_ONE_MINUS_DST_ALPHA: |
| if (imesa->glCtx->Visual.alphaBits == 0) |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero; |
| } |
| else |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode=DAM_1DstAlpha; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE; |
| } |
| break; |
| } |
| |
| switch (ctx->Color.BlendSrcRGB) |
| { |
| case GL_ZERO: |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_Zero; |
| break; |
| |
| case GL_ONE: |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One; |
| break; |
| |
| case GL_DST_COLOR: |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_DstClr; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_ONE_MINUS_DST_COLOR: |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_1DstClr; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_SRC_ALPHA: |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_SrcAlpha; |
| break; |
| |
| case GL_ONE_MINUS_SRC_ALPHA: |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_1SrcAlpha; |
| break; |
| |
| case GL_DST_ALPHA: |
| if (imesa->glCtx->Visual.alphaBits == 0) |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One; |
| } |
| else |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode= SAM_DstAlpha; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE; |
| } |
| break; |
| |
| case GL_ONE_MINUS_DST_ALPHA: |
| if (imesa->glCtx->Visual.alphaBits == 0) |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_Zero; |
| } |
| else |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode=SAM_1DstAlpha; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE; |
| } |
| break; |
| } |
| } |
| else |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.dstAlphaMode = DAM_Zero; |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One; |
| } |
| |
| /* alpha test*/ |
| |
| if(ctx->Color.AlphaEnabled) |
| { |
| ACmpFunc a; |
| GLubyte alphaRef; |
| |
| CLAMPED_FLOAT_TO_UBYTE(alphaRef,ctx->Color.AlphaRef); |
| |
| switch(ctx->Color.AlphaFunc) { |
| case GL_NEVER: a = CF_Never; break; |
| case GL_ALWAYS: a = CF_Always; break; |
| case GL_LESS: a = CF_Less; break; |
| case GL_LEQUAL: a = CF_LessEqual; break; |
| case GL_EQUAL: a = CF_Equal; break; |
| case GL_GREATER: a = CF_Greater; break; |
| case GL_GEQUAL: a = CF_GreaterEqual; break; |
| case GL_NOTEQUAL: a = CF_NotEqual; break; |
| default:return; |
| } |
| |
| imesa->regs.s4.drawCtrl1.ni.alphaTestEn = GL_TRUE; |
| imesa->regs.s4.drawCtrl1.ni.alphaTestCmpFunc = a; |
| imesa->regs.s4.drawCtrl0.ni.alphaRefVal = alphaRef; |
| } |
| else |
| { |
| imesa->regs.s4.drawCtrl1.ni.alphaTestEn = GL_FALSE; |
| } |
| |
| /* Set/Reset Z-after-alpha*/ |
| |
| imesa->regs.s4.drawLocalCtrl.ni.wrZafterAlphaTst = |
| imesa->regs.s4.drawCtrl1.ni.alphaTestEn; |
| /*imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = |
| ~drawLocalCtrl.ni.wrZafterAlphaTst;*/ |
| |
| if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| if (drawCtrl0 != imesa->regs.s4.drawCtrl0.ui || |
| drawCtrl1 != imesa->regs.s4.drawCtrl1.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; |
| } |
| static void savageBlendFunc_s3d(struct gl_context *ctx) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui; |
| uint32_t zBufCtrl = imesa->regs.s3d.zBufCtrl.ui; |
| |
| /* set up draw control register (including blending, alpha |
| * test, dithering, and shading model) |
| */ |
| |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = 0; |
| |
| /* |
| * blend modes |
| */ |
| if(ctx->Color.BlendEnabled){ |
| switch (ctx->Color.BlendDstRGB) |
| { |
| case GL_ZERO: |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero; |
| break; |
| |
| case GL_ONE: |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_One; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_SRC_COLOR: |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_SrcClr; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_ONE_MINUS_SRC_COLOR: |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_1SrcClr; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_SRC_ALPHA: |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_SrcAlpha; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_ONE_MINUS_SRC_ALPHA: |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_1SrcAlpha; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_DST_ALPHA: |
| if (imesa->glCtx->Visual.alphaBits == 0) |
| { |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_One; |
| } |
| else |
| { |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_DstAlpha; |
| } |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_ONE_MINUS_DST_ALPHA: |
| if (imesa->glCtx->Visual.alphaBits == 0) |
| { |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero; |
| } |
| else |
| { |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_1DstAlpha; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| } |
| break; |
| } |
| |
| switch (ctx->Color.BlendSrcRGB) |
| { |
| case GL_ZERO: |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_Zero; |
| break; |
| |
| case GL_ONE: |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One; |
| break; |
| |
| case GL_DST_COLOR: |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_DstClr; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_ONE_MINUS_DST_COLOR: |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1DstClr; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| break; |
| |
| case GL_SRC_ALPHA: |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_SrcAlpha; |
| break; |
| |
| case GL_ONE_MINUS_SRC_ALPHA: |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1SrcAlpha; |
| break; |
| |
| case GL_DST_ALPHA: |
| if (imesa->glCtx->Visual.alphaBits == 0) |
| { |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One; |
| } |
| else |
| { |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_DstAlpha; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| } |
| break; |
| |
| case GL_ONE_MINUS_DST_ALPHA: |
| if (imesa->glCtx->Visual.alphaBits == 0) |
| { |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_Zero; |
| } |
| else |
| { |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_1DstAlpha; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| } |
| break; |
| } |
| } |
| else |
| { |
| imesa->regs.s3d.drawCtrl.ni.dstAlphaMode = DAM_Zero; |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One; |
| } |
| |
| /* alpha test*/ |
| |
| if(ctx->Color.AlphaEnabled) |
| { |
| ACmpFunc a; |
| GLubyte alphaRef; |
| |
| CLAMPED_FLOAT_TO_UBYTE(alphaRef,ctx->Color.AlphaRef); |
| |
| switch(ctx->Color.AlphaFunc) { |
| case GL_NEVER: a = CF_Never; break; |
| case GL_ALWAYS: a = CF_Always; break; |
| case GL_LESS: a = CF_Less; break; |
| case GL_LEQUAL: a = CF_LessEqual; break; |
| case GL_EQUAL: a = CF_Equal; break; |
| case GL_GREATER: a = CF_Greater; break; |
| case GL_GEQUAL: a = CF_GreaterEqual; break; |
| case GL_NOTEQUAL: a = CF_NotEqual; break; |
| default:return; |
| } |
| |
| imesa->regs.s3d.drawCtrl.ni.alphaTestEn = GL_TRUE; |
| imesa->regs.s3d.drawCtrl.ni.alphaTestCmpFunc = a; |
| imesa->regs.s3d.drawCtrl.ni.alphaRefVal = alphaRef; |
| } |
| else |
| { |
| imesa->regs.s3d.drawCtrl.ni.alphaTestEn = GL_FALSE; |
| } |
| |
| /* Set/Reset Z-after-alpha*/ |
| |
| imesa->regs.s3d.zBufCtrl.ni.wrZafterAlphaTst = |
| imesa->regs.s3d.drawCtrl.ni.alphaTestEn; |
| |
| if (drawCtrl != imesa->regs.s3d.drawCtrl.ui || |
| zBufCtrl != imesa->regs.s3d.zBufCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| } |
| |
| static void savageDDBlendFuncSeparate_s4( struct gl_context *ctx, GLenum sfactorRGB, |
| GLenum dfactorRGB, GLenum sfactorA, |
| GLenum dfactorA ) |
| { |
| assert (dfactorRGB == dfactorA && sfactorRGB == sfactorA); |
| savageBlendFunc_s4( ctx ); |
| } |
| static void savageDDBlendFuncSeparate_s3d( struct gl_context *ctx, GLenum sfactorRGB, |
| GLenum dfactorRGB, GLenum sfactorA, |
| GLenum dfactorA ) |
| { |
| assert (dfactorRGB == dfactorA && sfactorRGB == sfactorA); |
| savageBlendFunc_s3d( ctx ); |
| } |
| |
| |
| |
| static void savageDDDepthFunc_s4(struct gl_context *ctx, GLenum func) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| ZCmpFunc zmode; |
| uint32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui; |
| uint32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui; |
| uint32_t zWatermarks = imesa->regs.s4.zWatermarks.ui; /* FIXME: in DRM */ |
| |
| /* set up z-buffer control register (global) |
| * set up z-buffer offset register (global) |
| * set up z read/write watermarks register (global) |
| */ |
| |
| switch(func) { /* reversed (see savageCalcViewport) */ |
| case GL_NEVER: zmode = CF_Never; break; |
| case GL_ALWAYS: zmode = CF_Always; break; |
| case GL_LESS: zmode = CF_Greater; break; |
| case GL_LEQUAL: zmode = CF_GreaterEqual; break; |
| case GL_EQUAL: zmode = CF_Equal; break; |
| case GL_GREATER: zmode = CF_Less; break; |
| case GL_GEQUAL: zmode = CF_LessEqual; break; |
| case GL_NOTEQUAL: zmode = CF_NotEqual; break; |
| default:return; |
| } |
| if (ctx->Depth.Test) |
| { |
| |
| imesa->regs.s4.zBufCtrl.ni.zCmpFunc = zmode; |
| imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = ctx->Depth.Mask; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE; |
| imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_TRUE; |
| } |
| else if (imesa->glCtx->Stencil._Enabled && imesa->hw_stencil) |
| { |
| /* Need to keep Z on for Stencil. */ |
| imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Always; |
| imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_TRUE; |
| imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE; |
| } |
| else |
| { |
| |
| if (imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn == GL_FALSE) |
| { |
| imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Always; |
| imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_TRUE; |
| } |
| else |
| |
| /* DRAWUPDATE_REQUIRES_Z_ENABLED*/ |
| { |
| imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_FALSE; |
| } |
| imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE; |
| } |
| |
| if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| if (zBufCtrl != imesa->regs.s4.zBufCtrl.ui || |
| zWatermarks != imesa->regs.s4.zWatermarks.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; |
| } |
| static void savageDDDepthFunc_s3d(struct gl_context *ctx, GLenum func) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| ZCmpFunc zmode; |
| uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui; |
| uint32_t zBufCtrl = imesa->regs.s3d.zBufCtrl.ui; |
| uint32_t zWatermarks = imesa->regs.s3d.zWatermarks.ui; /* FIXME: in DRM */ |
| |
| /* set up z-buffer control register (global) |
| * set up z-buffer offset register (global) |
| * set up z read/write watermarks register (global) |
| */ |
| switch(func) { /* reversed (see savageCalcViewport) */ |
| case GL_NEVER: zmode = CF_Never; break; |
| case GL_ALWAYS: zmode = CF_Always; break; |
| case GL_LESS: zmode = CF_Greater; break; |
| case GL_LEQUAL: zmode = CF_GreaterEqual; break; |
| case GL_EQUAL: zmode = CF_Equal; break; |
| case GL_GREATER: zmode = CF_Less; break; |
| case GL_GEQUAL: zmode = CF_LessEqual; break; |
| case GL_NOTEQUAL: zmode = CF_NotEqual; break; |
| default:return; |
| } |
| if (ctx->Depth.Test) |
| { |
| imesa->regs.s3d.zBufCtrl.ni.zBufEn = GL_TRUE; |
| imesa->regs.s3d.zBufCtrl.ni.zCmpFunc = zmode; |
| imesa->regs.s3d.zBufCtrl.ni.zUpdateEn = ctx->Depth.Mask; |
| |
| imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE; |
| } |
| else |
| { |
| if (imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn == GL_FALSE) { |
| imesa->regs.s3d.zBufCtrl.ni.zCmpFunc = CF_Always; |
| imesa->regs.s3d.zBufCtrl.ni.zBufEn = GL_TRUE; |
| } |
| else |
| |
| /* DRAWUPDATE_REQUIRES_Z_ENABLED*/ |
| { |
| imesa->regs.s3d.zBufCtrl.ni.zBufEn = GL_FALSE; |
| } |
| imesa->regs.s3d.zBufCtrl.ni.zUpdateEn = GL_FALSE; |
| imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_FALSE; |
| } |
| |
| if (drawCtrl != imesa->regs.s3d.drawCtrl.ui || |
| zBufCtrl != imesa->regs.s3d.zBufCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| if (zWatermarks != imesa->regs.s3d.zWatermarks.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; |
| } |
| |
| static void savageDDDepthMask_s4(struct gl_context *ctx, GLboolean flag) |
| { |
| savageDDDepthFunc_s4(ctx,ctx->Depth.Func); |
| } |
| static void savageDDDepthMask_s3d(struct gl_context *ctx, GLboolean flag) |
| { |
| savageDDDepthFunc_s3d(ctx,ctx->Depth.Func); |
| } |
| |
| |
| |
| |
| /* ============================================================= |
| * Hardware clipping |
| */ |
| |
| |
| static void savageDDScissor( struct gl_context *ctx, GLint x, GLint y, |
| GLsizei w, GLsizei h ) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| |
| /* Emit buffered commands with old scissor state. */ |
| FLUSH_BATCH(imesa); |
| |
| /* Mirror scissors in private context. */ |
| imesa->scissor.enabled = ctx->Scissor.Enabled; |
| imesa->scissor.x = x; |
| imesa->scissor.y = y; |
| imesa->scissor.w = w; |
| imesa->scissor.h = h; |
| } |
| |
| |
| |
| static void savageDDDrawBuffer(struct gl_context *ctx, GLenum mode ) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| uint32_t destCtrl = imesa->regs.s4.destCtrl.ui; |
| |
| if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) { |
| FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_TRUE ); |
| return; |
| } |
| |
| switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) { |
| case BUFFER_FRONT_LEFT: |
| imesa->IsDouble = GL_FALSE; |
| imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->frontOffset>>11; |
| break; |
| case BUFFER_BACK_LEFT: |
| imesa->IsDouble = GL_TRUE; |
| imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11; |
| break; |
| default: |
| FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_TRUE ); |
| return; |
| } |
| |
| imesa->NotFirstFrame = GL_FALSE; |
| savageXMesaSetClipRects(imesa); |
| FALLBACK(ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE); |
| |
| if (destCtrl != imesa->regs.s4.destCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; |
| } |
| |
| static void savageDDReadBuffer(struct gl_context *ctx, GLenum mode ) |
| { |
| /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ |
| } |
| |
| #if 0 |
| static void savageDDSetColor(struct gl_context *ctx, |
| GLubyte r, GLubyte g, |
| GLubyte b, GLubyte a ) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| imesa->MonoColor = savagePackColor( imesa->savageScreen->frontFormat, r, g, b, a ); |
| } |
| #endif |
| |
| /* ============================================================= |
| * Window position and viewport transformation |
| */ |
| |
| void savageCalcViewport( struct gl_context *ctx ) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| const GLfloat *v = ctx->Viewport._WindowMap.m; |
| GLfloat *m = imesa->hw_viewport; |
| |
| m[MAT_SX] = v[MAT_SX]; |
| m[MAT_TX] = v[MAT_TX] + imesa->drawX + SUBPIXEL_X; |
| m[MAT_SY] = - v[MAT_SY]; |
| m[MAT_TY] = - v[MAT_TY] + imesa->driDrawable->h + imesa->drawY + SUBPIXEL_Y; |
| /* Depth range is reversed (far: 0, near: 1) so that float depth |
| * compensates for loss of accuracy of far coordinates. */ |
| if (imesa->float_depth && imesa->savageScreen->zpp == 2) { |
| /* The Savage 16-bit floating point depth format can't encode |
| * numbers < 2^-16. Make sure all depth values stay greater |
| * than that. */ |
| m[MAT_SZ] = - v[MAT_SZ] * imesa->depth_scale * (65535.0/65536.0); |
| m[MAT_TZ] = 1.0 - v[MAT_TZ] * imesa->depth_scale * (65535.0/65536.0); |
| } else { |
| m[MAT_SZ] = - v[MAT_SZ] * imesa->depth_scale; |
| m[MAT_TZ] = 1.0 - v[MAT_TZ] * imesa->depth_scale; |
| } |
| |
| imesa->SetupNewInputs = ~0; |
| } |
| |
| static void savageViewport( struct gl_context *ctx, |
| GLint x, GLint y, |
| GLsizei width, GLsizei height ) |
| { |
| savageCalcViewport( ctx ); |
| } |
| |
| static void savageDepthRange( struct gl_context *ctx, |
| GLclampd nearval, GLclampd farval ) |
| { |
| savageCalcViewport( ctx ); |
| } |
| |
| |
| /* ============================================================= |
| * Miscellaneous |
| */ |
| |
| static void savageDDClearColor(struct gl_context *ctx, |
| const GLfloat color[4] ) |
| { |
| savageContextPtr imesa = SAVAGE_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]); |
| |
| imesa->ClearColor = savagePackColor( imesa->savageScreen->frontFormat, |
| c[0], c[1], c[2], c[3] ); |
| } |
| |
| /* Fallback to swrast for select and feedback. |
| */ |
| static void savageRenderMode( struct gl_context *ctx, GLenum mode ) |
| { |
| FALLBACK( ctx, SAVAGE_FALLBACK_RENDERMODE, (mode != GL_RENDER) ); |
| } |
| |
| |
| #if HW_CULL |
| |
| /* ============================================================= |
| * Culling - the savage isn't quite as clean here as the rest of |
| * its interfaces, but it's not bad. |
| */ |
| static void savageDDCullFaceFrontFace(struct gl_context *ctx, GLenum unused) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| GLuint cullMode=imesa->LcsCullMode; |
| switch (ctx->Polygon.CullFaceMode) |
| { |
| case GL_FRONT: |
| switch (ctx->Polygon.FrontFace) |
| { |
| case GL_CW: |
| cullMode = BCM_CW; |
| break; |
| case GL_CCW: |
| cullMode = BCM_CCW; |
| break; |
| } |
| break; |
| |
| case GL_BACK: |
| switch (ctx->Polygon.FrontFace) |
| { |
| case GL_CW: |
| cullMode = BCM_CCW; |
| break; |
| case GL_CCW: |
| cullMode = BCM_CW; |
| break; |
| } |
| break; |
| } |
| imesa->LcsCullMode = cullMode; |
| imesa->new_state |= SAVAGE_NEW_CULL; |
| } |
| #endif /* end #if HW_CULL */ |
| |
| static void savageUpdateCull( struct gl_context *ctx ) |
| { |
| #if HW_CULL |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| GLuint cullMode; |
| if (ctx->Polygon.CullFlag && |
| imesa->raster_primitive >= GL_TRIANGLES && |
| ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) |
| cullMode = imesa->LcsCullMode; |
| else |
| cullMode = BCM_None; |
| if (imesa->savageScreen->chipset >= S3_SAVAGE4) { |
| if (imesa->regs.s4.drawCtrl1.ni.cullMode != cullMode) { |
| imesa->regs.s4.drawCtrl1.ni.cullMode = cullMode; |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; |
| } |
| } else { |
| if (imesa->regs.s3d.drawCtrl.ni.cullMode != cullMode) { |
| imesa->regs.s3d.drawCtrl.ni.cullMode = cullMode; |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| } |
| } |
| #endif /* end #if HW_CULL */ |
| } |
| |
| |
| |
| /* ============================================================= |
| * Color masks |
| */ |
| |
| /* Savage4 can disable draw updates when all channels are |
| * masked. Savage3D has a bit called drawUpdateEn, but it doesn't seem |
| * to have any effect. If only some channels are masked we need a |
| * software fallback on all chips. |
| */ |
| static void savageDDColorMask_s4(struct gl_context *ctx, |
| GLboolean r, GLboolean g, |
| GLboolean b, GLboolean a ) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT( ctx ); |
| GLboolean passAny, passAll; |
| |
| if (ctx->Visual.alphaBits) { |
| passAny = b || g || r || a; |
| passAll = r && g && b && a; |
| } else { |
| passAny = b || g || r; |
| passAll = r && g && b; |
| } |
| |
| if (passAny) { |
| if (!imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn) { |
| imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_TRUE; |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| } |
| FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !passAll); |
| } else if (imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn) { |
| imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_FALSE; |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| } |
| } |
| static void savageDDColorMask_s3d(struct gl_context *ctx, |
| GLboolean r, GLboolean g, |
| GLboolean b, GLboolean a ) |
| { |
| if (ctx->Visual.alphaBits) |
| FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !(r && g && b && a)); |
| else |
| FALLBACK (ctx, SAVAGE_FALLBACK_COLORMASK, !(r && g && b)); |
| } |
| |
| static void savageUpdateSpecular_s4(struct gl_context *ctx) { |
| savageContextPtr imesa = SAVAGE_CONTEXT( ctx ); |
| uint32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui; |
| |
| if (NEED_SECONDARY_COLOR(ctx)) { |
| imesa->regs.s4.drawLocalCtrl.ni.specShadeEn = GL_TRUE; |
| } else { |
| imesa->regs.s4.drawLocalCtrl.ni.specShadeEn = GL_FALSE; |
| } |
| |
| if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| } |
| |
| static void savageUpdateSpecular_s3d(struct gl_context *ctx) { |
| savageContextPtr imesa = SAVAGE_CONTEXT( ctx ); |
| uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui; |
| |
| if (NEED_SECONDARY_COLOR(ctx)) { |
| imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_TRUE; |
| } else { |
| imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_FALSE; |
| } |
| |
| if (drawCtrl != imesa->regs.s3d.drawCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| } |
| |
| static void savageDDLightModelfv_s4(struct gl_context *ctx, GLenum pname, |
| const GLfloat *param) |
| { |
| savageUpdateSpecular_s4 (ctx); |
| } |
| static void savageDDLightModelfv_s3d(struct gl_context *ctx, GLenum pname, |
| const GLfloat *param) |
| { |
| savageUpdateSpecular_s3d (ctx); |
| } |
| |
| static void savageDDShadeModel_s4(struct gl_context *ctx, GLuint mod) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT( ctx ); |
| uint32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui; |
| |
| if (mod == GL_SMOOTH) |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.flatShadeEn = GL_FALSE; |
| } |
| else |
| { |
| imesa->regs.s4.drawLocalCtrl.ni.flatShadeEn = GL_TRUE; |
| } |
| |
| if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| } |
| static void savageDDShadeModel_s3d(struct gl_context *ctx, GLuint mod) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT( ctx ); |
| uint32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui; |
| |
| if (mod == GL_SMOOTH) |
| { |
| imesa->regs.s3d.drawCtrl.ni.flatShadeEn = GL_FALSE; |
| } |
| else |
| { |
| imesa->regs.s3d.drawCtrl.ni.flatShadeEn = GL_TRUE; |
| } |
| |
| if (drawCtrl != imesa->regs.s3d.drawCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| } |
| |
| |
| /* ============================================================= |
| * Fog |
| * The fogCtrl register has the same position and the same layout |
| * on savage3d and savage4. No need for two separate functions. |
| */ |
| |
| static void savageDDFogfv(struct gl_context *ctx, GLenum pname, const GLfloat *param) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| GLuint fogClr; |
| uint32_t fogCtrl = imesa->regs.s4.fogCtrl.ui; |
| |
| /*if ((ctx->Fog.Enabled) &&(pname == GL_FOG_COLOR))*/ |
| if (ctx->Fog.Enabled) |
| { |
| fogClr = (((GLubyte)(ctx->Fog.Color[0]*255.0F) << 16) | |
| ((GLubyte)(ctx->Fog.Color[1]*255.0F) << 8) | |
| ((GLubyte)(ctx->Fog.Color[2]*255.0F) << 0)); |
| imesa->regs.s4.fogCtrl.ni.fogEn = GL_TRUE; |
| /*cheap fog*/ |
| imesa->regs.s4.fogCtrl.ni.fogMode = GL_TRUE; |
| imesa->regs.s4.fogCtrl.ni.fogClr = fogClr; |
| } |
| else |
| { |
| /*No fog*/ |
| |
| imesa->regs.s4.fogCtrl.ni.fogEn = 0; |
| imesa->regs.s4.fogCtrl.ni.fogMode = 0; |
| } |
| |
| if (fogCtrl != imesa->regs.s4.fogCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; |
| } |
| |
| |
| static void |
| savageDDStencilFuncSeparate(struct gl_context *ctx, GLenum face, GLenum func, |
| GLint ref, GLuint mask) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| unsigned a=0; |
| const uint32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui; |
| const uint32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui; |
| |
| imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0] & 0xff; |
| imesa->regs.s4.stencilCtrl.ni.readMask = ctx->Stencil.ValueMask[0] & 0xff; |
| |
| switch (ctx->Stencil.Function[0]) |
| { |
| case GL_NEVER: a = CF_Never; break; |
| case GL_ALWAYS: a = CF_Always; break; |
| case GL_LESS: a = CF_Less; break; |
| case GL_LEQUAL: a = CF_LessEqual; break; |
| case GL_EQUAL: a = CF_Equal; break; |
| case GL_GREATER: a = CF_Greater; break; |
| case GL_GEQUAL: a = CF_GreaterEqual; break; |
| case GL_NOTEQUAL: a = CF_NotEqual; break; |
| default: |
| break; |
| } |
| |
| imesa->regs.s4.stencilCtrl.ni.cmpFunc = a; |
| |
| if (zBufCtrl != imesa->regs.s4.zBufCtrl.ui || |
| stencilCtrl != imesa->regs.s4.stencilCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; |
| } |
| |
| static void |
| savageDDStencilMaskSeparate(struct gl_context *ctx, GLenum face, GLuint mask) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| |
| if (imesa->regs.s4.stencilCtrl.ni.writeMask != (ctx->Stencil.WriteMask[0] & 0xff)) { |
| imesa->regs.s4.stencilCtrl.ni.writeMask = (ctx->Stencil.WriteMask[0] & 0xff); |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; |
| } |
| } |
| |
| static unsigned get_stencil_op_value( GLenum op ) |
| { |
| switch (op) |
| { |
| case GL_KEEP: return STENCIL_Keep; |
| case GL_ZERO: return STENCIL_Zero; |
| case GL_REPLACE: return STENCIL_Equal; |
| case GL_INCR: return STENCIL_IncClamp; |
| case GL_DECR: return STENCIL_DecClamp; |
| case GL_INVERT: return STENCIL_Invert; |
| case GL_INCR_WRAP: return STENCIL_Inc; |
| case GL_DECR_WRAP: return STENCIL_Dec; |
| } |
| |
| /* Should *never* get here. */ |
| return STENCIL_Keep; |
| } |
| |
| static void |
| savageDDStencilOpSeparate(struct gl_context *ctx, GLenum face, GLenum fail, |
| GLenum zfail, GLenum zpass) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| const uint32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui; |
| |
| imesa->regs.s4.stencilCtrl.ni.failOp = get_stencil_op_value( ctx->Stencil.FailFunc[0] ); |
| imesa->regs.s4.stencilCtrl.ni.passZfailOp = get_stencil_op_value( ctx->Stencil.ZFailFunc[0] ); |
| imesa->regs.s4.stencilCtrl.ni.passZpassOp = get_stencil_op_value( ctx->Stencil.ZPassFunc[0] ); |
| |
| if (stencilCtrl != imesa->regs.s4.stencilCtrl.ui) |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; |
| } |
| |
| |
| /* ============================================================= |
| */ |
| |
| static void savageDDEnable_s4(struct gl_context *ctx, GLenum cap, GLboolean state) |
| { |
| |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| switch(cap) { |
| case GL_ALPHA_TEST: |
| /* we should consider the disable case*/ |
| savageBlendFunc_s4(ctx); |
| break; |
| case GL_BLEND: |
| /*add the savageBlendFunc 2001/11/25 |
| * if call no such function, then glDisable(GL_BLEND) will do noting, |
| *our chip has no disable bit |
| */ |
| savageBlendFunc_s4(ctx); |
| case GL_COLOR_LOGIC_OP: |
| /* Fall through: |
| * For some reason enable(GL_BLEND) affects ColorLogicOpEnabled. |
| */ |
| FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP, |
| (ctx->Color.ColorLogicOpEnabled && |
| ctx->Color.LogicOp != GL_COPY)); |
| break; |
| case GL_DEPTH_TEST: |
| savageDDDepthFunc_s4(ctx,ctx->Depth.Func); |
| break; |
| case GL_SCISSOR_TEST: |
| savageDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, |
| ctx->Scissor.Width, ctx->Scissor.Height); |
| break; |
| case GL_STENCIL_TEST: |
| if (!imesa->hw_stencil) |
| FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state); |
| else { |
| imesa->regs.s4.stencilCtrl.ni.stencilEn = state; |
| if (ctx->Stencil._Enabled && |
| imesa->regs.s4.zBufCtrl.ni.zBufEn != GL_TRUE) |
| { |
| /* Stencil buffer requires Z enabled. */ |
| imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Always; |
| imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_TRUE; |
| imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE; |
| } |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL | SAVAGE_UPLOAD_LOCAL; |
| } |
| break; |
| case GL_FOG: |
| savageDDFogfv(ctx,0,0); |
| break; |
| case GL_CULL_FACE: |
| #if HW_CULL |
| if (state) |
| { |
| savageDDCullFaceFrontFace(ctx,0); |
| } |
| else |
| { |
| imesa->LcsCullMode = BCM_None; |
| imesa->new_state |= SAVAGE_NEW_CULL; |
| } |
| #endif |
| break; |
| case GL_DITHER: |
| if (state) |
| { |
| if ( ctx->Color.DitherFlag ) |
| { |
| imesa->regs.s4.drawCtrl1.ni.ditherEn=GL_TRUE; |
| } |
| } |
| if (!ctx->Color.DitherFlag ) |
| { |
| imesa->regs.s4.drawCtrl1.ni.ditherEn=GL_FALSE; |
| } |
| imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; |
| break; |
| |
| case GL_LIGHTING: |
| savageUpdateSpecular_s4 (ctx); |
| break; |
| case GL_TEXTURE_1D: |
| case GL_TEXTURE_3D: |
| imesa->new_state |= SAVAGE_NEW_TEXTURE; |
| break; |
| case GL_TEXTURE_2D: |
| imesa->new_state |= SAVAGE_NEW_TEXTURE; |
| break; |
| default: |
| ; |
| } |
| } |
| static void savageDDEnable_s3d(struct gl_context *ctx, GLenum cap, GLboolean state) |
| { |
| |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| switch(cap) { |
| case GL_ALPHA_TEST: |
| /* we should consider the disable case*/ |
| savageBlendFunc_s3d(ctx); |
| break; |
| case GL_BLEND: |
| /*add the savageBlendFunc 2001/11/25 |
| * if call no such function, then glDisable(GL_BLEND) will do noting, |
| *our chip has no disable bit |
| */ |
| savageBlendFunc_s3d(ctx); |
| case GL_COLOR_LOGIC_OP: |
| /* Fall through: |
| * For some reason enable(GL_BLEND) affects ColorLogicOpEnabled. |
| */ |
| FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP, |
| (ctx->Color.ColorLogicOpEnabled && |
| ctx->Color.LogicOp != GL_COPY)); |
| break; |
| case GL_DEPTH_TEST: |
| savageDDDepthFunc_s3d(ctx,ctx->Depth.Func); |
| break; |
| case GL_SCISSOR_TEST: |
| savageDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, |
| ctx->Scissor.Width, ctx->Scissor.Height); |
| break; |
| case GL_STENCIL_TEST: |
| FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state); |
| break; |
| case GL_FOG: |
| savageDDFogfv(ctx,0,0); |
| break; |
| case GL_CULL_FACE: |
| #if HW_CULL |
| if (state) |
| { |
| savageDDCullFaceFrontFace(ctx,0); |
| } |
| else |
| { |
| imesa->LcsCullMode = BCM_None; |
| imesa->new_state |= SAVAGE_NEW_CULL; |
| } |
| #endif |
| break; |
| case GL_DITHER: |
| if (state) |
| { |
| if ( ctx->Color.DitherFlag ) |
| { |
| imesa->regs.s3d.drawCtrl.ni.ditherEn=GL_TRUE; |
| } |
| } |
| if (!ctx->Color.DitherFlag ) |
| { |
| imesa->regs.s3d.drawCtrl.ni.ditherEn=GL_FALSE; |
| } |
| imesa->dirty |= SAVAGE_UPLOAD_LOCAL; |
| break; |
| |
| case GL_LIGHTING: |
| savageUpdateSpecular_s3d (ctx); |
| break; |
| case GL_TEXTURE_1D: |
| case GL_TEXTURE_3D: |
| imesa->new_state |= SAVAGE_NEW_TEXTURE; |
| break; |
| case GL_TEXTURE_2D: |
| imesa->new_state |= SAVAGE_NEW_TEXTURE; |
| break; |
| default: |
| ; |
| } |
| } |
| |
| void savageDDUpdateHwState( struct gl_context *ctx ) |
| { |
| savageContextPtr imesa = SAVAGE_CONTEXT(ctx); |
| |
| if (imesa->new_state) { |
| savageFlushVertices(imesa); |
| if (imesa->new_state & SAVAGE_NEW_TEXTURE) { |
| savageUpdateTextureState( ctx ); |
| } |
| if ((imesa->new_state & SAVAGE_NEW_CULL)) { |
| savageUpdateCull(ctx); |
| } |
| imesa->new_state = 0; |
| } |
| } |
| |
| |
| static void savageDDPrintDirty( const char *msg, GLuint state ) |
| { |
| fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s\n", |
| msg, |
| (unsigned int) state, |
| (state & SAVAGE_UPLOAD_LOCAL) ? "upload-local, " : "", |
| (state & SAVAGE_UPLOAD_TEX0) ? "upload-tex0, " : "", |
| (state & SAVAGE_UPLOAD_TEX1) ? "upload-tex1, " : "", |
| (state & SAVAGE_UPLOAD_FOGTBL) ? "upload-fogtbl, " : "", |
| (state & SAVAGE_UPLOAD_GLOBAL) ? "upload-global, " : "", |
| (state & SAVAGE_UPLOAD_TEXGLOBAL) ? "upload-texglobal, " : "" |
| ); |
| } |
| |
| |
| /** |
| * Check if global registers were changed |
| */ |
| static GLboolean savageGlobalRegChanged (savageContextPtr imesa, |
| GLuint first, GLuint last) { |
| GLuint i; |
| for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) { |
| if (((imesa->oldRegs.ui[i] ^ imesa->regs.ui[i]) & |
| imesa->globalRegMask.ui[i]) != 0) |
| return GL_TRUE; |
| } |
| return GL_FALSE; |
| } |
| static void savageEmitOldRegs (savageContextPtr imesa, |
| GLuint first, GLuint last, GLboolean global) { |
| GLuint n = last-first+1; |
| drm_savage_cmd_header_t *cmd = savageAllocCmdBuf(imesa, n*4); |
| cmd->state.cmd = SAVAGE_CMD_STATE; |
| cmd->state.global = global; |
| cmd->state.count = n; |
| cmd->state.start = first; |
| memcpy(cmd+1, &imesa->oldRegs.ui[first-SAVAGE_FIRST_REG], n*4); |
| } |
| static void savageEmitContiguousRegs (savageContextPtr imesa, |
| GLuint first, GLuint last) { |
| GLuint i; |
| GLuint n = last-first+1; |
| drm_savage_cmd_header_t *cmd = savageAllocCmdBuf(imesa, n*4); |
| cmd->state.cmd = SAVAGE_CMD_STATE; |
| cmd->state.global = savageGlobalRegChanged(imesa, first, last); |
| cmd->state.count = n; |
| cmd->state.start = first; |
| memcpy(cmd+1, &imesa->regs.ui[first-SAVAGE_FIRST_REG], n*4); |
| /* savageAllocCmdBuf may need to flush the cmd buffer and backup |
| * the current hardware state. It should see the "old" (current) |
| * state that has actually been emitted to the hardware. Therefore |
| * this update is done *after* savageAllocCmdBuf. */ |
| for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) |
| imesa->oldRegs.ui[i] = imesa->regs.ui[i]; |
| if (SAVAGE_DEBUG & DEBUG_STATE) |
| fprintf (stderr, "Emitting regs 0x%02x-0x%02x\n", first, last); |
| } |
| static void savageEmitChangedRegs (savageContextPtr imesa, |
| GLuint first, GLuint last) { |
| GLuint i, firstChanged; |
| firstChanged = SAVAGE_NR_REGS; |
| for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) { |
| if (imesa->oldRegs.ui[i] != imesa->regs.ui[i]) { |
| if (firstChanged == SAVAGE_NR_REGS) |
| firstChanged = i; |
| } else { |
| if (firstChanged != SAVAGE_NR_REGS) { |
| savageEmitContiguousRegs (imesa, firstChanged+SAVAGE_FIRST_REG, |
| i-1+SAVAGE_FIRST_REG); |
| firstChanged = SAVAGE_NR_REGS; |
| } |
| } |
| } |
| if (firstChanged != SAVAGE_NR_REGS) |
| savageEmitContiguousRegs (imesa, firstChanged+SAVAGE_FIRST_REG, |
| last); |
| } |
| static void savageEmitChangedRegChunk (savageContextPtr imesa, |
| GLuint first, GLuint last) { |
| GLuint i; |
| for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) { |
| if (imesa->oldRegs.ui[i] != imesa->regs.ui[i]) { |
| savageEmitContiguousRegs (imesa, first, last); |
| break; |
| } |
| } |
| } |
| static void savageUpdateRegister_s4(savageContextPtr imesa) |
| { |
| /* In case the texture image was changed without changing the |
| * texture address as well, we need to force emitting the texture |
| * address in order to flush texture cashes. */ |
| if ((imesa->dirty & SAVAGE_UPLOAD_TEX0) && |
| imesa->oldRegs.s4.texAddr[0].ui == imesa->regs.s4.texAddr[0].ui) |
| imesa->oldRegs.s4.texAddr[0].ui = 0xffffffff; |
| if ((imesa->dirty & SAVAGE_UPLOAD_TEX1) && |
| imesa->oldRegs.s4.texAddr[1].ui == imesa->regs.s4.texAddr[1].ui) |
| imesa->oldRegs.s4.texAddr[1].ui = 0xffffffff; |
| |
| /* Fix up watermarks */ |
| if (imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites) { |
| imesa->regs.s4.destTexWatermarks.ni.destWriteLow = 0; |
| imesa->regs.s4.destTexWatermarks.ni.destFlush = 1; |
| } else |
| imesa->regs.s4.destTexWatermarks.ni.destWriteLow = S4_DWLO; |
| if (imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites) |
| imesa->regs.s4.zWatermarks.ni.wLow = 0; |
| else |
| imesa->regs.s4.zWatermarks.ni.wLow = S4_ZWLO; |
| |
| savageEmitChangedRegs (imesa, 0x1e, 0x39); |
| |
| imesa->dirty=0; |
| } |
| static void savageUpdateRegister_s3d(savageContextPtr imesa) |
| { |
| /* In case the texture image was changed without changing the |
| * texture address as well, we need to force emitting the texture |
| * address in order to flush texture cashes. */ |
| if ((imesa->dirty & SAVAGE_UPLOAD_TEX0) && |
| imesa->oldRegs.s3d.texAddr.ui == imesa->regs.s3d.texAddr.ui) |
| imesa->oldRegs.s3d.texAddr.ui = 0xffffffff; |
| |
| /* Fix up watermarks */ |
| if (imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites) { |
| imesa->regs.s3d.destTexWatermarks.ni.destWriteLow = 0; |
| imesa->regs.s3d.destTexWatermarks.ni.destFlush = 1; |
| } else |
| imesa->regs.s3d.destTexWatermarks.ni.destWriteLow = S3D_DWLO; |
| if (imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites) |
| imesa->regs.s3d.zWatermarks.ni.wLow = 0; |
| else |
| imesa->regs.s3d.zWatermarks.ni.wLow = S3D_ZWLO; |
| |
| |
| /* the savage3d uses two contiguous ranges of BCI registers: |
| * 0x18-0x1c and 0x20-0x38. Some texture registers need to be |
| * emitted in one chunk or we get some funky rendering errors. */ |
| savageEmitChangedRegs (imesa, 0x18, 0x19); |
| savageEmitChangedRegChunk (imesa, 0x1a, 0x1c); |
| savageEmitChangedRegs (imesa, 0x20, 0x38); |
| |
| imesa->dirty=0; |
| } |
| |
| |
| void savageEmitOldState( savageContextPtr imesa ) |
| { |
| assert(imesa->cmdBuf.write == imesa->cmdBuf.base); |
| if (imesa->savageScreen->chipset >= S3_SAVAGE4) { |
| savageEmitOldRegs (imesa, 0x1e, 0x39, GL_TRUE); |
| } else { |
| savageEmitOldRegs (imesa, 0x18, 0x1c, GL_TRUE); |
| savageEmitOldRegs (imesa, 0x20, 0x38, GL_FALSE); |
| } |
| } |
| |
| |
| /* Push the state into the sarea and/or texture memory. |
| */ |
| void savageEmitChangedState( savageContextPtr imesa ) |
| { |
| if (SAVAGE_DEBUG & DEBUG_VERBOSE_API) |
| savageDDPrintDirty( "\n\n\nsavageEmitHwStateLocked", imesa->dirty ); |
| |
| if (imesa->dirty) |
| { |
| if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG) |
| fprintf (stderr, "... emitting state\n"); |
| if (imesa->savageScreen->chipset >= S3_SAVAGE4) |
| savageUpdateRegister_s4(imesa); |
| else |
| savageUpdateRegister_s3d(imesa); |
| } |
| |
| imesa->dirty = 0; |
| } |
| |
| |
| static void savageDDInitState_s4( savageContextPtr imesa ) |
| { |
| #if 1 |
| imesa->regs.s4.destCtrl.ui = 1<<7; |
| #endif |
| |
| imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Less; |
| imesa->regs.s4.zBufCtrl.ni.wToZEn = GL_TRUE; |
| if (imesa->float_depth) { |
| imesa->regs.s4.zBufCtrl.ni.zExpOffset = |
| imesa->savageScreen->zpp == 2 ? 16 : 32; |
| imesa->regs.s4.zBufCtrl.ni.floatZEn = GL_TRUE; |
| } else { |
| imesa->regs.s4.zBufCtrl.ni.zExpOffset = 0; |
| imesa->regs.s4.zBufCtrl.ni.floatZEn = GL_FALSE; |
| } |
| imesa->regs.s4.texBlendCtrl[0].ui = TBC_NoTexMap; |
| imesa->regs.s4.texBlendCtrl[1].ui = TBC_NoTexMap1; |
| imesa->regs.s4.drawCtrl0.ui = 0; |
| #if 0 |
| imesa->regs.s4.drawCtrl1.ni.xyOffsetEn = 1; |
| #endif |
| |
| /* Set DestTexWatermarks_31,30 to 01 always. |
| *Has no effect if dest. flush is disabled. |
| */ |
| #if 0 |
| imesa->regs.s4.zWatermarks.ui = 0x12000C04; |
| imesa->regs.s4.destTexWatermarks.ui = 0x40200400; |
| #else |
| /*imesa->regs.s4.zWatermarks.ui = 0x16001808;*/ |
| imesa->regs.s4.zWatermarks.ni.rLow = S4_ZRLO; |
| imesa->regs.s4.zWatermarks.ni.rHigh = S4_ZRHI; |
| imesa->regs.s4.zWatermarks.ni.wLow = S4_ZWLO; |
| imesa->regs.s4.zWatermarks.ni.wHigh = S4_ZWHI; |
| /*imesa->regs.s4.destTexWatermarks.ui = 0x4f000000;*/ |
| imesa->regs.s4.destTexWatermarks.ni.destReadLow = S4_DRLO; |
| imesa->regs.s4.destTexWatermarks.ni.destReadHigh = S4_DRHI; |
| imesa->regs.s4.destTexWatermarks.ni.destWriteLow = S4_DWLO; |
| imesa->regs.s4.destTexWatermarks.ni.destWriteHigh = S4_DWHI; |
| imesa->regs.s4.destTexWatermarks.ni.texRead = S4_TR; |
| imesa->regs.s4.destTexWatermarks.ni.destFlush = 1; |
| #endif |
| imesa->regs.s4.drawCtrl0.ni.dPerfAccelEn = GL_TRUE; |
| |
| /* clrCmpAlphaBlendCtrl is needed to get alphatest and |
| * alpha blending working properly |
| */ |
| |
| imesa->regs.s4.texCtrl[0].ni.dBias = 0x08; |
| imesa->regs.s4.texCtrl[1].ni.dBias = 0x08; |
| imesa->regs.s4.texCtrl[0].ni.texXprEn = GL_TRUE; |
| imesa->regs.s4.texCtrl[1].ni.texXprEn = GL_TRUE; |
| imesa->regs.s4.texCtrl[0].ni.dMax = 0x0f; |
| imesa->regs.s4.texCtrl[1].ni.dMax = 0x0f; |
| /* programm a valid tex address, in case texture state is emitted |
| * in wrong order. */ |
| if (imesa->lastTexHeap == 2 && imesa->savageScreen->textureSize[1]) { |
| /* AGP textures available */ |
| imesa->regs.s4.texAddr[0].ui = imesa->savageScreen->textureOffset[1]|3; |
| imesa->regs.s4.texAddr[1].ui = imesa->savageScreen->textureOffset[1]|3; |
| } else { |
| /* no AGP textures available, use local */ |
| imesa->regs.s4.texAddr[0].ui = imesa->savageScreen->textureOffset[0]|2; |
| imesa->regs.s4.texAddr[1].ui = imesa->savageScreen->textureOffset[0]|2; |
| } |
| imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_TRUE; |
| imesa->regs.s4.drawLocalCtrl.ni.srcAlphaMode = SAM_One; |
| imesa->regs.s4.drawLocalCtrl.ni.wrZafterAlphaTst = GL_FALSE; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites= GL_TRUE; |
| imesa->regs.s4.drawLocalCtrl.ni.flushPdDestWrites= GL_TRUE; |
| |
| imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn= GL_TRUE; |
| imesa->regs.s4.drawCtrl1.ni.ditherEn = ( |
| driQueryOptioni(&imesa->optionCache, "color_reduction") == |
| DRI_CONF_COLOR_REDUCTION_DITHER) ? GL_TRUE : GL_FALSE; |
| imesa->regs.s4.drawCtrl1.ni.cullMode = BCM_None; |
| |
| imesa->regs.s4.zBufCtrl.ni.stencilRefVal = 0x00; |
| |
| imesa->regs.s4.stencilCtrl.ni.stencilEn = GL_FALSE; |
| imesa->regs.s4.stencilCtrl.ni.cmpFunc = CF_Always; |
| imesa->regs.s4.stencilCtrl.ni.failOp = STENCIL_Keep; |
| imesa->regs.s4.stencilCtrl.ni.passZfailOp = STENCIL_Keep; |
| imesa->regs.s4.stencilCtrl.ni.passZpassOp = STENCIL_Keep; |
| imesa->regs.s4.stencilCtrl.ni.writeMask = 0xff; |
| imesa->regs.s4.stencilCtrl.ni.readMask = 0xff; |
| |
| imesa->LcsCullMode=BCM_None; |
| imesa->regs.s4.texDescr.ni.palSize = TPS_256; |
| |
| /* clear the local registers in the global reg mask */ |
| imesa->globalRegMask.s4.drawLocalCtrl.ui = 0; |
| imesa->globalRegMask.s4.texPalAddr.ui = 0; |
| imesa->globalRegMask.s4.texCtrl[0].ui = 0; |
| imesa->globalRegMask.s4.texCtrl[1].ui = 0; |
| imesa->globalRegMask.s4.texAddr[0].ui = 0; |
| imesa->globalRegMask.s4.texAddr[1].ui = 0; |
| imesa->globalRegMask.s4.texBlendCtrl[0].ui = 0; |
| imesa->globalRegMask.s4.texBlendCtrl[1].ui = 0; |
| imesa->globalRegMask.s4.texXprClr.ui = 0; |
| imesa->globalRegMask.s4.texDescr.ui = 0; |
| } |
| static void savageDDInitState_s3d( savageContextPtr imesa ) |
| { |
| #if 1 |
| imesa->regs.s3d.destCtrl.ui = 1<<7; |
| #endif |
| |
| imesa->regs.s3d.zBufCtrl.ni.zCmpFunc = CF_Less; |
| #if 0 |
| imesa->regs.s3d.drawCtrl.ni.xyOffsetEn = 1; |
| #endif |
| |
| /* Set DestTexWatermarks_31,30 to 01 always. |
| *Has no effect if dest. flush is disabled. |
| */ |
| #if 0 |
| imesa->regs.s3d.zWatermarks.ui = 0x12000C04; |
| imesa->regs.s3d.destTexWatermarks.ui = 0x40200400; |
| #else |
| /*imesa->regs.s3d.zWatermarks.ui = 0x16001808;*/ |
| imesa->regs.s3d.zWatermarks.ni.rLow = S3D_ZRLO; |
| imesa->regs.s3d.zWatermarks.ni.rHigh = S3D_ZRHI; |
| imesa->regs.s3d.zWatermarks.ni.wLow = S3D_ZWLO; |
| imesa->regs.s3d.zWatermarks.ni.wHigh = S3D_ZWHI; |
| /*imesa->regs.s3d.destTexWatermarks.ui = 0x4f000000;*/ |
| imesa->regs.s3d.destTexWatermarks.ni.destReadLow = S3D_DRLO; |
| imesa->regs.s3d.destTexWatermarks.ni.destReadHigh = S3D_DRHI; |
| imesa->regs.s3d.destTexWatermarks.ni.destWriteLow = S3D_DWLO; |
| imesa->regs.s3d.destTexWatermarks.ni.destWriteHigh = S3D_DWHI; |
| imesa->regs.s3d.destTexWatermarks.ni.texRead = S3D_TR; |
| imesa->regs.s3d.destTexWatermarks.ni.destFlush = 1; |
| #endif |
| |
| imesa->regs.s3d.texCtrl.ni.dBias = 0x08; |
| imesa->regs.s3d.texCtrl.ni.texXprEn = GL_TRUE; |
| /* texXprEn is needed to get alphatest and alpha blending working |
| * properly. However, this makes texels with color texXprClr |
| * completely transparent in some texture environment modes. I |
| * couldn't find a way to disable this. So choose an arbitrary and |
| * improbable color. (0 is a bad choice, makes all black texels |
| * transparent.) */ |
| imesa->regs.s3d.texXprClr.ui = 0x26ae26ae; |
| /* programm a valid tex address, in case texture state is emitted |
| * in wrong order. */ |
| if (imesa->lastTexHeap == 2 && imesa->savageScreen->textureSize[1]) { |
| /* AGP textures available */ |
| imesa->regs.s3d.texAddr.ui = imesa->savageScreen->textureOffset[1]|3; |
| } else { |
| /* no AGP textures available, use local */ |
| imesa->regs.s3d.texAddr.ui = imesa->savageScreen->textureOffset[0]|2; |
| } |
| |
| imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn = GL_TRUE; |
| imesa->regs.s3d.zBufCtrl.ni.wrZafterAlphaTst = GL_FALSE; |
| imesa->regs.s3d.zBufCtrl.ni.zUpdateEn = GL_TRUE; |
| |
| imesa->regs.s3d.drawCtrl.ni.srcAlphaMode = SAM_One; |
| imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE; |
| imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE; |
| |
| imesa->regs.s3d.drawCtrl.ni.ditherEn = ( |
| driQueryOptioni(&imesa->optionCache, "color_reduction") == |
| DRI_CONF_COLOR_REDUCTION_DITHER) ? GL_TRUE : GL_FALSE; |
| imesa->regs.s3d.drawCtrl.ni.cullMode = BCM_None; |
| |
| imesa->LcsCullMode = BCM_None; |
| imesa->regs.s3d.texDescr.ni.palSize = TPS_256; |
| |
| /* clear the local registers in the global reg mask */ |
| imesa->globalRegMask.s3d.texPalAddr.ui = 0; |
| imesa->globalRegMask.s3d.texXprClr.ui = 0; |
| imesa->globalRegMask.s3d.texAddr.ui = 0; |
| imesa->globalRegMask.s3d.texDescr.ui = 0; |
| imesa->globalRegMask.s3d.texCtrl.ui = 0; |
| |
| imesa->globalRegMask.s3d.fogCtrl.ui = 0; |
| |
| /* drawCtrl is local with some exceptions */ |
| imesa->globalRegMask.s3d.drawCtrl.ui = 0; |
| imesa->globalRegMask.s3d.drawCtrl.ni.cullMode = 0x3; |
| imesa->globalRegMask.s3d.drawCtrl.ni.alphaTestCmpFunc = 0x7; |
| imesa->globalRegMask.s3d.drawCtrl.ni.alphaTestEn = 0x1; |
| imesa->globalRegMask.s3d.drawCtrl.ni.alphaRefVal = 0xff; |
| |
| /* zBufCtrl is local with some exceptions */ |
| imesa->globalRegMask.s3d.zBufCtrl.ui = 0; |
| imesa->globalRegMask.s3d.zBufCtrl.ni.zCmpFunc = 0x7; |
| imesa->globalRegMask.s3d.zBufCtrl.ni.zBufEn = 0x1; |
| } |
| void savageDDInitState( savageContextPtr imesa ) { |
| memset (imesa->regs.ui, 0, SAVAGE_NR_REGS*sizeof(uint32_t)); |
| memset (imesa->globalRegMask.ui, 0xff, SAVAGE_NR_REGS*sizeof(uint32_t)); |
| if (imesa->savageScreen->chipset >= S3_SAVAGE4) |
| savageDDInitState_s4 (imesa); |
| else |
| savageDDInitState_s3d (imesa); |
| |
| /*fprintf(stderr,"DBflag:%d\n",imesa->glCtx->Visual->DBflag);*/ |
| /* zbufoffset and destctrl have the same position and layout on |
| * savage4 and savage3d. */ |
| if (imesa->glCtx->Visual.doubleBufferMode) { |
| imesa->IsDouble = GL_TRUE; |
| imesa->toggle = TARGET_BACK; |
| imesa->regs.s4.destCtrl.ni.offset = |
| imesa->savageScreen->backOffset>>11; |
| } else { |
| imesa->IsDouble = GL_FALSE; |
| imesa->toggle = TARGET_FRONT; |
| imesa->regs.s4.destCtrl.ni.offset = |
| imesa->savageScreen->frontOffset>>11; |
| } |
| if(imesa->savageScreen->cpp == 2) { |
| imesa->regs.s4.destCtrl.ni.dstPixFmt = 0; |
| imesa->regs.s4.destCtrl.ni.dstWidthInTile = |
| (imesa->savageScreen->width+63)>>6; |
| } else { |
| imesa->regs.s4.destCtrl.ni.dstPixFmt = 1; |
| imesa->regs.s4.destCtrl.ni.dstWidthInTile = |
| (imesa->savageScreen->width+31)>>5; |
| } |
| imesa->NotFirstFrame = GL_FALSE; |
| |
| imesa->regs.s4.zBufOffset.ni.offset=imesa->savageScreen->depthOffset>>11; |
| if(imesa->savageScreen->zpp == 2) { |
| imesa->regs.s4.zBufOffset.ni.zBufWidthInTiles = |
| (imesa->savageScreen->width+63)>>6; |
| imesa->regs.s4.zBufOffset.ni.zDepthSelect = 0; |
| } else { |
| imesa->regs.s4.zBufOffset.ni.zBufWidthInTiles = |
| (imesa->savageScreen->width+31)>>5; |
| imesa->regs.s4.zBufOffset.ni.zDepthSelect = 1; |
| } |
| |
| memcpy (imesa->oldRegs.ui, imesa->regs.ui, SAVAGE_NR_REGS*sizeof(uint32_t)); |
| |
| /* Emit the initial state to the (empty) command buffer. */ |
| assert (imesa->cmdBuf.write == imesa->cmdBuf.base); |
| savageEmitOldState(imesa); |
| imesa->cmdBuf.start = imesa->cmdBuf.write; |
| } |
| |
| |
| #define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|\ |
| NEW_TEXTURE_MATRIX|\ |
| NEW_USER_CLIP|NEW_CLIENT_STATE)) |
| |
| static void savageDDInvalidateState( struct gl_context *ctx, GLuint new_state ) |
| { |
| _swrast_InvalidateState( ctx, new_state ); |
| _swsetup_InvalidateState( ctx, new_state ); |
| _vbo_InvalidateState( ctx, new_state ); |
| _tnl_InvalidateState( ctx, new_state ); |
| SAVAGE_CONTEXT(ctx)->new_gl_state |= new_state; |
| } |
| |
| |
| void savageDDInitStateFuncs(struct gl_context *ctx) |
| { |
| ctx->Driver.UpdateState = savageDDInvalidateState; |
| ctx->Driver.BlendEquationSeparate = savageDDBlendEquationSeparate; |
| ctx->Driver.Fogfv = savageDDFogfv; |
| ctx->Driver.Scissor = savageDDScissor; |
| #if HW_CULL |
| ctx->Driver.CullFace = savageDDCullFaceFrontFace; |
| ctx->Driver.FrontFace = savageDDCullFaceFrontFace; |
| #else |
| ctx->Driver.CullFace = 0; |
| ctx->Driver.FrontFace = 0; |
| #endif /* end #if HW_CULL */ |
| ctx->Driver.DrawBuffer = savageDDDrawBuffer; |
| ctx->Driver.ReadBuffer = savageDDReadBuffer; |
| ctx->Driver.ClearColor = savageDDClearColor; |
| |
| ctx->Driver.DepthRange = savageDepthRange; |
| ctx->Driver.Viewport = savageViewport; |
| ctx->Driver.RenderMode = savageRenderMode; |
| |
| if (SAVAGE_CONTEXT( ctx )->savageScreen->chipset >= S3_SAVAGE4) { |
| ctx->Driver.Enable = savageDDEnable_s4; |
| ctx->Driver.AlphaFunc = savageDDAlphaFunc_s4; |
| ctx->Driver.DepthFunc = savageDDDepthFunc_s4; |
| ctx->Driver.DepthMask = savageDDDepthMask_s4; |
| ctx->Driver.BlendFuncSeparate = savageDDBlendFuncSeparate_s4; |
| ctx->Driver.ColorMask = savageDDColorMask_s4; |
| ctx->Driver.ShadeModel = savageDDShadeModel_s4; |
| ctx->Driver.LightModelfv = savageDDLightModelfv_s4; |
| ctx->Driver.StencilFuncSeparate = savageDDStencilFuncSeparate; |
| ctx->Driver.StencilMaskSeparate = savageDDStencilMaskSeparate; |
| ctx->Driver.StencilOpSeparate = savageDDStencilOpSeparate; |
| } else { |
| ctx->Driver.Enable = savageDDEnable_s3d; |
| ctx->Driver.AlphaFunc = savageDDAlphaFunc_s3d; |
| ctx->Driver.DepthFunc = savageDDDepthFunc_s3d; |
| ctx->Driver.DepthMask = savageDDDepthMask_s3d; |
| ctx->Driver.BlendFuncSeparate = savageDDBlendFuncSeparate_s3d; |
| ctx->Driver.ColorMask = savageDDColorMask_s3d; |
| ctx->Driver.ShadeModel = savageDDShadeModel_s3d; |
| ctx->Driver.LightModelfv = savageDDLightModelfv_s3d; |
| ctx->Driver.StencilFuncSeparate = NULL; |
| ctx->Driver.StencilMaskSeparate = NULL; |
| ctx->Driver.StencilOpSeparate = NULL; |
| } |
| } |