| /* |
| * 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 "glheader.h" |
| #include "context.h" |
| #include "macros.h" |
| #include "colormac.h" |
| #include "enums.h" |
| #include "dd.h" |
| |
| #include "mm.h" |
| #include "via_context.h" |
| #include "via_state.h" |
| #include "via_tex.h" |
| #include "via_tris.h" |
| #include "via_ioctl.h" |
| #include "via_3d_reg.h" |
| |
| #include "swrast/swrast.h" |
| #include "vbo/vbo.h" |
| #include "tnl/tnl.h" |
| #include "swrast_setup/swrast_setup.h" |
| |
| #include "tnl/t_pipeline.h" |
| |
| |
| static GLuint ROP[16] = { |
| HC_HROP_BLACK, /* GL_CLEAR 0 */ |
| HC_HROP_DPa, /* GL_AND s & d */ |
| HC_HROP_PDna, /* GL_AND_REVERSE s & ~d */ |
| HC_HROP_P, /* GL_COPY s */ |
| HC_HROP_DPna, /* GL_AND_INVERTED ~s & d */ |
| HC_HROP_D, /* GL_NOOP d */ |
| HC_HROP_DPx, /* GL_XOR s ^ d */ |
| HC_HROP_DPo, /* GL_OR s | d */ |
| HC_HROP_DPon, /* GL_NOR ~(s | d) */ |
| HC_HROP_DPxn, /* GL_EQUIV ~(s ^ d) */ |
| HC_HROP_Dn, /* GL_INVERT ~d */ |
| HC_HROP_PDno, /* GL_OR_REVERSE s | ~d */ |
| HC_HROP_Pn, /* GL_COPY_INVERTED ~s */ |
| HC_HROP_DPno, /* GL_OR_INVERTED ~s | d */ |
| HC_HROP_DPan, /* GL_NAND ~(s & d) */ |
| HC_HROP_WHITE /* GL_SET 1 */ |
| }; |
| |
| /* |
| * Compute the 'S5.5' lod bias factor from the floating point OpenGL bias. |
| */ |
| static GLuint viaComputeLodBias(GLfloat bias) |
| { |
| int b = (int) (bias * 32.0); |
| if (b > 511) |
| b = 511; |
| else if (b < -512) |
| b = -512; |
| return (GLuint) b; |
| } |
| |
| void viaEmitState(struct via_context *vmesa) |
| { |
| GLcontext *ctx = vmesa->glCtx; |
| GLuint i = 0; |
| GLuint j = 0; |
| RING_VARS; |
| |
| viaCheckDma(vmesa, 0x110); |
| |
| BEGIN_RING(5); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_NotTex << 16) ); |
| OUT_RING( ((HC_SubA_HEnable << 24) | vmesa->regEnable) ); |
| OUT_RING( ((HC_SubA_HFBBMSKL << 24) | vmesa->regHFBBMSKL) ); |
| OUT_RING( ((HC_SubA_HROP << 24) | vmesa->regHROP) ); |
| ADVANCE_RING(); |
| |
| if (vmesa->have_hw_stencil) { |
| GLuint pitch, format, offset; |
| |
| format = HC_HZWBFM_24; |
| offset = vmesa->depth.offset; |
| pitch = vmesa->depth.pitch; |
| |
| BEGIN_RING(6); |
| OUT_RING( (HC_SubA_HZWBBasL << 24) | (offset & 0xFFFFFF) ); |
| OUT_RING( (HC_SubA_HZWBBasH << 24) | ((offset & 0xFF000000) >> 24) ); |
| OUT_RING( (HC_SubA_HZWBType << 24) | HC_HDBLoc_Local | HC_HZONEasFF_MASK | |
| format | pitch ); |
| OUT_RING( (HC_SubA_HZWTMD << 24) | vmesa->regHZWTMD ); |
| OUT_RING( (HC_SubA_HSTREF << 24) | vmesa->regHSTREF ); |
| OUT_RING( (HC_SubA_HSTMD << 24) | vmesa->regHSTMD ); |
| ADVANCE_RING(); |
| } |
| else if (vmesa->hasDepth) { |
| GLuint pitch, format, offset; |
| |
| if (vmesa->depthBits == 16) { |
| format = HC_HZWBFM_16; |
| } |
| else { |
| format = HC_HZWBFM_32; |
| } |
| |
| |
| offset = vmesa->depth.offset; |
| pitch = vmesa->depth.pitch; |
| |
| BEGIN_RING(4); |
| OUT_RING( (HC_SubA_HZWBBasL << 24) | (offset & 0xFFFFFF) ); |
| OUT_RING( (HC_SubA_HZWBBasH << 24) | ((offset & 0xFF000000) >> 24) ); |
| OUT_RING( (HC_SubA_HZWBType << 24) | HC_HDBLoc_Local | HC_HZONEasFF_MASK | |
| format | pitch ); |
| OUT_RING( (HC_SubA_HZWTMD << 24) | vmesa->regHZWTMD ); |
| ADVANCE_RING(); |
| } |
| |
| if (ctx->Color.AlphaEnabled) { |
| BEGIN_RING(1); |
| OUT_RING( (HC_SubA_HATMD << 24) | vmesa->regHATMD ); |
| ADVANCE_RING(); |
| i++; |
| } |
| |
| if (ctx->Color.BlendEnabled) { |
| BEGIN_RING(11); |
| OUT_RING( (HC_SubA_HABLCsat << 24) | vmesa->regHABLCsat ); |
| OUT_RING( (HC_SubA_HABLCop << 24) | vmesa->regHABLCop ); |
| OUT_RING( (HC_SubA_HABLAsat << 24) | vmesa->regHABLAsat ); |
| OUT_RING( (HC_SubA_HABLAop << 24) | vmesa->regHABLAop ); |
| OUT_RING( (HC_SubA_HABLRCa << 24) | vmesa->regHABLRCa ); |
| OUT_RING( (HC_SubA_HABLRFCa << 24) | vmesa->regHABLRFCa ); |
| OUT_RING( (HC_SubA_HABLRCbias << 24) | vmesa->regHABLRCbias ); |
| OUT_RING( (HC_SubA_HABLRCb << 24) | vmesa->regHABLRCb ); |
| OUT_RING( (HC_SubA_HABLRFCb << 24) | vmesa->regHABLRFCb ); |
| OUT_RING( (HC_SubA_HABLRAa << 24) | vmesa->regHABLRAa ); |
| OUT_RING( (HC_SubA_HABLRAb << 24) | vmesa->regHABLRAb ); |
| ADVANCE_RING(); |
| } |
| |
| if (ctx->Fog.Enabled) { |
| BEGIN_RING(3); |
| OUT_RING( (HC_SubA_HFogLF << 24) | vmesa->regHFogLF ); |
| OUT_RING( (HC_SubA_HFogCL << 24) | vmesa->regHFogCL ); |
| OUT_RING( (HC_SubA_HFogCH << 24) | vmesa->regHFogCH ); |
| ADVANCE_RING(); |
| } |
| |
| if (ctx->Line.StippleFlag) { |
| BEGIN_RING(2); |
| OUT_RING( (HC_SubA_HLP << 24) | ctx->Line.StipplePattern ); |
| OUT_RING( (HC_SubA_HLPRF << 24) | ctx->Line.StippleFactor ); |
| ADVANCE_RING(); |
| } |
| |
| BEGIN_RING(1); |
| OUT_RING( (HC_SubA_HPixGC << 24) | 0x0 ); |
| ADVANCE_RING(); |
| |
| QWORD_PAD_RING(); |
| |
| |
| if (ctx->Texture._EnabledUnits) { |
| |
| struct gl_texture_unit *texUnit0 = &ctx->Texture.Unit[0]; |
| struct gl_texture_unit *texUnit1 = &ctx->Texture.Unit[1]; |
| |
| { |
| GLuint nDummyValue = 0; |
| |
| BEGIN_RING( 8 ); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_Tex << 16) | (HC_SubType_TexGeneral << 24) ); |
| |
| if (texUnit0->Enabled && texUnit1->Enabled) { |
| nDummyValue = (HC_SubA_HTXSMD << 24) | (1 << 3); |
| } |
| else { |
| nDummyValue = (HC_SubA_HTXSMD << 24) | 0; |
| } |
| |
| if (vmesa->clearTexCache) { |
| vmesa->clearTexCache = 0; |
| OUT_RING( nDummyValue | HC_HTXCHCLR_MASK ); |
| OUT_RING( nDummyValue ); |
| } |
| else { |
| OUT_RING( nDummyValue ); |
| OUT_RING( nDummyValue ); |
| } |
| |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( HC_ParaType_NotTex << 16 ); |
| OUT_RING( (HC_SubA_HEnable << 24) | vmesa->regEnable ); |
| OUT_RING( (HC_SubA_HEnable << 24) | vmesa->regEnable ); |
| ADVANCE_RING(); |
| } |
| |
| if (texUnit0->Enabled) { |
| struct gl_texture_object *texObj = texUnit0->_Current; |
| struct via_texture_object *t = (struct via_texture_object *)texObj; |
| GLuint numLevels = t->lastLevel - t->firstLevel + 1; |
| if (VIA_DEBUG & DEBUG_STATE) { |
| fprintf(stderr, "texture0 enabled\n"); |
| } |
| if (numLevels == 8) { |
| BEGIN_RING(27); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_Tex << 16) | (0 << 24) ); |
| OUT_RING( t->regTexFM ); |
| OUT_RING( (HC_SubA_HTXnL0OS << 24) | |
| ((t->lastLevel) << HC_HTXnLVmax_SHIFT) | t->firstLevel ); |
| OUT_RING( t->regTexWidthLog2[0] ); |
| OUT_RING( t->regTexWidthLog2[1] ); |
| OUT_RING( t->regTexHeightLog2[0] ); |
| OUT_RING( t->regTexHeightLog2[1] ); |
| OUT_RING( t->regTexBaseH[0] ); |
| OUT_RING( t->regTexBaseH[1] ); |
| OUT_RING( t->regTexBaseH[2] ); |
| OUT_RING( t->regTexBaseAndPitch[0].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[0].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[1].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[1].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[2].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[2].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[3].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[3].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[4].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[4].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[5].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[5].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[6].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[6].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[7].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[7].pitchLog2 ); |
| ADVANCE_RING(); |
| } |
| else if (numLevels > 1) { |
| |
| BEGIN_RING(12 + numLevels * 2); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_Tex << 16) | (0 << 24) ); |
| OUT_RING( t->regTexFM ); |
| OUT_RING( (HC_SubA_HTXnL0OS << 24) | |
| ((t->lastLevel) << HC_HTXnLVmax_SHIFT) | t->firstLevel ); |
| OUT_RING( t->regTexWidthLog2[0] ); |
| OUT_RING( t->regTexHeightLog2[0] ); |
| |
| if (numLevels > 6) { |
| OUT_RING( t->regTexWidthLog2[1] ); |
| OUT_RING( t->regTexHeightLog2[1] ); |
| } |
| |
| OUT_RING( t->regTexBaseH[0] ); |
| |
| if (numLevels > 3) { |
| OUT_RING( t->regTexBaseH[1] ); |
| } |
| if (numLevels > 6) { |
| OUT_RING( t->regTexBaseH[2] ); |
| } |
| if (numLevels > 9) { |
| OUT_RING( t->regTexBaseH[3] ); |
| } |
| |
| for (j = 0; j < numLevels; j++) { |
| OUT_RING( t->regTexBaseAndPitch[j].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[j].pitchLog2 ); |
| } |
| |
| ADVANCE_RING_VARIABLE(); |
| } |
| else { |
| |
| BEGIN_RING(9); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_Tex << 16) | (0 << 24) ); |
| OUT_RING( t->regTexFM ); |
| OUT_RING( (HC_SubA_HTXnL0OS << 24) | |
| ((t->lastLevel) << HC_HTXnLVmax_SHIFT) | t->firstLevel ); |
| OUT_RING( t->regTexWidthLog2[0] ); |
| OUT_RING( t->regTexHeightLog2[0] ); |
| OUT_RING( t->regTexBaseH[0] ); |
| OUT_RING( t->regTexBaseAndPitch[0].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[0].pitchLog2 ); |
| ADVANCE_RING(); |
| } |
| |
| BEGIN_RING(14); |
| OUT_RING( (HC_SubA_HTXnTB << 24) | vmesa->regHTXnTB[0] ); |
| OUT_RING( (HC_SubA_HTXnMPMD << 24) | vmesa->regHTXnMPMD[0] ); |
| OUT_RING( (HC_SubA_HTXnTBLCsat << 24) | vmesa->regHTXnTBLCsat[0] ); |
| OUT_RING( (HC_SubA_HTXnTBLCop << 24) | vmesa->regHTXnTBLCop[0] ); |
| OUT_RING( (HC_SubA_HTXnTBLMPfog << 24) | vmesa->regHTXnTBLMPfog[0] ); |
| OUT_RING( (HC_SubA_HTXnTBLAsat << 24) | vmesa->regHTXnTBLAsat[0] ); |
| OUT_RING( (HC_SubA_HTXnTBLRCb << 24) | vmesa->regHTXnTBLRCb[0] ); |
| OUT_RING( (HC_SubA_HTXnTBLRAa << 24) | vmesa->regHTXnTBLRAa[0] ); |
| OUT_RING( (HC_SubA_HTXnTBLRFog << 24) | vmesa->regHTXnTBLRFog[0] ); |
| OUT_RING( (HC_SubA_HTXnTBLRCa << 24) | vmesa->regHTXnTBLRCa[0] ); |
| OUT_RING( (HC_SubA_HTXnTBLRCc << 24) | vmesa->regHTXnTBLRCc[0] ); |
| OUT_RING( (HC_SubA_HTXnTBLRCbias << 24) | vmesa->regHTXnTBLRCbias[0] ); |
| OUT_RING( (HC_SubA_HTXnTBC << 24) | vmesa->regHTXnTBC[0] ); |
| OUT_RING( (HC_SubA_HTXnTRAH << 24) | vmesa->regHTXnTRAH[0] ); |
| /* OUT_RING( (HC_SubA_HTXnCLODu << 24) | vmesa->regHTXnCLOD[0] ); */ |
| ADVANCE_RING(); |
| |
| /* KW: This test never succeeds: |
| */ |
| if (t->regTexFM == HC_HTXnFM_Index8) { |
| const struct gl_color_table *table = &texObj->Palette; |
| const GLfloat *tableF = table->TableF; |
| |
| BEGIN_RING(2 + table->Size); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_Palette << 16) | (0 << 24) ); |
| for (j = 0; j < table->Size; j++) |
| OUT_RING( tableF[j] ); |
| ADVANCE_RING(); |
| |
| } |
| |
| QWORD_PAD_RING(); |
| } |
| |
| if (texUnit1->Enabled) { |
| struct gl_texture_object *texObj = texUnit1->_Current; |
| struct via_texture_object *t = (struct via_texture_object *)texObj; |
| GLuint numLevels = t->lastLevel - t->firstLevel + 1; |
| int texunit = (texUnit0->Enabled ? 1 : 0); |
| if (VIA_DEBUG & DEBUG_STATE) { |
| fprintf(stderr, "texture1 enabled\n"); |
| } |
| if (numLevels == 8) { |
| BEGIN_RING(27); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_Tex << 16) | (texunit << 24) ); |
| OUT_RING( t->regTexFM ); |
| OUT_RING( (HC_SubA_HTXnL0OS << 24) | |
| ((t->lastLevel) << HC_HTXnLVmax_SHIFT) | t->firstLevel ); |
| OUT_RING( t->regTexWidthLog2[0] ); |
| OUT_RING( t->regTexWidthLog2[1] ); |
| OUT_RING( t->regTexHeightLog2[0] ); |
| OUT_RING( t->regTexHeightLog2[1] ); |
| OUT_RING( t->regTexBaseH[0] ); |
| OUT_RING( t->regTexBaseH[1] ); |
| OUT_RING( t->regTexBaseH[2] ); |
| OUT_RING( t->regTexBaseAndPitch[0].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[0].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[1].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[1].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[2].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[2].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[3].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[3].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[4].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[4].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[5].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[5].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[6].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[6].pitchLog2 ); |
| OUT_RING( t->regTexBaseAndPitch[7].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[7].pitchLog2 ); |
| ADVANCE_RING(); |
| } |
| else if (numLevels > 1) { |
| BEGIN_RING(12 + numLevels * 2); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_Tex << 16) | (texunit << 24) ); |
| OUT_RING( t->regTexFM ); |
| OUT_RING( (HC_SubA_HTXnL0OS << 24) | |
| ((t->lastLevel) << HC_HTXnLVmax_SHIFT) | t->firstLevel ); |
| OUT_RING( t->regTexWidthLog2[0] ); |
| OUT_RING( t->regTexHeightLog2[0] ); |
| |
| if (numLevels > 6) { |
| OUT_RING( t->regTexWidthLog2[1] ); |
| OUT_RING( t->regTexHeightLog2[1] ); |
| i += 2; |
| } |
| |
| OUT_RING( t->regTexBaseH[0] ); |
| |
| if (numLevels > 3) { |
| OUT_RING( t->regTexBaseH[1] ); |
| } |
| if (numLevels > 6) { |
| OUT_RING( t->regTexBaseH[2] ); |
| } |
| if (numLevels > 9) { |
| OUT_RING( t->regTexBaseH[3] ); |
| } |
| |
| for (j = 0; j < numLevels; j++) { |
| OUT_RING( t->regTexBaseAndPitch[j].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[j].pitchLog2 ); |
| } |
| ADVANCE_RING_VARIABLE(); |
| } |
| else { |
| BEGIN_RING(9); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_Tex << 16) | (texunit << 24) ); |
| OUT_RING( t->regTexFM ); |
| OUT_RING( (HC_SubA_HTXnL0OS << 24) | |
| ((t->lastLevel) << HC_HTXnLVmax_SHIFT) | t->firstLevel ); |
| OUT_RING( t->regTexWidthLog2[0] ); |
| OUT_RING( t->regTexHeightLog2[0] ); |
| OUT_RING( t->regTexBaseH[0] ); |
| OUT_RING( t->regTexBaseAndPitch[0].baseL ); |
| OUT_RING( t->regTexBaseAndPitch[0].pitchLog2 ); |
| ADVANCE_RING(); |
| } |
| |
| BEGIN_RING(14); |
| OUT_RING( (HC_SubA_HTXnTB << 24) | vmesa->regHTXnTB[1] ); |
| OUT_RING( (HC_SubA_HTXnMPMD << 24) | vmesa->regHTXnMPMD[1] ); |
| OUT_RING( (HC_SubA_HTXnTBLCsat << 24) | vmesa->regHTXnTBLCsat[1] ); |
| OUT_RING( (HC_SubA_HTXnTBLCop << 24) | vmesa->regHTXnTBLCop[1] ); |
| OUT_RING( (HC_SubA_HTXnTBLMPfog << 24) | vmesa->regHTXnTBLMPfog[1] ); |
| OUT_RING( (HC_SubA_HTXnTBLAsat << 24) | vmesa->regHTXnTBLAsat[1] ); |
| OUT_RING( (HC_SubA_HTXnTBLRCb << 24) | vmesa->regHTXnTBLRCb[1] ); |
| OUT_RING( (HC_SubA_HTXnTBLRAa << 24) | vmesa->regHTXnTBLRAa[1] ); |
| OUT_RING( (HC_SubA_HTXnTBLRFog << 24) | vmesa->regHTXnTBLRFog[1] ); |
| OUT_RING( (HC_SubA_HTXnTBLRCa << 24) | vmesa->regHTXnTBLRCa[1] ); |
| OUT_RING( (HC_SubA_HTXnTBLRCc << 24) | vmesa->regHTXnTBLRCc[1] ); |
| OUT_RING( (HC_SubA_HTXnTBLRCbias << 24) | vmesa->regHTXnTBLRCbias[1] ); |
| OUT_RING( (HC_SubA_HTXnTBC << 24) | vmesa->regHTXnTBC[1] ); |
| OUT_RING( (HC_SubA_HTXnTRAH << 24) | vmesa->regHTXnTRAH[1] ); |
| /* OUT_RING( (HC_SubA_HTXnCLODu << 24) | vmesa->regHTXnCLOD[1] ); */ |
| ADVANCE_RING(); |
| |
| /* KW: This test never succeeds: |
| */ |
| if (t->regTexFM == HC_HTXnFM_Index8) { |
| const struct gl_color_table *table = &texObj->Palette; |
| const GLfloat *tableF = table->TableF; |
| |
| BEGIN_RING(2 + table->Size); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_Palette << 16) | (texunit << 24) ); |
| for (j = 0; j < table->Size; j++) { |
| OUT_RING( tableF[j] ); |
| } |
| ADVANCE_RING(); |
| } |
| |
| QWORD_PAD_RING(); |
| } |
| } |
| |
| #if 0 |
| /* Polygon stipple is broken - for certain stipple values, |
| * eg. 0xf0f0f0f0, the hardware will refuse to accept the stipple. |
| * Coincidentally, conform generates just such a stipple. |
| */ |
| if (ctx->Polygon.StippleFlag) { |
| GLuint *stipple = &ctx->PolygonStipple[0]; |
| __DRIdrawablePrivate *dPriv = vmesa->driDrawable; |
| struct via_renderbuffer *const vrb = |
| (struct via_renderbuffer *) dPriv->driverPrivate; |
| GLint i; |
| |
| BEGIN_RING(38); |
| OUT_RING( HC_HEADER2 ); |
| |
| OUT_RING( ((HC_ParaType_Palette << 16) | (HC_SubType_Stipple << 24)) ); |
| for (i = 31; i >= 0; i--) { |
| GLint j; |
| GLuint k = 0; |
| |
| /* Need to flip bits left to right: |
| */ |
| for (j = 0 ; j < 32; j++) |
| if (stipple[i] & (1<<j)) |
| k |= 1 << (31-j); |
| |
| OUT_RING( k ); |
| } |
| |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_NotTex << 16) ); |
| OUT_RING( (HC_SubA_HSPXYOS << 24) ); |
| OUT_RING( (HC_SubA_HSPXYOS << 24) ); |
| |
| ADVANCE_RING(); |
| } |
| #endif |
| |
| vmesa->newEmitState = 0; |
| } |
| |
| |
| static INLINE GLuint viaPackColor(GLuint bpp, |
| GLubyte r, GLubyte g, |
| GLubyte b, GLubyte a) |
| { |
| switch (bpp) { |
| case 16: |
| return PACK_COLOR_565(r, g, b); |
| case 32: |
| return PACK_COLOR_8888(a, r, g, b); |
| default: |
| assert(0); |
| return 0; |
| } |
| } |
| |
| static void viaBlendEquationSeparate(GLcontext *ctx, |
| GLenum rgbMode, |
| GLenum aMode) |
| { |
| if (VIA_DEBUG & DEBUG_STATE) |
| fprintf(stderr, "%s in\n", __FUNCTION__); |
| |
| /* GL_EXT_blend_equation_separate not supported */ |
| ASSERT(rgbMode == aMode); |
| |
| /* Can only do GL_ADD equation in hardware */ |
| FALLBACK(VIA_CONTEXT(ctx), VIA_FALLBACK_BLEND_EQ, |
| rgbMode != GL_FUNC_ADD_EXT); |
| |
| /* BlendEquation sets ColorLogicOpEnabled in an unexpected |
| * manner. |
| */ |
| FALLBACK(VIA_CONTEXT(ctx), VIA_FALLBACK_LOGICOP, |
| (ctx->Color.ColorLogicOpEnabled && |
| ctx->Color.LogicOp != GL_COPY)); |
| } |
| |
| static void viaBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| GLboolean fallback = GL_FALSE; |
| if (VIA_DEBUG & DEBUG_STATE) |
| fprintf(stderr, "%s in\n", __FUNCTION__); |
| |
| switch (ctx->Color.BlendSrcRGB) { |
| case GL_SRC_ALPHA_SATURATE: |
| case GL_CONSTANT_COLOR: |
| case GL_ONE_MINUS_CONSTANT_COLOR: |
| case GL_CONSTANT_ALPHA: |
| case GL_ONE_MINUS_CONSTANT_ALPHA: |
| fallback = GL_TRUE; |
| break; |
| default: |
| break; |
| } |
| |
| switch (ctx->Color.BlendDstRGB) { |
| case GL_CONSTANT_COLOR: |
| case GL_ONE_MINUS_CONSTANT_COLOR: |
| case GL_CONSTANT_ALPHA: |
| case GL_ONE_MINUS_CONSTANT_ALPHA: |
| fallback = GL_TRUE; |
| break; |
| default: |
| break; |
| } |
| |
| FALLBACK(vmesa, VIA_FALLBACK_BLEND_FUNC, fallback); |
| } |
| |
| /* Shouldn't be called as the extension is disabled. |
| */ |
| static void viaBlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, |
| GLenum dfactorRGB, GLenum sfactorA, |
| GLenum dfactorA) |
| { |
| if (dfactorRGB != dfactorA || sfactorRGB != sfactorA) { |
| _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendEquation (disabled)"); |
| } |
| |
| viaBlendFunc(ctx, sfactorRGB, dfactorRGB); |
| } |
| |
| |
| |
| |
| /* ============================================================= |
| * Hardware clipping |
| */ |
| static void viaScissor(GLcontext *ctx, GLint x, GLint y, |
| GLsizei w, GLsizei h) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| if (!vmesa->driDrawable) |
| return; |
| |
| if (VIA_DEBUG & DEBUG_STATE) |
| fprintf(stderr, "%s %d,%d %dx%d, drawH %d\n", __FUNCTION__, |
| x,y,w,h, vmesa->driDrawable->h); |
| |
| if (vmesa->scissor) { |
| VIA_FLUSH_DMA(vmesa); /* don't pipeline cliprect changes */ |
| } |
| |
| vmesa->scissorRect.x1 = x; |
| vmesa->scissorRect.y1 = vmesa->driDrawable->h - y - h; |
| vmesa->scissorRect.x2 = x + w; |
| vmesa->scissorRect.y2 = vmesa->driDrawable->h - y; |
| } |
| |
| static void viaEnable(GLcontext *ctx, GLenum cap, GLboolean state) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| switch (cap) { |
| case GL_SCISSOR_TEST: |
| VIA_FLUSH_DMA(vmesa); |
| vmesa->scissor = state; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| |
| |
| /* Fallback to swrast for select and feedback. |
| */ |
| static void viaRenderMode(GLcontext *ctx, GLenum mode) |
| { |
| FALLBACK(VIA_CONTEXT(ctx), VIA_FALLBACK_RENDERMODE, (mode != GL_RENDER)); |
| } |
| |
| |
| static void viaDrawBuffer(GLcontext *ctx, GLenum mode) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| if (VIA_DEBUG & (DEBUG_DRI|DEBUG_STATE)) |
| fprintf(stderr, "%s in\n", __FUNCTION__); |
| |
| if (!ctx->DrawBuffer) |
| return; |
| |
| if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) { |
| FALLBACK(vmesa, VIA_FALLBACK_DRAW_BUFFER, GL_TRUE); |
| return; |
| } |
| |
| switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) { |
| case BUFFER_FRONT_LEFT: |
| VIA_FLUSH_DMA(vmesa); |
| vmesa->drawBuffer = &vmesa->front; |
| FALLBACK(vmesa, VIA_FALLBACK_DRAW_BUFFER, GL_FALSE); |
| break; |
| case BUFFER_BACK_LEFT: |
| VIA_FLUSH_DMA(vmesa); |
| vmesa->drawBuffer = &vmesa->back; |
| FALLBACK(vmesa, VIA_FALLBACK_DRAW_BUFFER, GL_FALSE); |
| break; |
| default: |
| FALLBACK(vmesa, VIA_FALLBACK_DRAW_BUFFER, GL_TRUE); |
| return; |
| } |
| |
| |
| viaXMesaWindowMoved(vmesa); |
| } |
| |
| static void viaClearColor(GLcontext *ctx, const GLfloat color[4]) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| GLubyte pcolor[4]; |
| CLAMPED_FLOAT_TO_UBYTE(pcolor[0], color[0]); |
| CLAMPED_FLOAT_TO_UBYTE(pcolor[1], color[1]); |
| CLAMPED_FLOAT_TO_UBYTE(pcolor[2], color[2]); |
| CLAMPED_FLOAT_TO_UBYTE(pcolor[3], color[3]); |
| vmesa->ClearColor = viaPackColor(vmesa->viaScreen->bitsPerPixel, |
| pcolor[0], pcolor[1], |
| pcolor[2], pcolor[3]); |
| } |
| |
| #define WRITEMASK_ALPHA_SHIFT 31 |
| #define WRITEMASK_RED_SHIFT 30 |
| #define WRITEMASK_GREEN_SHIFT 29 |
| #define WRITEMASK_BLUE_SHIFT 28 |
| |
| static void viaColorMask(GLcontext *ctx, |
| GLboolean r, GLboolean g, |
| GLboolean b, GLboolean a) |
| { |
| struct via_context *vmesa = VIA_CONTEXT( ctx ); |
| |
| if (VIA_DEBUG & DEBUG_STATE) |
| fprintf(stderr, "%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a); |
| |
| vmesa->ClearMask = (((!r) << WRITEMASK_RED_SHIFT) | |
| ((!g) << WRITEMASK_GREEN_SHIFT) | |
| ((!b) << WRITEMASK_BLUE_SHIFT) | |
| ((!a) << WRITEMASK_ALPHA_SHIFT)); |
| } |
| |
| |
| |
| /* This hardware just isn't capable of private back buffers without |
| * glitches and/or a hefty locking scheme. |
| */ |
| void viaCalcViewport(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| __DRIdrawablePrivate *dPriv = vmesa->driDrawable; |
| struct via_renderbuffer *const vrb = |
| (struct via_renderbuffer *) dPriv->driverPrivate; |
| const GLfloat *v = ctx->Viewport._WindowMap.m; |
| GLfloat *m = vmesa->ViewportMatrix.m; |
| |
| m[MAT_SX] = v[MAT_SX]; |
| m[MAT_TX] = v[MAT_TX] + vrb->drawX + SUBPIXEL_X; |
| m[MAT_SY] = - v[MAT_SY]; |
| m[MAT_TY] = - v[MAT_TY] + vrb->drawY + SUBPIXEL_Y + vrb->drawH; |
| m[MAT_SZ] = v[MAT_SZ] * (1.0 / vmesa->depth_max); |
| m[MAT_TZ] = v[MAT_TZ] * (1.0 / vmesa->depth_max); |
| } |
| |
| static void viaViewport(GLcontext *ctx, |
| GLint x, GLint y, |
| GLsizei width, GLsizei height) |
| { |
| viaCalcViewport(ctx); |
| } |
| |
| static void viaDepthRange(GLcontext *ctx, |
| GLclampd nearval, GLclampd farval) |
| { |
| viaCalcViewport(ctx); |
| } |
| |
| void viaInitState(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| vmesa->regCmdB = HC_ACMD_HCmdB; |
| vmesa->regEnable = HC_HenCW_MASK; |
| |
| /* Mesa should do this for us: |
| */ |
| |
| ctx->Driver.BlendEquationSeparate( ctx, |
| ctx->Color.BlendEquationRGB, |
| ctx->Color.BlendEquationA); |
| |
| ctx->Driver.BlendFuncSeparate( ctx, |
| ctx->Color.BlendSrcRGB, |
| ctx->Color.BlendDstRGB, |
| ctx->Color.BlendSrcA, |
| ctx->Color.BlendDstA); |
| |
| ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, |
| ctx->Scissor.Width, ctx->Scissor.Height ); |
| |
| ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] ); |
| } |
| |
| /** |
| * Convert S and T texture coordinate wrap modes to hardware bits. |
| */ |
| static u_int32_t |
| get_wrap_mode( GLenum sWrap, GLenum tWrap ) |
| { |
| u_int32_t v = 0; |
| |
| |
| switch( sWrap ) { |
| case GL_REPEAT: |
| v |= HC_HTXnMPMD_Srepeat; |
| break; |
| case GL_CLAMP: |
| case GL_CLAMP_TO_EDGE: |
| v |= HC_HTXnMPMD_Sclamp; |
| break; |
| case GL_MIRRORED_REPEAT: |
| v |= HC_HTXnMPMD_Smirror; |
| break; |
| } |
| |
| switch( tWrap ) { |
| case GL_REPEAT: |
| v |= HC_HTXnMPMD_Trepeat; |
| break; |
| case GL_CLAMP: |
| case GL_CLAMP_TO_EDGE: |
| v |= HC_HTXnMPMD_Tclamp; |
| break; |
| case GL_MIRRORED_REPEAT: |
| v |= HC_HTXnMPMD_Tmirror; |
| break; |
| } |
| |
| return v; |
| } |
| |
| static u_int32_t |
| get_minmag_filter( GLenum min, GLenum mag ) |
| { |
| u_int32_t v = 0; |
| |
| switch (min) { |
| case GL_NEAREST: |
| v = HC_HTXnFLSs_Nearest | |
| HC_HTXnFLTs_Nearest; |
| break; |
| case GL_LINEAR: |
| v = HC_HTXnFLSs_Linear | |
| HC_HTXnFLTs_Linear; |
| break; |
| case GL_NEAREST_MIPMAP_NEAREST: |
| v = HC_HTXnFLSs_Nearest | |
| HC_HTXnFLTs_Nearest; |
| v |= HC_HTXnFLDs_Nearest; |
| break; |
| case GL_LINEAR_MIPMAP_NEAREST: |
| v = HC_HTXnFLSs_Linear | |
| HC_HTXnFLTs_Linear; |
| v |= HC_HTXnFLDs_Nearest; |
| break; |
| case GL_NEAREST_MIPMAP_LINEAR: |
| v = HC_HTXnFLSs_Nearest | |
| HC_HTXnFLTs_Nearest; |
| v |= HC_HTXnFLDs_Linear; |
| break; |
| case GL_LINEAR_MIPMAP_LINEAR: |
| v = HC_HTXnFLSs_Linear | |
| HC_HTXnFLTs_Linear; |
| v |= HC_HTXnFLDs_Linear; |
| break; |
| default: |
| break; |
| } |
| |
| switch (mag) { |
| case GL_LINEAR: |
| v |= HC_HTXnFLSe_Linear | |
| HC_HTXnFLTe_Linear; |
| break; |
| case GL_NEAREST: |
| v |= HC_HTXnFLSe_Nearest | |
| HC_HTXnFLTe_Nearest; |
| break; |
| default: |
| break; |
| } |
| |
| return v; |
| } |
| |
| |
| static GLboolean viaChooseTextureState(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| struct gl_texture_unit *texUnit0 = &ctx->Texture.Unit[0]; |
| struct gl_texture_unit *texUnit1 = &ctx->Texture.Unit[1]; |
| |
| if (texUnit0->_ReallyEnabled || texUnit1->_ReallyEnabled) { |
| vmesa->regEnable |= HC_HenTXMP_MASK | HC_HenTXCH_MASK | HC_HenTXPP_MASK; |
| |
| if (texUnit0->_ReallyEnabled) { |
| struct gl_texture_object *texObj = texUnit0->_Current; |
| |
| vmesa->regHTXnTB[0] = get_minmag_filter( texObj->MinFilter, |
| texObj->MagFilter ); |
| |
| vmesa->regHTXnMPMD[0] &= ~(HC_HTXnMPMD_SMASK | HC_HTXnMPMD_TMASK); |
| vmesa->regHTXnMPMD[0] |= get_wrap_mode( texObj->WrapS, |
| texObj->WrapT ); |
| |
| vmesa->regHTXnTB[0] &= ~(HC_HTXnTB_TBC_S | HC_HTXnTB_TBC_T); |
| if (texObj->Image[0][texObj->BaseLevel]->Border > 0) { |
| vmesa->regHTXnTB[0] |= (HC_HTXnTB_TBC_S | HC_HTXnTB_TBC_T); |
| vmesa->regHTXnTBC[0] = |
| PACK_COLOR_888(FLOAT_TO_UBYTE(texObj->BorderColor[0]), |
| FLOAT_TO_UBYTE(texObj->BorderColor[1]), |
| FLOAT_TO_UBYTE(texObj->BorderColor[2])); |
| vmesa->regHTXnTRAH[0] = FLOAT_TO_UBYTE(texObj->BorderColor[3]); |
| } |
| |
| if (texUnit0->LodBias != 0.0f) { |
| GLuint b = viaComputeLodBias(texUnit0->LodBias); |
| vmesa->regHTXnTB[0] &= ~HC_HTXnFLDs_MASK; |
| vmesa->regHTXnTB[0] |= HC_HTXnFLDs_ConstLOD; |
| vmesa->regHTXnCLOD[0] = (b&0x1f) | (((~b)&0x1f)<<10); /* FIXME */ |
| } |
| |
| if (!viaTexCombineState( vmesa, texUnit0->_CurrentCombine, 0 )) { |
| if (VIA_DEBUG & DEBUG_TEXTURE) |
| fprintf(stderr, "viaTexCombineState failed for unit 0\n"); |
| return GL_FALSE; |
| } |
| } |
| |
| if (texUnit1->_ReallyEnabled) { |
| struct gl_texture_object *texObj = texUnit1->_Current; |
| |
| vmesa->regHTXnTB[1] = get_minmag_filter( texObj->MinFilter, |
| texObj->MagFilter ); |
| vmesa->regHTXnMPMD[1] &= ~(HC_HTXnMPMD_SMASK | HC_HTXnMPMD_TMASK); |
| vmesa->regHTXnMPMD[1] |= get_wrap_mode( texObj->WrapS, |
| texObj->WrapT ); |
| |
| vmesa->regHTXnTB[1] &= ~(HC_HTXnTB_TBC_S | HC_HTXnTB_TBC_T); |
| if (texObj->Image[0][texObj->BaseLevel]->Border > 0) { |
| vmesa->regHTXnTB[1] |= (HC_HTXnTB_TBC_S | HC_HTXnTB_TBC_T); |
| vmesa->regHTXnTBC[1] = |
| PACK_COLOR_888(FLOAT_TO_UBYTE(texObj->BorderColor[0]), |
| FLOAT_TO_UBYTE(texObj->BorderColor[1]), |
| FLOAT_TO_UBYTE(texObj->BorderColor[2])); |
| vmesa->regHTXnTRAH[1] = FLOAT_TO_UBYTE(texObj->BorderColor[3]); |
| } |
| |
| |
| if (texUnit1->LodBias != 0.0f) { |
| GLuint b = viaComputeLodBias(texUnit1->LodBias); |
| vmesa->regHTXnTB[1] &= ~HC_HTXnFLDs_MASK; |
| vmesa->regHTXnTB[1] |= HC_HTXnFLDs_ConstLOD; |
| vmesa->regHTXnCLOD[1] = (b&0x1f) | (((~b)&0x1f)<<10); /* FIXME */ |
| } |
| |
| if (!viaTexCombineState( vmesa, texUnit1->_CurrentCombine, 1 )) { |
| if (VIA_DEBUG & DEBUG_TEXTURE) |
| fprintf(stderr, "viaTexCombineState failed for unit 1\n"); |
| return GL_FALSE; |
| } |
| } |
| } |
| else { |
| vmesa->regEnable &= ~(HC_HenTXMP_MASK | HC_HenTXCH_MASK | |
| HC_HenTXPP_MASK); |
| } |
| |
| return GL_TRUE; |
| } |
| |
| static void viaChooseColorState(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| GLenum s = ctx->Color.BlendSrcRGB; |
| GLenum d = ctx->Color.BlendDstRGB; |
| |
| /* The HW's blending equation is: |
| * (Ca * FCa + Cbias + Cb * FCb) << Cshift |
| */ |
| |
| if (ctx->Color.BlendEnabled) { |
| vmesa->regEnable |= HC_HenABL_MASK; |
| /* Ca -- always from source color. |
| */ |
| vmesa->regHABLCsat = HC_HABLCsat_MASK | HC_HABLCa_OPC | HC_HABLCa_Csrc; |
| /* Aa -- always from source alpha. |
| */ |
| vmesa->regHABLAsat = HC_HABLAsat_MASK | HC_HABLAa_OPA | HC_HABLAa_Asrc; |
| /* FCa -- depend on following condition. |
| * FAa -- depend on following condition. |
| */ |
| switch (s) { |
| case GL_ZERO: |
| /* (0, 0, 0, 0) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_HABLRCa; |
| vmesa->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_HABLFRA; |
| vmesa->regHABLRFCa = 0x0; |
| vmesa->regHABLRAa = 0x0; |
| break; |
| case GL_ONE: |
| /* (1, 1, 1, 1) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_HABLRCa; |
| vmesa->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_HABLFRA; |
| vmesa->regHABLRFCa = 0x0; |
| vmesa->regHABLRAa = 0x0; |
| break; |
| case GL_SRC_COLOR: |
| /* (Rs, Gs, Bs, As) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_Csrc; |
| vmesa->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_Asrc; |
| break; |
| case GL_ONE_MINUS_SRC_COLOR: |
| /* (1, 1, 1, 1) - (Rs, Gs, Bs, As) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_Csrc; |
| vmesa->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_Asrc; |
| break; |
| case GL_DST_COLOR: |
| /* (Rd, Gd, Bd, Ad) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_Cdst; |
| vmesa->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_Adst; |
| break; |
| case GL_ONE_MINUS_DST_COLOR: |
| /* (1, 1, 1, 1) - (Rd, Gd, Bd, Ad) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_Cdst; |
| vmesa->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_Adst; |
| break; |
| case GL_SRC_ALPHA: |
| /* (As, As, As, As) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_Asrc; |
| vmesa->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_Asrc; |
| break; |
| case GL_ONE_MINUS_SRC_ALPHA: |
| /* (1, 1, 1, 1) - (As, As, As, As) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_Asrc; |
| vmesa->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_Asrc; |
| break; |
| case GL_DST_ALPHA: |
| { |
| if (vmesa->viaScreen->bitsPerPixel == 16) { |
| /* (1, 1, 1, 1) |
| */ |
| vmesa->regHABLCsat |= (HC_HABLFCa_InvOPC | |
| HC_HABLFCa_HABLRCa); |
| vmesa->regHABLAsat |= (HC_HABLFAa_InvOPA | |
| HC_HABLFAa_HABLFRA); |
| vmesa->regHABLRFCa = 0x0; |
| vmesa->regHABLRAa = 0x0; |
| } |
| else { |
| /* (Ad, Ad, Ad, Ad) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_Adst; |
| vmesa->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_Adst; |
| } |
| } |
| break; |
| case GL_ONE_MINUS_DST_ALPHA: |
| { |
| if (vmesa->viaScreen->bitsPerPixel == 16) { |
| /* (1, 1, 1, 1) - (1, 1, 1, 1) = (0, 0, 0, 0) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_HABLRCa; |
| vmesa->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_HABLFRA; |
| vmesa->regHABLRFCa = 0x0; |
| vmesa->regHABLRAa = 0x0; |
| } |
| else { |
| /* (1, 1, 1, 1) - (Ad, Ad, Ad, Ad) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_Adst; |
| vmesa->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_Adst; |
| } |
| } |
| break; |
| case GL_SRC_ALPHA_SATURATE: |
| { |
| if (vmesa->viaScreen->bitsPerPixel == 16) { |
| /* (f, f, f, 1), f = min(As, 1 - Ad) = min(As, 1 - 1) = 0 |
| * So (f, f, f, 1) = (0, 0, 0, 1) |
| */ |
| vmesa->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_HABLRCa; |
| vmesa->regHABLAsat |= (HC_HABLFAa_InvOPA | |
| HC_HABLFAa_HABLFRA); |
| vmesa->regHABLRFCa = 0x0; |
| vmesa->regHABLRAa = 0x0; |
| } |
| else { |
| /* (f, f, f, 1), f = min(As, 1 - Ad) |
| */ |
| vmesa->regHABLCsat |= (HC_HABLFCa_OPC | |
| HC_HABLFCa_mimAsrcInvAdst); |
| vmesa->regHABLAsat |= (HC_HABLFAa_InvOPA | |
| HC_HABLFAa_HABLFRA); |
| vmesa->regHABLRFCa = 0x0; |
| vmesa->regHABLRAa = 0x0; |
| } |
| } |
| break; |
| } |
| |
| /* Op is add. |
| */ |
| |
| /* bias is 0. |
| */ |
| vmesa->regHABLCsat |= HC_HABLCbias_HABLRCbias; |
| vmesa->regHABLAsat |= HC_HABLAbias_HABLRAbias; |
| |
| /* Cb -- always from destination color. |
| */ |
| vmesa->regHABLCop = HC_HABLCb_OPC | HC_HABLCb_Cdst; |
| /* Ab -- always from destination alpha. |
| */ |
| vmesa->regHABLAop = HC_HABLAb_OPA | HC_HABLAb_Adst; |
| /* FCb -- depend on following condition. |
| */ |
| switch (d) { |
| case GL_ZERO: |
| /* (0, 0, 0, 0) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_HABLRCb; |
| vmesa->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_HABLFRA; |
| vmesa->regHABLRFCb = 0x0; |
| vmesa->regHABLRAb = 0x0; |
| break; |
| case GL_ONE: |
| /* (1, 1, 1, 1) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_HABLRCb; |
| vmesa->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_HABLFRA; |
| vmesa->regHABLRFCb = 0x0; |
| vmesa->regHABLRAb = 0x0; |
| break; |
| case GL_SRC_COLOR: |
| /* (Rs, Gs, Bs, As) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_Csrc; |
| vmesa->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_Asrc; |
| break; |
| case GL_ONE_MINUS_SRC_COLOR: |
| /* (1, 1, 1, 1) - (Rs, Gs, Bs, As) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_Csrc; |
| vmesa->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_Asrc; |
| break; |
| case GL_DST_COLOR: |
| /* (Rd, Gd, Bd, Ad) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_Cdst; |
| vmesa->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_Adst; |
| break; |
| case GL_ONE_MINUS_DST_COLOR: |
| /* (1, 1, 1, 1) - (Rd, Gd, Bd, Ad) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_Cdst; |
| vmesa->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_Adst; |
| break; |
| case GL_SRC_ALPHA: |
| /* (As, As, As, As) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_Asrc; |
| vmesa->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_Asrc; |
| break; |
| case GL_ONE_MINUS_SRC_ALPHA: |
| /* (1, 1, 1, 1) - (As, As, As, As) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_Asrc; |
| vmesa->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_Asrc; |
| break; |
| case GL_DST_ALPHA: |
| { |
| if (vmesa->viaScreen->bitsPerPixel == 16) { |
| /* (1, 1, 1, 1) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_HABLRCb; |
| vmesa->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_HABLFRA; |
| vmesa->regHABLRFCb = 0x0; |
| vmesa->regHABLRAb = 0x0; |
| } |
| else { |
| /* (Ad, Ad, Ad, Ad) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_Adst; |
| vmesa->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_Adst; |
| } |
| } |
| break; |
| case GL_ONE_MINUS_DST_ALPHA: |
| { |
| if (vmesa->viaScreen->bitsPerPixel == 16) { |
| /* (1, 1, 1, 1) - (1, 1, 1, 1) = (0, 0, 0, 0) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_HABLRCb; |
| vmesa->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_HABLFRA; |
| vmesa->regHABLRFCb = 0x0; |
| vmesa->regHABLRAb = 0x0; |
| } |
| else { |
| /* (1, 1, 1, 1) - (Ad, Ad, Ad, Ad) |
| */ |
| vmesa->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_Adst; |
| vmesa->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_Adst; |
| } |
| } |
| break; |
| default: |
| vmesa->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_HABLRCb; |
| vmesa->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_HABLFRA; |
| vmesa->regHABLRFCb = 0x0; |
| vmesa->regHABLRAb = 0x0; |
| break; |
| } |
| |
| if (vmesa->viaScreen->bitsPerPixel <= 16) |
| vmesa->regEnable &= ~HC_HenDT_MASK; |
| |
| } |
| else { |
| vmesa->regEnable &= (~HC_HenABL_MASK); |
| } |
| |
| if (ctx->Color.AlphaEnabled) { |
| vmesa->regEnable |= HC_HenAT_MASK; |
| vmesa->regHATMD = FLOAT_TO_UBYTE(ctx->Color.AlphaRef) | |
| ((ctx->Color.AlphaFunc - GL_NEVER) << 8); |
| } |
| else { |
| vmesa->regEnable &= (~HC_HenAT_MASK); |
| } |
| |
| if (ctx->Color.DitherFlag && (vmesa->viaScreen->bitsPerPixel < 32)) { |
| if (ctx->Color.BlendEnabled) { |
| vmesa->regEnable &= ~HC_HenDT_MASK; |
| } |
| else { |
| vmesa->regEnable |= HC_HenDT_MASK; |
| } |
| } |
| |
| |
| vmesa->regEnable &= ~HC_HenDT_MASK; |
| |
| if (ctx->Color.ColorLogicOpEnabled) |
| vmesa->regHROP = ROP[ctx->Color.LogicOp & 0xF]; |
| else |
| vmesa->regHROP = HC_HROP_P; |
| |
| vmesa->regHFBBMSKL = PACK_COLOR_888(ctx->Color.ColorMask[0], |
| ctx->Color.ColorMask[1], |
| ctx->Color.ColorMask[2]); |
| vmesa->regHROP |= ctx->Color.ColorMask[3]; |
| |
| if (ctx->Color.ColorMask[3]) |
| vmesa->regEnable |= HC_HenAW_MASK; |
| else |
| vmesa->regEnable &= ~HC_HenAW_MASK; |
| } |
| |
| static void viaChooseFogState(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| if (ctx->Fog.Enabled) { |
| GLubyte r, g, b, a; |
| |
| vmesa->regEnable |= HC_HenFOG_MASK; |
| |
| /* Use fog equation 0 (OpenGL's default) & local fog. |
| */ |
| vmesa->regHFogLF = 0x0; |
| |
| r = (GLubyte)(ctx->Fog.Color[0] * 255.0F); |
| g = (GLubyte)(ctx->Fog.Color[1] * 255.0F); |
| b = (GLubyte)(ctx->Fog.Color[2] * 255.0F); |
| a = (GLubyte)(ctx->Fog.Color[3] * 255.0F); |
| vmesa->regHFogCL = (r << 16) | (g << 8) | b; |
| vmesa->regHFogCH = a; |
| } |
| else { |
| vmesa->regEnable &= ~HC_HenFOG_MASK; |
| } |
| } |
| |
| static void viaChooseDepthState(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| if (ctx->Depth.Test) { |
| vmesa->regEnable |= HC_HenZT_MASK; |
| if (ctx->Depth.Mask) |
| vmesa->regEnable |= HC_HenZW_MASK; |
| else |
| vmesa->regEnable &= (~HC_HenZW_MASK); |
| vmesa->regHZWTMD = (ctx->Depth.Func - GL_NEVER) << 16; |
| |
| } |
| else { |
| vmesa->regEnable &= ~HC_HenZT_MASK; |
| |
| /*=* [DBG] racer : can't display cars in car selection menu *=*/ |
| /*if (ctx->Depth.Mask) |
| vmesa->regEnable |= HC_HenZW_MASK; |
| else |
| vmesa->regEnable &= (~HC_HenZW_MASK);*/ |
| vmesa->regEnable &= (~HC_HenZW_MASK); |
| } |
| } |
| |
| static void viaChooseLineState(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| if (ctx->Line.StippleFlag) { |
| vmesa->regEnable |= HC_HenLP_MASK; |
| vmesa->regHLP = ctx->Line.StipplePattern; |
| vmesa->regHLPRF = ctx->Line.StippleFactor; |
| } |
| else { |
| vmesa->regEnable &= ~HC_HenLP_MASK; |
| } |
| } |
| |
| static void viaChoosePolygonState(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| #if 0 |
| /* Polygon stipple is broken - see via_state.c |
| */ |
| if (ctx->Polygon.StippleFlag) { |
| vmesa->regEnable |= HC_HenSP_MASK; |
| } |
| else { |
| vmesa->regEnable &= ~HC_HenSP_MASK; |
| } |
| #else |
| FALLBACK(vmesa, VIA_FALLBACK_POLY_STIPPLE, |
| ctx->Polygon.StippleFlag); |
| #endif |
| |
| if (ctx->Polygon.CullFlag) { |
| vmesa->regEnable |= HC_HenFBCull_MASK; |
| } |
| else { |
| vmesa->regEnable &= ~HC_HenFBCull_MASK; |
| } |
| } |
| |
| static void viaChooseStencilState(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| if (ctx->Stencil.Enabled) { |
| GLuint temp; |
| |
| vmesa->regEnable |= HC_HenST_MASK; |
| temp = (ctx->Stencil.Ref[0] & 0xFF) << HC_HSTREF_SHIFT; |
| temp |= 0xFF << HC_HSTOPMSK_SHIFT; |
| temp |= (ctx->Stencil.ValueMask[0] & 0xFF); |
| vmesa->regHSTREF = temp; |
| |
| temp = (ctx->Stencil.Function[0] - GL_NEVER) << 16; |
| |
| switch (ctx->Stencil.FailFunc[0]) { |
| case GL_KEEP: |
| temp |= HC_HSTOPSF_KEEP; |
| break; |
| case GL_ZERO: |
| temp |= HC_HSTOPSF_ZERO; |
| break; |
| case GL_REPLACE: |
| temp |= HC_HSTOPSF_REPLACE; |
| break; |
| case GL_INVERT: |
| temp |= HC_HSTOPSF_INVERT; |
| break; |
| case GL_INCR: |
| temp |= HC_HSTOPSF_INCR; |
| break; |
| case GL_DECR: |
| temp |= HC_HSTOPSF_DECR; |
| break; |
| } |
| |
| switch (ctx->Stencil.ZFailFunc[0]) { |
| case GL_KEEP: |
| temp |= HC_HSTOPSPZF_KEEP; |
| break; |
| case GL_ZERO: |
| temp |= HC_HSTOPSPZF_ZERO; |
| break; |
| case GL_REPLACE: |
| temp |= HC_HSTOPSPZF_REPLACE; |
| break; |
| case GL_INVERT: |
| temp |= HC_HSTOPSPZF_INVERT; |
| break; |
| case GL_INCR: |
| temp |= HC_HSTOPSPZF_INCR; |
| break; |
| case GL_DECR: |
| temp |= HC_HSTOPSPZF_DECR; |
| break; |
| } |
| |
| switch (ctx->Stencil.ZPassFunc[0]) { |
| case GL_KEEP: |
| temp |= HC_HSTOPSPZP_KEEP; |
| break; |
| case GL_ZERO: |
| temp |= HC_HSTOPSPZP_ZERO; |
| break; |
| case GL_REPLACE: |
| temp |= HC_HSTOPSPZP_REPLACE; |
| break; |
| case GL_INVERT: |
| temp |= HC_HSTOPSPZP_INVERT; |
| break; |
| case GL_INCR: |
| temp |= HC_HSTOPSPZP_INCR; |
| break; |
| case GL_DECR: |
| temp |= HC_HSTOPSPZP_DECR; |
| break; |
| } |
| vmesa->regHSTMD = temp; |
| } |
| else { |
| vmesa->regEnable &= ~HC_HenST_MASK; |
| } |
| } |
| |
| |
| |
| static void viaChooseTriangle(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| if (ctx->Polygon.CullFlag == GL_TRUE) { |
| switch (ctx->Polygon.CullFaceMode) { |
| case GL_FRONT: |
| if (ctx->Polygon.FrontFace == GL_CCW) |
| vmesa->regCmdB |= HC_HBFace_MASK; |
| else |
| vmesa->regCmdB &= ~HC_HBFace_MASK; |
| break; |
| case GL_BACK: |
| if (ctx->Polygon.FrontFace == GL_CW) |
| vmesa->regCmdB |= HC_HBFace_MASK; |
| else |
| vmesa->regCmdB &= ~HC_HBFace_MASK; |
| break; |
| case GL_FRONT_AND_BACK: |
| return; |
| } |
| } |
| } |
| |
| void viaValidateState( GLcontext *ctx ) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| if (vmesa->newState & _NEW_TEXTURE) { |
| GLboolean ok = (viaChooseTextureState(ctx) && |
| viaUpdateTextureState(ctx)); |
| |
| FALLBACK(vmesa, VIA_FALLBACK_TEXTURE, !ok); |
| } |
| |
| if (vmesa->newState & _NEW_COLOR) |
| viaChooseColorState(ctx); |
| |
| if (vmesa->newState & _NEW_DEPTH) |
| viaChooseDepthState(ctx); |
| |
| if (vmesa->newState & _NEW_FOG) |
| viaChooseFogState(ctx); |
| |
| if (vmesa->newState & _NEW_LINE) |
| viaChooseLineState(ctx); |
| |
| if (vmesa->newState & (_NEW_POLYGON | _NEW_POLYGONSTIPPLE)) { |
| viaChoosePolygonState(ctx); |
| viaChooseTriangle(ctx); |
| } |
| |
| if ((vmesa->newState & _NEW_STENCIL) && vmesa->have_hw_stencil) |
| viaChooseStencilState(ctx); |
| |
| if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) |
| vmesa->regEnable |= HC_HenCS_MASK; |
| else |
| vmesa->regEnable &= ~HC_HenCS_MASK; |
| |
| if (ctx->Point.SmoothFlag || |
| ctx->Line.SmoothFlag || |
| ctx->Polygon.SmoothFlag) |
| vmesa->regEnable |= HC_HenAA_MASK; |
| else |
| vmesa->regEnable &= ~HC_HenAA_MASK; |
| |
| vmesa->newEmitState |= vmesa->newState; |
| vmesa->newState = 0; |
| } |
| |
| static void viaInvalidateState(GLcontext *ctx, GLuint newState) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| VIA_FINISH_PRIM( vmesa ); |
| vmesa->newState |= newState; |
| |
| _swrast_InvalidateState(ctx, newState); |
| _swsetup_InvalidateState(ctx, newState); |
| _vbo_InvalidateState(ctx, newState); |
| _tnl_InvalidateState(ctx, newState); |
| } |
| |
| void viaInitStateFuncs(GLcontext *ctx) |
| { |
| /* Callbacks for internal Mesa events. |
| */ |
| ctx->Driver.UpdateState = viaInvalidateState; |
| |
| /* API callbacks |
| */ |
| ctx->Driver.BlendEquationSeparate = viaBlendEquationSeparate; |
| ctx->Driver.BlendFuncSeparate = viaBlendFuncSeparate; |
| ctx->Driver.ClearColor = viaClearColor; |
| ctx->Driver.ColorMask = viaColorMask; |
| ctx->Driver.DrawBuffer = viaDrawBuffer; |
| ctx->Driver.RenderMode = viaRenderMode; |
| ctx->Driver.Scissor = viaScissor; |
| ctx->Driver.DepthRange = viaDepthRange; |
| ctx->Driver.Viewport = viaViewport; |
| ctx->Driver.Enable = viaEnable; |
| |
| /* XXX this should go away */ |
| ctx->Driver.ResizeBuffers = viaReAllocateBuffers; |
| } |