summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/savage
diff options
context:
space:
mode:
authorFelix Kuehling <fxkuehl@gmx.de>2004-02-22 16:11:12 +0000
committerFelix Kuehling <fxkuehl@gmx.de>2004-02-22 16:11:12 +0000
commit263581bba4d61291c54313648063a30c47106f0b (patch)
tree6d078c08002c4c02a6ece9a3f1dd6ea8f1885b3c /src/mesa/drivers/dri/savage
parent6e450f22bb86a18b66ec4053d5aacdf7788753dd (diff)
Imported the Savage DRI driver from the savage-2-0-0-branch of DRI CVS
with modifications to make it work with current Mesa 6.
Diffstat (limited to 'src/mesa/drivers/dri/savage')
-rw-r--r--src/mesa/drivers/dri/savage/savage_3d_reg.h1063
-rw-r--r--src/mesa/drivers/dri/savage/savage_bci.h741
-rw-r--r--src/mesa/drivers/dri/savage/savage_init.h161
-rw-r--r--src/mesa/drivers/dri/savage/savage_xmesa.c800
-rw-r--r--src/mesa/drivers/dri/savage/savagecontext.h299
-rw-r--r--src/mesa/drivers/dri/savage/savagedd.c106
-rw-r--r--src/mesa/drivers/dri/savage/savagedd.h33
-rw-r--r--src/mesa/drivers/dri/savage/savagedma.c298
-rw-r--r--src/mesa/drivers/dri/savage/savagedma.h50
-rw-r--r--src/mesa/drivers/dri/savage/savageioctl.c521
-rw-r--r--src/mesa/drivers/dri/savage/savageioctl.h72
-rw-r--r--src/mesa/drivers/dri/savage/savagespan.c313
-rw-r--r--src/mesa/drivers/dri/savage/savagespan.h30
-rw-r--r--src/mesa/drivers/dri/savage/savagestate.c2444
-rw-r--r--src/mesa/drivers/dri/savage/savagestate.h69
-rw-r--r--src/mesa/drivers/dri/savage/savagetex.c2022
-rw-r--r--src/mesa/drivers/dri/savage/savagetex.h117
-rw-r--r--src/mesa/drivers/dri/savage/savagetris.c817
-rw-r--r--src/mesa/drivers/dri/savage/savagetris.h49
-rw-r--r--src/mesa/drivers/dri/savage/savagevb.c470
-rw-r--r--src/mesa/drivers/dri/savage/savagevb.h62
21 files changed, 10537 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/savage/savage_3d_reg.h b/src/mesa/drivers/dri/savage/savage_3d_reg.h
new file mode 100644
index 0000000000..b56a9004f3
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savage_3d_reg.h
@@ -0,0 +1,1063 @@
+/*
+ * 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.
+ */
+
+
+#ifndef SAVAGE_3D_REG_H
+#define SAVAGE_3D_REG_H
+
+#define uint32 unsigned long
+#define uint16 unsigned short
+
+#define VIDEO_MEM_ADR 0x02
+#define SYSTEM_MEM_ADR 0x01
+#define AGP_MEM_ADR 0x03
+
+/***********************************************************
+
+ ----------- 3D ENGINE UNIT Registers -------------
+
+ *********************************************************/
+
+typedef union
+{
+ struct
+ {
+ unsigned int reserved : 4;
+ unsigned int ofs : 28;
+ }ni;
+ unsigned int ui;
+} Reg_ZPixelOffset;
+
+typedef union
+{
+ /* This reg exists only on Savage4. */
+ struct
+ {
+ unsigned int cmpFunc : 3;
+ unsigned int stencilEn : 1;
+ unsigned int readMask : 8;
+ unsigned int writeMask : 8;
+ unsigned int failOp : 3;
+ unsigned int passZfailOp : 3;
+ unsigned int passZpassOp : 3;
+ unsigned int reserved : 3;
+ }ni;
+ unsigned int ui;
+} Reg_StencilCtrl;
+
+/**************************
+ Texture Registers
+**************************/
+typedef union
+{
+ /* The layout of this reg differs between Savage4 and Savage3D. */
+ struct
+ {
+ unsigned int tex0Width : 4;
+ unsigned int tex0Height : 4;
+ unsigned int tex0Fmt : 4;
+ unsigned int tex1Width : 4;
+ unsigned int tex1Height : 4;
+ unsigned int tex1Fmt : 4;
+ unsigned int texBLoopEn : 1;
+ unsigned int tex0En : 1;
+ unsigned int tex1En : 1;
+ unsigned int orthProjEn : 1;
+ unsigned int reserved : 1;
+ unsigned int palSize : 2;
+ unsigned int newPal : 1;
+ }s4;
+ struct
+ {
+ unsigned int texWidth : 4;
+ unsigned int reserved1 : 4;
+ unsigned int texHeight : 4;
+ unsigned int reserved2 : 4;
+ /* Savage3D supports only the first 8 texture formats defined in
+ enum TexFmt in savge_bci.h. */
+ unsigned int texFmt : 3;
+ unsigned int palSize : 2;
+ unsigned int reserved3 : 10;
+ unsigned int newPal : 1;
+ }s3d;
+ unsigned int ui;
+} Reg_TexDescr;
+
+typedef union
+{
+ /* The layout of this reg is the same on Savage4 and Savage3D,
+ but the Savage4 has two of them, Savage3D has only one. */
+ struct
+ {
+ unsigned int inSysTex : 1;
+ unsigned int inAGPTex : 1;
+ unsigned int reserved : 1;
+ unsigned int addr : 29;
+ }ni;
+ unsigned int ui;
+} Reg_TexAddr;
+
+typedef union
+{
+ /* The layout of this reg is the same on Savage4 and Savage3D,
+ but the Savage4 has two of them, Savage3D has only one. */
+ struct
+ {
+ unsigned int reserved : 3;
+ unsigned int addr : 29;
+ }ni;
+ unsigned int ui;
+} Reg_TexPalAddr;
+
+typedef union
+{
+ /* The layout of this reg on Savage4 and Savage3D are very similar. */
+ struct
+ {
+ unsigned int xprClr0 : 16;
+ unsigned int xprClr1 : 16; /* this is reserved on Savage3D */
+ }ni;
+ unsigned int ui;
+} Reg_TexXprClr; /* transparency color in RGB565 format*/
+
+typedef union
+{
+ /* The layout of this reg differs between Savage4 and Savage3D.
+ * Savage4 has two of them, Savage3D has only one. */
+ struct
+ {
+ unsigned int filterMode : 2;
+ unsigned int mipmapEnable : 1;
+ unsigned int dBias : 9;
+ unsigned int dMax : 4;
+ unsigned int uMode : 2;
+ unsigned int vMode : 2;
+ unsigned int useDFraction : 1;
+ unsigned int texXprEn : 1;
+ unsigned int clrBlendAlphaSel : 2;
+ unsigned int clrArg1CopyAlpha : 1;
+ unsigned int clrArg2CopyAlpha : 1;
+ unsigned int clrArg1Invert : 1;
+ unsigned int clrArg2Invert : 1;
+ unsigned int alphaBlendAlphaSel : 2;
+ unsigned int alphaArg1Invert : 1;
+ unsigned int alphaArg2Invert : 1;
+ }s4;
+ struct
+ {
+ unsigned int filterMode : 2;
+ unsigned int mipmapDisable : 1;
+ unsigned int dBias : 9;
+ unsigned int uWrapEn : 1;
+ unsigned int vWrapEn : 1;
+ unsigned int wrapMode : 2;
+ unsigned int texEn : 1;
+ unsigned int useDFraction : 1;
+ unsigned int reserved1 : 1;
+ /* Color Compare Alpha Blend Control
+ 0 - reduce dest alpha to 0 or 1
+ 1 - blend with destination
+ The Utah-Driver doesn't know how to use it and sets it to 0. */
+ unsigned int CCA : 1;
+ unsigned int texXprEn : 1;
+ unsigned int reserved2 : 11;
+ }s3d;
+ unsigned int ui;
+} Reg_TexCtrl;
+
+typedef union
+{
+ /* This reg exists only on Savage4. */
+ struct
+ {
+ unsigned int colorArg1Sel : 2;
+ unsigned int colorArg2Sel : 3;
+ unsigned int colorInvAlphaEn : 1;
+ unsigned int colorInvArg2En : 1;
+ unsigned int colorPremodSel : 1;
+ unsigned int colorMod1Sel : 1;
+ unsigned int colorMod2Sel : 2;
+ unsigned int colorAddSel : 2;
+ unsigned int colorDoBlend : 1;
+ unsigned int colorDo2sCompl : 1;
+ unsigned int colorAddBiasEn : 1;
+ unsigned int alphaArg1Sel : 2;
+ unsigned int alphaArg2Sel : 3;
+ unsigned int alphaMod1Sel : 1;
+ unsigned int alphaMod2Sel : 2;
+ unsigned int alphaAdd0Sel : 1;
+ unsigned int alphaDoBlend : 1;
+ unsigned int alphaDo2sCompl : 1;
+ unsigned int colorStageClamp : 1;
+ unsigned int alphaStageClamp : 1;
+ unsigned int colorDoDiffMul : 1;
+ unsigned int LeftShiftVal : 2;
+ }ni;
+ unsigned int ui;
+} Reg_TexBlendCtrl;
+
+typedef union
+{
+ /* This reg exists only on Savage4. */
+ struct
+ {
+ unsigned int blue : 8;
+ unsigned int green : 8;
+ unsigned int red : 8;
+ unsigned int alpha : 8;
+ }ni;
+ unsigned int ui;
+} Reg_TexBlendColor;
+
+/********************************
+ Tiled Surface Registers
+**********************************/
+
+typedef union
+{
+ struct
+ {
+ unsigned int frmBufOffset : 13;
+ unsigned int reserved : 12;
+ unsigned int widthInTile : 6;
+ unsigned int bitPerPixel : 1;
+ }ni;
+ unsigned int ui;
+} Reg_TiledSurface;
+
+/********************************
+ Draw/Shading Control Registers
+**********************************/
+
+typedef union
+{
+ /* This reg exists only on Savage4. */
+ struct
+ {
+ unsigned int scissorXStart : 11;
+ unsigned int DPerfAccelEn : 1;
+ unsigned int scissorYStart : 12;
+ unsigned int alphaRefVal : 8;
+ }ni;
+ unsigned int ui;
+} Reg_DrawCtrl0;
+
+typedef union
+{
+ /* This reg exists only on Savage4. */
+ struct
+ {
+ unsigned int scissorXEnd : 11;
+ unsigned int XYOffsetEn : 1;
+ unsigned int scissorYEnd : 12;
+ unsigned int ditherEn : 1;
+ unsigned int nonNormTexCoord : 1;
+ unsigned int cullMode : 2;
+ unsigned int alphaTestCmpFunc : 3;
+ unsigned int alphaTestEn : 1;
+ }ni;
+ unsigned int ui;
+} Reg_DrawCtrl1;
+
+typedef union
+{
+ /* This reg exists only on Savage4. */
+ struct
+ {
+ unsigned int dstAlphaMode : 3;
+ unsigned int DstMinusSrc : 1;
+ unsigned int srcAlphaMode : 3;
+ unsigned int binaryFinalAlpha : 1;
+ unsigned int dstAlphaModeHighBit : 1;
+ unsigned int srcAlphaModeHighBit : 1;
+ unsigned int reserved1 : 15;
+ unsigned int wrZafterAlphaTst : 1;
+ unsigned int drawUpdateEn : 1;
+ unsigned int zUpdateEn : 1;
+ unsigned int flatShadeEn : 1;
+ unsigned int specShadeEn : 1;
+ unsigned int flushPdDestWrites : 1;
+ unsigned int flushPdZbufWrites : 1;
+ }ni;
+ unsigned int ui;
+} Reg_DrawLocalCtrl;
+
+typedef union
+{
+ /* This reg exists only on Savage3D. */
+ struct
+ {
+ unsigned int ditherEn : 1;
+ unsigned int XYOffsetEn : 1;
+ unsigned int cullMode : 2;
+ unsigned int vertexCountReset : 1;
+ unsigned int flatShadeEn : 1;
+ unsigned int specShadeEn : 1;
+ unsigned int dstAlphaMode : 3;
+ unsigned int srcAlphaMode : 3;
+ unsigned int reserved1 : 1;
+ unsigned int alphaTestCmpFunc : 3;
+ unsigned int alphaTestEn : 1;
+ unsigned int alphaRefVal : 8;
+ unsigned int texBlendCtrl : 3;
+ unsigned int flushPdDestWrites : 1;
+ unsigned int flushPdZbufWrites : 1;
+ /* havn't found an equivalent for Savage4. Utah-driver sets it to 0. */
+ unsigned int interpMode : 1;
+ }ni;
+ unsigned int ui;
+} Reg_DrawCtrl;
+
+#define SAVAGETBC_DECAL_S3D 0
+#define SAVAGETBC_MODULATE_S3D 1
+#define SAVAGETBC_DECALALPHA_S3D 2
+#define SAVAGETBC_MODULATEALPHA_S3D 3
+#define SAVAGETBC_4_S3D 4
+#define SAVAGETBC_5_S3D 5
+#define SAVAGETBC_COPY_S3D 6
+#define SAVAGETBC_7_S3D 7
+
+typedef union
+{
+ /* This reg exists only on Savage3D. */
+ struct
+ {
+ unsigned int scissorXStart : 11;
+ unsigned int reserved1 : 5;
+ unsigned int scissorYStart : 11;
+ unsigned int reserved2 : 5;
+ } ni;
+ unsigned int ui;
+} Reg_ScissorsStart;
+
+typedef union
+{
+ /* This reg exists only on Savage3D. */
+ struct
+ {
+ unsigned int scissorXEnd : 11;
+ unsigned int reserved1 : 5;
+ unsigned int scissorYEnd : 11;
+ unsigned int reserved2 : 5;
+ } ni;
+ unsigned int ui;
+} Reg_ScissorsEnd;
+
+/********************************
+ Address Registers
+**********************************/
+
+typedef union
+{
+ /* I havn't found a Savage3D equivalent of this reg in the Utah-driver.
+ * But Tim Roberts claims that the Savage3D supports DMA vertex and
+ * command buffers. */
+ struct
+ {
+ unsigned int isSys : 1;
+ unsigned int isAGP : 1;
+ unsigned int reserved : 1;
+ unsigned int addr : 29; /*quad word aligned*/
+ }ni;
+ unsigned int ui;
+} Reg_VertBufAddr;
+
+typedef union
+{
+ /* I havn't found a Savage3D equivalent of this reg in the Utah-driver.
+ * But Tim Roberts claims that the Savage3D supports DMA vertex and
+ * command buffers. */
+ struct
+ {
+ unsigned int isSys : 1;
+ unsigned int isAGP : 1;
+ unsigned int reserved : 1;
+ unsigned int addr : 29; /*4-quad word aligned*/
+ }ni;
+ unsigned int ui;
+} Reg_DMABufAddr;
+
+/********************************
+ H/W Debug Registers
+**********************************/
+typedef union
+{
+ /* The layout of this reg is the same on Savage4 and Savage3D. */
+ struct
+ {
+ unsigned int y01 : 1;
+ unsigned int y12 : 1;
+ unsigned int y20 : 1;
+ unsigned int u01 : 1;
+ unsigned int u12 : 1;
+ unsigned int u20 : 1;
+ unsigned int v01 : 1;
+ unsigned int v12 : 1;
+ unsigned int v20 : 1;
+ unsigned int cullEn : 1;
+ unsigned int cullOrient : 1;
+ unsigned int loadNewTex : 1;
+ unsigned int loadNewPal : 1;
+ unsigned int doDSetup : 1;
+ unsigned int reserved : 17;
+ unsigned int kickOff : 1;
+ }ni;
+ unsigned int ui;
+} Reg_Flag;
+
+/********************************
+ Z Buffer Registers -- Global
+**********************************/
+
+typedef union
+{
+ /* The layout of this reg differs between Savage4 and Savage3D. */
+ struct
+ {
+ unsigned int zCmpFunc : 3;
+ unsigned int reserved1 : 2;
+ unsigned int zBufEn : 1;
+ unsigned int reserved2 : 1;
+ unsigned int zExpOffset : 8;
+ unsigned int reserved3 : 1;
+ unsigned int stencilRefVal : 8;
+ unsigned int autoZEnable : 1;
+ unsigned int frameID : 1;
+ unsigned int reserved4 : 4;
+ unsigned int floatZEn : 1;
+ unsigned int wToZEn : 1;
+ }s4;
+ struct {
+ unsigned int zCmpFunc : 3;
+ unsigned int drawUpdateEn : 1;
+ unsigned int zUpdateEn : 1;
+ unsigned int zBufEn : 1;
+ unsigned int reserved1 : 2;
+ unsigned int zExpOffset : 8;
+ unsigned int wrZafterAlphaTst : 1;
+ unsigned int reserved2 : 15;
+ }s3d;
+ GLuint ui;
+}Reg_ZBufCtrl;
+
+typedef union
+{
+ /* The layout of this reg on Savage4 and Savage3D are very similar. */
+ struct
+ {
+ /* In the Utah-Driver the offset is defined as 13-bit, 2k-aligned. */
+ unsigned int offset : 14;
+ unsigned int reserved : 11; /* 12-bits in Utah-driver */
+ unsigned int zBufWidthInTiles : 6;
+ unsigned int zDepthSelect : 1;
+ }ni;
+ unsigned int ui;
+} Reg_ZBufOffset;
+
+typedef union
+{
+ /* The layout of this reg is the same on Savage4 and Savage3D. */
+ struct
+ {
+ unsigned int rLow : 6;
+ unsigned int reserved1 : 2;
+ unsigned int rHigh : 6;
+ unsigned int reserved2 : 2;
+ unsigned int wLow : 6;
+ unsigned int reserved3 : 2;
+ unsigned int wHigh : 6;
+ unsigned int reserved4 : 2;
+ }ni;
+ unsigned int ui;
+} Reg_ZWatermarks;
+
+/********************************
+ Fog Registers -- Global
+**********************************/
+typedef union
+{
+ /* The layout of this reg is the same on Savage4 and Savage3D. */
+ struct
+ {
+ unsigned int fogClr : 24;
+ unsigned int expShift : 3;
+ unsigned int reserved : 1;
+ unsigned int fogEn : 1;
+ unsigned int fogMode : 1;
+ unsigned int fogEndShift : 2;
+ }ni;
+ unsigned int ui;
+}Reg_FogCtrl;
+
+typedef struct
+{
+ /* According to the Utah-driver the fog table has 64 entries on
+ Savage3D. Savage4 uses only 32 entries. */
+ union
+ {
+ unsigned char ucEntry[64];
+ uint32 ulEntry[16];
+ }ni;
+} Reg_FogTable;
+
+/*not in spec, but tempo for pp and driver*/
+typedef union
+{
+ struct
+ {
+ unsigned int fogDensity : 16;
+ unsigned int fogStart : 16;
+ }ni;
+ unsigned int ui;
+}Reg_FogParam;
+
+/**************************************
+ Destination Buffer Registers -- Global
+***************************************/
+
+typedef union
+{
+ /* The layout of this reg on Savage4 and Savage3D are very similar. */
+ struct
+ {
+ unsigned int dstWidthInTile : 7;
+ unsigned int reserved : 1;
+ /* In the Utah-Driver the offset is defined as 13-bit, 2k-aligned. */
+ unsigned int offset : 14;
+ unsigned int reserved1 : 7;
+ /* antiAliasMode does not exist in the Utah-driver. But it includes the
+ * high bit of this in the destPixFmt. However, only values 0 and 2
+ * are used as dstPixFmt, so antiAliasMode is effectively always 0
+ * in the Utah-driver. In other words, treat as reserved on SavageIX.*/
+ unsigned int antiAliasMode : 2;
+ unsigned int dstPixFmt : 1;
+ }ni;
+ unsigned int ui;
+}Reg_DestCtrl;
+
+typedef union
+{
+ /* The layout of this reg on Savage4 and Savage3D are very similar. */
+ struct
+ {
+ unsigned int destReadLow : 6;
+ unsigned int destReadHigh : 6;
+ unsigned int destWriteLow : 6;
+ unsigned int destWriteHigh : 6;
+ unsigned int texRead : 4;
+ unsigned int reserved4 : 2;
+ /* The Utah-driver calls this pixel FIFO length:
+ * 00 - 240, 01 - 180, 10 - 120, 11 - 60
+ * However, it is not used in either driver. */
+ unsigned int destFlush : 2;
+ }ni;
+ unsigned int ui;
+}Reg_DestTexWatermarks;
+
+typedef struct _REGISTERS_
+{
+ union
+ {
+ struct
+ {
+ unsigned int fDrawLocalCtrlChanged : 1;
+ unsigned int fTexPalAddrChanged : 1;
+ unsigned int fTex0CtrlChanged : 1;
+ unsigned int fTex1CtrlChanged : 1;
+
+ unsigned int fTex0AddrChanged : 1;
+ unsigned int fTex1AddrChanged : 1;
+ unsigned int fTex0BlendCtrlChanged : 1;
+ unsigned int fTex1BlendCtrlChanged : 1;
+
+ unsigned int fTexXprClrChanged : 1;
+ unsigned int fTexDescrChanged : 1;
+ unsigned int fFogTableChanged : 1;
+ unsigned int fFogCtrlChanged : 1;
+
+ unsigned int fStencilCtrlChanged : 1;
+ unsigned int fZBufCtrlChanged : 1;
+ unsigned int fZBufOffsetChanged : 1;
+ unsigned int fDestCtrlChanged : 1;
+
+ unsigned int fDrawCtrl0Changed : 1;
+ unsigned int fDrawCtrl1Changed : 1;
+ unsigned int fZWatermarksChanged : 1;
+ unsigned int fDestTexWatermarksChanged : 1;
+
+ unsigned int fTexBlendColorChanged : 1;
+ unsigned int fDrawCtrlChanged : 1;
+ unsigned int fScissorsStartChanged : 1;
+ unsigned int fScissorsEndChanged : 1;
+
+ unsigned int fScissorsChanged : 1; /* doesn't correspond to
+ a real register. */
+
+ unsigned int fReserved : 7;
+ }ni;
+ GLuint uiRegistersChanged;
+ }changed;
+
+ Reg_DrawLocalCtrl DrawLocalCtrl; /* Savage4 only */
+
+ Reg_TexPalAddr TexPalAddr;
+ Reg_TexCtrl TexCtrl[2]; /* Savage3D uses only one */
+ Reg_TexAddr TexAddr[2]; /* Savage3D uses only one */
+ Reg_TexBlendCtrl TexBlendCtrl[2]; /* Savage4 only */
+
+ Reg_TexXprClr TexXprClr;
+ Reg_TexDescr TexDescr;
+
+ Reg_FogTable FogTable; /* Savage4 uses only 32 entries */
+
+ Reg_FogCtrl FogCtrl;
+
+ Reg_StencilCtrl StencilCtrl; /* Savage4 only */
+ Reg_ZBufCtrl ZBufCtrl;
+ Reg_ZBufOffset ZBufOffset;
+ Reg_DestCtrl DestCtrl;
+ Reg_DrawCtrl0 DrawCtrl0; /* Savage4 only */
+ Reg_DrawCtrl1 DrawCtrl1; /* Savage4 only */
+ Reg_ZWatermarks ZWatermarks;
+ Reg_DestTexWatermarks DestTexWatermarks;
+ Reg_TexBlendColor TexBlendColor; /* Savage4 only */
+
+ Reg_DrawCtrl DrawCtrl; /* Savage3D only */
+ Reg_ScissorsStart ScissorsStart; /* Savage3D only */
+ Reg_ScissorsEnd ScissorsEnd; /* Savage3D only */
+} REGISTERS;
+
+/* All registers that affect textures */
+#define SAVAGE_TEXTURE_CHANGED 0x000002FE
+/* Engine must be idle when global registers are changed */
+#define SAVAGE_GLOBAL_CHANGED 0x00FFFC00
+
+/* Savage4/Twister/ProSavage register BCI addresses */
+#define SAVAGE_DRAWLOCALCTRL_S4 0x1e
+#define SAVAGE_TEXPALADDR_S4 0x1f
+#define SAVAGE_TEXCTRL0_S4 0x20
+#define SAVAGE_TEXCTRL1_S4 0x21
+#define SAVAGE_TEXADDR0_S4 0x22
+#define SAVAGE_TEXADDR1_S4 0x23
+#define SAVAGE_TEXBLEND0_S4 0x24
+#define SAVAGE_TEXBLEND1_S4 0x25
+#define SAVAGE_TEXXPRCLR_S4 0x26 /* never used */
+#define SAVAGE_TEXDESCR_S4 0x27
+#define SAVAGE_FOGTABLE_S4 0x28
+#define SAVAGE_FOGCTRL_S4 0x30
+#define SAVAGE_STENCILCTRL_S4 0x31
+#define SAVAGE_ZBUFCTRL_S4 0x32
+#define SAVAGE_ZBUFOFF_S4 0x33
+#define SAVAGE_DESTCTRL_S4 0x34
+#define SAVAGE_DRAWCTRLGLOBAL0_S4 0x35
+#define SAVAGE_DRAWCTRLGLOBAL1_S4 0x36
+#define SAVAGE_ZWATERMARK_S4 0x37
+#define SAVAGE_DESTTEXRWWATERMARK_S4 0x38
+#define SAVAGE_TEXBLENDCOLOR_S4 0x39
+/* Savage3D/MX/IC register BCI addresses */
+#define SAVAGE_TEXPALADDR_S3D 0x18
+#define SAVAGE_TEXXPRCLR_S3D 0x19 /* never used */
+#define SAVAGE_TEXADDR_S3D 0x1A
+#define SAVAGE_TEXDESCR_S3D 0x1B
+#define SAVAGE_TEXCTRL_S3D 0x1C
+#define SAVAGE_FOGTABLE_S3D 0x20
+#define SAVAGE_FOGCTRL_S3D 0x30
+#define SAVAGE_DRAWCTRL_S3D 0x31
+#define SAVAGE_ZBUFCTRL_S3D 0x32
+#define SAVAGE_ZBUFOFF_S3D 0x33
+#define SAVAGE_DESTCTRL_S3D 0x34
+#define SAVAGE_SCSTART_S3D 0x35
+#define SAVAGE_SCEND_S3D 0x36
+#define SAVAGE_ZWATERMARK_S3D 0x37
+#define SAVAGE_DESTTEXRWWATERMARK_S3D 0x38
+
+#define DV_PF_555 (0x1<<8)
+#define DV_PF_565 (0x2<<8)
+#define DV_PF_8888 (0x4<<8)
+
+#define SAVAGEPACKCOLORA4L4(l,a) \
+ ((l >> 4) | (a & 0xf0))
+
+#define SAVAGEPACKCOLOR4444(r,g,b,a) \
+ ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
+
+#define SAVAGEPACKCOLOR1555(r,g,b,a) \
+ ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
+ ((a) ? 0x8000 : 0))
+
+#define SAVAGEPACKCOLOR8888(r,g,b,a) \
+ (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+
+#define SAVAGEPACKCOLOR565(r,g,b) \
+ ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
+
+
+
+/*AlphaFunc*/
+#define LCS_A_NEVER 0x0200
+#define LCS_A_LESS 0x0201
+#define LCS_A_EQUAL 0x0202
+#define LCS_A_LEQUAL 0x0203
+#define LCS_A_GREATER 0x0204
+#define LCS_A_NOTEQUAL 0x0205
+#define LCS_A_GEQUAL 0x0206
+#define LCS_A_ALWAYS 0x0207
+/*stencilFunc*/
+#define LCS_S_NEVER 0x0200
+#define LCS_S_LESS 0x0201
+#define LCS_S_EQUAL 0x0202
+#define LCS_S_LEQUAL 0x0203
+#define LCS_S_GREATER 0x0204
+#define LCS_S_NOTEQUAL 0x0205
+#define LCS_S_GEQUAL 0x0206
+#define LCS_S_ALWAYS 0x0207
+/*depthFunc*/
+
+#define LCS_Z_NEVER 0x0200
+#define LCS_Z_LESS 0x0201
+#define LCS_Z_EQUAL 0x0202
+#define LCS_Z_LEQUAL 0x0203
+#define LCS_Z_GREATER 0x0204
+#define LCS_Z_NOTEQUAL 0x0205
+#define LCS_Z_GEQUAL 0x0206
+#define LCS_Z_ALWAYS 0x0207
+#if 0
+#define LCS_UPDATE_LINEWIDTH (0x1<<15)
+#define LCS_LINEWIDTH_MASK (0x7<<12)
+#define LCS_LINEWIDTH_SHIFT 12
+#define LCS_LINEWIDTH_0_5 (0x1<<12)
+#define LCS_LINEWIDTH_1_0 (0x2<<12)
+#define LCS_LINEWIDTH_2_0 (0x4<<12)
+#define LCS_LINEWIDTH_3_0 (0x6<<12)
+#define LCS_UPDATE_ALPHA_INTERP (0x1<<11)
+#define LCS_ALPHA_FLAT (0x1<<10)
+#define LCS_ALPHA_INTERP (0x0<<10)
+#define LCS_UPDATE_FOG_INTERP (0x1<<9)
+#define LCS_FOG_INTERP (0x0<<8)
+#define LCS_FOG_FLAT (0x1<<8)
+#define LCS_UPDATE_SPEC_INTERP (0x1<<7)
+#define LCS_SPEC_INTERP (0x0<<6)
+#define LCS_SPEC_FLAT (0x1<<6)
+#define LCS_UPDATE_RGB_INTERP (0x1<<5)
+#define LCS_RGB_INTERP (0x0<<4)
+#define LCS_RGB_FLAT (0x1<<4)
+#define LCS_UPDATE_CULL_MODE (0x1<<3)
+#define LCS_CULL_MASK (0x7<<0)
+#define LCS_CULL_DISABLE (0x1<<0)
+#define LCS_CULL_CW (0x2<<0)
+#define LCS_CULL_CCW (0x3<<0)
+#define LCS_CULL_BOTH (0x4<<0)
+
+#define LCS_INTERP_FLAT (LCS_ALPHA_FLAT|LCS_RGB_FLAT|LCS_SPEC_FLAT)
+#define LCS_UPDATE_INTERP (LCS_UPDATE_ALPHA_INTERP| \
+ LCS_UPDATE_RGB_INTERP| \
+ LCS_UPDATE_SPEC_INTERP)
+
+#endif
+
+/*#define GFX_OP_PRIMITIVE ((0x3<<29)|(0x1f<<24))*/
+#define PR_TRIANGLES (0x0<<18)
+/*#define PR_TRISTRIP_0 (0x1<<18)*/
+/*#define PR_TRISTRIP_1 (0x2<<18)*/
+/*#define PR_TRIFAN (0x3<<18)*/
+#define PR_POLYGON (0x4<<18)
+#define PR_LINES (0x5<<18)
+/*#define PR_LINESTRIP (0x6<<18)*/
+/*#define PR_RECTS (0x7<<18)*/
+
+/* GFXRENDERSTATE_MAP_COORD_SETS, p116
+ */
+#define GFX_OP_MAP_COORD_SETS ((0x3<<29)|(0x1c<<24)|(0x1<<19))
+#define MCS_COORD_ID_SHIFT 16
+#define MCS_COORD_0 (0<<16)
+#define MCS_COORD_1 (1<<16)
+#define MCS_UPDATE_NORMALIZED (1<<15)
+#define MCS_NORMALIZED_COORDS_MASK (1<<14)
+#define MCS_NORMALIZED_COORDS (1<<14)
+#define MCS_UPDATE_V_STATE (1<<7)
+#define MCS_V_STATE_MASK (0x3<<4)
+#define MCS_V_WRAP (0x0<<4)
+#define MCS_V_MIRROR (0x1<<4)
+#define MCS_V_CLAMP (0x2<<4)
+#define MCS_V_WRAP_SHORTEST (0x3<<4)
+#define MCS_UPDATE_U_STATE (1<<3)
+#define MCS_U_STATE_MASK (0x3<<0)
+#define MCS_U_WRAP (0x0<<0)
+#define MCS_U_MIRROR (0x1<<0)
+#define MCS_U_CLAMP (0x2<<0)
+#define MCS_U_WRAP_SHORTEST (0x3<<0)
+
+#define GFX_OP_MAP_TEXELS ((0x3<<29)|(0x1c<<24)|(0x0<<19))
+#define MT_UPDATE_TEXEL1_STATE (1<<15)
+#define MT_TEXEL1_DISABLE (0<<14)
+#define MT_TEXEL1_ENABLE (1<<14)
+#define MT_TEXEL1_COORD0 (0<<11)
+#define MT_TEXEL1_COORD1 (1<<11)
+#define MT_TEXEL1_MAP0 (0<<8)
+#define MT_TEXEL1_MAP1 (1<<8)
+#define MT_UPDATE_TEXEL0_STATE (1<<7)
+#define MT_TEXEL0_DISABLE (0<<6)
+#define MT_TEXEL0_ENABLE (1<<6)
+#define MT_TEXEL0_COORD0 (0<<3)
+#define MT_TEXEL0_COORD1 (1<<3)
+#define MT_TEXEL0_MAP0 (0<<0)
+#define MT_TEXEL0_MAP1 (1<<0)
+
+#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+
+/* GFXRENDERSTATE_MAP_ALPHA_BLEND_STAGES, p132
+ */
+#define GFX_OP_MAP_ALPHA_STAGES ((0x3<<29)|(0x1<<24))
+#define MA_STAGE_SHIFT 20
+#define MA_STAGE_0 (0<<20)
+#define MA_STAGE_1 (1<<20)
+#define MA_STAGE_2 (2<<20)
+#define MA_UPDATE_ARG1 (1<<18)
+#define MA_ARG1_MASK ((0x7<<15)|(0x1<<13))
+#define MA_ARG1_ALPHA_FACTOR (0x1<<15)
+#define MA_ARG1_ITERATED_ALPHA (0x3<<15)
+#define MA_ARG1_CURRENT_ALPHA (0x5<<15)
+#define MA_ARG1_TEX0_ALPHA (0x6<<15)
+#define MA_ARG1_TEX1_ALPHA (0x7<<15)
+#define MA_ARG1_INVERT (0x1<<13)
+#define MA_ARG1_DONT_INVERT (0x0<<13)
+#define MA_UPDATE_ARG2 (1<<12)
+#define MA_ARG2_MASK ((0x7<<8)|(0x1<<6))
+#define MA_ARG2_ALPHA_FACTOR (0x1<<8)
+#define MA_ARG2_ITERATED_ALPHA (0x3<<8)
+#define MA_ARG2_CURRENT_ALPHA (0x5<<8)
+#define MA_ARG2_TEX0_ALPHA (0x6<<8)
+#define MA_ARG2_TEX1_ALPHA (0x7<<8)
+#define MA_ARG2_INVERT (0x1<<6)
+#define MA_ARG2_DONT_INVERT (0x0<<6)
+#define MA_UPDATE_OP (1<<5)
+#define MA_OP_MASK (0xf)
+#define MA_OP_ARG1 (0x1)
+#define MA_OP_ARG2 (0x2)
+#define MA_OP_MODULATE (0x3)
+#define MA_OP_MODULATE_X2 (0x4)
+#define MA_OP_MODULATE_X4 (0x5)
+#define MA_OP_ADD (0x6)
+#define MA_OP_ADD_SIGNED (0x7)
+#define MA_OP_LIN_BLEND_ITER_ALPHA (0x8)
+#define MA_OP_LIN_BLEND_ALPHA_FACTOR (0xa)
+#define MA_OP_LIN_BLEND_TEX0_ALPHA (0x10)
+#define MA_OP_LIN_BLEND_TEX1_ALPHA (0x11)
+
+
+/* GFXRENDERSTATE_MAP_COLOR_BLEND_STAGES, p129
+ */
+#define GFX_OP_MAP_COLOR_STAGES ((0x3<<29)|(0x0<<24))
+#define MC_STAGE_SHIFT 20
+#define MC_STAGE_0 (0<<20)
+#define MC_STAGE_1 (1<<20)
+#define MC_STAGE_2 (2<<20)
+#define MC_UPDATE_DEST (1<<19)
+#define MC_DEST_MASK (1<<18)
+#define MC_DEST_CURRENT (0<<18)
+#define MC_DEST_ACCUMULATOR (1<<18)
+#define MC_UPDATE_ARG1 (1<<17)
+#define MC_ARG1_MASK ((0x7<<14)|(0x1<<13)|(0x1<<12))
+#define MC_ARG1_ONE (0x0<<14)
+#define MC_ARG1_COLOR_FACTOR (0x1<<14)
+#define MC_ARG1_ACCUMULATOR (0x2<<14)
+#define MC_ARG1_ITERATED_COLOR (0x3<<14)
+#define MC_ARG1_SPECULAR_COLOR (0x4<<14)
+#define MC_ARG1_CURRENT_COLOR (0x5<<14)
+#define MC_ARG1_TEX0_COLOR (0x6<<14)
+#define MC_ARG1_TEX1_COLOR (0x7<<14)
+#define MC_ARG1_DONT_REPLICATE_ALPHA (0x0<<13)
+#define MC_ARG1_REPLICATE_ALPHA (0x1<<13)
+#define MC_ARG1_DONT_INVERT (0x0<<12)
+#define MC_ARG1_INVERT (0x1<<12)
+#define MC_UPDATE_ARG2 (1<<11)
+#define MC_ARG2_MASK ((0x7<<8)|(0x1<<7)|(0x1<<6))
+#define MC_ARG2_ONE (0x0<<8)
+#define MC_ARG2_COLOR_FACTOR (0x1<<8)
+#define MC_ARG2_ACCUMULATOR (0x2<<8)
+#define MC_ARG2_ITERATED_COLOR (0x3<<8)
+#define MC_ARG2_SPECULAR_COLOR (0x4<<8)
+#define MC_ARG2_CURRENT_COLOR (0x5<<8)
+#define MC_ARG2_TEX0_COLOR (0x6<<8)
+#define MC_ARG2_TEX1_COLOR (0x7<<8)
+#define MC_ARG2_DONT_REPLICATE_ALPHA (0x0<<7)
+#define MC_ARG2_REPLICATE_ALPHA (0x1<<7)
+#define MC_ARG2_DONT_INVERT (0x0<<6)
+#define MC_ARG2_INVERT (0x1<<6)
+#define MC_UPDATE_OP (1<<5)
+#define MC_OP_MASK (0xf)
+#define MC_OP_DISABLE (0x0)
+#define MC_OP_ARG1 (0x1)
+#define MC_OP_ARG2 (0x2)
+#define MC_OP_MODULATE (0x3)
+#define MC_OP_MODULATE_X2 (0x4)
+#define MC_OP_MODULATE_X4 (0x5)
+#define MC_OP_ADD (0x6)
+#define MC_OP_ADD_SIGNED (0x7)
+#define MC_OP_LIN_BLEND_ITER_ALPHA (0x8)
+#define MC_OP_LIN_BLEND_ALPHA_FACTOR (0xa)
+#define MC_OP_LIN_BLEND_TEX0_ALPHA (0x10)
+#define MC_OP_LIN_BLEND_TEX1_ALPHA (0x11)
+#define MC_OP_LIN_BLEND_TEX0_COLOR (0x12)
+#define MC_OP_LIN_BLEND_TEX1_COLOR (0x13)
+#define MC_OP_SUBTRACT (0x14)
+
+/* GFXRENDERSTATE_MAP_PALETTE_LOAD, p128
+ *
+ * Format:
+ * 0: GFX_OP_MAP_PALETTE_LOAD
+ * 1: 16bpp color[0]
+ * ...
+ * 256: 16bpp color[255]
+ */
+#define GFX_OP_MAP_PALETTE_LOAD ((0x3<<29)|(0x1d<<24)|(0x82<<16)|0xff)
+
+/* GFXRENDERSTATE_MAP_LOD_CONTROL, p127
+ */
+#define GFX_OP_MAP_LOD_CTL ((0x3<<29)|(0x1c<<24)|(0x4<<19))
+#define MLC_MAP_ID_SHIFT 16
+#define MLC_MAP_0 (0<<16)
+#define MLC_MAP_1 (1<<16)
+#define MLC_UPDATE_DITHER_WEIGHT (1<<10)
+#define MLC_DITHER_WEIGHT_MASK (0x3<<8)
+#define MLC_DITHER_WEIGHT_FULL (0x0<<8)
+#define MLC_DITHER_WEIGHT_50 (0x1<<8)
+#define MLC_DITHER_WEIGHT_25 (0x2<<8)
+#define MLC_DITHER_WEIGHT_12 (0x3<<8)
+#define MLC_UPDATE_LOD_BIAS (1<<7)
+#define MLC_LOD_BIAS_MASK ((1<<7)-1)
+
+/* GFXRENDERSTATE_MAP_LOD_LIMITS, p126
+ */
+#define GFX_OP_MAP_LOD_LIMITS ((0x3<<29)|(0x1c<<24)|(0x3<<19))
+#define MLL_MAP_ID_SHIFT 16
+#define MLL_MAP_0 (0<<16)
+#define MLL_MAP_1 (1<<16)
+#define MLL_UPDATE_MAX_MIP (1<<13)
+#define MLL_MAX_MIP_SHIFT 5
+#define MLL_MAX_MIP_MASK (0xff<<5)
+#define MLL_MAX_MIP_ONE (0x10<<5)
+#define MLL_UPDATE_MIN_MIP (1<<4)
+#define MLL_MIN_MIP_SHIFT 0
+#define MLL_MIN_MIP_MASK (0xf<<0)
+
+/* GFXRENDERSTATE_MAP_FILTER, p124
+ */
+#define GFX_OP_MAP_FILTER ((0x3<<29)|(0x1c<<24)|(0x2<<19))
+#define MF_MAP_ID_SHIFT 16
+#define MF_MAP_0 (0<<16)
+#define MF_MAP_1 (1<<16)
+#define MF_UPDATE_ANISOTROPIC (1<<12)
+#define MF_ANISOTROPIC_MASK (1<<10)
+#define MF_ANISOTROPIC_ENABLE (1<<10)
+#define MF_UPDATE_MIP_FILTER (1<<9)
+#define MF_MIP_MASK (0x3<<6)
+#define MF_MIP_NONE (0x0<<6)
+#define MF_MIP_NEAREST (0x1<<6)
+#define MF_MIP_DITHER (0x2<<6)
+#define MF_MIP_LINEAR (0x3<<6)
+#define MF_UPDATE_MAG_FILTER (1<<5)
+#define MF_MAG_MASK (1<<3)
+#define MF_MAG_LINEAR (1<<3)
+#define MF_MAG_NEAREST (0<<3)
+#define MF_UPDATE_MIN_FILTER (1<<2)
+#define MF_MIN_MASK (1<<0)
+#define MF_MIN_LINEAR (1<<0)
+#define MF_MIN_NEAREST (0<<0)
+
+/* GFXRENDERSTATE_MAP_INFO, p118
+ */
+#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x2)
+#define MI1_MAP_ID_SHIFT 28
+#define MI1_MAP_0 (0<<28)
+#define MI1_MAP_1 (1<<28)
+#define MI1_FMT_MASK (0x7<<24)
+#define MI1_FMT_8CI (0x0<<24)
+#define MI1_FMT_8BPP (0x1<<24)
+#define MI1_FMT_16BPP (0x2<<24)
+#define MI1_FMT_422 (0x5<<24)
+#define MI1_PF_MASK (0x3<<21)
+#define MI1_PF_8CI_RGB565 (0x0<<21)
+#define MI1_PF_8CI_ARGB1555 (0x1<<21)
+#define MI1_PF_8CI_ARGB4444 (0x2<<21)
+#define MI1_PF_8CI_AY88 (0x3<<21)
+#define MI1_PF_16BPP_RGB565 (0x0<<21)
+#define MI1_PF_16BPP_ARGB1555 (0x1<<21)
+#define MI1_PF_16BPP_ARGB4444 (0x2<<21)
+#define MI1_PF_16BPP_AY88 (0x3<<21)
+#define MI1_PF_422_YCRCB_SWAP_Y (0x0<<21)
+#define MI1_PF_422_YCRCB (0x1<<21)
+#define MI1_PF_422_YCRCB_SWAP_UV (0x2<<21)
+#define MI1_PF_422_YCRCB_SWAP_YUV (0x3<<21)
+#define MI1_OUTPUT_CHANNEL_MASK (0x3<<19)
+#define MI1_COLOR_CONV_ENABLE (1<<18)
+#define MI1_VERT_STRIDE_MASK (1<<17)
+#define MI1_VERT_STRIDE_1 (1<<17)
+#define MI1_VERT_OFFSET_MASK (1<<16)
+#define MI1_VERT_OFFSET_1 (1<<16)
+#define MI1_ENABLE_FENCE_REGS (1<<10)
+#define MI1_TILED_SURFACE (1<<9)
+#define MI1_TILE_WALK_X (0<<8)
+#define MI1_TILE_WALK_Y (1<<8)
+#define MI1_PITCH_MASK (0xf<<0)
+#define MI2_DIMENSIONS_ARE_LOG2 (1<<31)
+#define MI2_DIMENSIONS_ARE_EXACT (0<<31)
+#define MI2_HEIGHT_SHIFT 16
+#define MI2_HEIGHT_MASK (0x1ff<<16)
+#define MI2_WIDTH_SHIFT 0
+#define MI2_WIDTH_MASK (0x1ff<<0)
+#define MI3_BASE_ADDR_MASK (~0xf)
+
+#define SAVAGE_VFMT_T0 (GFX_OP_VERTEX_FMT | \
+ VF_TEXCOORD_COUNT_1 | \
+ VF_SPEC_FOG_ENABLE | \
+ VF_RGBA_ENABLE | \
+ VF_XYZW)
+
+#define SAVAGE_VFMT_T0T1 (GFX_OP_VERTEX_FMT | \
+ VF_TEXCOORD_COUNT_2 | \
+ VF_SPEC_FOG_ENABLE | \
+ VF_RGBA_ENABLE | \
+ VF_XYZW)
+
+#define GFX_OP_VERTEX_FMT ((0x3<<29)|(0x5<<24))
+#define VF_TEXCOORD_COUNT_SHIFT 8
+#define VF_TEXCOORD_COUNT_0 (0<<8)
+#define VF_TEXCOORD_COUNT_1 (1<<8)
+#define VF_TEXCOORD_COUNT_2 (2<<8)
+#define VF_SPEC_FOG_ENABLE (1<<7)
+#define VF_RGBA_ENABLE (1<<6)
+#define VF_Z_OFFSET_ENABLE (1<<5)
+#define VF_XYZ (0x1<<1)
+#define VF_XYZW (0x2<<1)
+#define VF_XY (0x3<<1)
+#define VF_XYW (0x4<<1)
+
+/* Master data transfer engine */
+#define MDT_SRCADD_ALIGMENT (~0x1fUL)
+#define MDT_SRC_PCI 0x1
+#define MDT_SRC_AGP 0x3
+#endif
+
+
diff --git a/src/mesa/drivers/dri/savage/savage_bci.h b/src/mesa/drivers/dri/savage/savage_bci.h
new file mode 100644
index 0000000000..adaf579a91
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savage_bci.h
@@ -0,0 +1,741 @@
+/*
+ * 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.
+ */
+
+
+#ifndef SAVAGE_BCI_H
+#define SAVAGE_BCI_H
+/***********************
+ 3D and 2D command
+************************/
+
+typedef enum {
+ AMO_BurstCmdData= 0x01010000,
+ AMO_3DReg= 0x01048500,
+ AMO_MotionCompReg= 0x01048900,
+ AMO_VideoEngUnit= 0x01048A00,
+ AMO_CmdBufAddr= 0x01048c14,
+ AMO_TiledSurfReg0= 0x01048C40,
+ AMO_TiledSurfReg1= 0x01048C44,
+ AMO_TiledSurfReg2= 0x01048C48,
+ AMO_TiledSurfReg3= 0x01048C4C,
+ AMO_TiledSurfReg4= 0x01048C50,
+ AMO_TiledSurfReg5= 0x01048C54,
+ AMO_TiledSurfReg6= 0x01048C58,
+ AMO_TiledSurfReg7= 0x01048C5C,
+ AMO_LPBModeReg= 0x0100FF00,
+ AMO_LPBFifoSat= 0x0100FF04,
+ AMO_LPBIntFlag= 0x0100FF08,
+ AMO_LPBFmBufA0= 0x0100FF0C,
+ AMO_LPBFmBufA1= 0x0100FF10,
+ AMO_LPBRdWtAdr= 0x0100FF14,
+ AMO_LPBRdWtDat= 0x0100FF18,
+ AMO_LPBIOPort = 0x0100FF1C,
+ AMO_LPBSerPort= 0x0100FF20,
+ AMO_LPBVidInWinSz= 0x0100FF24,
+ AMO_LPBVidDatOffs= 0x0100FF28,
+ AMO_LPBHorScalCtrl= 0x0100FF2C,
+ AMO_LPBVerDeciCtrl= 0x0100FF30,
+ AMO_LPBLnStride= 0x0100FF34,
+ AMO_LPBFmBufAddr2= 0x0100FF38,
+ AMO_LPBVidCapVDCtrl=0x0100FF3C,
+
+ AMO_LPBVidCapFdStAd=0x0100FF60,
+ AMO_LPBVidCapFdMdAd=0x0100FF64,
+ AMO_LPBVidCapFdBtAd=0x0100FF68,
+ AMO_LPBVidCapFdSize=0x0100FF6C,
+ AMO_LPBBilinDecim1= 0x0100FF70,
+ AMO_LPBBilinDecim2= 0x0100FF74,
+ AMO_LPBBilinDecim3= 0x0100FF78,
+ AMO_LPBDspVEUHorSRR=0x0100FF7C,
+ AMO_LPBDspVEUVerSRR=0x0100FF80,
+ AMO_LPBDspVeuDnScDR=0x0100FF84,
+ AMO_LPB_VEUERPReg= 0x0100FF88,
+ AMO_LPB_VBISelReg= 0x0100FF8C,
+ AMO_LPB_VBIBasAdReg=0x0100FF90,
+ AMO_LPB_DatOffsReg= 0x0100FF94,
+ AMO_LPB_VBIVerDcReg=0x0100FF98,
+ AMO_LPB_VBICtrlReg= 0x0100FF9C,
+ AMO_LPB_VIPXferCtrl=0x0100FFA0,
+ AMO_LPB_FIFOWtMark= 0x0100FFA4,
+ AMO_LPB_FIFOCount= 0x0100FFA8,
+ AMO_LPBFdSkipPat= 0x0100FFAC,
+ AMO_LPBCapVEUHorSRR=0x0100FFB0,
+ AMO_LPBCapVEUVerSRR=0x0100FFB4,
+ AMO_LPBCapVeuDnScDR=0x0100FFB8
+
+}AddressMapOffset;
+/*more to add*/
+
+
+typedef enum {
+ CMD_DrawPrim=0x10, /*10000*/
+ CMD_DrawIdxPrim=0x11, /*10001*/
+ CMD_SetRegister=0x12, /*10010*/
+ CMD_UpdateShadowStat=0x13 , /*10011*/
+ CMD_PageFlip=0x14, /* 10100*/
+ CMD_BusMasterImgXfer=0x15, /* 10101*/
+ CMD_ScaledImgXfer=0x16, /* 10110*/
+ CMD_Macroblock=0x17, /*10111*/
+ CMD_Wait= 0x18, /*11000*/
+ CMD_2D_NOP=0x08, /* 01000*/
+ CMD_2D_RCT=0x09, /*01001 rectangular fill*/
+ CMD_2D_SCNL=0x0a, /* 01010 scan line*/
+ CMD_2D_LIN=0x0b, /*01011 line*/
+ CMD_2D_SMTXT=0x0c, /*01100*/
+ CMD_2D_BPTXT=0x0d, /*01101*/
+ CMD_InitFlag=0x1f /*11111, for S/W initialization control*/
+}Command;
+
+
+typedef enum {
+ VRR_List,
+ VRR_Strip,
+ VRR_Fan,
+ VRR_QuadList
+}VertexReplaceRule;
+
+/***********************
+ Destination
+************************/
+
+typedef enum {
+ DFT_RGB565 = 0,
+ DFT_XRGB8888
+}DestinationFmt;
+
+
+/*************************
+ Z Buffer / Alpha test
+*************************/
+
+typedef enum {
+ ZCF_Never,
+ ZCF_Less,
+ ZCF_Equal,
+ ZCF_LessEqual,
+ ZCF_Greater,
+ ZCF_NotEqual,
+ ZCF_GreaterEqual,
+ ZCF_Always
+}ZCmpFunc; /* same for Alpha test compare function*/
+
+
+typedef enum {
+ ZDS_16i, /* .16 fixed*/
+ ZDS_32f /* 1.8.15 float*/
+}ZDepthSelect;
+
+
+/**********************************
+ BCI Register Addressing Index
+***********************************/
+typedef enum {
+
+ CRI_VTX0_X = 0x00,
+ CRI_VTX0_Y = 0x01,
+ CRI_VTX0_W = 0x02,
+ CRI_VTX0_DIFFU= 0x03,
+ CRI_VTX0_SPECU= 0x04,
+ CRI_VTX0_U = 0x05,
+ CRI_VTX0_V = 0x06,
+ CRI_VTX0_U2 = 0x07,
+ CRI_VTX0_V2 = 0x08,
+ CRI_VTX1_X = 0x09,
+ CRI_VTX1_Y = 0x0a,
+ CRI_VTX1_W = 0x0b,
+ CRI_VTX1_DIFFU= 0x0c,
+ CRI_VTX1_SPECU= 0x0d,
+ CRI_VTX1_U = 0x0e,
+ CRI_VTX1_V = 0x0f,
+ CRI_VTX1_U2 = 0x10,
+ CRI_VTX1_V2 = 0x11,
+ CRI_VTX2_X = 0x12,
+ CRI_VTX2_Y = 0x13,
+ CRI_VTX2_W = 0x14,
+ CRI_VTX2_DIFFU= 0x15,
+ CRI_VTX2_SPECU= 0x16,
+ CRI_VTX2_U = 0x17,
+ CRI_VTX2_V = 0x18,
+ CRI_VTX2_U2 = 0x19,
+ CRI_VTX2_V2 = 0x1a,
+
+ CRI_ZPixelOffset = 0x1d,
+ CRI_DrawCtrlLocal = 0x1e,
+ CRI_TexPalAddr = 0x1f,
+ CRI_TexCtrl0 = 0x20,
+ CRI_TexCtrl1 = 0x21,
+ CRI_TexAddr0 = 0x22,
+ CRI_TexAddr1 = 0x23,
+ CRI_TexBlendCtrl0 = 0x24,
+ CRI_TexBlendCtrl1 = 0x25,
+ CRI_TexXprClr = 0x26,
+ CRI_TexDescr = 0x27,
+
+ CRI_FogTable00= 0x28,
+ CRI_FogTable04= 0x29,
+ CRI_FogTable08= 0x2a,
+ CRI_FogTable12= 0x2b,
+ CRI_FogTable16= 0x2c,
+ CRI_FogTable20= 0x2d,
+ CRI_FogTable24= 0x2e,
+ CRI_FogTable28= 0x2f,
+ CRI_FogCtrl= 0x30,
+ CRI_StencilCtrl= 0x31,
+ CRI_ZBufCtrl= 0x32,
+ CRI_ZBufOffset= 0x33,
+ CRI_DstCtrl= 0x34,
+ CRI_DrawCtrlGlobal0= 0x35,
+ CRI_DrawCtrlGlobal1= 0x36,
+ CRI_ZRW_WTMK = 0x37,
+ CRI_DST_WTMK = 0x38,
+ CRI_TexBlendColor= 0x39,
+
+ CRI_VertBufAddr= 0x3e,
+ /* new in ms1*/
+ CRI_MauFrameAddr0 = 0x40,
+ CRI_MauFrameAddr1 = 0x41,
+ CRI_MauFrameAddr2 = 0x42,
+ CRI_MauFrameAddr3 = 0x43,
+ CRI_FrameDesc = 0x44,
+ CRI_IDCT9bitEn = 0x45,
+ CRI_MV0 = 0x46,
+ CRI_MV1 = 0x47,
+ CRI_MV2 = 0x48,
+ CRI_MV3 = 0x49,
+ CRI_MacroDescr = 0x4a, /*kickoff?*/
+
+ CRI_MeuCtrl = 0x50,
+ CRI_SrcYAddr = 0x51,
+ CRI_DestAddr = 0x52,
+ CRI_FmtrSrcDimen = 0x53,
+ CRI_FmtrDestDimen = 0x54,
+ CRI_SrcCbAddr = 0x55,
+ CRI_SrcCrAddr = 0x56,
+ CRI_SrcCrCbStride = 0x57,
+
+ CRI_BCI_Power= 0x5f,
+
+ CRI_PSCtrl=0xA0,
+ CRI_SSClrKeyCtrl=0xA1,
+ CRI_SSCtrl=0xA4,
+ CRI_SSChromUpBound=0xA5,
+ CRI_SSHoriScaleCtrl=0xA6,
+ CRI_SSClrAdj=0xA7,
+ CRI_SSBlendCtrl=0xA8,
+ CRI_PSFBAddr0=0xB0,
+ CRI_PSFBAddr1=0xB1,
+ CRI_PSStride=0xB2,
+ CRI_DB_LPB_Support=0xB3,
+ CRI_SSFBAddr0=0xB4,
+ CRI_SSFBAddr1=0xB5,
+ CRI_SSStride=0xB6,
+ CRI_SSOpaqueCtrl=0xB7,
+ CRI_SSVertScaleCtrl=0xB8,
+ CRI_SSVertInitValue=0xB9,
+ CRI_SSSrcLineCnt=0xBA,
+ CRI_FIFO_RAS_Ctrl=0xBB,
+ CRI_PSWinStartCoord=0xBC,
+ CRI_PSWinSize=0xBD,
+ CRI_SSWinStartCoord=0xBE,
+ CRI_SSWinSize=0xBF,
+ CRI_PSFIFOMon0=0xC0,
+ CRI_SSFIFOMon0=0xC1,
+ CRI_PSFIFOMon1=0xC2,
+ CRI_SSFIFOMon1=0xC3,
+ CRI_PSFBSize=0xC4,
+ CRI_SSFBSize=0xC5,
+ CRI_SSFBAddr2=0xC6,
+ /* 2D register starts at D0*/
+ CRI_CurrXY=0xD0,
+ CRI_DstXYorStep=0xD1 ,
+ CRI_LineErr=0xD2 ,
+ CRI_DrawCmd=0xD3, /*kick off for image xfer*/
+ CRI_ShortStrkVecXfer=0xD4,
+ CRI_BackClr=0xD5,
+ CRI_ForeClr=0xD6,
+ CRI_BitPlaneWtMask=0xD7,
+ CRI_BitPlaneRdMask=0xD8,
+ CRI_ClrCmp=0xD9 ,
+ CRI_BackAndForeMix=0xDA ,
+ CRI_TopLeftSciss=0xDB ,
+ CRI_BotRightSciss=0xDC ,
+ CRI_PixOrMultiCtrl=0xDD ,
+ CRI_MultiCtrlOrRdSelct=0xDE ,
+ CRI_MinorOrMajorAxisCnt=0xDF ,
+ CRI_GlobalBmpDesc1=0xE0 ,
+ CRI_GlobalBmpDesc2=0xE1 ,
+ CRI_BurstPriBmpDesc1=0xE2 ,
+ CRI_BurstPriBmpDesc2=0xE3 ,
+ CRI_BurstSecBmpDesc1=0xE4 ,
+ CRI_BurstSecBmpDesc2=0xE5,
+ CRI_ImageDataPort=0xF8
+
+}CtrlRegIdx;
+
+/***********************
+ Fog Mode
+************************/
+typedef enum
+{
+ FGM_Z_FOG, /*Table*/
+ FGM_V_FOG /*Vertex*/
+} FogMode;
+
+/***********************
+ Texture
+************************/
+typedef enum
+{
+ TAM_Wrap,
+ TAM_Clamp,
+ TAM_Mirror
+} TexAddressModel;
+
+typedef enum
+{
+ TFT_S3TC4Bit,
+ TFT_Pal8Bit565,
+ TFT_Pal8Bit1555,
+ TFT_ARGB8888,
+ TFT_ARGB1555,
+ TFT_ARGB4444,
+ TFT_RGB565,
+ TFT_Pal8Bit4444,
+ TFT_S3TC4A4Bit, /*like S3TC4Bit but with 4 bit alpha*/
+ TFT_S3TC4CA4Bit, /*like S3TC4Bit, but with 4 bit compressed alpha*/
+ TFT_S3TCL4,
+ TFT_S3TCA4L4,
+ TFT_L8,
+ TFT_A4L4,
+ TFT_I8,
+ TFT_A8
+} TexFmt;
+
+typedef enum
+{
+ TPS_64,
+ TPS_128,
+ TPS_192,
+ TPS_256
+} TexPaletteSize;
+
+ #define MAX_MIPMAP_LOD_BIAS 255
+ #define MIN_MIPMAP_LOD_BIAS -255
+
+typedef enum
+{
+ TFM_Point, /*1 TPP*/
+ TFM_Bilin, /*2 TPP*/
+ TFM_Reserved,
+ TFM_Trilin /*16 TPP*/
+} TexFilterMode;
+
+
+#define TBC_Decal 0x00850410
+#define TBC_Modul 0x00850011
+#define TBC_DecalAlpha 0x00852A04
+#define TBC_ModulAlpha 0x00110011
+#define TBC_Copy 0x00840410
+#define TBC_CopyAlpha 0x00900405
+#define TBC_NoTexMap 0x00850405
+#define TBC_Blend0 0x00810004
+#define TBC_Blend1 0x00870e02
+#define TBC_BlendAlpha0 0x00040004
+#define TBC_BlendAlpha1 TBC_Blend1
+#define TBC_BlendInt0 0x00040004
+#define TBC_BlendInt1 0x01c20e02
+#define TBC_AddAlpha 0x19910c11
+
+#define TBC_Decal1 0x00870410
+#define TBC_Modul1 0x00870013
+#define TBC_DecalAlpha1 0x00832A00
+#define TBC_ModulAlpha1 0x00130013
+#define TBC_NoTexMap1 0x00870407
+#define TBC_Copy1 0x00870400
+#define TBC_CopyAlpha1 0x00900400
+#define TBC_AddAlpha1 0x19930c13
+
+/*
+ * derived from TexBlendCtrl
+ */
+
+typedef enum
+{
+ TBC_UseSrc,
+ TBC_UseTex,
+ TBC_TexTimesSrc,
+ TBC_BlendTexWithSrc
+} TexBlendCtrlMode;
+
+/***********************
+ Draw Control
+************************/
+typedef enum
+{
+ BCM_Reserved,
+ BCM_None,
+ BCM_CW,
+ BCM_CCW
+} BackfaceCullingMode;
+
+typedef enum
+{
+ SAM_Zero,
+ SAM_One,
+ SAM_DstClr,
+ SAM_1DstClr,
+ SAM_SrcAlpha,
+ SAM_1SrcAlpha,
+ SAM_DstAlpha,
+ SAM_1DstAlpha
+} SrcAlphaBlendMode;
+
+/* -1 from state*/
+typedef enum
+{
+ DAM_Zero,
+ DAM_One,
+ DAM_SrcClr,
+ DAM_1SrcClr,
+ DAM_SrcAlpha,
+ DAM_1SrcAlpha,
+ DAM_DstAlpha,
+ DAM_1DstAlpha
+} DstAlphaBlendMode;
+
+/*
+ * stencil control
+ */
+
+typedef enum
+{
+ STC_COMP_Never,
+ STC_COMP_Less,
+ STC_COMP_Equal,
+ STC_COMP_LessEqual,
+ STC_COMP_Greater,
+ STC_COMP_NotEqual,
+ STC_COMP_GreaterEqual,
+ STC_COMP_Always
+} StencilCompareMode;
+
+typedef enum
+{
+ STC_FAIL_Keep,
+ STC_FAIL_Zero,
+ STC_FAIL_Equal,
+ STC_FAIL_IncClamp,
+ STC_FAIL_DecClamp,
+ STC_FAIL_Invert,
+ STC_FAIL_Inc,
+ STC_FAIL_Dec
+} StencilFailOp;
+
+typedef enum
+{
+ STC_ZPASS_Keep,
+ STC_ZPASS_Zero,
+ STC_ZPASS_Equal,
+ STC_ZPASS_IncClamp,
+ STC_ZPASS_DecClamp,
+ STC_ZPASS_Invert,
+ STC_ZPASS_Inc,
+ STC_ZPASS_Dec
+} StencilZPassOp;
+
+typedef enum
+{
+ STC_ZFAIL_Keep,
+ STC_ZFAIL_Zero,
+ STC_ZFAIL_Equal,
+ STC_ZFAIL_IncClamp,
+ STC_ZFAIL_DecClamp,
+ STC_ZFAIL_Invert,
+ STC_ZFAIL_Inc,
+ STC_ZFAIL_Dec
+} StencilZFailOp;
+
+/***************************************************************
+*** Bitfield Structures for Programming Interface **************
+***************************************************************/
+
+/**************************
+ Command Header Entry
+**************************/
+
+typedef struct { /*for DrawIndexPrimitive command, vert0Idx is meaningful.*/
+ unsigned int vert0Idx:16;
+ unsigned int vertCnt:8;
+ unsigned int cont:1;
+ unsigned int type:2; /*00=list, 01=strip, 10=fan, 11=reserved*/
+ unsigned int cmd:5;
+}Reg_DrawIndexPrimitive;
+
+typedef struct { /*for DrawIndexPrimitive command, vert0Idx is meaningful.*/
+ unsigned int noW:1;
+ unsigned int noCd:1;
+ unsigned int noCs:1;
+ unsigned int noU:1;
+ unsigned int noV:1;
+ unsigned int noU2:1;
+ unsigned int noV2:1;
+
+ unsigned int reserved:9;
+ unsigned int vertCnt:8;
+ unsigned int cont:1;
+ unsigned int type:2; /* 00=list, 01=strip, 10=fan, 11=reserved*/
+ unsigned int cmd:5;
+}Reg_DrawPrimitive;
+
+
+typedef struct {
+ unsigned int startRegIdx:8;
+ unsigned int reserved:8;
+ unsigned int regCnt:8;
+ unsigned int resvered1:1;
+ unsigned int lowEn:1;
+ unsigned int highEn:1;
+ unsigned int cmd:5;
+}Reg_SetRegister;
+
+typedef struct {
+ unsigned int reserved1:22;
+ unsigned int isPrimary:1;
+ unsigned int MIU_SYNC:1;
+ unsigned int reserved2:3;
+ unsigned int cmd:5;
+}Reg_QueuedPageFlip;
+
+typedef struct {
+ unsigned int reserved1:22;
+ unsigned int DIR:1;
+ unsigned int CTG:1; /*set to 0*/
+ unsigned int BPP:1;
+ unsigned int reserved2:1;
+ unsigned int cmd:5;
+}Reg_MasterImgXfer;
+
+typedef struct {
+ unsigned int PD:4; /*PM=mono, PS=descriptor specified*/
+ unsigned int PT:1;
+ unsigned int SD:4;
+ unsigned int ST:1;
+ unsigned int DD:3;
+ unsigned int DC:2; /*DC=destination clip*/
+ unsigned int CS:1; /*cs=color specified*/
+ unsigned int MIX3:8;
+ unsigned int XP:1;
+ unsigned int YP:1;
+ unsigned int LP:1;
+ unsigned int cmd:5;
+}Reg_2D;
+
+typedef struct {
+ unsigned int CodedBlkPattern:6;
+ unsigned int DCT_Type:1;
+ unsigned int MB_Type:2;
+ unsigned int MotionType:2;
+ unsigned int MB_Row:6;
+ unsigned int MB_Column:6;
+ unsigned int mv3:1;
+ unsigned int mv2:1;
+ unsigned int mv1:1;
+ unsigned int mv0:1;
+ unsigned int cmd:5;
+}Reg_MacroBlock;
+
+typedef struct {
+ unsigned int scanLnCnt:11;
+ unsigned int clkCnt:5;
+ unsigned int e3d:1;
+ unsigned int e2d:1;
+ unsigned int mau:1;
+ unsigned int veu:1;
+ unsigned int meuMit:1;
+ unsigned int meuSit:1;
+ unsigned int meuVx:1;
+ unsigned int meuMau:1;
+ unsigned int pageFlip:1;
+ unsigned int scanLn:1;
+ unsigned int clk:1;
+ unsigned int cmd:5;
+}Reg_Wait;
+
+typedef struct{
+ unsigned int reserved:27;
+ unsigned int cmd:5;
+}Reg_ScaledImgXfer ;
+
+typedef struct{
+ unsigned int eventTag:16;
+ unsigned int reserved2:6;
+ unsigned int ET:1;
+ unsigned int INT:1;
+ unsigned int reserved1:3;
+ unsigned int cmd:5;
+}Reg_UpdtShadowStat;
+
+typedef union {
+ Reg_DrawPrimitive vert;
+ Reg_DrawIndexPrimitive vertIdx;
+ Reg_SetRegister set;
+ Reg_QueuedPageFlip pageFlip;
+ Reg_MasterImgXfer masterImgXfer;
+ Reg_ScaledImgXfer scaledImgXfer;
+ Reg_UpdtShadowStat updtShadow;
+ Reg_MacroBlock macroBlk;
+ Reg_2D cmd2D;
+ Reg_Wait wait;
+}CmdHeaderUnion;
+
+
+/*frank 2001/11/14 add BCI write macros*/
+/* Registers not used in the X server
+ */
+
+#define SAVAGE_NOP_ID 0x2094
+#define SAVAGE_NOP_ID_MASK ((1<<22)-1)
+
+
+/* 3D instructions
+ */
+
+/* Draw Primitive Control */
+
+
+#define SAVAGE_HW_NO_Z (1<<0)
+#define SAVAGE_HW_NO_W (1<<1)
+#define SAVAGE_HW_NO_CD (1<<2)
+#define SAVAGE_HW_NO_CS (1<<3)
+#define SAVAGE_HW_NO_UV0 ((1<<4) | (1<<5))
+#define SAVAGE_HW_NO_UV1 ((1<<6) | (1<<7))
+
+#define SAVAGE_HW_TRIANGLE_TYPE (3UL<<25)
+#define SAVAGE_HW_TRIANGLE_CONT (1UL<<24)
+#define SAVAGE_HW_TRIANGLE_LIST (0<<25)
+#define SAVAGE_HW_TRIANGLE_STRIP (1<<25)
+#define SAVAGE_HW_TRIANGLE_FAN (2<<25)
+#define SAVAGE_HW_QUAD (3<<25)
+
+#define __HW_TEXTURE_CHANGED 0x00002FE
+#define __HW_HAS_SCISSORS_CHANGED 0x00001800
+#define __HW_ALL_CHANGED 0x1FFFFFF
+/*Frank 2001/11/14 Wait commands*/
+#define WAIT_3D_IDLE 0xC0010000
+#define WAIT_3D_2D_IDLE 0xC0030000
+
+#define SET_REGISTER(index, count) \
+ ((CMD_SetRegister << 27) | (0x6000000) | ((count) << 16) | (index))
+
+/*frank 2001/11/20 */
+#define MAXLOOP 0xFFFFFF
+/*#define MAXFIFO 0x7F00*/
+#define MAXFIFO 0x1FF00
+
+/* get eventtag from shadow status */
+/* here we use eventTag1 because eventTag0 is used by HWXvMC*/
+#define GET_EVENTTAG \
+ (((*(volatile GLuint *)(imesa->MMIO_BASE+0x48c04)) & 0xffff0000L)>>16)
+
+#define SHADOW_WAIT(imesa ) do \
+{ \
+ int loop=0; \
+ imesa->shadowCounter = (imesa->shadowCounter + 1) & 0xffff;\
+ if(imesa->shadowCounter == 0)\
+ imesa->shadowCounter = MAX_SHADOWCOUNTER;\
+ *(volatile GLuint *)imesa->BCIBase = imesa->shadowCounter | 0x98400000L;\
+ while(\
+ (GET_EVENTTAG) != imesa->shadowCounter &&\
+ (loop++ < MAXLOOP));\
+}while(0);
+
+#define SHADOW_WAIT_IDLE(imesa ) do \
+{ \
+ int loop=0; \
+ imesa->shadowCounter = (imesa->shadowCounter + 1) & 0xffff;\
+ if(imesa->shadowCounter == 0)\
+ imesa->shadowCounter = MAX_SHADOWCOUNTER;\
+/* *(volatile GLuint *)imesa->BCIBase = WAIT_3D_IDLE;\*/\
+ *(volatile GLuint *)imesa->BCIBase = imesa->shadowCounter | 0x98400000L;\
+ while ( \
+ (GET_EVENTTAG) != imesa->shadowCounter && \
+ (loop++ < MAXLOOP)); \
+}while(0);
+
+#if 0
+#define ALT_STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c60))
+
+#define PAGE_PENDING(result) do{\
+result=((ALT_STATUS_WORD0 & 0x08000000)?GL_TRUE:GL_FALSE);\
+}while(0)
+
+#define WAIT_FOR_FIFO(count) do{\
+int loop = 0; \
+int slots = MAXFIFO-count; \
+while(((ALT_STATUS_WORD0 &0x001fffff)>slots)&&(loop++<MAXLOOP)); \
+}while(0)
+
+
+#define WAIT_IDLE_EMPTY do{\
+int loop = 0; \
+ if (/*imesa->shadowStatus*/0)\
+ {\
+ SHADOW_WAIT_IDLE(imesa);\
+ }\
+ else\
+ { \
+ while(((ALT_STATUS_WORD0 &0x00ffffff)!=0x00E00000L)&&(loop++<MAXLOOP));\
+ }\
+}while(0)
+
+#define WAIT_IDLE do{\
+int loop = 0; \
+if (imesa->shadowStatus)\
+ while((((*imesa->shadowPointer) & 0x0E000000L)!=0x0E000000L)&&(loop++<MAXLOOP));\
+else\
+while(((ALT_STATUS_WORD0 &0x00E00000)!=0x00E00000L)&&(loop++<MAXLOOP)); \
+}while(0)
+#endif /* 0 */
+
+#define SAVAGE_DRAW_PRIMITIVE(count, typeandvertexSkip, isCont) \
+ ( ((count)<<16) | (typeandvertexSkip) | (isCont | (1<<31)));
+
+static __inline volatile GLuint * SAVAGE_GET_BCI_POINTER(savageContextPtr imesa, GLuint count)
+{
+ WAIT_FOR_FIFO(count);
+ return (volatile GLuint *)(imesa->BCIBase);
+}
+
+/*use this set bci cmd now!*/
+#define WRITE_CMD(buf,cmd,type) do {\
+ *((type*)buf)=cmd;\
+ buf++;\
+ }while(0)
+#endif
+
+
+
+
+
+
diff --git a/src/mesa/drivers/dri/savage/savage_init.h b/src/mesa/drivers/dri/savage/savage_init.h
new file mode 100644
index 0000000000..c55c62df9c
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savage_init.h
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+
+#ifndef _SAVAGE_INIT_H_
+#define _SAVAGE_INIT_H_
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <sys/time.h>
+#include "dri_util.h"
+#include "mtypes.h"
+
+typedef struct {
+ drmHandle handle;
+ drmSize size;
+ char *map;
+} savageRegion, *savageRegionPtr;
+
+typedef struct {
+ savageRegion front;
+ savageRegion back;
+ savageRegion depth;
+ savageRegion aperture;
+
+ int chipset;
+ int width;
+ int height;
+ int mem;
+
+ int cpp; /* for front and back buffers */
+ int zpp;
+#if 0
+ int bitsPerPixel;
+#endif
+ unsigned int frontFormat;
+ unsigned int frontOffset;
+ unsigned int frontPitch;
+ unsigned int frontBitmapDesc;
+
+ unsigned int backOffset;
+ unsigned int backBitmapDesc;
+ unsigned int depthOffset;
+ unsigned int depthBitmapDesc;
+
+ unsigned int backPitch;
+ unsigned int backPitchBits;
+
+ unsigned int textureOffset[SAVAGE_NR_TEX_HEAPS];
+ unsigned int textureSize[SAVAGE_NR_TEX_HEAPS];
+ unsigned int logTextureGranularity[SAVAGE_NR_TEX_HEAPS];
+ drmAddress texVirtual[SAVAGE_NR_TEX_HEAPS];
+
+ __DRIscreenPrivate *driScrnPriv;
+ drmBufMapPtr bufs;
+ int use_copy_buf;
+ unsigned int sarea_priv_offset;
+} savageScreenPrivate;
+
+
+#include "savagecontext.h"
+
+extern void savageGetLock( savageContextPtr imesa, GLuint flags );
+extern void savageEmitHwStateLocked( savageContextPtr imesa );
+extern void savageEmitScissorValues( savageContextPtr imesa, int box_nr, int emit );
+extern void savageEmitDrawingRectangle( savageContextPtr imesa );
+extern void savageXMesaSetBackClipRects( savageContextPtr imesa );
+extern void savageXMesaSetFrontClipRects( savageContextPtr imesa );
+
+
+#define GET_DISPATCH_AGE( imesa ) imesa->sarea->last_dispatch
+#define GET_ENQUEUE_AGE( imesa ) imesa->sarea->last_enqueue
+
+
+/* Lock the hardware and validate our state.
+ */
+#define LOCK_HARDWARE( imesa ) \
+ do { \
+ char __ret=0; \
+ DRM_CAS(imesa->driHwLock, imesa->hHWContext, \
+ (DRM_LOCK_HELD|imesa->hHWContext), __ret); \
+ if (__ret) \
+ savageGetLock( imesa, 0 ); \
+ } while (0)
+
+
+
+/* Unlock the hardware using the global current context
+ */
+#define UNLOCK_HARDWARE(imesa) \
+ DRM_UNLOCK(imesa->driFd, imesa->driHwLock, imesa->hHWContext);
+
+
+/* This is the wrong way to do it, I'm sure. Otherwise the drm
+ * bitches that I've already got the heavyweight lock. At worst,
+ * this is 3 ioctls. The best solution probably only gets me down
+ * to 2 ioctls in the worst case.
+ */
+#define LOCK_HARDWARE_QUIESCENT( imesa ) do { \
+ LOCK_HARDWARE( imesa ); \
+ savageRegetLockQuiescent( imesa ); \
+} while(0)
+
+/* The following definitions are copied from savage_regs.h in the XFree86
+ * driver. They are unlikely to change. If they do we need to keep them in
+ * sync. */
+
+#define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
+
+#define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) \
+ || (chip==S3_PROSAVAGE) \
+ || (chip==S3_TWISTER) \
+ || (chip==S3_PROSAVAGEDDR))
+
+#define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
+
+#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
+
+#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) \
+ ||(chip==S3_PROSAVAGEDDR))
+
+/* Chip tags. These are used to group the adapters into
+ * related families.
+ */
+
+enum S3CHIPTAGS {
+ S3_UNKNOWN = 0,
+ S3_SAVAGE3D,
+ S3_SAVAGE_MX,
+ S3_SAVAGE4,
+ S3_PROSAVAGE,
+ S3_TWISTER,
+ S3_PROSAVAGEDDR,
+ S3_SUPERSAVAGE,
+ S3_SAVAGE2000,
+ S3_LAST
+};
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/savage/savage_xmesa.c b/src/mesa/drivers/dri/savage/savage_xmesa.c
new file mode 100644
index 0000000000..bc15e0bd30
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savage_xmesa.c
@@ -0,0 +1,800 @@
+/*
+ * 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.
+ */
+
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <X11/Xlibint.h>
+#include <stdio.h>
+
+#include "savagecontext.h"
+#include "context.h"
+#include "matrix.h"
+
+#include "simple_list.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "array_cache/acache.h"
+
+#include "tnl/t_pipeline.h"
+
+#include "drivers/common/driverfuncs.h"
+
+#include "savagedd.h"
+#include "savagestate.h"
+#include "savagetex.h"
+#include "savagespan.h"
+#include "savagetris.h"
+#include "savagevb.h"
+#include "savageioctl.h"
+#include "savage_bci.h"
+
+#include "savage_dri.h"
+
+#include "savagedma.h"
+
+#ifndef SAVAGE_DEBUG
+int SAVAGE_DEBUG = (0
+/* | DEBUG_ALWAYS_SYNC */
+/* | DEBUG_VERBOSE_RING */
+/* | DEBUG_VERBOSE_OUTREG */
+/* | DEBUG_VERBOSE_MSG */
+/* | DEBUG_NO_OUTRING */
+/* | DEBUG_NO_OUTREG */
+/* | DEBUG_VERBOSE_API */
+/* | DEBUG_VERBOSE_2D */
+/* | DEBUG_VERBOSE_DRI */
+/* | DEBUG_VALIDATE_RING */
+/* | DEBUG_VERBOSE_IOCTL */
+ );
+#endif
+
+
+/*For time caculating test*/
+#if defined(DEBUG_TIME) && DEBUG_TIME
+struct timeval tv_s,tv_f;
+unsigned long time_sum=0;
+struct timeval tv_s1,tv_f1;
+#endif
+
+/* this is first function called in dirver*/
+
+static GLboolean
+savageInitDriver(__DRIscreenPrivate *sPriv)
+{
+ savageScreenPrivate *savageScreen;
+ SAVAGEDRIPtr gDRIPriv = (SAVAGEDRIPtr)sPriv->pDevPriv;
+
+
+ /* Check the DRI version */
+ {
+ int major, minor, patch;
+ if (XF86DRIQueryVersion(sPriv->display, &major, &minor, &patch)) {
+ if (major != 4 || minor < 0) {
+ __driUtilMessage("savage DRI driver expected DRI version 4.0.x but got version %d.%d.%d", major, minor, patch);
+ return GL_FALSE;
+ }
+ }
+ }
+
+ /* Check that the DDX driver version is compatible */
+ if (sPriv->ddxMajor != 1 ||
+ sPriv->ddxMinor < 0) {
+ __driUtilMessage("savage DRI driver expected DDX driver version 1.0.x but got version %d.%d.%d", sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch);
+ return GL_FALSE;
+ }
+
+ /* Check that the DRM driver version is compatible */
+ if (sPriv->drmMajor != 1 ||
+ sPriv->drmMinor < 0) {
+ __driUtilMessage("savage DRI driver expected DRM driver version 1.1.x but got version %d.%d.%d", sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch);
+ return GL_FALSE;
+ }
+
+ /* Allocate the private area */
+ savageScreen = (savageScreenPrivate *)Xmalloc(sizeof(savageScreenPrivate));
+ if (!savageScreen)
+ return GL_FALSE;
+
+ savageScreen->driScrnPriv = sPriv;
+ sPriv->private = (void *)savageScreen;
+
+ savageScreen->chipset=gDRIPriv->chipset;
+ savageScreen->width=gDRIPriv->width;
+ savageScreen->height=gDRIPriv->height;
+ savageScreen->mem=gDRIPriv->mem;
+ savageScreen->cpp=gDRIPriv->cpp;
+ savageScreen->zpp=gDRIPriv->zpp;
+ savageScreen->frontPitch=gDRIPriv->frontPitch;
+ savageScreen->frontOffset=gDRIPriv->frontOffset;
+ savageScreen->frontBitmapDesc = gDRIPriv->frontBitmapDesc;
+
+ if (gDRIPriv->cpp == 4)
+ savageScreen->frontFormat = DV_PF_8888;
+ else
+ savageScreen->frontFormat = DV_PF_565;
+
+ savageScreen->backOffset = gDRIPriv->backOffset;
+ savageScreen->backBitmapDesc = gDRIPriv->backBitmapDesc;
+ savageScreen->depthOffset=gDRIPriv->depthOffset;
+ savageScreen->depthBitmapDesc = gDRIPriv->depthBitmapDesc;
+#if 0
+ savageScreen->backPitch = gDRIPriv->auxPitch;
+ savageScreen->backPitchBits = gDRIPriv->auxPitchBits;
+#endif
+ savageScreen->textureOffset[SAVAGE_CARD_HEAP] =
+ gDRIPriv->textureOffset;
+ savageScreen->textureSize[SAVAGE_CARD_HEAP] =
+ gDRIPriv->textureSize;
+ savageScreen->logTextureGranularity[SAVAGE_CARD_HEAP] =
+ gDRIPriv->logTextureGranularity;
+
+ savageScreen->textureOffset[SAVAGE_AGP_HEAP] =
+ gDRIPriv->agpTextures.handle;
+ savageScreen->textureSize[SAVAGE_AGP_HEAP] =
+ gDRIPriv->agpTextures.size;
+ savageScreen->logTextureGranularity[SAVAGE_AGP_HEAP] =
+ gDRIPriv->logAgpTextureGranularity;
+
+ savageScreen->back.handle = gDRIPriv->backbuffer;
+ savageScreen->back.size = gDRIPriv->backbufferSize;
+ savageScreen->back.map =
+ (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->backOffset);
+
+ savageScreen->depth.handle = gDRIPriv->depthbuffer;
+ savageScreen->depth.size = gDRIPriv->depthbufferSize;
+
+ savageScreen->depth.map =
+ (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->depthOffset);
+
+ savageScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
+
+ savageScreen->texVirtual[SAVAGE_CARD_HEAP] =
+ (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->textureOffset);
+#if 0
+ savageDDFastPathInit();
+ savageDDTrifuncInit();
+ savageDDSetupInit();
+#endif
+ return GL_TRUE;
+}
+
+/* Accessed by dlsym from dri_mesa_init.c
+ */
+static void
+savageDestroyScreen(__DRIscreenPrivate *sPriv)
+{
+ savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
+
+
+ Xfree(savageScreen);
+ sPriv->private = NULL;
+}
+
+#if 0
+GLvisual *XMesaCreateVisual(Display *dpy,
+ __DRIscreenPrivate *driScrnPriv,
+ const XVisualInfo *visinfo,
+ const __GLXvisualConfig *config)
+{
+ /* Drivers may change the args to _mesa_create_visual() in order to
+ * setup special visuals.
+ */
+ return _mesa_create_visual( config->rgba,
+ config->doubleBuffer,
+ config->stereo,
+ _mesa_bitcount(visinfo->red_mask),
+ _mesa_bitcount(visinfo->green_mask),
+ _mesa_bitcount(visinfo->blue_mask),
+ config->alphaSize,
+ 0, /* index bits */
+ config->depthSize,
+ config->stencilSize,
+ config->accumRedSize,
+ config->accumGreenSize,
+ config->accumBlueSize,
+ config->accumAlphaSize,
+ 0 /* num samples */ );
+}
+#endif
+
+
+static GLboolean
+savageCreateContext( const __GLcontextModes *mesaVis,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate )
+{
+ GLcontext *ctx, *shareCtx;
+ savageContextPtr imesa;
+ __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+ struct dd_function_table functions;
+ SAVAGEDRIPtr gDRIPriv = (SAVAGEDRIPtr)sPriv->pDevPriv;
+ savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
+ drm_savage_sarea_t *saPriv=(drm_savage_sarea_t *)(((char*)sPriv->pSAREA)+
+ savageScreen->sarea_priv_offset);
+ int i;
+ imesa = (savageContextPtr)Xcalloc(sizeof(savageContext), 1);
+ if (!imesa) {
+ return GL_FALSE;
+ }
+
+ /* Init default driver functions then plug in savage-specific texture
+ * functions that are needed as early as during context creation. */
+ _mesa_init_driver_functions( &functions );
+ savageDDInitTextureFuncs( &functions );
+
+ /* Allocate the Mesa context */
+ if (sharedContextPrivate)
+ shareCtx = ((savageContextPtr) sharedContextPrivate)->glCtx;
+ else
+ shareCtx = NULL;
+ ctx = _mesa_create_context(mesaVis, shareCtx, &functions, imesa);
+ if (!ctx) {
+ Xfree(imesa);
+ return GL_FALSE;
+ }
+ driContextPriv->driverPrivate = imesa;
+
+ /* BEGIN;*/
+ /* Set the maximum texture size small enough that we can guarentee
+ * that both texture units can bind a maximal texture and have them
+ * in memory at once.
+ */
+ if (savageScreen->textureSize[SAVAGE_CARD_HEAP] < 2*1024*1024) {
+ ctx->Const.MaxTextureLevels = 9;
+ } else if (savageScreen->textureSize[SAVAGE_CARD_HEAP] < 8*1024*1024) {
+ ctx->Const.MaxTextureLevels = 10;
+ } else {
+ ctx->Const.MaxTextureLevels = 11;
+ }
+ if (savageScreen->chipset >= S3_SAVAGE4)
+ ctx->Const.MaxTextureUnits = 2;
+ else
+ ctx->Const.MaxTextureUnits = 1;
+
+#if 0
+ ctx->Const.MinLineWidth = 1.0;
+ ctx->Const.MinLineWidthAA = 1.0;
+ ctx->Const.MaxLineWidth = 3.0;
+ ctx->Const.MaxLineWidthAA = 3.0;
+ ctx->Const.LineWidthGranularity = 1.0;
+#endif
+
+ /* Dri stuff
+ */
+ imesa->hHWContext = driContextPriv->hHWContext;
+ imesa->driFd = sPriv->fd;
+ imesa->driHwLock = &sPriv->pSAREA->lock;
+
+ imesa->savageScreen = savageScreen;
+ imesa->driScreen = sPriv;
+ imesa->sarea = saPriv;
+ imesa->glBuffer = NULL;
+
+ /* DMA buffer */
+
+ /*The shadow pointer*/
+ imesa->shadowPointer =
+ (volatile GLuint *)((((GLuint)(&saPriv->shadow_status)) + 31) & 0xffffffe0L) ;
+ /* here we use eventTag1 because eventTag0 is used by HWXvMC*/
+ imesa->eventTag1 = (volatile GLuint *)(imesa->shadowPointer + 6);
+ /* imesa->eventTag1=(volatile GLuint *)(imesa->MMIO_BASE+0x48c04);*/
+ imesa->shadowCounter = MAX_SHADOWCOUNTER;
+ imesa->shadowStatus = GL_TRUE;/*Will judge by 2d message */
+
+ if (drmMap(sPriv->fd,
+ gDRIPriv->registers.handle,
+ gDRIPriv->registers.size,
+ (drmAddress *)&(gDRIPriv->registers.map)) != 0)
+ {
+ Xfree(savageScreen);
+ sPriv->private = NULL;
+ return GL_FALSE;
+ }
+
+ if (drmMap(sPriv->fd,
+ gDRIPriv->agpTextures.handle,
+ gDRIPriv->agpTextures.size,
+ (drmAddress *)&(gDRIPriv->agpTextures.map)) != 0)
+ {
+ Xfree(savageScreen);
+ sPriv->private = NULL;
+ return GL_FALSE;
+ }
+
+/* agp texture*/
+ savageScreen->texVirtual[SAVAGE_AGP_HEAP] =
+ (drmAddress)(gDRIPriv->agpTextures.map);
+
+
+
+ gDRIPriv->BCIcmdBuf.map = (drmAddress *)
+ ((unsigned int)gDRIPriv->registers.map+0x00010000);
+
+ imesa->MMIO_BASE = (GLuint)gDRIPriv->registers.map;
+ imesa->BCIBase= (GLuint)gDRIPriv->BCIcmdBuf.map;
+
+ savageScreen->aperture.handle = gDRIPriv->aperture.handle;
+ savageScreen->aperture.size = gDRIPriv->aperture.size;
+ if (drmMap(sPriv->fd,
+ savageScreen->aperture.handle,
+ savageScreen->aperture.size,
+ (drmAddress *)&savageScreen->aperture.map) != 0)
+ {
+ Xfree(savageScreen);
+ sPriv->private = NULL;
+ return GL_FALSE;
+ }
+
+
+
+
+
+ for(i=0;i<5;i++)
+ {
+ imesa->apertureBase[i] = ((GLuint)savageScreen->aperture.map +
+ 0x01000000 * i );
+
+
+ }
+
+ {
+ volatile unsigned int * tmp;
+
+ tmp=(volatile unsigned int *)(imesa->MMIO_BASE + 0x850C);
+
+
+ tmp=(volatile unsigned int *)(imesa->MMIO_BASE + 0x48C40);
+
+
+ tmp=(volatile unsigned int *)(imesa->MMIO_BASE + 0x48C44);
+
+
+ tmp=(volatile unsigned int *)(imesa->MMIO_BASE + 0x48C48);
+
+
+
+ }
+
+ imesa->aperturePitch = gDRIPriv->aperturePitch;
+
+
+ /* change texHeap initialize to support two kind of texture heap*/
+ /* here is some parts of initialization, others in InitDriver() */
+
+ imesa->lastTexHeap = savageScreen->texVirtual[SAVAGE_AGP_HEAP] ? 2 : 1;
+
+ /*allocate texHeap for multi-tex*/
+ {
+ int i;
+
+ for(i=0;i<SAVAGE_NR_TEX_HEAPS;i++)
+ {
+ imesa->texHeap[i] = mmInit( 0, savageScreen->textureSize[i] );
+ make_empty_list(&imesa->TexObjList[i]);
+ }
+
+ make_empty_list(&imesa->SwappedOut);
+ }
+
+ imesa->hw_stencil = GL_FALSE;
+#if HW_STENCIL
+ imesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
+#endif
+ imesa->depth_scale = (imesa->savageScreen->zpp == 2) ?
+ (1.0F/0x10000):(1.0F/0x1000000);
+
+ /* Utah stuff
+ */
+ imesa->new_state = ~0;
+ imesa->RenderIndex = ~0;
+ imesa->dirty = ~0;
+ imesa->vertex_format = 0;
+ imesa->TextureMode = ctx->Texture.Unit[0].EnvMode;
+ imesa->CurrentTexObj[0] = 0;
+ imesa->CurrentTexObj[1] = 0;
+ imesa->texAge[SAVAGE_CARD_HEAP]=0;
+ imesa->texAge[SAVAGE_AGP_HEAP]=0;
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ _swrast_CreateContext( ctx );
+ _ac_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+
+ _swsetup_CreateContext( ctx );
+
+ /* Install the customized pipeline:
+ */
+#if 0
+ _tnl_destroy_pipeline( ctx );
+ _tnl_install_pipeline( ctx, savage_pipeline );
+#endif
+
+ /* Configure swrast to match hardware characteristics:
+ */
+ _swrast_allow_pixel_fog( ctx, GL_FALSE );
+ _swrast_allow_vertex_fog( ctx, GL_TRUE );
+
+ ctx->DriverCtx = (void *) imesa;
+ imesa->glCtx = ctx;
+ if (savageDMAInit(imesa) == GL_FALSE)
+ return GL_FALSE;
+
+ savageDDExtensionsInit( ctx );
+
+ savageDDInitStateFuncs( ctx );
+ savageDDInitSpanFuncs( ctx );
+ savageDDInitDriverFuncs( ctx );
+ savageDDInitIoctlFuncs( ctx );
+ savageInitTriFuncs( ctx );
+
+ savageInitVB( ctx );
+ savageDDInitState( imesa );
+
+ driContextPriv->driverPrivate = (void *) imesa;
+
+ return GL_TRUE;
+}
+
+static void
+savageDestroyContext(__DRIcontextPrivate *driContextPriv)
+{
+ savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
+
+ assert (imesa); /* should never be NULL */
+ if (imesa) {
+ savageTextureObjectPtr next_t, t;
+
+ /* update for multi-tex*/
+ {
+ int i;
+ for(i=0;i<SAVAGE_NR_TEX_HEAPS;i++)
+ foreach_s (t, next_t, &(imesa->TexObjList[i]))
+ savageDestroyTexObj(imesa, t);
+ }
+ foreach_s (t, next_t, &(imesa->SwappedOut))
+ savageDestroyTexObj(imesa, t);
+ /*free the dma buffer*/
+ savageDMAClose(imesa);
+ _swsetup_DestroyContext(imesa->glCtx );
+ _tnl_DestroyContext( imesa->glCtx );
+ _ac_DestroyContext( imesa->glCtx );
+ _swrast_DestroyContext( imesa->glCtx );
+
+ savageFreeVB( imesa->glCtx );
+
+ /* free the Mesa context */
+ imesa->glCtx->DriverCtx = NULL;
+ _mesa_destroy_context(imesa->glCtx);
+
+ /* no longer use vertex_dma_buf*/
+ Xfree(imesa);
+ }
+}
+
+static GLboolean
+savageCreateBuffer( __DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *mesaVis,
+ GLboolean isPixmap)
+{
+ if (isPixmap) {
+ return GL_FALSE; /* not implemented */
+ }
+ else {
+#if HW_STENCIL
+ GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
+#else
+ GLboolean swStencil = mesaVis->stencilBits > 0;
+#endif
+ driDrawPriv->driverPrivate = (void *)
+ _mesa_create_framebuffer(mesaVis,
+ GL_FALSE, /* software depth buffer? */
+ swStencil,
+ mesaVis->accumRedBits > 0,
+ mesaVis->alphaBits > 0 );
+
+ return (driDrawPriv->driverPrivate != NULL);
+ }
+}
+
+static void
+savageDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+ _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+}
+
+#if 0
+void XMesaSwapBuffers(__DRIdrawablePrivate *driDrawPriv)
+{
+ /* XXX should do swap according to the buffer, not the context! */
+ savageContextPtr imesa = savageCtx;
+
+ FLUSH_VB( imesa->glCtx, "swap buffers" );
+ savageSwapBuffers(imesa);
+}
+#endif
+
+void savageXMesaSetFrontClipRects( savageContextPtr imesa )
+{
+ __DRIdrawablePrivate *dPriv = imesa->driDrawable;
+
+ imesa->numClipRects = dPriv->numClipRects;
+ imesa->pClipRects = dPriv->pClipRects;
+ imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
+ imesa->drawX = dPriv->x;
+ imesa->drawY = dPriv->y;
+
+ savageEmitDrawingRectangle( imesa );
+}
+
+
+void savageXMesaSetBackClipRects( savageContextPtr imesa )
+{
+ __DRIdrawablePrivate *dPriv = imesa->driDrawable;
+
+ if (dPriv->numBackClipRects == 0)
+ {
+
+
+ imesa->numClipRects = dPriv->numClipRects;
+ imesa->pClipRects = dPriv->pClipRects;
+ imesa->drawX = dPriv->x;
+ imesa->drawY = dPriv->y;
+ } else {
+
+
+ imesa->numClipRects = dPriv->numBackClipRects;
+ imesa->pClipRects = dPriv->pBackClipRects;
+ imesa->drawX = dPriv->backX;
+ imesa->drawY = dPriv->backY;
+ }
+
+ savageEmitDrawingRectangle( imesa );
+ imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
+
+
+}
+
+
+static void savageXMesaWindowMoved( savageContextPtr imesa )
+{
+ if (0)
+ fprintf(stderr, "savageXMesaWindowMoved\n\n");
+
+ switch (imesa->glCtx->Color._DrawDestMask) {
+ case FRONT_LEFT_BIT:
+ savageXMesaSetFrontClipRects( imesa );
+ break;
+ case BACK_LEFT_BIT:
+ savageXMesaSetBackClipRects( imesa );
+ break;
+ default:
+ break;
+ }
+}
+
+
+static GLboolean
+savageUnbindContext(__DRIcontextPrivate *driContextPriv)
+{
+ savageContextPtr savage = (savageContextPtr) driContextPriv->driverPrivate;
+ if (savage)
+ savage->dirty = ~0;
+
+ return GL_TRUE;
+}
+
+static GLboolean
+savageOpenFullScreen(__DRIcontextPrivate *driContextPriv)
+{
+
+
+
+ if (driContextPriv) {
+ savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
+ imesa->IsFullScreen = GL_TRUE;
+ imesa->backup_frontOffset = imesa->savageScreen->frontOffset;
+ imesa->backup_backOffset = imesa->savageScreen->backOffset;
+ imesa->backup_frontBitmapDesc = imesa->savageScreen->frontBitmapDesc;
+ imesa->savageScreen->frontBitmapDesc = imesa->savageScreen->backBitmapDesc;
+ imesa->toggle = TARGET_BACK;
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean
+savageCloseFullScreen(__DRIcontextPrivate *driContextPriv)
+{
+
+ if (driContextPriv) {
+ savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
+ WAIT_IDLE_EMPTY;
+ imesa->IsFullScreen = GL_FALSE;
+ imesa->savageScreen->frontOffset = imesa->backup_frontOffset;
+ imesa->savageScreen->backOffset = imesa->backup_backOffset;
+ imesa->savageScreen->frontBitmapDesc = imesa->backup_frontBitmapDesc;
+ }
+ return GL_TRUE;
+}
+
+
+static GLboolean
+savageMakeCurrent(__DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv)
+{
+ if (driContextPriv) {
+ savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
+
+ imesa->driReadable = driReadPriv;
+ imesa->driDrawable = driDrawPriv;
+ imesa->mesa_drawable = driDrawPriv;
+ imesa->dirty = ~0;
+
+ _mesa_make_current2(imesa->glCtx,
+ (GLframebuffer *) driDrawPriv->driverPrivate,
+ (GLframebuffer *) driReadPriv->driverPrivate);
+
+ savageXMesaWindowMoved( imesa );
+
+ if (!imesa->glCtx->Viewport.Width)
+ _mesa_set_viewport(imesa->glCtx, 0, 0,
+ driDrawPriv->w, driDrawPriv->h);
+ }
+ else
+ {
+ _mesa_make_current(NULL, NULL);
+ }
+ return GL_TRUE;
+}
+
+
+void savageGetLock( savageContextPtr imesa, GLuint flags )
+{
+ __DRIdrawablePrivate *dPriv = imesa->driDrawable;
+ __DRIscreenPrivate *sPriv = imesa->driScreen;
+ drm_savage_sarea_t *sarea = imesa->sarea;
+ int me = imesa->hHWContext;
+ int stamp = dPriv->lastStamp;
+ int heap;
+
+
+
+ /* We know there has been contention.
+ */
+ drmGetLock(imesa->driFd, imesa->hHWContext, flags);
+
+
+ /* Note contention for throttling hint
+ */
+ imesa->any_contend = 1;
+
+ /* If the window moved, may need to set a new cliprect now.
+ *
+ * NOTE: This releases and regains the hw lock, so all state
+ * checking must be done *after* this call:
+ */
+ DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
+
+
+
+
+ /* If we lost context, need to dump all registers to hardware.
+ * Note that we don't care about 2d contexts, even if they perform
+ * accelerated commands, so the DRI locking in the X server is even
+ * more broken than usual.
+ */
+ if (sarea->ctxOwner != me) {
+ imesa->dirty |= (SAVAGE_UPLOAD_CTX |
+ SAVAGE_UPLOAD_CLIPRECTS |
+ SAVAGE_UPLOAD_TEX0 |
+ SAVAGE_UPLOAD_TEX1);
+ imesa->Registers.changed.uiRegistersChanged = __HW_ALL_CHANGED;
+ sarea->ctxOwner = me;
+ }
+
+ /* Shared texture managment - if another client has played with
+ * texture space, figure out which if any of our textures have been
+ * ejected, and update our global LRU.
+ */
+ /*frank just for compiling,texAge,texList,AGP*/
+
+ for(heap= 0 ;heap < imesa->lastTexHeap ; heap++)
+ {
+ if (sarea->texAge[heap] != imesa->texAge[heap]) {
+ int sz = 1 << (imesa->savageScreen->logTextureGranularity[heap]);
+ int idx, nr = 0;
+
+ /* Have to go right round from the back to ensure stuff ends up
+ * LRU in our local list...
+ */
+ for (idx = sarea->texList[heap][SAVAGE_NR_TEX_REGIONS].prev ;
+ idx != SAVAGE_NR_TEX_REGIONS && nr < SAVAGE_NR_TEX_REGIONS ;
+ idx = sarea->texList[heap][idx].prev, nr++)
+ {
+ if (sarea->texList[heap][idx].age > imesa->texAge[heap])
+ {
+ savageTexturesGone(imesa, heap ,idx * sz, sz,
+ sarea->texList[heap][idx].in_use);
+ }
+ }
+
+ if (nr == SAVAGE_NR_TEX_REGIONS)
+ {
+ savageTexturesGone(imesa, heap, 0,
+ imesa->savageScreen->textureSize[heap], 0);
+ savageResetGlobalLRU( imesa , heap );
+ }
+
+ imesa->dirty |= SAVAGE_UPLOAD_TEX0IMAGE;
+ imesa->dirty |= SAVAGE_UPLOAD_TEX1IMAGE;
+ imesa->texAge[heap] = sarea->texAge[heap];
+ }
+ } /* end of for loop */
+
+ if (dPriv->lastStamp != stamp)
+ savageXMesaWindowMoved( imesa );
+
+
+
+}
+
+
+
+static const struct __DriverAPIRec savageAPI = {
+ savageInitDriver,
+ savageDestroyScreen,
+ savageCreateContext,
+ savageDestroyContext,
+ savageCreateBuffer,
+ savageDestroyBuffer,
+ savageSwapBuffers,
+ savageMakeCurrent,
+ savageUnbindContext,
+ savageOpenFullScreen,
+ savageCloseFullScreen
+};
+
+
+
+/*
+ * This is the bootstrap function for the driver.
+ * The __driCreateScreen name is the symbol that libGL.so fetches.
+ * Return: pointer to a __DRIscreenPrivate.
+ */
+void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config)
+{
+ __DRIscreenPrivate *psp;
+ psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &savageAPI);
+ return (void *) psp;
+}
+
+
+#endif
diff --git a/src/mesa/drivers/dri/savage/savagecontext.h b/src/mesa/drivers/dri/savage/savagecontext.h
new file mode 100644
index 0000000000..6eaf58eca5
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagecontext.h
@@ -0,0 +1,299 @@
+/*
+ * 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.
+ */
+
+
+
+#ifndef SAVAGECONTEXT_INC
+#define SAVAGECONTEXT_INC
+
+typedef struct savage_context_t savageContext;
+typedef struct savage_context_t *savageContextPtr;
+typedef struct savage_texture_object_t *savageTextureObjectPtr;
+
+#include <X11/Xlibint.h>
+#include "dri_util.h"
+#include "mtypes.h"
+#include "xf86drm.h"
+#include "drm.h"
+#include "savage_drm.h"
+#include "savage_sarea.h"
+#include "savage_init.h"
+#include "mm.h"
+
+#include "savagetex.h"
+#include "savagedma.h"
+
+/* Reasons to fallback on all primitives.
+ */
+#define SAVAGE_FALLBACK_TEXTURE 0x1
+#define SAVAGE_FALLBACK_DRAW_BUFFER 0x2
+#define SAVAGE_FALLBACK_READ_BUFFER 0x4
+#define SAVAGE_FALLBACK_COLORMASK 0x8
+#define SAVAGE_FALLBACK_STIPPLE 0x10
+#define SAVAGE_FALLBACK_SPECULAR 0x20
+#define SAVAGE_FALLBACK_LOGICOP 0x40
+/*frank 2001/11/12 add the stencil fallbak*/
+#define SAVAGE_FALLBACK_STENCIL 0x80
+#define SAVAGE_FALLBACK_RENDERMODE 0x100
+#define SAVAGE_FALLBACK_BLEND_EQ 0x200
+
+
+#define HW_STENCIL 1
+#define HW_CULL 1
+
+/* for savagectx.new_state - manage GL->driver state changes
+ */
+#define SAVAGE_NEW_TEXTURE 0x1
+
+
+/*define the max numer of vertex in vertex buf*/
+#define SAVAGE_MAX_VERTEXS 0x10000
+
+/* Use the templated vertex formats:
+ */
+#define TAG(x) savage##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+typedef void (*savage_tri_func)( savageContextPtr, savageVertex *,
+ savageVertex *, savageVertex * );
+typedef void (*savage_line_func)( savageContextPtr,
+ savageVertex *, savageVertex * );
+typedef void (*savage_point_func)( savageContextPtr, savageVertex * );
+
+
+/**************************************************************
+ **************** enums for chip IDs ************************
+ **************************************************************/
+
+#define CHIP_S3GX3MS1NB 0x8A25
+#define CHIP_S3GX3MS1NBK 0x8A26
+#define CHIP_S3TWISTER 0x8D01
+#define CHIP_S3TWISTERK 0x8D02
+#define CHIP_S3TWISTER_P4M 0x8D04
+#define CHIP_S3PARAMOUNT128 0x8C22 /*SuperSavage 128/MX*/
+#define CHIP_S3TRISTAR128SDR 0x8C2A /*SuperSavage 128/IX*/
+#define CHIP_S3TRISTAR64SDRM7 0x8C2C /*SuperSavage/IX M7 Package*/
+#define CHIP_S3TRISTAR64SDR 0x8C2E /*SuperSavage/IX*/
+#define CHIP_S3TRISTAR64CDDR 0x8C2F /*SuperSavage/IXC DDR*/
+
+#define IS_SAVAGE(imesa) (imesa->savageScreen->deviceID == CHIP_S3GX3MS1NB || \
+ imesa->savageScreen->deviceID == CHIP_S3GX3MS1NBK || \
+ imesa->savageScreen->deviceID == CHIP_S3TWISTER || \
+ imesa->savageScreen->deviceID == CHIP_S3TWISTERK || \
+ imesa->savageScreen->deviceID == CHIP_S3TWISTER_P4M || \
+ imesa->savageScreen->deviceID == CHIP_S3PARAMOUNT128 || \
+ imesa->savageScreen->deviceID == CHIP_S3TRISTAR128SDR || \
+ imesa->savageScreen->deviceID == CHIP_S3TRISTAR64SDRM7 || \
+ imesa->savageScreen->deviceID == CHIP_S3TRISTAR64SDR || \
+ imesa->savageScreen->deviceID == CHIP_S3TRISTAR64CDDR )
+
+
+
+
+struct savage_context_t {
+ GLint refcount;
+
+ GLcontext *glCtx;
+
+ int lastTexHeap;
+ savageTextureObjectPtr CurrentTexObj[2];
+
+ struct savage_texture_object_t TexObjList[SAVAGE_NR_TEX_HEAPS];
+ struct savage_texture_object_t SwappedOut;
+
+ GLuint c_texupload;
+ GLuint c_texusage;
+ GLuint tex_thrash;
+
+ GLuint TextureMode;
+
+
+ /* Hardware state
+ */
+
+ REGISTERS Registers;
+
+ /* Manage our own state */
+ GLuint new_state;
+ GLuint new_gl_state;
+
+ GLuint BCIBase;
+ GLuint MMIO_BASE;
+
+ /* DMA command buffer */
+ DMABuffer_t DMABuf;
+
+ /* aperture base */
+ GLuint apertureBase[5];
+ GLuint aperturePitch;
+ /* Manage hardware state */
+ GLuint dirty;
+ memHeap_t *texHeap[SAVAGE_NR_TEX_HEAPS];
+ GLuint bTexEn1;
+ /* One of the few bits of hardware state that can't be calculated
+ * completely on the fly:
+ */
+ GLuint LcsCullMode;
+
+ /* Rasterization state
+ */
+ GLuint SetupNewInputs;
+ GLuint SetupIndex;
+ GLuint RenderIndex;
+
+ GLuint hw_primitive;
+ GLenum raster_primitive;
+ GLenum render_primitive;
+
+ GLubyte *verts;
+ GLuint vertex_format;
+ GLuint vertex_size;
+ GLuint DrawPrimitiveCmd;
+ GLuint DrawPrimitiveMask;
+
+ /* Fallback rasterization functions
+ */
+ savage_point_func draw_point;
+ savage_line_func draw_line;
+ savage_tri_func draw_tri;
+
+ /* Funny mesa mirrors
+ */
+ GLuint MonoColor;
+ GLuint ClearColor;
+ GLfloat depth_scale;
+ GLfloat hw_viewport[16];
+ /* DRI stuff */
+ drmBufPtr vertex_dma_buffer;
+
+ GLframebuffer *glBuffer;
+
+ /* Two flags to keep track of fallbacks. */
+ GLuint Fallback;
+
+ GLuint needClip;
+
+ /* These refer to the current draw (front vs. back) buffer:
+ */
+ char *drawMap; /* draw buffer address in virtual mem */
+ char *readMap;
+ int drawX; /* origin of drawable in draw buffer */
+ int drawY;
+ GLuint numClipRects; /* cliprects for that buffer */
+ GLint currentClip;
+ XF86DRIClipRectPtr pClipRects;
+
+ /* use this bit to support single/double buffer */
+ GLuint IsDouble;
+ /* use this to indicate Fullscreen mode */
+ GLuint IsFullScreen;
+ GLuint backup_frontOffset;
+ GLuint backup_backOffset;
+ GLuint backup_frontBitmapDesc;
+ GLuint toggle;
+ GLuint backup_streamFIFO;
+ GLuint NotFirstFrame;
+
+ GLuint lastSwap;
+ GLuint secondLastSwap;
+ GLuint ctxAge;
+ GLuint dirtyAge;
+ GLuint any_contend; /* throttle me harder */
+
+ GLuint scissor;
+ drm_clip_rect_t draw_rect;
+ drm_clip_rect_t scissor_rect;
+ XF86DRIClipRectRec tmp_boxes[2][SAVAGE_NR_SAREA_CLIPRECTS];
+ /*Texture aging and DMA based aging*/
+ unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
+
+ drmContext hHWContext;
+ drmLock *driHwLock;
+ GLuint driFd;
+
+ __DRIdrawablePrivate *driDrawable;
+ __DRIdrawablePrivate *driReadable;
+
+ /**
+ * Drawable used by Mesa for software fallbacks for reading and
+ * writing. It is set by Mesa's \c SetBuffer callback, and will always be
+ * either \c mga_context_t::driDrawable or \c mga_context_t::driReadable.
+ */
+ __DRIdrawablePrivate *mesa_drawable;
+
+ __DRIscreenPrivate *driScreen;
+ savageScreenPrivate *savageScreen;
+ drm_savage_sarea_t *sarea;
+
+ GLboolean hw_stencil;
+
+ /*shadow pointer*/
+ volatile GLuint *shadowPointer;
+ volatile GLuint *eventTag1;
+ GLuint shadowCounter;
+ GLboolean shadowStatus;
+};
+
+#define SAVAGE_CONTEXT(ctx) ((savageContextPtr)(ctx->DriverCtx))
+
+/* To remove all debugging, make sure SAVAGE_DEBUG is defined as a
+ * preprocessor symbol, and equal to zero.
+ */
+#define SAVAGE_DEBUG 0
+#ifndef SAVAGE_DEBUG
+#warning "Debugging enabled - expect reduced performance"
+extern int SAVAGE_DEBUG;
+#endif
+
+#define DEBUG_VERBOSE_2D 0x1
+#define DEBUG_VERBOSE_RING 0x8
+#define DEBUG_VERBOSE_OUTREG 0x10
+#define DEBUG_ALWAYS_SYNC 0x40
+#define DEBUG_VERBOSE_MSG 0x80
+#define DEBUG_NO_OUTRING 0x100
+#define DEBUG_NO_OUTREG 0x200
+#define DEBUG_VERBOSE_API 0x400
+#define DEBUG_VALIDATE_RING 0x800
+#define DEBUG_VERBOSE_LRU 0x1000
+#define DEBUG_VERBOSE_DRI 0x2000
+#define DEBUG_VERBOSE_IOCTL 0x4000
+
+#define TARGET_FRONT 0x0
+#define TARGET_BACK 0x1
+#define TARGET_DEPTH 0x2
+
+#define SAVAGEDEBUG 0
+#define _SAVAGE_DEBUG
+/*frank remove the least debug information*/
+#ifdef _SAVAGE_DEBUG
+#define fprintf fprintf
+#else
+#define fprintf(...)
+#endif
+
+#define SUBPIXEL_X -0.5
+#define SUBPIXEL_Y -0.375
+
+#endif
diff --git a/src/mesa/drivers/dri/savage/savagedd.c b/src/mesa/drivers/dri/savage/savagedd.c
new file mode 100644
index 0000000000..96773e5a71
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagedd.c
@@ -0,0 +1,106 @@
+/*
+ * 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 "mtypes.h"
+
+#include <stdio.h>
+
+#include "mm.h"
+#include "savagedd.h"
+#include "savagestate.h"
+#include "savagespan.h"
+#include "savagetex.h"
+#include "savagetris.h"
+#include "savagevb.h"
+#include "savagecontext.h"
+#include "extensions.h"
+
+
+extern int xf86VTSema;
+
+
+/***************************************
+ * Mesa's Driver Functions
+ ***************************************/
+
+
+static const GLubyte *savageDDGetString( GLcontext *ctx, GLenum name )
+{
+ switch (name) {
+ case GL_VENDOR:
+ return (GLubyte *)"S3 Graphics Inc.";
+ case GL_RENDERER:
+ return (GLubyte *)"Mesa DRI SAVAGE Linux_1.1.18";
+ default:
+ return 0;
+ }
+}
+#if 0
+static GLint savageGetParameteri(const GLcontext *ctx, GLint param)
+{
+ switch (param) {
+ case DD_HAVE_HARDWARE_FOG:
+ return 1;
+ default:
+ return 0;
+ }
+}
+#endif
+
+
+static void savageBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+
+ /* Need to lock to make sure the driDrawable is uptodate. This
+ * information is used to resize Mesa's software buffers, so it has
+ * to be correct.
+ */
+ LOCK_HARDWARE(imesa);
+ *width = imesa->driDrawable->w;
+ *height = imesa->driDrawable->h;
+ UNLOCK_HARDWARE(imesa);
+}
+
+
+
+
+void savageDDExtensionsInit( GLcontext *ctx )
+{
+ _mesa_enable_extension( ctx, "GL_ARB_multitexture" );
+ _mesa_enable_extension( ctx, "GL_EXT_texture_lod_bias" );
+ _mesa_enable_extension( ctx, "GL_EXT_texture_env_add" );
+}
+
+
+
+
+void savageDDInitDriverFuncs( GLcontext *ctx )
+{
+ ctx->Driver.GetBufferSize = savageBufferSize;
+ ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+ ctx->Driver.GetString = savageDDGetString;
+}
diff --git a/src/mesa/drivers/dri/savage/savagedd.h b/src/mesa/drivers/dri/savage/savagedd.h
new file mode 100644
index 0000000000..8d058f3de1
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagedd.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+
+#ifndef SAVAGEDD_INC
+#define SAVAGEDD_INC
+
+#include "context.h"
+
+void savageDDExtensionsInit( GLcontext *ctx );
+void savageDDInitDriverFuncs( GLcontext *ctx );
+#endif
diff --git a/src/mesa/drivers/dri/savage/savagedma.c b/src/mesa/drivers/dri/savage/savagedma.c
new file mode 100644
index 0000000000..9b0bdc8b9f
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagedma.c
@@ -0,0 +1,298 @@
+/*
+ * 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 <X11/Xlibint.h>
+#include <stdio.h>
+#include "savageioctl.h"
+#include "savagedma.h"
+#include "savage_bci.h"
+#include <time.h>
+#include <unistd.h>
+
+/* Commit does not depend on whether we use real DMA or fake it via the BCI */
+void savageDMACommit (savageContextPtr imesa, void *endPtr) {
+ DMABufferPtr dmaBuff = &imesa->DMABuf;
+ GLuint end = (GLuint)endPtr;
+
+ /* make sure that enough space was allocated */
+ assert (end <= dmaBuff->allocEnd);
+
+ dmaBuff->allocEnd = dmaBuff->end = end;
+
+ /* TODO: check commands, either here or in flush */
+}
+
+#if SAVAGE_CMD_DMA
+/* flag =
+ 0 return -1 if no available page
+ 1 wait until a page be available */
+static GLuint getDMAPage (savageContextPtr imesa, int flag) {
+ DMABufferPtr dmaBuff = &imesa->DMABuf;
+ GLuint page;
+ GLuint eventTag1;
+
+ if (dmaBuff->kickFlag == GL_FALSE)
+ return dmaBuff->usingPage;
+
+ page = dmaBuff->usingPage + 1;
+
+ /* overflow */
+ if (page >= (dmaBuff->buf->size * dmaBuff->buf->type)/DMA_PAGE_SIZE)
+ page = 0;
+
+ eventTag1 = GET_EVENTTAG;
+ if ( eventTag1 == page) { /* is kicking off */
+ if (flag == 1)
+ while (GET_EVENTTAG == page); /* FIXME: add a max loop count? */
+ else
+ return -1;
+ }
+
+ /* ok, that's it */
+ dmaBuff->usingPage = page;
+ dmaBuff->start = dmaBuff->end = dmaBuff->allocEnd =
+ (dmaBuff->buf->linear + DMA_PAGE_SIZE * page);
+ dmaBuff->kickFlag = GL_FALSE;
+
+ return page;
+}
+
+/* Allocate space in a real DMA buffer */
+void *savageDMAAlloc (savageContextPtr imesa, GLuint size) {
+ DMABufferPtr dmaBuff = &imesa->DMABuf;
+
+ /* make sure that everything has been filled in and committed */
+ assert (dmaBuff->end == dmaBuff->allocEnd);
+
+ size *= sizeof (GLuint); /* size in bytes */
+ if (dmaBuff->kickFlag == GL_TRUE) {
+ if (size > DMA_PAGE_SIZE)
+ return NULL;
+ getDMAPage (imesa, 1);
+ } else if (dmaBuff->end + size >=
+ dmaBuff->buf->linear + DMA_PAGE_SIZE*(dmaBuff->usingPage+1)) {
+ /* need kick off */
+ savageDMAFlush (imesa);
+ getDMAPage (imesa, 1);
+ }
+ dmaBuff->allocEnd = dmaBuff->end + size;
+ return (void *)dmaBuff->end;
+}
+
+/* Flush DMA buffer via DMA */
+void savageDMAFlush (savageContextPtr imesa) {
+ volatile GLuint* BCIbase;
+ DMABufferPtr dmaBuff = &imesa->DMABuf;
+ GLuint phyAddress;
+ GLuint dmaCount, dmaCount1, remain;
+ int i;
+
+ /* make sure that everything has been filled in and committed */
+ assert (dmaBuff->allocEnd == dmaBuff->end);
+
+ if (dmaBuff->kickFlag == GL_TRUE) /* has been kicked off? */
+ return;
+ if (dmaBuff->start == dmaBuff->end) /* no command? */
+ return;
+
+ /* get bci base */
+ BCIbase = (volatile GLuint *)SAVAGE_GET_BCI_POINTER(imesa,4);
+
+ /* set the eventtag */
+ *BCIbase = (dmaBuff->usingPage & 0xffffL) | (CMD_UpdateShadowStat << 27)
+ | (1 << 22);
+ *BCIbase = 0x96010051; /* set register x51*/
+ /* set the DMA buffer address */
+ phyAddress = (dmaBuff->buf->phyaddress + dmaBuff->usingPage*DMA_PAGE_SIZE)
+ & MDT_SRCADD_ALIGMENT;
+ if (dmaBuff->buf->location == DRM_SAVAGE_MEM_LOCATION_AGP)
+ *BCIbase = (phyAddress) | MDT_SRC_AGP;
+ else
+ *BCIbase = (phyAddress) | MDT_SRC_PCI;
+
+ /* pad with noops to multiple of 32 bytes */
+ dmaCount = (GLuint)(dmaBuff->end - dmaBuff->start);
+ dmaCount1 = (dmaCount + 31UL) & ~31UL;
+ remain = (dmaCount1 - dmaCount) >> 2;
+ for (i = 0; i < remain; i++) {
+ *((GLuint *)dmaBuff->end) = 0x40000000L;
+ dmaBuff->end+=4;
+ }
+ dmaCount = (dmaCount1 >> 3) - 1;
+ dmaBuff->allocEnd = dmaBuff->end;
+
+ /* kick off */
+ *BCIbase = (0xA8000000L)|dmaCount;
+ dmaBuff->kickFlag = GL_TRUE;
+}
+
+/* Init real DMA */
+int savageDMAInit (savageContextPtr imesa)
+{
+ DMABufferPtr dmaBuff = &imesa->DMABuf;
+ drm_savage_alloc_cont_mem_t * req;
+ int i;
+ long ret;
+
+ req = (drm_savage_alloc_cont_mem_t *)
+ malloc (sizeof(drm_savage_alloc_cont_mem_t));
+ if (!req)
+ return GL_FALSE;
+
+ req->type = DRM_SAVAGE_MEM_PAGE;
+ req->linear = 0;
+
+ /* try agp first */
+ req->phyaddress = imesa->sarea->agp_offset;
+ if (req->phyaddress) {
+ if (drmMap (imesa->driFd,
+ req->phyaddress,
+ DRM_SAVAGE_DMA_AGP_SIZE,
+ (drmAddressPtr)&req->linear) < 0) {
+ fprintf (stderr, "AGP map error.\n");
+ goto dma;
+ }
+ if (0) fprintf (stderr,"Using AGP dma|\n");
+ req->location = DRM_SAVAGE_MEM_LOCATION_AGP;
+ req->size = DRM_SAVAGE_DMA_AGP_SIZE/DRM_SAVAGE_MEM_PAGE;
+ }
+
+ dma:
+ if (!req->linear) {
+ req->size = DMA_BUFFER_SIZE/DRM_SAVAGE_MEM_PAGE;
+ for (i = 0; i < DMA_TRY_COUNT; i++) {
+ if ((ret = savageAllocDMABuffer (imesa, req)) != 0)
+ break;
+ req->size = req->size/2;
+ }
+
+ if (ret <= 0) {
+ fprintf(stderr, "Can't alloc DMA memory(system and agp)\n");
+ return GL_FALSE;
+ }
+ req->location = DRM_SAVAGE_MEM_LOCATION_PCI;
+ }
+
+ dmaBuff->buf = req;
+
+ dmaBuff->start = dmaBuff->end = dmaBuff->allocEnd = req->linear;
+ dmaBuff->usingPage = 0;
+ dmaBuff->kickFlag = GL_FALSE;
+
+ return GL_TRUE;
+}
+
+/* Close real DMA */
+int savageDMAClose (savageContextPtr imesa)
+{
+ DMABufferPtr dmaBuff = &imesa->DMABuf;
+ drm_savage_alloc_cont_mem_t * req = dmaBuff->buf;
+
+ if(req->location == DRM_SAVAGE_MEM_LOCATION_PCI)
+ savageFreeDMABuffer (imesa, req);
+ else { /* AGP memory */
+ drmUnmap ((drmAddress)req->linear, req->size*req->type);
+ drmRmMap (imesa->driFd, req->phyaddress);
+ }
+ free (req);
+
+ return GL_TRUE;
+}
+#else
+/* Allocate space in faked DMA buffer */
+void *savageDMAAlloc (savageContextPtr imesa, GLuint size) {
+ DMABufferPtr dmaBuff = &imesa->DMABuf;
+
+ /* make sure that everything has been filled in and committed */
+ assert (dmaBuff->end == dmaBuff->allocEnd);
+
+ size *= sizeof (GLuint); /* size in bytes */
+ if (dmaBuff->end + size >= dmaBuff->buf->linear + DMA_PAGE_SIZE) {
+ /* need kick off */
+ savageDMAFlush (imesa);
+ }
+ dmaBuff->allocEnd = dmaBuff->end + size;
+ return (void *)dmaBuff->end;
+}
+
+/* Flush DMA buffer via BCI (faked DMA) */
+void savageDMAFlush(savageContextPtr imesa) {
+ volatile GLuint* BCIbase;
+ DMABufferPtr dmaBuff = &imesa->DMABuf;
+ GLuint *entry;
+
+ /* make sure that everything has been filled in and committed */
+ assert (dmaBuff->allocEnd == dmaBuff->end);
+
+ if (dmaBuff->start == dmaBuff->end) /* no command? */
+ return;
+
+ /* get bci base */
+ BCIbase = (volatile GLuint *)SAVAGE_GET_BCI_POINTER(
+ imesa, (dmaBuff->end - dmaBuff->start) / sizeof (GLuint));
+
+ for (entry = (GLuint *)dmaBuff->start;
+ entry < (GLuint *)dmaBuff->end; ++entry)
+ *BCIbase = *entry;
+
+ dmaBuff->end = dmaBuff->allocEnd = dmaBuff->start;
+}
+
+/* Init faked DMA */
+int savageDMAInit (savageContextPtr imesa) {
+ DMABufferPtr dmaBuff = &imesa->DMABuf;
+ drm_savage_alloc_cont_mem_t * req;
+
+ req = (drm_savage_alloc_cont_mem_t *)
+ malloc (sizeof(drm_savage_alloc_cont_mem_t));
+ if (!req)
+ return GL_FALSE;
+
+ req->linear = (GLuint)malloc (DMA_PAGE_SIZE);
+ if (!req->linear) {
+ free (req);
+ return GL_FALSE;
+ }
+
+ dmaBuff->buf = req;
+
+ dmaBuff->start = dmaBuff->end = dmaBuff->allocEnd = req->linear;
+ dmaBuff->usingPage = 0;
+ dmaBuff->kickFlag = GL_FALSE;
+
+ return GL_TRUE;
+}
+
+/* Close faked DMA */
+int savageDMAClose (savageContextPtr imesa) {
+ DMABufferPtr dmaBuff = &imesa->DMABuf;
+ drm_savage_alloc_cont_mem_t * req = dmaBuff->buf;
+
+ free ((void *)req->linear);
+ free (req);
+
+ return GL_TRUE;
+}
+
+#endif
diff --git a/src/mesa/drivers/dri/savage/savagedma.h b/src/mesa/drivers/dri/savage/savagedma.h
new file mode 100644
index 0000000000..2945685846
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagedma.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+
+#ifndef SAVAGEDMA
+#define SAVAGEDMA
+
+/* Whether use DMA to transfer the 3d commands and data */
+#define SAVAGE_CMD_DMA 0
+
+#define DMA_BUFFER_SIZE (4*1024*1024) /*4M*/
+#define MAX_DMA_BUFFER_SIZE (16*1024*1024)
+#define DMA_PAGE_SIZE (4*1024) /* savage4 , twister, prosavage,...*/
+#define DMA_TRY_COUNT 4
+
+#define MAX_SHADOWCOUNTER (MAX_DMA_BUFFER_SIZE / DMA_PAGE_SIZE)
+typedef struct DMABuffer{
+ drm_savage_alloc_cont_mem_t * buf;
+ GLuint start, end, allocEnd;
+ GLuint usingPage; /*current page */
+ unsigned int kickFlag; /* usingPage is kicked off ?*/
+} DMABuffer_t, * DMABufferPtr;
+
+void *savageDMAAlloc (savageContextPtr imesa, GLuint size);
+void savageDMACommit (savageContextPtr imesa, void *end);
+void savageDMAFlush (savageContextPtr imesa);
+int savageDMAInit (savageContextPtr imesa);
+int savageDMAClose (savageContextPtr);
+#endif
diff --git a/src/mesa/drivers/dri/savage/savageioctl.c b/src/mesa/drivers/dri/savage/savageioctl.c
new file mode 100644
index 0000000000..7f85ef920a
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savageioctl.c
@@ -0,0 +1,521 @@
+/*
+ * 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 <unistd.h>
+#include <sys/mman.h>
+
+#include "mtypes.h"
+#include "macros.h"
+#include "dd.h"
+#include "context.h"
+#include "swrast/swrast.h"
+
+#include "mm.h"
+#include "savagecontext.h"
+#include "savageioctl.h"
+#include "savage_bci.h"
+#include "savagedma.h"
+
+#include "drm.h"
+#include <sys/ioctl.h>
+#include <sys/timeb.h>
+
+extern GLuint bcicount;
+#define DEPTH_SCALE_16 ((1<<16)-1)
+#define DEPTH_SCALE_24 ((1<<24)-1)
+
+static void savage_BCI_clear(GLcontext *ctx, drm_savage_clear_t *pclear)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ int nbox = imesa->sarea->nbox;
+ drm_clip_rect_t *pbox = imesa->sarea->boxes;
+ int i;
+
+
+ if (nbox > SAVAGE_NR_SAREA_CLIPRECTS)
+ nbox = SAVAGE_NR_SAREA_CLIPRECTS;
+
+ for (i = 0 ; i < nbox ; i++, pbox++) {
+ unsigned int x = pbox->x1;
+ unsigned int y = pbox->y1;
+ unsigned int width = pbox->x2 - x+1;
+ unsigned int height = pbox->y2 - y+1;
+ unsigned int *bciptr;
+
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+ pbox->x2 > imesa->savageScreen->width ||
+ pbox->y2 > imesa->savageScreen->height)
+ continue;
+
+ if ( (pclear->flags & SAVAGE_FRONT) && imesa->IsFullScreen) {
+ bciptr = savageDMAAlloc (imesa, 8);
+ WRITE_CMD((bciptr) , 0x4BCC8C00,GLuint);
+ WRITE_CMD((bciptr) , imesa->savageScreen->frontOffset,GLuint);
+ WRITE_CMD((bciptr) , imesa->savageScreen->frontBitmapDesc,GLuint);
+ WRITE_CMD((bciptr) , pclear->clear_color,GLuint);
+ WRITE_CMD((bciptr) , (y <<16) | x,GLuint);
+ WRITE_CMD((bciptr) , (height << 16) | width,GLuint);
+ savageDMACommit (imesa, bciptr);
+ }
+ else if ( pclear->flags & (SAVAGE_BACK|SAVAGE_FRONT) ) {
+ bciptr = savageDMAAlloc (imesa, 8);
+ WRITE_CMD((bciptr) , 0x4BCC8C00,GLuint);
+ WRITE_CMD((bciptr) , imesa->savageScreen->backOffset,GLuint);
+ WRITE_CMD((bciptr) , imesa->savageScreen->backBitmapDesc,GLuint);
+ WRITE_CMD((bciptr) , pclear->clear_color,GLuint);
+ WRITE_CMD((bciptr) , (y <<16) | x,GLuint);
+ WRITE_CMD((bciptr) , (height << 16) | width,GLuint);
+ savageDMACommit (imesa, bciptr);
+ }
+
+ if ( pclear->flags & (SAVAGE_DEPTH |SAVAGE_STENCIL) ) {
+ GLuint writeMask = 0x0;
+#if HW_STENCIL
+ if(imesa->hw_stencil)
+ {
+ if(pclear->flags & SAVAGE_STENCIL)
+ {
+
+ writeMask |= 0xFF000000;
+ }
+ if(pclear->flags & SAVAGE_DEPTH)
+ {
+ writeMask |= 0x00FFFFFF;
+ }
+ }
+#endif
+ if(imesa->IsFullScreen && imesa->NotFirstFrame &&
+ imesa->savageScreen->chipset >= S3_SAVAGE4)
+ {
+ imesa->Registers.ZBufCtrl.s4.autoZEnable = GL_TRUE;
+ imesa->Registers.ZBufCtrl.s4.frameID = ~imesa->Registers.ZBufCtrl.s4.frameID;
+
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ else
+ {
+ if(imesa->IsFullScreen)
+ imesa->NotFirstFrame = GL_TRUE;
+
+#if HW_STENCIL
+ if(imesa->hw_stencil)
+ {
+ bciptr = savageDMAAlloc (imesa, 10);
+ if(writeMask != 0xFFFFFFFF)
+ {
+ WRITE_CMD((bciptr) , 0x960100D7,GLuint);
+ WRITE_CMD((bciptr) , writeMask,GLuint);
+ }
+ }
+ else
+#endif
+ {
+ bciptr = savageDMAAlloc (imesa, 6);
+ }
+
+ WRITE_CMD((bciptr) , 0x4BCC8C00,GLuint);
+ WRITE_CMD((bciptr) , imesa->savageScreen->depthOffset,GLuint);
+ WRITE_CMD((bciptr) , imesa->savageScreen->depthBitmapDesc,GLuint);
+ WRITE_CMD((bciptr) , pclear->clear_depth,GLuint);
+ WRITE_CMD((bciptr) , (y <<16) | x,GLuint);
+ WRITE_CMD((bciptr) , (height << 16) | width,GLuint);
+#if HW_STENCIL
+ if(imesa->hw_stencil)
+ {
+ if(writeMask != 0xFFFFFFFF)
+ {
+ WRITE_CMD((bciptr) , 0x960100D7,GLuint);
+ WRITE_CMD((bciptr) , 0xFFFFFFFF,GLuint);
+ }
+ }
+#endif
+ savageDMACommit (imesa, bciptr);
+ }
+ }
+ }
+ /* FK: Make sure that the clear stuff is emitted. Otherwise a
+ software fallback may get overwritten by a delayed clear. */
+ savageDMAFlush (imesa);
+}
+
+struct timeb a,b;
+
+static void savage_BCI_swap(savageContextPtr imesa)
+{
+ int nbox = imesa->sarea->nbox;
+ drm_clip_rect_t *pbox = imesa->sarea->boxes;
+ int i;
+ volatile unsigned int *bciptr;
+
+ if (nbox > SAVAGE_NR_SAREA_CLIPRECTS)
+ nbox = SAVAGE_NR_SAREA_CLIPRECTS;
+ savageDMAFlush (imesa);
+ WAIT_IDLE_EMPTY;
+
+ if(imesa->IsFullScreen)
+ { /* full screen*/
+ unsigned int tmp0;
+ tmp0 = imesa->savageScreen->frontOffset;
+ imesa->savageScreen->frontOffset = imesa->savageScreen->backOffset;
+ imesa->savageScreen->backOffset = tmp0;
+
+ if(imesa->toggle == TARGET_BACK)
+ imesa->toggle = TARGET_FRONT;
+ else
+ imesa->toggle = TARGET_BACK;
+
+ imesa->drawMap = (char *)imesa->apertureBase[imesa->toggle];
+ imesa->readMap = (char *)imesa->apertureBase[imesa->toggle];
+
+ imesa->Registers.DestCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
+ imesa->Registers.changed.ni.fDestCtrlChanged = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ bciptr = SAVAGE_GET_BCI_POINTER(imesa,3);
+ *(bciptr) = 0x960100B0;
+ *(bciptr) = (imesa->savageScreen->frontOffset);
+ *(bciptr) = 0xA0000000;
+ }
+
+ else
+ { /* Use bitblt copy from back to front buffer*/
+
+ for (i = 0 ; i < nbox; i++, pbox++)
+ {
+ unsigned int w = pbox->x2 - pbox->x1;
+ unsigned int h = pbox->y2 - pbox->y1;
+
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+ pbox->x2 > imesa->savageScreen->width ||
+ pbox->y2 > imesa->savageScreen->height)
+ continue;
+
+ bciptr = SAVAGE_GET_BCI_POINTER(imesa,6);
+
+ *(bciptr) = 0x4BCC00C0;
+
+ *(bciptr) = imesa->savageScreen->backOffset;
+ *(bciptr) = imesa->savageScreen->backBitmapDesc;
+ *(bciptr) = (pbox->y1 <<16) | pbox->x1; /*x0, y0*/
+ *(bciptr) = (pbox->y1 <<16) | pbox->x1;
+ *(bciptr) = (h << 16) | w;
+ }
+
+ }
+}
+
+
+static void savageDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint cx, GLint cy, GLint cw, GLint ch )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+ __DRIdrawablePrivate *dPriv = imesa->driDrawable;
+ const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
+ drm_savage_clear_t clear;
+ int i;
+
+ clear.flags = 0;
+ clear.clear_color = imesa->ClearColor;
+
+ if(imesa->savageScreen->zpp == 2)
+ clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE_16);
+ else
+ clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE_24);
+#if 0
+ FLUSH_BATCH( imesa );
+#endif
+ if ((mask & DD_FRONT_LEFT_BIT) && ((colorMask&0xffffffUL)==0xffffffUL) ){
+ clear.flags |= SAVAGE_FRONT;
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+
+ if ((mask & DD_BACK_LEFT_BIT) && ((colorMask&0xffffffUL)==0xffffffUL) ) {
+ clear.flags |= SAVAGE_BACK;
+ mask &= ~DD_BACK_LEFT_BIT;
+ }
+
+ if ((mask & DD_DEPTH_BIT) && ctx->Depth.Mask) {
+ clear.flags |= SAVAGE_DEPTH;
+ mask &= ~DD_DEPTH_BIT;
+ }
+
+ if((mask & DD_STENCIL_BIT) && imesa->hw_stencil)
+ {
+ clear.flags |= SAVAGE_STENCIL;
+ mask &= ~DD_STENCIL_BIT;
+ }
+
+ if (clear.flags) {
+ LOCK_HARDWARE( imesa );
+
+ /* flip top to bottom */
+ cy = dPriv->h-cy-ch;
+ cx += imesa->drawX;
+ cy += imesa->drawY;
+
+ for (i = 0 ; i < imesa->numClipRects ; ) {
+ int nr = MIN2(i + SAVAGE_NR_SAREA_CLIPRECTS, imesa->numClipRects);
+ XF86DRIClipRectRec *box = imesa->pClipRects;
+ drm_clip_rect_t *b = imesa->sarea->boxes;
+ int n = 0;
+
+ if (!all) {
+ for ( ; i < nr ; i++) {
+ GLint x = box[i].x1;
+ GLint y = box[i].y1;
+ GLint w = box[i].x2 - x;
+ GLint h = box[i].y2 - y;
+
+ if (x < cx) w -= cx - x, x = cx;
+ if (y < cy) h -= cy - y, y = cy;
+ if (x + w > cx + cw) w = cx + cw - x;
+ if (y + h > cy + ch) h = cy + ch - y;
+ if (w <= 0) continue;
+ if (h <= 0) continue;
+
+ b->x1 = x;
+ b->y1 = y;
+ b->x2 = x + w;
+ b->y2 = y + h;
+ b++;
+ n++;
+ }
+ } else {
+ for ( ; i < nr ; i++) {
+ *b++ = *(drm_clip_rect_t *)&box[i];
+ n++;
+ }
+ }
+
+ imesa->sarea->nbox = n;
+
+ savage_BCI_clear(ctx,&clear);
+ }
+
+ UNLOCK_HARDWARE( imesa );
+ imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS|SAVAGE_UPLOAD_CTX;
+ }
+
+ if (mask)
+ _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
+}
+
+
+
+
+/*
+ * Copy the back buffer to the front buffer.
+ */
+void savageSwapBuffers( __DRIdrawablePrivate *dPriv )
+{
+ savageContextPtr imesa;
+ XF86DRIClipRectPtr pbox;
+ int nbox;
+ int i;
+
+ GLboolean pending;
+
+ assert(dPriv);
+ assert(dPriv->driContextPriv);
+ assert(dPriv->driContextPriv->driverPrivate);
+
+ imesa = (savageContextPtr) dPriv->driContextPriv->driverPrivate;
+ if (imesa->IsDouble)
+ _mesa_notifySwapBuffers( imesa->glCtx );
+
+ LOCK_HARDWARE( imesa );
+ PAGE_PENDING(pending);
+
+ if(!pending)
+ {
+ pbox = dPriv->pClipRects;
+ nbox = dPriv->numClipRects;
+
+ for (i = 0 ; i < nbox ; )
+ {
+ int nr = MIN2(i + SAVAGE_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
+ XF86DRIClipRectRec *b = (XF86DRIClipRectRec *)imesa->sarea->boxes;
+
+ imesa->sarea->nbox = nr - i;
+
+ for ( ; i < nr ; i++)
+ *b++ = pbox[i];
+ savage_BCI_swap(imesa) ;
+ }
+ }
+ UNLOCK_HARDWARE( imesa );
+
+
+}
+
+/* This waits for *everybody* to finish rendering -- overkill.
+ */
+void savageDmaFinish( savageContextPtr imesa )
+{
+ savageDMAFlush(imesa);
+ WAIT_IDLE_EMPTY;
+}
+
+
+void savageRegetLockQuiescent( savageContextPtr imesa )
+{
+
+
+}
+
+void savageWaitAgeLocked( savageContextPtr imesa, int age )
+{
+}
+
+
+void savageWaitAge( savageContextPtr imesa, int age )
+{
+}
+
+
+
+void savageFlushVertices( savageContextPtr imesa )
+{
+
+}
+
+
+void savageFlushVerticesLocked( savageContextPtr imesa )
+{
+
+}
+
+
+int savage_check_copy(int fd)
+{
+ return 0;
+}
+
+static void savageDDFlush( GLcontext *ctx )
+{
+
+}
+
+static void savageDDFinish( GLcontext *ctx )
+{
+}
+
+#define ALT_STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c60))
+#define STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c00))
+#define MAXFIFO_S4 0x1FF00
+#define MAXFIFO_S3D 0x7F00
+
+static GLboolean savagePagePending_s4( savageContextPtr imesa ) {
+ return (ALT_STATUS_WORD0 & 0x08000000) ? GL_TRUE : GL_FALSE;
+}
+static GLboolean savagePagePending_s3d( savageContextPtr imesa ) {
+ return GL_FALSE;
+}
+static void savageWaitForFIFO_s4( savageContextPtr imesa, unsigned count ) {
+ int loop = 0;
+ int slots = MAXFIFO_S4-count;
+ while((ALT_STATUS_WORD0 & 0x001fffff) > slots && loop++ < MAXLOOP);
+}
+static void savageWaitForFIFO_s3d( savageContextPtr imesa, unsigned count ) {
+ int loop = 0;
+ int slots = MAXFIFO_S3D-count;
+ while((STATUS_WORD0 & 0x0001ffff) > slots && loop++ < MAXLOOP);
+}
+static void savageWaitIdleEmpty_s4( savageContextPtr imesa ) {
+ int loop = 0;
+ while((ALT_STATUS_WORD0 & 0x00ffffff) != 0x00E00000L && loop++ < MAXLOOP);
+}
+static void savageWaitIdleEmpty_s3d( savageContextPtr imesa ) {
+ int loop = 0;
+ while((STATUS_WORD0 & 0x000fffff) != 0x000E0000L && loop++ < MAXLOOP);
+}
+
+GLboolean (*savagePagePending)( savageContextPtr imesa ) = NULL;
+void (*savageWaitForFIFO)( savageContextPtr imesa, unsigned count ) = NULL;
+void (*savageWaitIdleEmpty)( savageContextPtr imesa ) = NULL;
+
+
+void savageDDInitIoctlFuncs( GLcontext *ctx )
+{
+ ctx->Driver.Clear = savageDDClear;
+ ctx->Driver.Flush = savageDDFlush;
+ ctx->Driver.Finish = savageDDFinish;
+ if (SAVAGE_CONTEXT( ctx )->savageScreen->chipset >= S3_SAVAGE4) {
+ savagePagePending = savagePagePending_s4;
+ savageWaitForFIFO = savageWaitForFIFO_s4;
+ savageWaitIdleEmpty = savageWaitIdleEmpty_s4;
+ } else {
+ savagePagePending = savagePagePending_s3d;
+ savageWaitForFIFO = savageWaitForFIFO_s3d;
+ savageWaitIdleEmpty = savageWaitIdleEmpty_s3d;
+ }
+}
+
+#if SAVAGE_CMD_DMA
+/* Alloc a continuous memory */
+/* return: 0 error when kernel alloc pages(can try a half memory size)
+ >0 sucess
+ <0 Other error*/
+int savageAllocDMABuffer(savageContextPtr imesa, drm_savage_alloc_cont_mem_t *req)
+{
+ int ret;
+ if (req ==NULL)
+ return 0;
+
+ if ((ret=ioctl(imesa->driFd, DRM_IOCTL_SAVAGE_ALLOC_CONTINUOUS_MEM, req)) <=0)
+ return ret;
+
+ return 1;
+
+}
+
+/* get the physics address*/
+GLuint savageGetPhyAddress(savageContextPtr imesa,void * pointer)
+{
+
+ drm_savage_get_physcis_address_t req;
+ int ret;
+
+ req.v_address = (GLuint )pointer;
+ ret = ioctl(imesa->driFd, DRM_IOCTL_SAVAGE_GET_PHYSICS_ADDRESS,&req);
+
+ return req.p_address;
+}
+
+/* free the buffer got by savageAllocDMABuffe*/
+int savageFreeDMABuffer(savageContextPtr imesa, drm_savage_alloc_cont_mem_t *req)
+{
+ GLuint ret;
+ if (req ==NULL)
+ return 0;
+
+ if ((ret=ioctl(imesa->driFd, DRM_IOCTL_SAVAGE_FREE_CONTINUOUS_MEM, req)) <=0)
+ return ret;
+ return 1;
+
+}
+#endif
diff --git a/src/mesa/drivers/dri/savage/savageioctl.h b/src/mesa/drivers/dri/savage/savageioctl.h
new file mode 100644
index 0000000000..94b02e3319
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savageioctl.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+
+#ifndef SAVAGE_IOCTL_H
+#define SAVAGE_IOCTL_H
+
+#include "savagecontext.h"
+#include "savagedma.h"
+
+void savageGetGeneralDmaBufferLocked( savageContextPtr mmesa );
+
+void savageFlushVertices( savageContextPtr mmesa );
+void savageFlushVerticesLocked( savageContextPtr mmesa );
+
+void savageFlushGeneralLocked( savageContextPtr imesa );
+void savageWaitAgeLocked( savageContextPtr imesa, int age );
+void savageWaitAge( savageContextPtr imesa, int age );
+
+void savageDmaFinish( savageContextPtr imesa );
+
+void savageRegetLockQuiescent( savageContextPtr imesa );
+
+void savageDDInitIoctlFuncs( GLcontext *ctx );
+
+void savageSwapBuffers( __DRIdrawablePrivate *dPriv );
+
+int savage_check_copy(int fd);
+
+extern GLboolean (*savagePagePending)( savageContextPtr imesa );
+extern void (*savageWaitForFIFO)( savageContextPtr imesa, unsigned count );
+extern void (*savageWaitIdleEmpty)( savageContextPtr imesa );
+
+#define PAGE_PENDING(result) do { \
+ result = savagePagePending(imesa); \
+} while (0)
+#define WAIT_FOR_FIFO(count) do { \
+ savageWaitForFIFO(imesa, count); \
+} while (0)
+#define WAIT_IDLE_EMPTY do { \
+ savageWaitIdleEmpty(imesa); \
+} while (0)
+
+#if SAVAGE_CMD_DMA
+int savageAllocDMABuffer(savageContextPtr imesa, drm_savage_alloc_cont_mem_t *req);
+GLuint savageGetPhyAddress(savageContextPtr imesa,void * pointer);
+int savageFreeDMABuffer(savageContextPtr, drm_savage_alloc_cont_mem_t*);
+#endif
+
+#define FLUSH_BATCH(imesa) savageDMAFlush(imesa)
+#endif
diff --git a/src/mesa/drivers/dri/savage/savagespan.c b/src/mesa/drivers/dri/savage/savagespan.c
new file mode 100644
index 0000000000..aa13cfcb1d
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagespan.c
@@ -0,0 +1,313 @@
+/*
+ * 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 "mtypes.h"
+#include "savagedd.h"
+#include "savagespan.h"
+#include "savageioctl.h"
+#include "savage_bci.h"
+#include "savage_3d_reg.h"
+#include "swrast/swrast.h"
+
+#define DBG 0
+
+#define LOCAL_VARS \
+ __DRIdrawablePrivate *dPriv = imesa->mesa_drawable; \
+ savageScreenPrivate *savageScreen = imesa->savageScreen; \
+ GLuint cpp = savageScreen->cpp; \
+ GLuint pitch = imesa->aperturePitch; \
+ GLuint height = dPriv->h; \
+ char *buf = (char *)(imesa->drawMap + \
+ dPriv->x * cpp + \
+ dPriv->y * pitch); \
+ char *read_buf = (char *)(imesa->readMap + \
+ dPriv->x * cpp + \
+ dPriv->y * pitch); \
+ GLuint p = SAVAGE_CONTEXT( ctx )->MonoColor; \
+ (void) read_buf; (void) buf; (void) p
+
+#define LOCAL_DEPTH_VARS \
+ __DRIdrawablePrivate *dPriv = imesa->mesa_drawable; \
+ savageScreenPrivate *savageScreen = imesa->savageScreen; \
+ GLuint zpp = savageScreen->zpp; \
+ GLuint pitch = imesa->aperturePitch; \
+ GLuint height = dPriv->h; \
+ char *buf = (char *)(imesa->apertureBase[TARGET_DEPTH] + \
+ dPriv->x * zpp + \
+ dPriv->y * pitch)
+
+#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
+
+#define INIT_MONO_PIXEL(p)
+
+#define CLIPPIXEL(_x,_y) (_x >= minx && _x < maxx && \
+ _y >= miny && _y < maxy)
+
+
+#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
+ if ( _y < miny || _y >= maxy ) { \
+ _n1 = 0, _x1 = x; \
+ } else { \
+ _n1 = _n; \
+ _x1 = _x; \
+ if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
+ if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
+ }
+
+#define Y_FLIP(_y) (height - _y - 1)
+
+#define HW_LOCK() savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
+ WAIT_IDLE_EMPTY;\
+
+#define HW_CLIPLOOP() \
+ do { \
+ __DRIdrawablePrivate *dPriv = imesa->driDrawable; \
+ int _nc = dPriv->numClipRects; \
+ while (_nc--) { \
+ int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
+ int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
+ int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
+ int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
+
+
+#define HW_ENDCLIPLOOP() \
+ } \
+ } while (0)
+
+#if 0
+#define HW_UNLOCK() \
+ UNLOCK_HARDWARE(imesa);
+#endif
+#define HW_UNLOCK() { }
+
+
+/* 16 bit, 565 rgb color spanline and pixel functions
+ */
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+ p = SAVAGEPACKCOLOR565( color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+do{ \
+ *(GLushort *)(buf + (_x<<1) + _y*pitch) = ( (((int)r & 0xf8) << 8) |\
+ (((int)g & 0xfc) << 3) | \
+ (((int)b & 0xf8) >> 3)); \
+}while(0)
+#define WRITE_PIXEL( _x, _y, p ) \
+do{ \
+ *(GLushort *)(buf + (_x<<1) + _y*pitch) = p; \
+}while(0)
+
+#define READ_RGBA( rgba, _x, _y ) \
+do { \
+ GLushort p = *(GLushort *)(read_buf + (_x<<1) + _y*pitch); \
+ rgba[0] = (((p >> 11) & 0x1f) * 255) >>5; \
+ rgba[1] = (((p >> 5) & 0x3f) * 255) >>6; \
+ rgba[2] = (((p >> 0) & 0x1f) * 255) >>5; \
+ rgba[3] = 255; \
+} while(0)
+
+#define TAG(x) savage##x##_565
+#include "spantmp.h"
+
+
+/* 32 bit, 8888 ARGB color spanline and pixel functions
+ */
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+ p = SAVAGEPACKCOLOR8888( color[0], color[1], color[2], color[3] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ *(GLuint *)(buf + (_x<<2) + _y*pitch) = ( ((GLuint)a << 24) | \
+ ((GLuint)r << 16) | \
+ ((GLuint)g << 8) | \
+ ((GLuint)b ))
+#define WRITE_PIXEL( _x, _y, p ) \
+ *(GLuint *)(buf + (_x<<2) + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y ) \
+do { \
+ GLuint p = *(GLuint *)(read_buf + (_x<<2) + _y*pitch); \
+ rgba[0] = (p >> 16) & 0xFF; \
+ rgba[1] = (p >> 8) & 0xFF; \
+ rgba[2] = (p >> 0) & 0xFF; \
+ rgba[3] = 0xFF; \
+} while(0)
+
+#define TAG(x) savage##x##_8888
+#include "spantmp.h"
+
+
+
+
+/* 16 bit depthbuffer functions.
+ */
+#define WRITE_DEPTH( _x, _y, d ) \
+do{ \
+ *(GLushort *)(buf + (_x<<1) + _y*pitch) = d; \
+}while(0)
+
+#define READ_DEPTH( d, _x, _y ) \
+do{ \
+ d = *(GLushort *)(buf + (_x<<1) + _y*pitch); \
+}while(0)
+
+/* d = 0xffff; */
+
+#define TAG(x) savage##x##_16
+#include "depthtmp.h"
+
+
+
+
+
+/* 8-bit stencil /24-bit depth depthbuffer functions.
+ */
+#define WRITE_DEPTH( _x, _y, d ) { \
+ GLuint tmp = *(GLuint *)(buf + (_x<<2) + _y*pitch); \
+ tmp &= 0xFF000000; \
+ tmp |= d; \
+ *(GLuint *)(buf + (_x<<2) + _y*pitch) = tmp; \
+}
+
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLuint *)(buf + (_x<<2) + _y*pitch) & 0x00FFFFFF;
+
+/* d = 0x00ffffff; */
+
+#define TAG(x) savage##x##_8_24
+#include "depthtmp.h"
+
+
+#define WRITE_STENCIL( _x, _y, d ) { \
+ GLuint tmp = *(GLuint *)(buf + (_x<<2) + _y*pitch); \
+ tmp &= 0x00FFFFFF; \
+ tmp |= (((GLuint)d)<<24) & 0xFF000000; \
+ *(GLuint *)(buf + (_x<<2) + _y*pitch) = tmp; \
+}
+
+#define READ_STENCIL( d, _x, _y ) \
+ d = (GLstencil)((*(GLuint *)(buf + (_x<<2) + _y*pitch) & 0xFF000000) >> 24);
+
+#define TAG(x) savage##x##_8_24
+#include "stenciltmp.h"
+
+
+/*
+ * This function is called to specify which buffer to read and write
+ * for software rasterization (swrast) fallbacks. This doesn't necessarily
+ * correspond to glDrawBuffer() or glReadBuffer() calls.
+ */
+static void savageDDSetBuffer(GLcontext *ctx, GLframebuffer *buffer,
+ GLuint bufferBit)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ char *map;
+
+ assert( (bufferBit == FRONT_LEFT_BIT) || (bufferBit == BACK_LEFT_BIT) );
+
+ map = (bufferBit == FRONT_LEFT_BIT)
+ ? (char*)imesa->apertureBase[TARGET_FRONT]
+ : (char*)imesa->apertureBase[TARGET_BACK];
+
+ imesa->drawMap = map;
+ imesa->readMap = map;
+
+ assert( (buffer == imesa->driDrawable->driverPrivate)
+ || (buffer == imesa->driReadable->driverPrivate) );
+
+ imesa->mesa_drawable = (buffer == imesa->driDrawable->driverPrivate)
+ ? imesa->driDrawable : imesa->driReadable;
+}
+
+
+void savageDDInitSpanFuncs( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+
+ swdd->SetBuffer = savageDDSetBuffer;
+
+ switch (imesa->savageScreen->cpp)
+ {
+ case 2:
+ swdd->WriteRGBASpan = savageWriteRGBASpan_565;
+ swdd->WriteRGBSpan = savageWriteRGBSpan_565;
+ swdd->WriteMonoRGBASpan = savageWriteMonoRGBASpan_565;
+ swdd->WriteRGBAPixels = savageWriteRGBAPixels_565;
+ swdd->WriteMonoRGBAPixels = savageWriteMonoRGBAPixels_565;
+ swdd->ReadRGBASpan = savageReadRGBASpan_565;
+ swdd->ReadRGBAPixels = savageReadRGBAPixels_565;
+
+ break;
+
+ case 4:
+ swdd->WriteRGBASpan = savageWriteRGBASpan_8888;
+ swdd->WriteRGBSpan = savageWriteRGBSpan_8888;
+ swdd->WriteMonoRGBASpan = savageWriteMonoRGBASpan_8888;
+ swdd->WriteRGBAPixels = savageWriteRGBAPixels_8888;
+ swdd->WriteMonoRGBAPixels = savageWriteMonoRGBAPixels_8888;
+ swdd->ReadRGBASpan = savageReadRGBASpan_8888;
+ swdd->ReadRGBAPixels = savageReadRGBAPixels_8888;
+ }
+
+ switch (imesa->savageScreen->zpp)
+ {
+ case 2:
+ swdd->ReadDepthSpan = savageReadDepthSpan_16;
+ swdd->WriteDepthSpan = savageWriteDepthSpan_16;
+ swdd->ReadDepthPixels = savageReadDepthPixels_16;
+ swdd->WriteDepthPixels = savageWriteDepthPixels_16;
+
+ break;
+ case 4:
+ swdd->ReadDepthSpan = savageReadDepthSpan_8_24;
+ swdd->WriteDepthSpan = savageWriteDepthSpan_8_24;
+ swdd->ReadDepthPixels = savageReadDepthPixels_8_24;
+ swdd->WriteDepthPixels = savageWriteDepthPixels_8_24;
+#if HW_STENCIL
+ swdd->ReadStencilSpan = savageReadStencilSpan_8_24;
+ swdd->WriteStencilSpan = savageWriteStencilSpan_8_24;
+ swdd->ReadStencilPixels = savageReadStencilPixels_8_24;
+ swdd->WriteStencilPixels = savageWriteStencilPixels_8_24;
+#endif
+ break;
+
+ }
+ swdd->WriteCI8Span =NULL;
+ swdd->WriteCI32Span =NULL;
+ swdd->WriteMonoCISpan =NULL;
+ swdd->WriteCI32Pixels =NULL;
+ swdd->WriteMonoCIPixels =NULL;
+ swdd->ReadCI32Span =NULL;
+ swdd->ReadCI32Pixels =NULL;
+
+ /* Pixel path fallbacks.
+ */
+ ctx->Driver.Accum = _swrast_Accum;
+ ctx->Driver.Bitmap = _swrast_Bitmap;
+ ctx->Driver.CopyPixels = _swrast_CopyPixels;
+ ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ ctx->Driver.ReadPixels = _swrast_ReadPixels;
+}
diff --git a/src/mesa/drivers/dri/savage/savagespan.h b/src/mesa/drivers/dri/savage/savagespan.h
new file mode 100644
index 0000000000..35247b4706
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagespan.h
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#ifndef _SAVAGE_SPAN_H
+#define _SAVAGE_SPAN_H
+
+extern void savageDDInitSpanFuncs( GLcontext *ctx );
+
+#endif
diff --git a/src/mesa/drivers/dri/savage/savagestate.c b/src/mesa/drivers/dri/savage/savagestate.c
new file mode 100644
index 0000000000..622e4362ab
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagestate.c
@@ -0,0 +1,2444 @@
+/*
+ * 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 "mtypes.h"
+#include "enums.h"
+#include "macros.h"
+#include "dd.h"
+
+#include "mm.h"
+#include "savagedd.h"
+#include "savagecontext.h"
+
+#include "savagestate.h"
+#include "savagetex.h"
+#include "savagevb.h"
+#include "savagetris.h"
+#include "savageioctl.h"
+#include "savage_bci.h"
+
+#include "swrast/swrast.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "swrast_setup/swrast_setup.h"
+
+static void savageBlendFunc_s4(GLcontext *);
+static void savageBlendFunc_s3d(GLcontext *);
+
+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(GLcontext *ctx, GLenum func, GLfloat ref)
+{
+ /* This can be done in BlendFunc*/
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ savageBlendFunc_s4(ctx);
+}
+static void savageDDAlphaFunc_s3d(GLcontext *ctx, GLenum func, GLfloat ref)
+{
+ /* This can be done in BlendFunc*/
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ savageBlendFunc_s3d(ctx);
+}
+
+static void savageDDBlendEquationSeparate(GLcontext *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(GLcontext *ctx)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ Reg_DrawLocalCtrl DrawLocalCtrl;
+
+ /* set up draw control register (including blending, alpha
+ * test, dithering, and shading model)
+ */
+
+ /*
+ * And mask removes flushPdDestWrites
+ */
+
+ DrawLocalCtrl.ui = imesa->Registers.DrawLocalCtrl.ui & ~0x40000000;
+
+ /*
+ * blend modes
+ */
+ if(ctx->Color.BlendEnabled){
+ switch (ctx->Color.BlendDstRGB)
+ {
+ case GL_ZERO:
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
+ break;
+
+ case GL_ONE:
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_One;
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_SRC_COLOR:
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_SrcClr;
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_ONE_MINUS_SRC_COLOR:
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_1SrcClr;
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_SRC_ALPHA:
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_SrcAlpha;
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_ONE_MINUS_SRC_ALPHA:
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_1SrcAlpha;
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_DST_ALPHA:
+ if (imesa->glCtx->Visual.alphaBits == 0)
+ {
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_One;
+ }
+ else
+ {
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_DstAlpha;
+ }
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_ONE_MINUS_DST_ALPHA:
+ if (imesa->glCtx->Visual.alphaBits == 0)
+ {
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
+ }
+ else
+ {
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_1DstAlpha;
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ }
+ break;
+ }
+
+ switch (ctx->Color.BlendSrcRGB)
+ {
+ case GL_ZERO:
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_Zero;
+ break;
+
+ case GL_ONE:
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_One;
+ break;
+
+ case GL_DST_COLOR:
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_DstClr;
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_ONE_MINUS_DST_COLOR:
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_1DstClr;
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_SRC_ALPHA:
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_SrcAlpha;
+ break;
+
+ case GL_ONE_MINUS_SRC_ALPHA:
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_1SrcAlpha;
+ break;
+
+ case GL_DST_ALPHA:
+ if (imesa->glCtx->Visual.alphaBits == 0)
+ {
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_One;
+ }
+ else
+ {
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_DstAlpha;
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ }
+ break;
+
+ case GL_ONE_MINUS_DST_ALPHA:
+ if (imesa->glCtx->Visual.alphaBits == 0)
+ {
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_Zero;
+ }
+ else
+ {
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_1DstAlpha;
+ DrawLocalCtrl.ni.flushPdDestWrites = GL_TRUE;
+ }
+ break;
+ }
+ }
+ else
+ {
+ DrawLocalCtrl.ni.dstAlphaMode = DAM_Zero;
+ DrawLocalCtrl.ni.srcAlphaMode = SAM_One;
+ }
+
+ /* alpha test*/
+
+ if(ctx->Color.AlphaEnabled)
+ {
+ int a;
+ GLubyte alphaRef;
+
+ CLAMPED_FLOAT_TO_UBYTE(alphaRef,ctx->Color.AlphaRef);
+
+ switch(ctx->Color.AlphaFunc) {
+ case GL_NEVER: a = LCS_A_NEVER; break;
+ case GL_ALWAYS: a = LCS_A_ALWAYS; break;
+ case GL_LESS: a = LCS_A_LESS; break;
+ case GL_LEQUAL: a = LCS_A_LEQUAL; break;
+ case GL_EQUAL: a = LCS_A_EQUAL; break;
+ case GL_GREATER: a = LCS_A_GREATER; break;
+ case GL_GEQUAL: a = LCS_A_GEQUAL; break;
+ case GL_NOTEQUAL: a = LCS_A_NOTEQUAL; break;
+ default:return;
+ }
+
+ if (imesa->Registers.DrawCtrl1.ni.alphaTestEn != GL_TRUE)
+ {
+ imesa->Registers.DrawCtrl1.ni.alphaTestEn = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
+ }
+
+ if (imesa->Registers.DrawCtrl1.ni.alphaTestCmpFunc !=
+ (a & 0x0F))
+ {
+ imesa->Registers.DrawCtrl1.ni.alphaTestCmpFunc =
+ a & 0x0F;
+ imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
+ }
+
+ /* looks like rounding control is different on katmai than p2*/
+
+ if (imesa->Registers.DrawCtrl0.ni.alphaRefVal != alphaRef)
+ {
+ imesa->Registers.DrawCtrl0.ni.alphaRefVal = alphaRef;
+ imesa->Registers.changed.ni.fDrawCtrl0Changed = GL_TRUE;
+ }
+ }
+ else
+ {
+ if (imesa->Registers.DrawCtrl1.ni.alphaTestEn != GL_FALSE)
+ {
+ imesa->Registers.DrawCtrl1.ni.alphaTestEn = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
+ }
+ }
+
+ /* Set/Reset Z-after-alpha*/
+
+ DrawLocalCtrl.ni.wrZafterAlphaTst = imesa->Registers.DrawCtrl1.ni.alphaTestEn;
+ /*DrawLocalCtrl.ni.zUpdateEn = ~DrawLocalCtrl.ni.wrZafterAlphaTst;*/
+
+ if (imesa->Registers.DrawLocalCtrl.ui != DrawLocalCtrl.ui)
+ {
+ imesa->Registers.DrawLocalCtrl.ui = DrawLocalCtrl.ui;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ }
+
+ /* dithering*/
+
+ if ( ctx->Color.DitherFlag )
+ {
+ if (imesa->Registers.DrawCtrl1.ni.ditherEn != GL_TRUE)
+ {
+ imesa->Registers.DrawCtrl1.ni.ditherEn = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
+ }
+ }
+ else
+ {
+ if (imesa->Registers.DrawCtrl1.ni.ditherEn != GL_FALSE)
+ {
+ imesa->Registers.DrawCtrl1.ni.ditherEn = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
+ }
+ }
+}
+static void savageBlendFunc_s3d(GLcontext *ctx)
+{
+
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ Reg_DrawCtrl DrawCtrl;
+
+ /* set up draw control register (including blending, alpha
+ * test, dithering, and shading model)
+ */
+
+ /*
+ * And mask removes flushPdDestWrites
+ */
+
+ DrawCtrl.ui = imesa->Registers.DrawCtrl.ui & ~0x20000000;
+
+ /*
+ * blend modes
+ */
+ if(ctx->Color.BlendEnabled){
+ switch (ctx->Color.BlendDstRGB)
+ {
+ case GL_ZERO:
+ DrawCtrl.ni.dstAlphaMode = DAM_Zero;
+ break;
+
+ case GL_ONE:
+ DrawCtrl.ni.dstAlphaMode = DAM_One;
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_SRC_COLOR:
+ DrawCtrl.ni.dstAlphaMode = DAM_SrcClr;
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_ONE_MINUS_SRC_COLOR:
+ DrawCtrl.ni.dstAlphaMode = DAM_1SrcClr;
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_SRC_ALPHA:
+ DrawCtrl.ni.dstAlphaMode = DAM_SrcAlpha;
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_ONE_MINUS_SRC_ALPHA:
+ DrawCtrl.ni.dstAlphaMode = DAM_1SrcAlpha;
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_DST_ALPHA:
+ if (imesa->glCtx->Visual.alphaBits == 0)
+ {
+ DrawCtrl.ni.dstAlphaMode = DAM_One;
+ }
+ else
+ {
+ DrawCtrl.ni.dstAlphaMode = DAM_DstAlpha;
+ }
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_ONE_MINUS_DST_ALPHA:
+ if (imesa->glCtx->Visual.alphaBits == 0)
+ {
+ DrawCtrl.ni.dstAlphaMode = DAM_Zero;
+ }
+ else
+ {
+ DrawCtrl.ni.dstAlphaMode = DAM_1DstAlpha;
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ }
+ break;
+ }
+
+ switch (ctx->Color.BlendSrcRGB)
+ {
+ case GL_ZERO:
+ DrawCtrl.ni.srcAlphaMode = SAM_Zero;
+ break;
+
+ case GL_ONE:
+ DrawCtrl.ni.srcAlphaMode = SAM_One;
+ break;
+
+ case GL_DST_COLOR:
+ DrawCtrl.ni.srcAlphaMode = SAM_DstClr;
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_ONE_MINUS_DST_COLOR:
+ DrawCtrl.ni.srcAlphaMode = SAM_1DstClr;
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ break;
+
+ case GL_SRC_ALPHA:
+ DrawCtrl.ni.srcAlphaMode = SAM_SrcAlpha;
+ break;
+
+ case GL_ONE_MINUS_SRC_ALPHA:
+ DrawCtrl.ni.srcAlphaMode = SAM_1SrcAlpha;
+ break;
+
+ case GL_DST_ALPHA:
+ if (imesa->glCtx->Visual.alphaBits == 0)
+ {
+ DrawCtrl.ni.srcAlphaMode = SAM_One;
+ }
+ else
+ {
+ DrawCtrl.ni.srcAlphaMode = SAM_DstAlpha;
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ }
+ break;
+
+ case GL_ONE_MINUS_DST_ALPHA:
+ if (imesa->glCtx->Visual.alphaBits == 0)
+ {
+ DrawCtrl.ni.srcAlphaMode = SAM_Zero;
+ }
+ else
+ {
+ DrawCtrl.ni.srcAlphaMode = SAM_1DstAlpha;
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ }
+ break;
+ }
+ }
+ else
+ {
+ DrawCtrl.ni.dstAlphaMode = DAM_Zero;
+ DrawCtrl.ni.srcAlphaMode = SAM_One;
+ }
+
+ /* alpha test*/
+
+ if(ctx->Color.AlphaEnabled)
+ {
+ GLint a;
+ GLubyte alphaRef;
+
+ CLAMPED_FLOAT_TO_UBYTE(alphaRef,ctx->Color.AlphaRef);
+
+ switch(ctx->Color.AlphaFunc) {
+ case GL_NEVER: a = LCS_A_NEVER; break;
+ case GL_ALWAYS: a = LCS_A_ALWAYS; break;
+ case GL_LESS: a = LCS_A_LESS; break;
+ case GL_LEQUAL: a = LCS_A_LEQUAL; break;
+ case GL_EQUAL: a = LCS_A_EQUAL; break;
+ case GL_GREATER: a = LCS_A_GREATER; break;
+ case GL_GEQUAL: a = LCS_A_GEQUAL; break;
+ case GL_NOTEQUAL: a = LCS_A_NOTEQUAL; break;
+ default:return;
+ }
+
+ DrawCtrl.ni.alphaTestEn = GL_TRUE;
+ DrawCtrl.ni.alphaTestCmpFunc = a & 0x07;
+ DrawCtrl.ni.alphaRefVal = alphaRef;
+ }
+ else
+ {
+ DrawCtrl.ni.alphaTestEn = GL_FALSE;
+ }
+
+ /* Set/Reset Z-after-alpha*/
+
+ if (imesa->Registers.ZBufCtrl.s3d.wrZafterAlphaTst !=
+ DrawCtrl.ni.alphaTestEn)
+ {
+ imesa->Registers.ZBufCtrl.s3d.wrZafterAlphaTst =
+ DrawCtrl.ni.alphaTestEn;
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+ }
+ /*DrawLocalCtrl.ni.zUpdateEn = ~DrawLocalCtrl.ni.wrZafterAlphaTst;*/
+
+ /* dithering*/
+
+ if ( ctx->Color.DitherFlag )
+ {
+ DrawCtrl.ni.ditherEn = GL_TRUE;
+ }
+ else
+ {
+ DrawCtrl.ni.ditherEn = GL_FALSE;
+ }
+
+ if (imesa->Registers.DrawCtrl.ui != DrawCtrl.ui)
+ {
+ imesa->Registers.DrawCtrl.ui = DrawCtrl.ui;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+ }
+}
+
+static void savageDDBlendFuncSeparate_s4( GLcontext *ctx, GLenum sfactorRGB,
+ GLenum dfactorRGB, GLenum sfactorA,
+ GLenum dfactorA )
+{
+ assert (dfactorRGB == dfactorA && sfactorRGB == sfactorA);
+ savageBlendFunc_s4( ctx );
+}
+static void savageDDBlendFuncSeparate_s3d( GLcontext *ctx, GLenum sfactorRGB,
+ GLenum dfactorRGB, GLenum sfactorA,
+ GLenum dfactorA )
+{
+ assert (dfactorRGB == dfactorA && sfactorRGB == sfactorA);
+ savageBlendFunc_s3d( ctx );
+}
+
+
+
+static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ int zmode;
+#define depthIndex 0
+
+ /* set up z-buffer control register (global)
+ * set up z-buffer offset register (global)
+ * set up z read/write watermarks register (global)
+ */
+
+ switch(func) {
+ case GL_NEVER: zmode = LCS_Z_NEVER; break;
+ case GL_ALWAYS: zmode = LCS_Z_ALWAYS; break;
+ case GL_LESS: zmode = LCS_Z_LESS; break;
+ case GL_LEQUAL: zmode = LCS_Z_LEQUAL; break;
+ case GL_EQUAL: zmode = LCS_Z_EQUAL; break;
+ case GL_GREATER: zmode = LCS_Z_GREATER; break;
+ case GL_GEQUAL: zmode = LCS_Z_GEQUAL; break;
+ case GL_NOTEQUAL: zmode = LCS_Z_NOTEQUAL; break;
+ default:return;
+ }
+ if (ctx->Depth.Test)
+ {
+
+ if (imesa->Registers.ZBufCtrl.s4.zCmpFunc != (zmode & 0x0F))
+ {
+ imesa->Registers.ZBufCtrl.s4.zCmpFunc = zmode & 0x0F;
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.DrawLocalCtrl.ni.zUpdateEn != ctx->Depth.Mask)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.zUpdateEn = ctx->Depth.Mask;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites == GL_FALSE)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+#if 1
+ imesa->Registers.ZWatermarks.ni.wLow = 0;
+ imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
+#endif
+ }
+
+ if (imesa->Registers.ZBufCtrl.s4.zBufEn != GL_TRUE)
+ {
+ imesa->Registers.ZBufCtrl.s4.zBufEn = GL_TRUE;
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+ }
+ }
+ else if (imesa->glCtx->Stencil.Enabled &&
+ !imesa->glCtx->DrawBuffer->UseSoftwareStencilBuffer)
+ {
+#define STENCIL (0x27)
+
+ /* by Jiayo, tempory disable HW stencil in 24 bpp */
+#if HW_STENCIL
+ if(imesa->hw_stencil)
+ {
+ if ((imesa->Registers.ZBufCtrl.ui & STENCIL) != STENCIL)
+ {
+ imesa->Registers.ZBufCtrl.s4.zCmpFunc = GL_ALWAYS & 0x0F;
+ imesa->Registers.ZBufCtrl.s4.zBufEn = GL_TRUE;
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.DrawLocalCtrl.ni.zUpdateEn != GL_FALSE)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.zUpdateEn = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites == GL_TRUE)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+
+ imesa->Registers.ZWatermarks.ni.wLow = 8;
+ imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
+ }
+ }
+#endif /* end #if HW_STENCIL */
+ }
+ else
+ {
+
+ if (imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn == GL_FALSE)
+ {
+ imesa->Registers.ZBufCtrl.s4.zCmpFunc = LCS_Z_ALWAYS & 0x0F;
+ imesa->Registers.ZBufCtrl.s4.zBufEn = GL_TRUE;
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+
+ if (imesa->Registers.DrawLocalCtrl.ni.zUpdateEn != GL_FALSE)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.zUpdateEn = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites == GL_TRUE)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+
+ imesa->Registers.ZWatermarks.ni.wLow = 8;
+ imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
+
+ }
+ }
+ else
+
+ /* DRAWUPDATE_REQUIRES_Z_ENABLED*/
+ {
+ if (imesa->Registers.ZBufCtrl.s4.zBufEn != GL_FALSE)
+ {
+ imesa->Registers.ZBufCtrl.s4.zBufEn = GL_FALSE;
+ imesa->Registers.DrawLocalCtrl.ni.zUpdateEn = GL_FALSE;
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
+ imesa->Registers.ZWatermarks.ni.wLow = 8;
+ imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
+ }
+ }
+ }
+
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+}
+static void savageDDDepthFunc_s3d(GLcontext *ctx, GLenum func)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ Reg_ZBufCtrl ZBufCtrl;
+ int zmode;
+#define depthIndex 0
+
+ /* set up z-buffer control register (global)
+ * set up z-buffer offset register (global)
+ * set up z read/write watermarks register (global)
+ */
+ ZBufCtrl.ui = imesa->Registers.ZBufCtrl.ui;
+
+ switch(func) {
+ case GL_NEVER: zmode = LCS_Z_NEVER; break;
+ case GL_ALWAYS: zmode = LCS_Z_ALWAYS; break;
+ case GL_LESS: zmode = LCS_Z_LESS; break;
+ case GL_LEQUAL: zmode = LCS_Z_LEQUAL; break;
+ case GL_EQUAL: zmode = LCS_Z_EQUAL; break;
+ case GL_GREATER: zmode = LCS_Z_GREATER; break;
+ case GL_GEQUAL: zmode = LCS_Z_GEQUAL; break;
+ case GL_NOTEQUAL: zmode = LCS_Z_NOTEQUAL; break;
+ default:return;
+ }
+ if (ctx->Depth.Test)
+ {
+ ZBufCtrl.s3d.zBufEn = GL_TRUE;
+ ZBufCtrl.s3d.zCmpFunc = zmode & 0x0F;
+ ZBufCtrl.s3d.zUpdateEn = ctx->Depth.Mask;
+
+ if (imesa->Registers.DrawCtrl.ni.flushPdZbufWrites == GL_FALSE)
+ {
+ imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+#if 1
+ imesa->Registers.ZWatermarks.ni.wLow = 0;
+ imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
+#endif
+ }
+ }
+ else
+ {
+ if (ZBufCtrl.s3d.drawUpdateEn == GL_FALSE) {
+ ZBufCtrl.s3d.zCmpFunc = LCS_Z_ALWAYS & 0x0F;
+ ZBufCtrl.s3d.zBufEn = GL_TRUE;
+ ZBufCtrl.s3d.zUpdateEn = GL_FALSE;
+ }
+ else
+
+ /* DRAWUPDATE_REQUIRES_Z_ENABLED*/
+ {
+ ZBufCtrl.s3d.zBufEn = GL_FALSE;
+ ZBufCtrl.s3d.zUpdateEn = GL_FALSE;
+ }
+
+ if (imesa->Registers.DrawCtrl.ni.flushPdZbufWrites == GL_TRUE)
+ {
+ imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+
+ imesa->Registers.ZWatermarks.ni.wLow = 8;
+ imesa->Registers.changed.ni.fZWatermarksChanged = GL_TRUE;
+ }
+ }
+
+ if (imesa->Registers.ZBufCtrl.ui != ZBufCtrl.ui)
+ {
+ imesa->Registers.ZBufCtrl.ui = ZBufCtrl.ui;
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+ }
+
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+}
+
+static void savageDDDepthMask_s4(GLcontext *ctx, GLboolean flag)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ if (flag)
+ {
+ if (imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites == GL_FALSE)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ }
+ }
+ else
+ {
+ if (imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites == GL_TRUE)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ }
+ }
+ savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
+}
+static void savageDDDepthMask_s3d(GLcontext *ctx, GLboolean flag)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ if (flag)
+ {
+ if (imesa->Registers.DrawCtrl.ni.flushPdZbufWrites == GL_FALSE)
+ {
+ imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+ }
+ }
+ else
+ {
+ if (imesa->Registers.DrawCtrl.ni.flushPdZbufWrites == GL_TRUE)
+ {
+ imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+ }
+ }
+ savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
+}
+
+
+
+
+/* =============================================================
+ * Hardware clipping
+ */
+
+
+ void savageDDScissor( GLcontext *ctx, GLint x, GLint y,
+ GLsizei w, GLsizei h )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ imesa->scissor_rect.x1 = MAX2(imesa->drawX+x,imesa->draw_rect.x1);
+ imesa->scissor_rect.y1 = MAX2(imesa->drawY+imesa->driDrawable->h -(y+h),
+ imesa->draw_rect.y1);
+ imesa->scissor_rect.x2 = MIN2(imesa->drawX+x+w,imesa->draw_rect.x2);
+ imesa->scissor_rect.y2 = MIN2(imesa->drawY+imesa->driDrawable->h - y,
+ imesa->draw_rect.y2);
+
+
+ imesa->Registers.changed.ni.fScissorsChanged=GL_TRUE;
+
+ imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
+}
+
+
+
+static void savageDDDrawBuffer(GLcontext *ctx, GLenum mode )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+
+ /*
+ * _DrawDestMask is easier to cope with than <mode>.
+ */
+ switch ( ctx->Color._DrawDestMask ) {
+ case FRONT_LEFT_BIT:
+ imesa->IsDouble = GL_FALSE;
+
+ if(imesa->IsFullScreen)
+ {
+ imesa->drawMap = (char *)imesa->apertureBase[TARGET_FRONT];
+ imesa->readMap = (char *)imesa->apertureBase[TARGET_FRONT];
+ }
+ else
+ {
+ imesa->drawMap = (char *)imesa->apertureBase[TARGET_BACK];
+ imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
+ }
+ imesa->NotFirstFrame = GL_FALSE;
+ imesa->dirty |= SAVAGE_UPLOAD_BUFFERS;
+ savageXMesaSetFrontClipRects( imesa );
+ FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE );
+ break;
+ case BACK_LEFT_BIT:
+ imesa->IsDouble = GL_TRUE;
+ imesa->drawMap = (char *)imesa->apertureBase[TARGET_BACK];
+ imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
+ imesa->NotFirstFrame = GL_FALSE;
+ imesa->dirty |= SAVAGE_UPLOAD_BUFFERS;
+ savageXMesaSetBackClipRects( imesa );
+ FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE );
+ break;
+ default:
+ FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_TRUE );
+ return;
+ }
+
+ /* We want to update the s/w rast state too so that r200SetBuffer() (?)
+ * gets called.
+ */
+ _swrast_DrawBuffer(ctx, mode);
+}
+
+static void savageDDReadBuffer(GLcontext *ctx, GLenum mode )
+{
+ /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
+}
+
+#if 0
+static void savageDDSetColor(GLcontext *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
+ */
+
+static void savageCalcViewport( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+ GLfloat *m = imesa->hw_viewport;
+
+ /* See also mga_translate_vertex.
+ */
+ 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;
+ m[MAT_SZ] = v[MAT_SZ] * imesa->depth_scale;
+ m[MAT_TZ] = v[MAT_TZ] * imesa->depth_scale;
+
+ imesa->SetupNewInputs = ~0;
+}
+
+static void savageViewport( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height )
+{
+ savageCalcViewport( ctx );
+}
+
+static void savageDepthRange( GLcontext *ctx,
+ GLclampd nearval, GLclampd farval )
+{
+ savageCalcViewport( ctx );
+}
+
+
+/* =============================================================
+ * Miscellaneous
+ */
+
+static void savageDDClearColor(GLcontext *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( GLcontext *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(GLcontext *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;
+}
+#endif /* end #if HW_CULL */
+
+static void savageUpdateCull( GLcontext *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->Registers.DrawCtrl1.ni.cullMode != cullMode) {
+ imesa->Registers.DrawCtrl1.ni.cullMode = cullMode;
+ imesa->Registers.changed.ni.fDrawCtrl1Changed = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ } else {
+ if (imesa->Registers.DrawCtrl.ni.cullMode != cullMode) {
+ imesa->Registers.DrawCtrl.ni.cullMode = cullMode;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ }
+#endif /* end #if HW_CULL */
+}
+
+
+
+/* =============================================================
+ * Color masks
+ */
+
+/* Mesa calls this from the wrong place - it is called a very large
+ * number of redundant times.
+ *
+ * Colormask can be simulated by multipass or multitexture techniques.
+ */
+static void savageDDColorMask_s4(GLcontext *ctx,
+ GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+ GLuint enable;
+
+ if (ctx->Visual.alphaBits)
+ {
+ enable = b | g | r | a;
+ }
+ else
+ {
+ enable = b | g | r;
+ }
+
+ if (enable)
+ {
+ if (imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn == GL_FALSE)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ }
+ else
+ {
+ if (imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ }
+ /* TODO: need a software fallback */
+}
+static void savageDDColorMask_s3d(GLcontext *ctx,
+ GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+ GLuint enable;
+
+ if (ctx->Visual.alphaBits)
+ {
+ enable = b | g | r | a;
+ }
+ else
+ {
+ enable = b | g | r;
+ }
+
+ if (enable)
+ {
+ if (imesa->Registers.ZBufCtrl.s3d.drawUpdateEn == GL_FALSE)
+ {
+ imesa->Registers.ZBufCtrl.s3d.drawUpdateEn = GL_TRUE;
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ }
+ else
+ {
+ if (imesa->Registers.ZBufCtrl.s3d.drawUpdateEn)
+ {
+ imesa->Registers.ZBufCtrl.s3d.drawUpdateEn = GL_FALSE;
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ }
+ /* TODO: need a software fallback */
+}
+
+/* Seperate specular not fully implemented in hardware... Needs
+ * some interaction with material state? Just punt to software
+ * in all cases?
+ * FK: Don't fall back for now. Let's see the failure cases and
+ * fix them the right way. I don't see how this could be a
+ * hardware limitation.
+ */
+static void savageUpdateSpecular_s4(GLcontext *ctx) {
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+
+ if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
+ ctx->Light.Enabled) {
+ if (imesa->Registers.DrawLocalCtrl.ni.specShadeEn == GL_FALSE) {
+ imesa->Registers.DrawLocalCtrl.ni.specShadeEn = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ }
+ /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_TRUE);*/
+ } else {
+ if (imesa->Registers.DrawLocalCtrl.ni.specShadeEn == GL_TRUE) {
+ imesa->Registers.DrawLocalCtrl.ni.specShadeEn = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ }
+ /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_FALSE);*/
+ }
+}
+static void savageUpdateSpecular_s3d(GLcontext *ctx) {
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+
+ if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
+ ctx->Light.Enabled) {
+ if (imesa->Registers.DrawCtrl.ni.specShadeEn == GL_FALSE) {
+ imesa->Registers.DrawCtrl.ni.specShadeEn = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+ }
+ FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_TRUE);
+ } else {
+ if (imesa->Registers.DrawCtrl.ni.specShadeEn == GL_TRUE) {
+ imesa->Registers.DrawCtrl.ni.specShadeEn = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+ }
+ FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_FALSE);
+ }
+}
+
+static void savageDDLightModelfv_s4(GLcontext *ctx, GLenum pname,
+ const GLfloat *param)
+{
+ savageUpdateSpecular_s4 (ctx);
+}
+static void savageDDLightModelfv_s3d(GLcontext *ctx, GLenum pname,
+ const GLfloat *param)
+{
+ savageUpdateSpecular_s3d (ctx);
+}
+
+static void savageDDShadeModel_s4(GLcontext *ctx, GLuint mod)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+
+ if (mod == GL_SMOOTH)
+ {
+ if(imesa->Registers.DrawLocalCtrl.ni.flatShadeEn == GL_TRUE)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.flatShadeEn = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ }
+ else
+ {
+ if(imesa->Registers.DrawLocalCtrl.ni.flatShadeEn == GL_FALSE)
+ {
+ imesa->Registers.DrawLocalCtrl.ni.flatShadeEn = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ }
+}
+static void savageDDShadeModel_s3d(GLcontext *ctx, GLuint mod)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+
+ if (mod == GL_SMOOTH)
+ {
+ if(imesa->Registers.DrawCtrl.ni.flatShadeEn == GL_TRUE)
+ {
+ imesa->Registers.DrawCtrl.ni.flatShadeEn = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ }
+ else
+ {
+ if(imesa->Registers.DrawCtrl.ni.flatShadeEn == GL_FALSE)
+ {
+ imesa->Registers.DrawCtrl.ni.flatShadeEn = GL_TRUE;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ }
+}
+
+
+/* =============================================================
+ * Fog
+ */
+
+static void savageDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ GLuint fogClr;
+
+ /*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));
+ if (imesa->Registers.FogCtrl.ni.fogEn != GL_TRUE)
+ {
+ imesa->Registers.FogCtrl.ni.fogEn = GL_TRUE;
+ imesa->Registers.changed.ni.fFogCtrlChanged = GL_TRUE;
+ }
+ /*cheap fog*/
+ if (imesa->Registers.FogCtrl.ni.fogMode != GL_TRUE)
+ {
+ imesa->Registers.FogCtrl.ni.fogMode = GL_TRUE;
+ imesa->Registers.changed.ni.fFogCtrlChanged = GL_TRUE;
+ }
+ if (imesa->Registers.FogCtrl.ni.fogClr != fogClr)
+ {
+ imesa->Registers.FogCtrl.ni.fogClr = fogClr;
+ imesa->Registers.changed.ni.fFogCtrlChanged = GL_TRUE;
+ }
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ else
+ {
+ /*No fog*/
+
+ if (imesa->Registers.FogCtrl.ni.fogEn != 0)
+ {
+ imesa->Registers.FogCtrl.ni.fogEn = 0;
+ imesa->Registers.FogCtrl.ni.fogMode = 0;
+ imesa->Registers.changed.ni.fFogCtrlChanged = GL_TRUE;
+ }
+ return;
+ }
+}
+
+
+#if HW_STENCIL
+static void savageStencilFunc(GLcontext *);
+
+static void savageDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
+ GLuint mask)
+{
+ savageStencilFunc(ctx);
+}
+
+static void savageDDStencilMask(GLcontext *ctx, GLuint mask)
+{
+ savageStencilFunc(ctx);
+}
+
+static void savageDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
+ GLenum zpass)
+{
+ savageStencilFunc(ctx);
+}
+
+static void savageStencilFunc(GLcontext *ctx)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ Reg_StencilCtrl StencilCtrl;
+ int a=0;
+
+ StencilCtrl.ui = 0x0;
+
+ if (ctx->Stencil.Enabled)
+ {
+
+ switch (ctx->Stencil.Function[0])
+ {
+ case GL_NEVER: a = LCS_S_NEVER; break;
+ case GL_ALWAYS: a = LCS_S_ALWAYS; break;
+ case GL_LESS: a = LCS_S_LESS; break;
+ case GL_LEQUAL: a = LCS_S_LEQUAL; break;
+ case GL_EQUAL: a = LCS_S_EQUAL; break;
+ case GL_GREATER: a = LCS_S_GREATER; break;
+ case GL_GEQUAL: a = LCS_S_GEQUAL; break;
+ case GL_NOTEQUAL: a = LCS_S_NOTEQUAL; break;
+ default:
+ break;
+ }
+
+ StencilCtrl.ni.cmpFunc = (GLuint)a & 0x0F;
+ StencilCtrl.ni.stencilEn = GL_TRUE;
+ StencilCtrl.ni.readMask = ctx->Stencil.ValueMask[0];
+ StencilCtrl.ni.writeMask = ctx->Stencil.WriteMask[0];
+
+ switch (ctx->Stencil.FailFunc[0])
+ {
+ case GL_KEEP:
+ StencilCtrl.ni.failOp = STC_FAIL_Keep;
+ break;
+ case GL_ZERO:
+ StencilCtrl.ni.failOp = STC_FAIL_Zero;
+ break;
+ case GL_REPLACE:
+ StencilCtrl.ni.failOp = STC_FAIL_Equal;
+ break;
+ case GL_INCR:
+ StencilCtrl.ni.failOp = STC_FAIL_IncClamp;
+ break;
+ case GL_DECR:
+ StencilCtrl.ni.failOp = STC_FAIL_DecClamp;
+ break;
+ case GL_INVERT:
+ StencilCtrl.ni.failOp = STC_FAIL_Invert;
+ break;
+#if GL_EXT_stencil_wrap
+ case GL_INCR_WRAP_EXT:
+ StencilCtrl.ni.failOp = STC_FAIL_Inc;
+ break;
+ case GL_DECR_WRAP_EXT:
+ StencilCtrl.ni.failOp = STC_FAIL_Dec;
+ break;
+#endif
+ }
+
+ switch (ctx->Stencil.ZFailFunc[0])
+ {
+ case GL_KEEP:
+ StencilCtrl.ni.passZfailOp = STC_FAIL_Keep;
+ break;
+ case GL_ZERO:
+ StencilCtrl.ni.passZfailOp = STC_FAIL_Zero;
+ break;
+ case GL_REPLACE:
+ StencilCtrl.ni.passZfailOp = STC_FAIL_Equal;
+ break;
+ case GL_INCR:
+ StencilCtrl.ni.passZfailOp = STC_FAIL_IncClamp;
+ break;
+ case GL_DECR:
+ StencilCtrl.ni.passZfailOp = STC_FAIL_DecClamp;
+ break;
+ case GL_INVERT:
+ StencilCtrl.ni.passZfailOp = STC_FAIL_Invert;
+ break;
+#if GL_EXT_stencil_wrap
+ case GL_INCR_WRAP_EXT:
+ StencilCtrl.ni.passZfailOp = STC_FAIL_Inc;
+ break;
+ case GL_DECR_WRAP_EXT:
+ StencilCtrl.ni.passZfailOp = STC_FAIL_Dec;
+ break;
+#endif
+ }
+
+ switch (ctx->Stencil.ZPassFunc[0])
+ {
+ case GL_KEEP:
+ StencilCtrl.ni.passZpassOp = STC_FAIL_Keep;
+ break;
+ case GL_ZERO:
+ StencilCtrl.ni.passZpassOp = STC_FAIL_Zero;
+ break;
+ case GL_REPLACE:
+ StencilCtrl.ni.passZpassOp = STC_FAIL_Equal;
+ break;
+ case GL_INCR:
+ StencilCtrl.ni.passZpassOp = STC_FAIL_IncClamp;
+ break;
+ case GL_DECR:
+ StencilCtrl.ni.passZpassOp = STC_FAIL_DecClamp;
+ break;
+ case GL_INVERT:
+ StencilCtrl.ni.passZpassOp = STC_FAIL_Invert;
+ break;
+#if GL_EXT_stencil_wrap
+ case GL_INCR_WRAP_EXT:
+ StencilCtrl.ni.passZpassOp = STC_FAIL_Inc;
+ break;
+ case GL_DECR_WRAP_EXT:
+ StencilCtrl.ni.passZpassOp = STC_FAIL_Dec;
+ break;
+#endif
+ }
+
+
+ if (imesa->Registers.StencilCtrl.ui != StencilCtrl.ui)
+ {
+ imesa->Registers.StencilCtrl.ui = StencilCtrl.ui;
+ imesa->Registers.changed.ni.fStencilCtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.ZBufCtrl.s4.stencilRefVal != (GLuint) ctx->Stencil.Ref) {
+ imesa->Registers.ZBufCtrl.s4.stencilRefVal = ctx->Stencil.Ref[0];
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+ }
+
+ /*
+ * force Z on, HW limitation
+ */
+
+ if (imesa->Registers.ZBufCtrl.s4.zBufEn != GL_TRUE)
+ {
+ imesa->Registers.ZBufCtrl.s4.zCmpFunc = LCS_Z_ALWAYS & 0x0F;
+ imesa->Registers.ZBufCtrl.s4.zBufEn = GL_TRUE;
+ imesa->Registers.changed.ni.fZBufCtrlChanged = GL_TRUE;
+ imesa->Registers.DrawLocalCtrl.ni.zUpdateEn = GL_FALSE;
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged = GL_TRUE;
+ }
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+ else
+ {
+ if (imesa->Registers.StencilCtrl.ni.stencilEn != GL_FALSE)
+ {
+ imesa->Registers.StencilCtrl.ni.stencilEn = GL_FALSE;
+ imesa->Registers.changed.ni.fStencilCtrlChanged = GL_TRUE;
+ }
+ }
+}
+#endif /* end #if HW_STENCIL */
+/* =============================================================
+ */
+
+static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ unsigned int ui;
+ switch(cap) {
+ case GL_ALPHA_TEST:
+ /* we should consider the disable case*/
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ savageBlendFunc_s4(ctx);
+ break;
+ case GL_BLEND:
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ /*Can't find Enable bit in the 3D registers.*/
+ /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
+ */
+ FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP,
+ (ctx->Color.ColorLogicOpEnabled &&
+ ctx->Color.LogicOp != GL_COPY));
+ /*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);
+ break;
+ case GL_DEPTH_TEST:
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
+ break;
+ case GL_SCISSOR_TEST:
+ imesa->scissor = state;
+ imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
+ break;
+#if 0
+ case GL_LINE_SMOOTH:
+ if (ctx->PB->primitive == GL_LINE) {
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ if (state) {
+ ui=imesa->Registers.DrawLocalCtrl.ui;
+ imesa->Registers.DrawLocalCtrl.ni.flatShadeEn=GL_TRUE;
+ if(imesa->Registers.DrawLocalCtrl.ui!=ui)
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged=GL_TRUE;
+ }
+ }
+ break;
+ case GL_POINT_SMOOTH:
+ if (ctx->PB->primitive == GL_POINT) {
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ if (state)
+ {
+ ui=imesa->Registers.DrawLocalCtrl.ui;
+ imesa->Registers.DrawLocalCtrl.ni.flatShadeEn=GL_FALSE;
+ if(imesa->Registers.DrawLocalCtrl.ui!=ui)
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged=GL_TRUE;
+ }
+ }
+ break;
+ case GL_POLYGON_SMOOTH:
+ if (ctx->PB->primitive == GL_POLYGON) {
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ if (state) {
+ ui=imesa->Registers.DrawLocalCtrl.ui;
+ imesa->Registers.DrawLocalCtrl.ni.flatShadeEn=GL_TRUE;
+ if(imesa->Registers.DrawLocalCtrl.ui!=ui)
+ imesa->Registers.changed.ni.fDrawLocalCtrlChanged=GL_TRUE;
+ }
+ }
+ break;
+#endif
+ case GL_STENCIL_TEST:
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ if (state)
+ {
+#if HW_STENCIL
+ if(imesa->hw_stencil)
+ {
+ ui=imesa->Registers.StencilCtrl.ui;
+#endif /* end if HW_STENCIL */
+ if(!imesa->hw_stencil)
+ FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, GL_TRUE);
+
+#if HW_STENCIL
+ imesa->Registers.StencilCtrl.ni.stencilEn=GL_TRUE;
+ if(imesa->Registers.StencilCtrl.ui!=ui)
+ imesa->Registers.changed.ni.fStencilCtrlChanged=GL_TRUE;
+ }
+#endif /* end if HW_STENCIL */
+ }
+
+ else
+ {
+#if HW_STENCIL
+ if(imesa->hw_stencil)
+ {
+ if(imesa->Registers.StencilCtrl.ni.stencilEn == GL_TRUE)
+ {
+ imesa->Registers.StencilCtrl.ni.stencilEn=GL_FALSE;
+ imesa->Registers.changed.ni.fStencilCtrlChanged=GL_TRUE;
+ }
+ }
+ FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, GL_FALSE);
+#endif
+ }
+ break;
+ case GL_FOG:
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ savageDDFogfv(ctx,0,0);
+ break;
+ case GL_CULL_FACE:
+#if HW_CULL
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ ui=imesa->Registers.DrawCtrl1.ui;
+ if (state)
+ {
+ savageDDCullFaceFrontFace(ctx,0);
+ }
+ else
+ {
+ imesa->Registers.DrawCtrl1.ni.cullMode=BCM_None;
+ }
+ if(imesa->Registers.DrawCtrl1.ui!=ui)
+ imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;
+#endif
+ break;
+ case GL_DITHER:
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ if (state)
+ {
+ if ( ctx->Color.DitherFlag )
+ {
+ ui=imesa->Registers.DrawCtrl1.ui;
+ imesa->Registers.DrawCtrl1.ni.ditherEn=GL_TRUE;
+ if(imesa->Registers.DrawCtrl1.ui!=ui)
+ imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;
+ }
+ }
+ if (!ctx->Color.DitherFlag )
+ {
+ ui=imesa->Registers.DrawCtrl1.ui;
+ imesa->Registers.DrawCtrl1.ni.ditherEn=GL_FALSE;
+ if(imesa->Registers.DrawCtrl1.ui!=ui)
+ imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;
+ }
+ 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(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ unsigned int ui;
+ switch(cap) {
+ case GL_ALPHA_TEST:
+ /* we should consider the disable case*/
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ savageBlendFunc_s3d(ctx);
+ break;
+ case GL_BLEND:
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ /*Can't find Enable bit in the 3D registers.*/
+ /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
+ */
+ FALLBACK (ctx, SAVAGE_FALLBACK_LOGICOP,
+ (ctx->Color.ColorLogicOpEnabled &&
+ ctx->Color.LogicOp != GL_COPY));
+ /*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);
+ break;
+ case GL_DEPTH_TEST:
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
+ break;
+ case GL_SCISSOR_TEST:
+ imesa->scissor = state;
+ imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
+ break;
+ case GL_FOG:
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ savageDDFogfv(ctx,0,0);
+ break;
+ case GL_CULL_FACE:
+#if HW_CULL
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ ui=imesa->Registers.DrawCtrl.ui;
+ if (state)
+ {
+ savageDDCullFaceFrontFace(ctx,0);
+ }
+ else
+ {
+ imesa->Registers.DrawCtrl.ni.cullMode=BCM_None;
+ }
+ if(imesa->Registers.DrawCtrl.ui!=ui)
+ imesa->Registers.changed.ni.fDrawCtrlChanged=GL_TRUE;
+#endif
+ break;
+ case GL_DITHER:
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ if (state)
+ {
+ if ( ctx->Color.DitherFlag )
+ {
+ ui=imesa->Registers.DrawCtrl.ui;
+ imesa->Registers.DrawCtrl.ni.ditherEn=GL_TRUE;
+ if(imesa->Registers.DrawCtrl.ui!=ui)
+ imesa->Registers.changed.ni.fDrawCtrlChanged=GL_TRUE;
+ }
+ }
+ if (!ctx->Color.DitherFlag )
+ {
+ ui=imesa->Registers.DrawCtrl.ui;
+ imesa->Registers.DrawCtrl.ni.ditherEn=GL_FALSE;
+ if(imesa->Registers.DrawCtrl.ui!=ui)
+ imesa->Registers.changed.ni.fDrawCtrlChanged=GL_TRUE;
+ }
+ 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( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+
+ if(imesa->driDrawable)
+ {
+ LOCK_HARDWARE(imesa);
+ }
+
+ if (imesa->new_state & SAVAGE_NEW_TEXTURE) {
+ savageUpdateTextureState( ctx );
+ }
+ if((imesa->dirty!=0)|| (imesa->new_state!=0))
+ {
+ savageEmitHwStateLocked(imesa);
+ imesa->new_state = 0;
+ }
+ if(imesa->driDrawable)
+ {
+ UNLOCK_HARDWARE(imesa);
+ }
+}
+
+
+void savageEmitDrawingRectangle( savageContextPtr imesa )
+{
+ __DRIdrawablePrivate *dPriv = imesa->driDrawable;
+ savageScreenPrivate *savageScreen = imesa->savageScreen;
+ XF86DRIClipRectPtr pbox;
+ int nbox;
+
+
+ int x0 = imesa->drawX;
+ int y0 = imesa->drawY;
+ int x1 = x0 + dPriv->w;
+ int y1 = y0 + dPriv->h;
+
+ pbox = dPriv->pClipRects;
+ nbox = dPriv->numClipRects;
+
+
+
+ /* Coordinate origin of the window - may be offscreen.
+ */
+ /* imesa->BufferSetup[SAVAGE_DESTREG_DR4] = ((y0<<16) |
+ (((unsigned)x0)&0xFFFF));*/
+
+ /* Clip to screen.
+ */
+ if (x0 < 0) x0 = 0;
+ if (y0 < 0) y0 = 0;
+ if (x1 > savageScreen->width) x1 = savageScreen->width;
+ if (y1 > savageScreen->height) y1 = savageScreen->height;
+
+
+ if(nbox == 1)
+ {
+ imesa->draw_rect.x1 = MAX2(x0,pbox->x1);
+ imesa->draw_rect.y1 = MAX2(y0,pbox->y1);
+ imesa->draw_rect.x2 = MIN2(x1,pbox->x2);
+ imesa->draw_rect.y2 = MIN2(y1,pbox->y2);
+ }
+ else
+ {
+ imesa->draw_rect.x1 = x0;
+ imesa->draw_rect.y1 = y0;
+ imesa->draw_rect.x2 = x1;
+ imesa->draw_rect.y2 = y1;
+ }
+
+ imesa->Registers.changed.ni.fScissorsChanged=GL_TRUE;
+
+ /* imesa->Registers.changed.ni.fDrawCtrl0Changed=GL_TRUE;
+ imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;*/
+
+
+ imesa->dirty |= SAVAGE_UPLOAD_BUFFERS;
+}
+
+
+static void savageDDPrintDirty( const char *msg, GLuint state )
+{
+ fprintf(stderr, "%s (0x%x): %s%s%s%s%s\n",
+ msg,
+ (unsigned int) state,
+ (state & SAVAGE_UPLOAD_TEX0IMAGE) ? "upload-tex0, " : "",
+ (state & SAVAGE_UPLOAD_TEX1IMAGE) ? "upload-tex1, " : "",
+ (state & SAVAGE_UPLOAD_CTX) ? "upload-ctx, " : "",
+ (state & SAVAGE_UPLOAD_BUFFERS) ? "upload-bufs, " : "",
+ (state & SAVAGE_UPLOAD_CLIPRECTS) ? "upload-cliprects, " : ""
+ );
+}
+
+
+
+static void savageUpdateRegister_s4(savageContextPtr imesa)
+{
+ GLuint *pBCIBase;
+ pBCIBase = savageDMAAlloc (imesa, 100);
+ /*
+ *make sure there is enough room for everything
+ */
+ /*savageKickDMA(imesa);*/
+#define PARAMT 1
+#if defined(PARAMT) && PARAMT
+#define GLOBAL_REG SAVAGE_GLOBAL_CHANGED
+#else
+#define GLOBAL_REG (SAVAGE_GLOBAL_CHANGED | SAVAGE_TEXTURE_CHANGED)
+#endif
+ if (imesa->Registers.changed.uiRegistersChanged & GLOBAL_REG)
+ {
+ WRITE_CMD(pBCIBase,WAIT_3D_IDLE,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fTexPalAddrChanged)
+ {
+ WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXPALADDR_S4, 1),GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexPalAddr.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.uiRegistersChanged & 0xFC)
+ {
+ WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXCTRL0_S4, 6),GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexCtrl[0].ui,GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexCtrl[1].ui,GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexAddr[0].ui,GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexAddr[1].ui,GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexBlendCtrl[0].ui,GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexBlendCtrl[1].ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fTexDescrChanged)
+ {
+ WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXDESCR_S4, 1),GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexDescr.ui,GLuint);
+ imesa->Registers.TexDescr.s4.newPal = GL_FALSE;
+ }
+
+ if (imesa->Registers.changed.ni.fFogCtrlChanged)
+ {
+
+ WRITE_CMD(pBCIBase,SET_REGISTER(SAVAGE_FOGCTRL_S4, 1),GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.FogCtrl.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fDestCtrlChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DESTCTRL_S4,1),GLuint);
+ WRITE_CMD( pBCIBase ,imesa->Registers.DestCtrl.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fDrawLocalCtrlChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DRAWLOCALCTRL_S4,1),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.DrawLocalCtrl.ui,GLuint);
+ }
+ /*
+ * Scissors updates drawctrl0 and drawctrl 1
+ */
+
+ if (imesa->Registers.changed.ni.fScissorsChanged)
+ {
+ if(imesa->scissor)
+ {
+ imesa->Registers.DrawCtrl0.ni.scissorXStart = imesa->scissor_rect.x1;
+ imesa->Registers.DrawCtrl0.ni.scissorYStart = imesa->scissor_rect.y1;
+ imesa->Registers.DrawCtrl1.ni.scissorXEnd = imesa->scissor_rect.x2-1;
+ imesa->Registers.DrawCtrl1.ni.scissorYEnd = imesa->scissor_rect.y2-1;
+ }
+ else
+ {
+ imesa->Registers.DrawCtrl0.ni.scissorXStart = imesa->draw_rect.x1;
+ imesa->Registers.DrawCtrl0.ni.scissorYStart = imesa->draw_rect.y1;
+ imesa->Registers.DrawCtrl1.ni.scissorXEnd = imesa->draw_rect.x2-1;
+ imesa->Registers.DrawCtrl1.ni.scissorYEnd = imesa->draw_rect.y2-1;
+ }
+
+ imesa->Registers.changed.ni.fDrawCtrl0Changed=GL_TRUE;
+ imesa->Registers.changed.ni.fDrawCtrl1Changed=GL_TRUE;
+ }
+ if (imesa->Registers.changed.uiRegistersChanged )
+ {
+
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DRAWCTRLGLOBAL0_S4,2),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.DrawCtrl0.ui,GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.DrawCtrl1.ui,GLuint);
+
+ }
+
+ if (imesa->Registers.changed.ni.fZBufCtrlChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_ZBUFCTRL_S4,1),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.ZBufCtrl.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fStencilCtrlChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_STENCILCTRL_S4,1),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.StencilCtrl.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fTexBlendColorChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_TEXBLENDCOLOR_S4,1),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.TexBlendColor.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fZWatermarksChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_ZWATERMARK_S4,1),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.ZWatermarks.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fDestTexWatermarksChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DESTTEXRWWATERMARK_S4,1),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.DestTexWatermarks.ui,GLuint);
+ }
+
+ imesa->Registers.changed.uiRegistersChanged = 0;
+ imesa->dirty=0;
+ savageDMACommit (imesa, pBCIBase);
+}
+static void savageUpdateRegister_s3d(savageContextPtr imesa)
+{
+ GLuint *pBCIBase;
+ pBCIBase = savageDMAAlloc (imesa, 100);
+
+ /* Always wait for idle for now.
+ * FIXME: On the Savage3D individual fields in registers can be
+ * local/global. */
+ WRITE_CMD(pBCIBase,WAIT_3D_IDLE,GLuint);
+
+ if (imesa->Registers.changed.ni.fZBufCtrlChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_ZBUFCTRL_S3D,1),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.ZBufCtrl.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fDestCtrlChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DESTCTRL_S3D,1),GLuint);
+ WRITE_CMD( pBCIBase ,imesa->Registers.DestCtrl.ui,GLuint);
+ }
+ /* Better leave these alone. They don't seem to be needed and I
+ * don't know exactly what they ary good for. Changing them may
+ * have been responsible for lockups with texturing. */
+/*
+ if (imesa->Registers.changed.ni.fZWatermarksChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_ZWATERMARK_S3D,1),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.ZWatermarks.ui,GLuint);
+ }
+ if (imesa->Registers.changed.ni.fDestTexWatermarksChanged)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DESTTEXRWWATERMARK_S3D,1),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.DestTexWatermarks.ui,GLuint);
+ }
+*/
+ if (imesa->Registers.changed.ni.fDrawCtrlChanged)
+ {
+ /* Same as above. The utah-driver always sets these to true.
+ * Changing them definitely caused lockups with texturing. */
+ imesa->Registers.DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_TRUE;
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_DRAWCTRL_S3D,1),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.DrawCtrl.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fScissorsChanged)
+ {
+ if(imesa->scissor)
+ {
+ imesa->Registers.ScissorsStart.ni.scissorXStart =
+ imesa->scissor_rect.x1;
+ imesa->Registers.ScissorsStart.ni.scissorYStart =
+ imesa->scissor_rect.y1;
+ imesa->Registers.ScissorsEnd.ni.scissorXEnd =
+ imesa->scissor_rect.x2-1;
+ imesa->Registers.ScissorsEnd.ni.scissorYEnd =
+ imesa->scissor_rect.y2-1;
+ }
+ else
+ {
+ imesa->Registers.ScissorsStart.ni.scissorXStart =
+ imesa->draw_rect.x1;
+ imesa->Registers.ScissorsStart.ni.scissorYStart =
+ imesa->draw_rect.y1;
+ imesa->Registers.ScissorsEnd.ni.scissorXEnd =
+ imesa->draw_rect.x2-1;
+ imesa->Registers.ScissorsEnd.ni.scissorYEnd =
+ imesa->draw_rect.y2-1;
+ }
+
+ imesa->Registers.changed.ni.fScissorsStartChanged=GL_TRUE;
+ imesa->Registers.changed.ni.fScissorsEndChanged=GL_TRUE;
+ }
+ if (imesa->Registers.changed.uiRegistersChanged & 0x00C00000)
+ {
+ WRITE_CMD(pBCIBase , SET_REGISTER(SAVAGE_SCSTART_S3D,2),GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.ScissorsStart.ui,GLuint);
+ WRITE_CMD(pBCIBase , imesa->Registers.ScissorsEnd.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fTex0CtrlChanged)
+ {
+ WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXCTRL_S3D, 1),GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexCtrl[0].ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fFogCtrlChanged)
+ {
+ WRITE_CMD(pBCIBase,SET_REGISTER(SAVAGE_FOGCTRL_S3D, 1),GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.FogCtrl.ui,GLuint);
+ }
+
+ if (imesa->Registers.changed.ni.fTex0AddrChanged ||
+ imesa->Registers.changed.ni.fTexDescrChanged)
+ {
+ WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXADDR_S3D, 1),GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexAddr[0].ui,GLuint);
+ WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXDESCR_S3D, 1),GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexDescr.ui,GLuint);
+ imesa->Registers.TexDescr.s3d.newPal = GL_FALSE;
+ }
+
+ if (imesa->Registers.changed.ni.fTexPalAddrChanged)
+ {
+ WRITE_CMD(pBCIBase, SET_REGISTER(SAVAGE_TEXPALADDR_S3D, 1),GLuint);
+ WRITE_CMD(pBCIBase, imesa->Registers.TexPalAddr.ui,GLuint);
+ }
+
+ imesa->Registers.changed.uiRegistersChanged = 0;
+ imesa->dirty=0;
+ savageDMACommit (imesa, pBCIBase);
+}
+
+
+
+/* Push the state into the sarea and/or texture memory.
+ */
+void savageEmitHwStateLocked( savageContextPtr imesa )
+{
+ if (SAVAGE_DEBUG & DEBUG_VERBOSE_API)
+ savageDDPrintDirty( "\n\n\nsavageEmitHwStateLocked", imesa->dirty );
+
+ if (imesa->dirty & ~SAVAGE_UPLOAD_CLIPRECTS)
+ {
+ if (imesa->dirty & (SAVAGE_UPLOAD_CTX | SAVAGE_UPLOAD_TEX0 | \
+ SAVAGE_UPLOAD_TEX1 | SAVAGE_UPLOAD_BUFFERS))
+ {
+
+ SAVAGE_STATE_COPY(imesa);
+ /* update state to hw*/
+ if (imesa->driDrawable &&imesa->driDrawable->numClipRects ==0 )
+ {
+ return ;
+ }
+ if (imesa->savageScreen->chipset >= S3_SAVAGE4)
+ savageUpdateRegister_s4(imesa);
+ else
+ savageUpdateRegister_s3d(imesa);
+ }
+
+ imesa->sarea->dirty |= (imesa->dirty &
+ ~(SAVAGE_UPLOAD_TEX1|SAVAGE_UPLOAD_TEX0));
+ imesa->dirty &= SAVAGE_UPLOAD_CLIPRECTS;
+ }
+}
+
+
+
+static void savageDDInitState_s4( savageContextPtr imesa )
+{
+#if 1
+ *(GLuint *)&imesa->Registers.DestCtrl = 1<<7;
+#else
+ *(GLuint *)&imesa->Registers.DestCtrl = 0;
+#endif
+ *(GLuint *)&imesa->Registers.ZBufCtrl = 0;
+
+ imesa->Registers.ZBufCtrl.s4.zCmpFunc = LCS_Z_LESS;
+ imesa->Registers.ZBufCtrl.s4.wToZEn = GL_TRUE;
+ /*imesa->Registers.ZBufCtrl.ni.floatZEn = GL_TRUE;*/
+ *(GLuint *)&imesa->Registers.ZBufOffset = 0;
+ *(GLuint *)&imesa->Registers.FogCtrl = 0;
+ imesa->Registers.FogTable.ni.ulEntry[0] = 0;
+ imesa->Registers.FogTable.ni.ulEntry[1] = 0;
+ imesa->Registers.FogTable.ni.ulEntry[2] = 0;
+ imesa->Registers.FogTable.ni.ulEntry[3] = 0;
+ imesa->Registers.FogTable.ni.ulEntry[4] = 0;
+ imesa->Registers.FogTable.ni.ulEntry[5] = 0;
+ imesa->Registers.FogTable.ni.ulEntry[6] = 0;
+ imesa->Registers.FogTable.ni.ulEntry[7] = 0;
+ *(GLuint *)&imesa->Registers.TexDescr = 0;
+ imesa->Registers.TexAddr[0].ui = 0;
+ imesa->Registers.TexAddr[1].ui = 0;
+ imesa->Registers.TexPalAddr.ui = 0;
+ *(GLuint *)&imesa->Registers.TexCtrl[0] = 0;
+ *(GLuint *)&imesa->Registers.TexCtrl[1] = 0;
+ imesa->Registers.TexBlendCtrl[0].ui = TBC_NoTexMap;
+ imesa->Registers.TexBlendCtrl[1].ui = TBC_NoTexMap1;
+ *(GLuint *)&imesa->Registers.DrawCtrl0 = 0;
+#if 1/*def __GL_HALF_PIXEL_OFFSET*/
+ *(GLuint *)&imesa->Registers.DrawCtrl1 = 0;
+#else
+ *(GLuint *)&imesa->Registers.DrawCtrl1 = 1<<11;
+#endif
+ *(GLuint *)&imesa->Registers.DrawLocalCtrl = 0;
+ *(GLuint *)&imesa->Registers.StencilCtrl = 0;
+
+ /* Set DestTexWatermarks_31,30 to 01 always.
+ *Has no effect if dest. flush is disabled.
+ */
+#if 0
+ *(GLuint *)&imesa->Registers.ZWatermarks = 0x12000C04;
+ *(GLuint *)&imesa->Registers.DestTexWatermarks = 0x40200400;
+#else
+ *(GLuint *)&imesa->Registers.ZWatermarks = 0x16001808;
+ *(GLuint *)&imesa->Registers.DestTexWatermarks = 0x4f000000;
+#endif
+ imesa->Registers.DrawCtrl0.ni.DPerfAccelEn = GL_TRUE;
+
+ /* clrCmpAlphaBlendCtrl is needed to get alphatest and
+ * alpha blending working properly
+ */
+
+ imesa->Registers.TexCtrl[0].s4.dBias = 0x08;
+ imesa->Registers.TexCtrl[1].s4.dBias = 0x08;
+ imesa->Registers.TexCtrl[0].s4.texXprEn = GL_TRUE;
+ imesa->Registers.TexCtrl[1].s4.texXprEn = GL_TRUE;
+ imesa->Registers.TexCtrl[0].s4.dMax = 0x0f;
+ imesa->Registers.TexCtrl[1].s4.dMax = 0x0f;
+ imesa->Registers.DrawLocalCtrl.ni.drawUpdateEn = GL_TRUE;
+ imesa->Registers.DrawLocalCtrl.ni.srcAlphaMode = SAM_One;
+ imesa->Registers.DrawLocalCtrl.ni.wrZafterAlphaTst = GL_FALSE;
+ imesa->Registers.DrawLocalCtrl.ni.flushPdZbufWrites= GL_TRUE;
+ imesa->Registers.DrawLocalCtrl.ni.flushPdDestWrites= GL_TRUE;
+
+ imesa->Registers.DrawLocalCtrl.ni.zUpdateEn= GL_TRUE;
+ imesa->Registers.DrawCtrl1.ni.ditherEn=GL_TRUE;
+ imesa->Registers.DrawCtrl1.ni.cullMode = BCM_None;
+
+ imesa->LcsCullMode=BCM_None;
+ imesa->Registers.TexDescr.s4.palSize = TPS_256;
+}
+static void savageDDInitState_s3d( savageContextPtr imesa )
+{
+#if 1
+ imesa->Registers.DestCtrl.ui = 1<<7;
+#else
+ imesa->Registers.DestCtrl.ui = 0;
+#endif
+ imesa->Registers.ZBufCtrl.ui = 0;
+
+ imesa->Registers.ZBufCtrl.s3d.zCmpFunc = LCS_Z_LESS & 0x07;
+ imesa->Registers.ZBufOffset.ui = 0;
+ imesa->Registers.FogCtrl.ui = 0;
+ memset (imesa->Registers.FogTable.ni.ucEntry, 0, 64);
+ imesa->Registers.TexDescr.ui = 0;
+ imesa->Registers.TexAddr[0].ui = 0;
+ imesa->Registers.TexPalAddr.ui = 0;
+ imesa->Registers.TexCtrl[0].ui = 0;
+#if 1/*def __GL_HALF_PIXEL_OFFSET*/
+ imesa->Registers.DrawCtrl.ui = 0;
+#else
+ imesa->Registers.DrawCtrl.ui = 1<<1;
+#endif
+ imesa->Registers.ScissorsStart.ui = 0;
+ imesa->Registers.ScissorsEnd.ui = 0;
+
+ /* Set DestTexWatermarks_31,30 to 01 always.
+ *Has no effect if dest. flush is disabled.
+ */
+#if 0
+ imesa->Registers.ZWatermarks.ui = 0x12000C04;
+ imesa->Registers.DestTexWatermarks.ui = 0x40200400;
+#else
+ imesa->Registers.ZWatermarks.ui = 0x16001808;
+ imesa->Registers.DestTexWatermarks.ui = 0x4f000000;
+#endif
+
+ /* clrCmpAlphaBlendCtrl is needed to get alphatest and
+ * alpha blending working properly
+ */
+
+ imesa->Registers.TexCtrl[0].s3d.dBias = 0x08;
+ imesa->Registers.TexCtrl[0].s3d.texXprEn = GL_TRUE;
+
+ imesa->Registers.ZBufCtrl.s3d.drawUpdateEn = GL_TRUE;
+ imesa->Registers.ZBufCtrl.s3d.wrZafterAlphaTst = GL_FALSE;
+ imesa->Registers.ZBufCtrl.s3d.zUpdateEn = GL_TRUE;
+
+ imesa->Registers.DrawCtrl.ni.srcAlphaMode = SAM_One;
+ imesa->Registers.DrawCtrl.ni.flushPdZbufWrites = GL_TRUE;
+ imesa->Registers.DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+
+ imesa->Registers.DrawCtrl.ni.ditherEn = GL_TRUE;
+ imesa->Registers.DrawCtrl.ni.cullMode = BCM_None;
+
+ imesa->LcsCullMode = BCM_None;
+ imesa->Registers.TexDescr.s3d.palSize = TPS_256;
+}
+void savageDDInitState( savageContextPtr imesa ) {
+ volatile GLuint* pBCIBase;
+ if (imesa->savageScreen->chipset >= S3_SAVAGE4)
+ savageDDInitState_s4 (imesa);
+ else
+ savageDDInitState_s3d (imesa);
+
+ /*fprintf(stderr,"DBflag:%d\n",imesa->glCtx->Visual->DBflag);*/
+ imesa->Registers.DestCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
+ if(imesa->savageScreen->cpp == 2)
+ {
+ imesa->Registers.DestCtrl.ni.dstPixFmt = 0;
+ imesa->Registers.DestCtrl.ni.dstWidthInTile =
+ (imesa->savageScreen->width+63)>>6;
+ }
+ else
+ {
+ imesa->Registers.DestCtrl.ni.dstPixFmt = 1;
+ imesa->Registers.DestCtrl.ni.dstWidthInTile =
+ (imesa->savageScreen->width+31)>>5;
+ }
+
+ imesa->IsDouble = GL_TRUE;
+
+ imesa->NotFirstFrame = GL_FALSE;
+ imesa->Registers.ZBufOffset.ni.offset=imesa->savageScreen->depthOffset>>11;
+ if(imesa->savageScreen->zpp == 2)
+ {
+ imesa->Registers.ZBufOffset.ni.zBufWidthInTiles =
+ (imesa->savageScreen->width+63)>>6;
+ imesa->Registers.ZBufOffset.ni.zDepthSelect = 0;
+ }
+ else
+ {
+ imesa->Registers.ZBufOffset.ni.zBufWidthInTiles =
+ (imesa->savageScreen->width+31)>>5;
+ imesa->Registers.ZBufOffset.ni.zDepthSelect = 1;
+ }
+
+ if (imesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT) {
+ if(imesa->IsFullScreen)
+ {
+ imesa->toggle = TARGET_BACK;
+
+ imesa->drawMap = (char *)imesa->apertureBase[imesa->toggle];
+ imesa->readMap = (char *)imesa->apertureBase[imesa->toggle];
+ }
+ else
+ {
+ imesa->drawMap = (char *)imesa->apertureBase[TARGET_BACK];
+ imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
+ }
+
+ } else {
+
+ if(imesa->IsFullScreen)
+ {
+ imesa->toggle = TARGET_BACK;
+
+ imesa->drawMap = (char *)imesa->apertureBase[imesa->toggle];
+ imesa->readMap = (char *)imesa->apertureBase[imesa->toggle];
+ }
+ else
+ {
+ imesa->drawMap = (char *)imesa->apertureBase[TARGET_BACK];
+ imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
+ }
+ }
+
+#if 0
+ if(imesa->driDrawable)
+ {
+ LOCK_HARDWARE(imesa);
+ }
+ pBCIBase=SAVAGE_GET_BCI_POINTER(imesa,38);
+ *pBCIBase++ = WAIT_3D_IDLE;
+ pBCIBase[0] = SET_REGISTER(DST,1);
+ pBCIBase[1] = imesa->Registers.DestCtrl.ui;
+ pBCIBase+=2;
+
+ pBCIBase[0] = SET_REGISTER(ZBUFCTRL,1);
+ pBCIBase[1] = imesa->Registers.ZBufCtrl.ui;
+ pBCIBase+=2;
+
+ pBCIBase[0] = SET_REGISTER(ZBUFOFF,1);
+ pBCIBase[1] = imesa->Registers.ZBufOffset.ui;
+ pBCIBase+=2;
+
+ pBCIBase[0] = SET_REGISTER(FOGCTRL,1);
+ pBCIBase[1] = imesa->Registers.FogCtrl.ui;
+ pBCIBase+=2;
+
+
+ pBCIBase[0] = SET_REGISTER(FOGTABLE,8);
+ memcpy((GLvoid *)(pBCIBase+1),(GLvoid *)imesa->Registers.FogTable.ni.ulEntry,32);
+ pBCIBase+=9;
+
+ pBCIBase[0] = SET_REGISTER(DRAWLOCALCTRL,1);
+ pBCIBase[1] = imesa->Registers.DrawLocalCtrl.ui;
+ pBCIBase+=2;
+
+ pBCIBase[0] = SET_REGISTER(DRAWCTRLGLOBAL0,2);
+ pBCIBase[1] = imesa->Registers.DrawCtrl0.ui;
+ pBCIBase[2] = imesa->Registers.DrawCtrl1.ui;
+ pBCIBase+=3;
+
+
+ pBCIBase[0] = SET_REGISTER(TEXPALADDR,1);
+ pBCIBase[1] = imesa->Registers.TexPalAddr.ui;
+ pBCIBase+=2;
+
+
+ pBCIBase[0] = SET_REGISTER(TEXCTRL0,6);
+ pBCIBase[1] = imesa->Registers.TexCtrl[0].ui;
+ pBCIBase[2] = imesa->Registers.TexCtrl[1].ui;
+
+ pBCIBase[3] = imesa->Registers.TexAddr[0].ui;
+ pBCIBase[4] = imesa->Registers.TexAddr[1].ui;
+ pBCIBase[5] = imesa->Registers.TexBlendCtrl[0].ui;
+ pBCIBase[6] = imesa->Registers.TexBlendCtrl[1].ui;
+ pBCIBase+=7;
+
+ pBCIBase[0] = SET_REGISTER(TEXDESCR,1);
+ pBCIBase[1] = imesa->Registers.TexDescr.ui;
+ pBCIBase+=2;
+
+
+ pBCIBase[0] = SET_REGISTER(STENCILCTRL,1);
+ pBCIBase[1] = imesa->Registers.StencilCtrl.ui;
+ pBCIBase+=2;
+
+ pBCIBase[0] = SET_REGISTER(ZWATERMARK,1);
+ pBCIBase[1] = imesa->Registers.ZWatermarks.ui;
+ pBCIBase+=2;
+
+ pBCIBase[0] = SET_REGISTER(DESTTEXRWWATERMARK,1);
+ pBCIBase[1] = imesa->Registers.DestTexWatermarks.ui;
+ pBCIBase+=2;
+
+ if(imesa->driDrawable)
+ {
+ UNLOCK_HARDWARE(imesa);
+ }
+#else
+ if(imesa->driDrawable)
+ LOCK_HARDWARE(imesa);
+
+ /* This is the only reg that is not emitted in savageUpdateRegisters.
+ * FIXME: Should this be set by the Xserver? */
+ pBCIBase = SAVAGE_GET_BCI_POINTER(imesa,3);
+ *pBCIBase++ = WAIT_3D_IDLE;
+ *pBCIBase++ = SET_REGISTER(SAVAGE_ZBUFOFF_S4,1); /* The same on S3D. */
+ *pBCIBase++ = imesa->Registers.ZBufOffset.ui;
+
+ if(imesa->driDrawable)
+ UNLOCK_HARDWARE(imesa);
+ imesa->Registers.changed.uiRegistersChanged = ~0;
+#endif
+}
+
+
+#define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|\
+ NEW_TEXTURE_MATRIX|\
+ NEW_USER_CLIP|NEW_CLIENT_STATE))
+
+void savageDDRenderStart(GLcontext *ctx)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+ __DRIdrawablePrivate *dPriv = imesa->driDrawable;
+ XF86DRIClipRectPtr pbox;
+ GLint nbox;
+
+ /* if the screen is overrided by other application. set the scissor.
+ * In MulitPass, re-render the screen.
+ */
+ pbox = dPriv->pClipRects;
+ nbox = dPriv->numClipRects;
+ if (nbox)
+ {
+ imesa->currentClip = nbox;
+ /* set scissor to the first clip box*/
+ savageDDScissor(ctx,pbox->x1,pbox->y1,pbox->x2,pbox->y2);
+
+ savageUpdateCull(ctx);
+ savageDDUpdateHwState(ctx); /* update to hardware register*/
+ }
+ else /* need not render at all*/
+ {
+ /*ctx->VB->CopyStart = ctx->VB->Count;*/
+ }
+ LOCK_HARDWARE(SAVAGE_CONTEXT(ctx));
+}
+
+
+void savageDDRenderEnd(GLcontext *ctx)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+
+ UNLOCK_HARDWARE(SAVAGE_CONTEXT(ctx));
+ if(!imesa->IsDouble)
+ {
+ savageSwapBuffers(imesa->driDrawable);
+ }
+
+}
+
+static void savageDDInvalidateState( GLcontext *ctx, GLuint new_state )
+{
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+ SAVAGE_CONTEXT(ctx)->new_gl_state |= new_state;
+}
+
+
+void savageDDInitStateFuncs(GLcontext *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.PolygonMode=NULL;
+ ctx->Driver.PolygonStipple = 0;
+ ctx->Driver.LineStipple = 0;
+ ctx->Driver.LineWidth = 0;
+ ctx->Driver.LogicOpcode = 0;
+ ctx->Driver.DrawBuffer = savageDDDrawBuffer;
+ ctx->Driver.ReadBuffer = savageDDReadBuffer;
+ ctx->Driver.ClearColor = savageDDClearColor;
+
+ ctx->Driver.DepthRange = savageDepthRange;
+ ctx->Driver.Viewport = savageViewport;
+ ctx->Driver.RenderMode = savageRenderMode;
+
+ ctx->Driver.ClearIndex = 0;
+ ctx->Driver.IndexMask = 0;
+
+ 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;
+#if HW_STENCIL
+ ctx->Driver.StencilFunc = savageDDStencilFunc;
+ ctx->Driver.StencilMask = savageDDStencilMask;
+ ctx->Driver.StencilOp = savageDDStencilOp;
+#else
+ ctx->Driver.StencilFunc = 0;
+ ctx->Driver.StencilMask = 0;
+ ctx->Driver.StencilOp = 0;
+#endif /* end #if HW_STENCIL */
+ } 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.StencilFunc = 0;
+ ctx->Driver.StencilMask = 0;
+ ctx->Driver.StencilOp = 0;
+ }
+
+ /* Swrast hooks for imaging extensions:
+ */
+ ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+ ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+ ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+}
diff --git a/src/mesa/drivers/dri/savage/savagestate.h b/src/mesa/drivers/dri/savage/savagestate.h
new file mode 100644
index 0000000000..cc3038904d
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagestate.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+
+#ifndef _SAVAGE_STATE_H
+#define _SAVAGE_STATE_H
+
+#include "savagecontext.h"
+
+extern void savageDDUpdateHwState( GLcontext *ctx );
+extern void savageDDInitState( savageContextPtr imesa );
+extern void savageDDInitStateFuncs( GLcontext *ctx );
+extern void savageDDRenderStart(GLcontext *ctx);
+extern void savageDDRenderEnd(GLcontext *ctx);
+extern void savageDDScissor( GLcontext *ctx, GLint x, GLint y,GLsizei w, GLsizei h );
+
+/*frank 2001/11/13 add macro for sarea state copy*/
+#define SAVAGE_STATE_COPY(ctx) { \
+ctx->sarea->setup[0]=ctx->Registers.DrawLocalCtrl.ui; \
+ctx->sarea->setup[1]=ctx->Registers.TexPalAddr.ui; \
+ctx->sarea->setup[2]=ctx->Registers.TexCtrl[0].ui; \
+ctx->sarea->setup[3]=ctx->Registers.TexCtrl[1].ui; \
+ctx->sarea->setup[4]=ctx->Registers.TexAddr[0].ui; \
+ctx->sarea->setup[5]=ctx->Registers.TexAddr[1].ui; \
+ctx->sarea->setup[6]=ctx->Registers.TexBlendCtrl[0].ui; \
+ctx->sarea->setup[7]=ctx->Registers.TexBlendCtrl[1].ui; \
+ctx->sarea->setup[8]=ctx->Registers.TexXprClr.ui; \
+ctx->sarea->setup[9]=ctx->Registers.TexDescr.ui; \
+ctx->sarea->setup[10]=ctx->Registers.FogTable.ni.ulEntry[0]; \
+ctx->sarea->setup[11]=ctx->Registers.FogTable.ni.ulEntry[1]; \
+ctx->sarea->setup[12]=ctx->Registers.FogTable.ni.ulEntry[2]; \
+ctx->sarea->setup[13]=ctx->Registers.FogTable.ni.ulEntry[3]; \
+ctx->sarea->setup[14]=ctx->Registers.FogTable.ni.ulEntry[4]; \
+ctx->sarea->setup[15]=ctx->Registers.FogTable.ni.ulEntry[5]; \
+ctx->sarea->setup[16]=ctx->Registers.FogTable.ni.ulEntry[6]; \
+ctx->sarea->setup[17]=ctx->Registers.FogTable.ni.ulEntry[7]; \
+ctx->sarea->setup[18]=ctx->Registers.FogCtrl.ui; \
+ctx->sarea->setup[19]=ctx->Registers.StencilCtrl.ui; \
+ctx->sarea->setup[20]=ctx->Registers.ZBufCtrl.ui; \
+ctx->sarea->setup[21]=ctx->Registers.ZBufOffset.ui; \
+ctx->sarea->setup[22]=ctx->Registers.DestCtrl.ui; \
+ctx->sarea->setup[23]=ctx->Registers.DrawCtrl0.ui; \
+ctx->sarea->setup[24]=ctx->Registers.DrawCtrl1.ui; \
+ctx->sarea->setup[25]=ctx->Registers.ZWatermarks.ui; \
+ctx->sarea->setup[26]=ctx->Registers.DestTexWatermarks.ui; \
+ctx->sarea->setup[27]=ctx->Registers.TexBlendColor.ui; \
+}
+#endif
diff --git a/src/mesa/drivers/dri/savage/savagetex.c b/src/mesa/drivers/dri/savage/savagetex.c
new file mode 100644
index 0000000000..94a4b23aec
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagetex.c
@@ -0,0 +1,2022 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+
+#include <GL/gl.h>
+
+#include "mm.h"
+#include "savagecontext.h"
+#include "savagetex.h"
+#include "savagetris.h"
+#include "savageioctl.h"
+#include "simple_list.h"
+#include "enums.h"
+#include "savage_bci.h"
+
+#include "macros.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "texobj.h"
+
+#include "swrast/swrast.h"
+
+/* declarations of static and inline functions */
+__inline GLuint GetTiledCoordinates8(GLuint iBufferWidth, GLint x, GLint y);
+static GLuint GetTiledCoordinates16_4( GLint iBufferWidth,GLint x,GLint y );
+static GLuint GetTiledCoordinates16_8( GLint iBufferWidth,GLint x,GLint y );
+static GLuint GetTiledCoordinates32_4( GLint iBufferWidth, GLint x, GLint y );
+static GLuint GetTiledCoordinates32_8( GLint iBufferWidth, GLint x, GLint y );
+__inline GLuint GetTiledCoordinates( GLint iDepth,GLint iBufferWidth,GLint x,GLint y );
+__inline void savageUploadImage(savageTextureObjectPtr t, GLuint level, GLuint startx, GLuint starty, GLuint reloc);
+__inline void savageTileTex(savageTextureObjectPtr tex, GLuint level);
+
+/* tile sizes depending on texel color depth */
+GLuint gTileWidth[5] =
+{
+ 64, /* 4-bit */
+ 64, /* 8-bit */
+ 64, /* 16-bit */
+ 0, /* 24-bit */
+ 32 /* 32-bit */
+};
+
+GLuint gTileHeight[5] =
+{
+ 64, /* 4-bit */
+ 32, /* 8-bit */
+ 16, /* 16-bit */
+ 0, /* 24-bit */
+ 16 /* 32-bit */
+};
+
+__inline GLuint GetTiledCoordinates8(GLuint iBufferWidth, GLint x, GLint y)
+{
+ GLint x10, x106, x52;
+ GLint y20, y105, y43;
+ GLuint uWidthInTiles;
+
+ uWidthInTiles = (iBufferWidth + 63) >> 6;
+ x10 = x & 0x3;
+ x52 = (x & 0x3c) >> 2;
+ x106 = (x & 0x7c0) >> 6;
+
+ y20 = y & 0x7;
+ y43 = (y & 0x18) >> 3;
+ y105 = (y & 0x7e0) >> 5;
+
+ return ( x10 |
+ (y20 << 2) |
+ (x52 << 5) |
+ (y43 << 9) |
+ ((y105 * uWidthInTiles) + x106) << 11 );
+}
+
+/* 4-pixel wide subtiles */
+static GLuint GetTiledCoordinates16_4( GLint iBufferWidth,
+ GLint x,
+ GLint y )
+{
+ GLint x106;
+ GLint x10;
+ GLint x52;
+ GLint y104;
+ GLint y20;
+ GLint y3;
+ GLuint uiWidthInTiles;
+
+ /*
+ // calculating tiled address
+ */
+
+ uiWidthInTiles = (iBufferWidth + 63) >> 6;
+
+ x10 = x & 0x3;
+ x52 = (x & 0x3c ) >> 2;
+ x106 = (x & 0x7c0) >> 6;
+
+ y20 = y & 0x7;
+ y3 = (y & 8 ) >> 3;
+ y104 = (y & 0x7f0) >> 4;
+
+ return( (x10 << 1) |
+ (y20 << 3) |
+ (x52 << 6) |
+ (y3 << 10) |
+ ((y104 * uiWidthInTiles) + x106) << 11 );
+}
+/* 8-pixel wide subtiles */
+static GLuint GetTiledCoordinates16_8( GLint iBufferWidth,
+ GLint x,
+ GLint y )
+{
+ GLint x106;
+ GLint x20;
+ GLint x53;
+ GLint y104;
+ GLint y20;
+ GLint y3;
+ GLuint uiWidthInTiles;
+
+ /*
+ // calculating tiled address
+ */
+
+ uiWidthInTiles = (iBufferWidth + 63) >> 6;
+
+ x20 = x & 0x7;
+ x53 = (x & 0x38 ) >> 3;
+ x106 = (x & 0x7c0) >> 6;
+
+ y20 = y & 0x7;
+ y3 = (y & 8 ) >> 3;
+ y104 = (y & 0x7f0) >> 4;
+
+ return( (x20 << 1) |
+ (y20 << 4) |
+ (x53 << 7) |
+ (y3 << 10) |
+ ((y104 * uiWidthInTiles) + x106) << 11 );
+}
+/* function pointer set to the correct version in savageDDInitTextureFuncs */
+GLuint (*GetTiledCoordinates16) (GLint, GLint, GLint);
+
+/* 4-pixel wide subtiles */
+static GLuint GetTiledCoordinates32_4( GLint iBufferWidth,
+ GLint x,
+ GLint y )
+{
+ GLint x10;
+ GLint y20;
+ GLuint uiWidthInTiles;
+ GLint x42;
+ GLint x105;
+ GLint y3;
+ GLint y104;
+
+ /*
+ // calculating tiled address
+ */
+
+ uiWidthInTiles = (iBufferWidth + 31) >> 5;
+
+ x10 = x & 0x3;
+ x42 = (x & 0x1c ) >> 2;
+ x105 = (x & 0x7e0) >> 5;
+
+ y20 = y & 0x7;
+ y3 = (y & 8 ) >> 3;
+ y104 = (y & 0x7f0) >> 4;
+
+ return( (x10 << 2) |
+ (y20 << 4) |
+ (x42 << 7) |
+ (y3 << 10) |
+ ((y104 * uiWidthInTiles) + x105) << 11 );
+}
+/* 8-pixel wide subtiles */
+static GLuint GetTiledCoordinates32_8( GLint iBufferWidth,
+ GLint x,
+ GLint y )
+{
+ GLint x20;
+ GLint y20;
+ GLuint uiWidthInTiles;
+ GLint x43;
+ GLint x105;
+ GLint y3;
+ GLint y104;
+
+ /*
+ // calculating tiled address
+ */
+
+ uiWidthInTiles = (iBufferWidth + 31) >> 5;
+
+ x20 = x & 0x7;
+ x43 = (x & 0x18 ) >> 3;
+ x105 = (x & 0x7e0) >> 5;
+
+ y20 = y & 0x7;
+ y3 = (y & 8 ) >> 3;
+ y104 = (y & 0x7f0) >> 4;
+
+ return( (x20 << 2) |
+ (y20 << 5) |
+ (x43 << 8) |
+ (y3 << 10) |
+ ((y104 * uiWidthInTiles) + x105) << 11 );
+}
+/* function pointer set to the correct version in savageDDInitTextureFuncs */
+GLuint (*GetTiledCoordinates32) (GLint, GLint, GLint);
+
+__inline GLuint GetTiledCoordinates( GLint iDepth,
+ GLint iBufferWidth,
+ GLint x,
+ GLint y )
+{
+ /*
+ // don't check for 4 since we only have 3 types of fb
+ */
+
+ if (iDepth == 16)
+ {
+ return( GetTiledCoordinates16( iBufferWidth, x, y ) );
+ }
+ else if (iDepth == 32)
+ {
+ return( GetTiledCoordinates32( iBufferWidth, x, y ) );
+ }
+ else
+ {
+ return( GetTiledCoordinates8( iBufferWidth, x, y ) );
+ }
+}
+
+__inline void savageUploadImage(savageTextureObjectPtr t, GLuint level, GLuint startx, GLuint starty, GLuint reloc)
+{
+ GLuint uMaxTileWidth = gTileWidth[t->texelBytes];
+ GLuint x, y, w, row, col;
+ const struct gl_texture_image *image = t->image[level].image;
+ GLubyte * dst, * src, * pBuffer;
+ GLint xAdd, yAdd;
+ GLuint uRowSeparator, uChunk = MIN_TILE_CHUNK, uWrap;
+
+
+ pBuffer = (GLubyte *)(t->BufAddr + t->image[level].offset);
+ src = (GLubyte *)image->Data;
+ x = startx;
+ y = starty;
+ w = image->Width;
+
+ if(image->Format == GL_COLOR_INDEX)
+ {
+ if(w < MIN_TILE_CHUNK)
+ {
+ w = MIN_TILE_CHUNK;
+ }
+ else
+ {
+ if((w > 64 ) && (image->Height <= 16))
+ {
+ reloc = GL_TRUE;
+ if(image->Height == 16)
+ {
+ uChunk = MIN_TILE_CHUNK << 1;
+ }
+ }
+ }
+
+ if(!reloc & (w > (64 / 2)))
+ {
+ for(row = 0; row < image->Height; row++)
+ {
+ for(col = 0; col < image->Width; col++)
+ {
+ dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, w, x + col, y + row);
+ memcpy (dst, src, t->texelBytes);
+ src += t->texelBytes;
+ }
+ }
+ }
+ else
+ {
+ if(reloc & (w > 64))
+ {
+ uWrap = ((w + 63) >> 6) - 1;
+ for(row = 0; row < image->Height; row++)
+ {
+ for(col = 0; col < image->Width; col++)
+ {
+ xAdd = (col / (4 * 64)) * 64 + col % 64;
+ yAdd = row + ((col / 64) & 3) * uChunk;
+ dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, 64, x + xAdd, y + yAdd);
+ memcpy (dst, src, t->texelBytes);
+ src += t->texelBytes;
+ }
+ }
+ }
+ else
+ {
+ uRowSeparator = 64 * MIN_TILE_CHUNK / w;
+ for(row = 0; row < image->Height; row++)
+ {
+ xAdd = (w * (row / MIN_TILE_CHUNK)) % 64;
+ yAdd = row % MIN_TILE_CHUNK + MIN_TILE_CHUNK * (row / uRowSeparator);
+ for(col = 0; col < image->Width; col++)
+ {
+ dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, w, x + xAdd, y + yAdd);
+ memcpy (dst, src, t->texelBytes);
+ src += t->texelBytes;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if(w < MIN_TILE_CHUNK)
+ {
+ w = MIN_TILE_CHUNK;
+ }
+ else
+ {
+ if((w > uMaxTileWidth ) && (image->Height <= 8))
+ {
+ reloc = GL_TRUE;
+ }
+ }
+ if(!reloc & (w > uMaxTileWidth / 2))
+ {
+ for(row = 0; row < image->Height; row++)
+ {
+ for(col = 0; col < image->Width; col++)
+ {
+ dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, w, x + col, y + row);
+ memcpy (dst, src, t->texelBytes);
+ src += t->texelBytes;
+ }
+ }
+ }
+ else
+ {
+ if(reloc & (w > uMaxTileWidth))
+ {
+ for(row = 0; row < image->Height; row++)
+ {
+ for(col = 0; col < image->Width; col++)
+ {
+ xAdd = (col / (2 * uMaxTileWidth)) * uMaxTileWidth + col % uMaxTileWidth;
+ yAdd = row + ((col / uMaxTileWidth) & 1) * MIN_TILE_CHUNK;
+ dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, w, x + xAdd, y + yAdd);
+ memcpy (dst, src, t->texelBytes);
+ src += t->texelBytes;
+ }
+ }
+ }
+ else
+ {
+ uRowSeparator = uMaxTileWidth * MIN_TILE_CHUNK / w;
+ for(row = 0; row < image->Height; row++)
+ {
+ yAdd = row % MIN_TILE_CHUNK + MIN_TILE_CHUNK * (row / uRowSeparator);
+ xAdd = (w * (row / MIN_TILE_CHUNK)) % uMaxTileWidth;
+ for(col = 0; col < image->Width; col++)
+ {
+ dst = pBuffer + GetTiledCoordinates(t->texelBytes << 3, w, x + col + xAdd, y + yAdd);
+ memcpy (dst, src, t->texelBytes);
+ src += t->texelBytes;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+__inline void savageTileTex(savageTextureObjectPtr tex, GLuint level)
+{
+ GLuint uWidth, uHeight;
+ GLint xOffset, yOffset;
+ GLint xStart=0, yStart=0;
+ GLint minSize;
+ GLuint xRepeat, yRepeat;
+ GLuint startCol, startRow;
+ GLuint reloc;
+
+ const struct gl_texture_image *image = tex->image[level].image;
+
+ reloc = GL_FALSE;
+ uWidth = image->Width2;
+ uHeight = image->Height2;
+
+ if((uWidth > 4) || (uHeight > 4))
+ minSize = MIN_TILE_CHUNK;
+ else
+ minSize = MIPMAP_CHUNK;
+
+ if(image->Width >= minSize)
+ xRepeat = 1;
+ else
+ xRepeat = minSize / image->Width;
+
+ if(image->Height >= minSize)
+ yRepeat = 1;
+ else
+ {
+ yRepeat = minSize / image->Height;
+ if(minSize == MIN_TILE_CHUNK)
+ reloc = GL_TRUE;
+ }
+
+ if(((uWidth < 4) && (uHeight < 4)) && (tex->texelBytes >= 2))
+ {
+ if((uWidth == 2) || (uHeight == 2))
+ {
+ xStart = 4;
+ yStart = 0;
+ }
+
+ else
+ {
+ xStart = 4;
+ yStart = 4;
+ }
+ }
+ for(xOffset = 0; xOffset < xRepeat; xOffset++)
+ {
+ for(yOffset = 0; yOffset < yRepeat; yOffset++)
+ {
+ startCol = image->Width * xOffset + xStart;
+ startRow = image->Height * yOffset + yStart;
+ savageUploadImage(tex,level, startCol, startRow, reloc);
+ }
+ }
+}
+
+static void savageSetTexWrapping(savageTextureObjectPtr tex, GLenum s, GLenum t)
+{
+ tex->texParams.sWrapMode = s;
+ tex->texParams.tWrapMode = t;
+}
+
+static void savageSetTexFilter(savageTextureObjectPtr t,
+ GLenum minf, GLenum magf)
+{
+ t->texParams.minFilter = minf;
+ t->texParams.magFilter = magf;
+}
+
+
+/* Need a fallback ?
+ */
+static void savageSetTexBorderColor(savageTextureObjectPtr t, GLubyte color[4])
+{
+/* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
+ t->texParams.boarderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]);
+}
+
+
+
+static savageTextureObjectPtr
+savageAllocTexObj( struct gl_texture_object *texObj )
+{
+ savageTextureObjectPtr t;
+
+ t = (savageTextureObjectPtr) calloc(1,sizeof(*t));
+ texObj->DriverData = t;
+ if ( t != NULL ) {
+
+ /* Initialize non-image-dependent parts of the state:
+ */
+ t->globj = texObj;
+
+ /* FIXME Something here to set initial values for other parts of
+ * FIXME t->setup?
+ */
+
+ make_empty_list( t );
+
+ savageSetTexWrapping(t,texObj->WrapS,texObj->WrapT);
+ savageSetTexFilter(t,texObj->MinFilter,texObj->MagFilter);
+ savageSetTexBorderColor(t,texObj->_BorderChan);
+ }
+
+ return t;
+}
+
+/* Called by the _mesa_store_teximage[123]d() functions. */
+static const struct gl_texture_format *
+savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ const GLboolean do32bpt = GL_FALSE;
+ const GLboolean force16bpt = GL_FALSE;
+ const GLboolean isSavage4 = (imesa->savageScreen->chipset >= S3_SAVAGE4);
+ (void) format;
+ (void) type;
+
+ switch ( internalFormat ) {
+ case 4:
+ case GL_RGBA:
+ case GL_COMPRESSED_RGBA:
+ switch ( type ) {
+ case GL_UNSIGNED_INT_10_10_10_2:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ return &_mesa_texformat_argb4444;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ return &_mesa_texformat_argb1555;
+ default:
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+ }
+
+ case 3:
+ case GL_RGB:
+ case GL_COMPRESSED_RGB:
+ switch ( type ) {
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ return &_mesa_texformat_argb4444;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ return &_mesa_texformat_argb1555;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ return &_mesa_texformat_rgb565;
+ default:
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
+ }
+
+ case GL_RGBA8:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return !force16bpt ?
+ &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+
+ case GL_RGB10_A2:
+ return !force16bpt ?
+ &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
+
+ case GL_RGBA4:
+ case GL_RGBA2:
+ return &_mesa_texformat_argb4444;
+
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
+
+ case GL_RGB5:
+ case GL_RGB4:
+ case GL_R3_G3_B2:
+ return &_mesa_texformat_rgb565;
+
+ case GL_ALPHA:
+ case GL_COMPRESSED_ALPHA:
+ return isSavage4 ? &_mesa_texformat_a8 : (
+ do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+ case GL_ALPHA4:
+ return isSavage4 ? &_mesa_texformat_a8 : &_mesa_texformat_argb4444;
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return isSavage4 ? &_mesa_texformat_a8 : (
+ !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+
+ case 1:
+ case GL_LUMINANCE:
+ case GL_COMPRESSED_LUMINANCE:
+ /* no alpha, but use argb1555 in 16bit case to get pure grey values */
+ return isSavage4 ? &_mesa_texformat_l8 : (
+ do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555);
+ case GL_LUMINANCE4:
+ return isSavage4 ? &_mesa_texformat_l8 : &_mesa_texformat_argb1555;
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return isSavage4 ? &_mesa_texformat_l8 : (
+ !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555);
+
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ /* Savage4 has a al44 texture format. But it's not supported by Mesa. */
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ return &_mesa_texformat_argb4444;
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+
+ case GL_INTENSITY:
+ case GL_COMPRESSED_INTENSITY:
+ return isSavage4 ? &_mesa_texformat_i8 : (
+ do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+ case GL_INTENSITY4:
+ return isSavage4 ? &_mesa_texformat_i8 : &_mesa_texformat_argb4444;
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return isSavage4 ? &_mesa_texformat_i8 : (
+ !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
+/*
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return &_mesa_texformat_ci8;
+*/
+ default:
+ _mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
+ return NULL;
+ }
+}
+
+static void savageSetTexImages( savageContextPtr imesa,
+ const struct gl_texture_object *tObj )
+{
+ savageTextureObjectPtr t = (savageTextureObjectPtr) tObj->DriverData;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ GLuint offset, width, pitch, i, textureFormat, log_pitch;
+
+ assert(t);
+ assert(image);
+
+ switch (image->TexFormat->MesaFormat) {
+ case MESA_FORMAT_ARGB8888:
+ textureFormat = TFT_ARGB8888;
+ t->texelBytes = 4;
+ break;
+ case MESA_FORMAT_ARGB1555:
+ textureFormat = TFT_ARGB1555;
+ t->texelBytes = 2;
+ break;
+ case MESA_FORMAT_ARGB4444:
+ textureFormat = TFT_ARGB4444;
+ t->texelBytes = 2;
+ break;
+ case MESA_FORMAT_RGB565:
+ textureFormat = TFT_RGB565;
+ t->texelBytes = 2;
+ break;
+ case MESA_FORMAT_L8:
+ textureFormat = TFT_L8;
+ t->texelBytes = 1;
+ break;
+ case MESA_FORMAT_I8:
+ textureFormat = TFT_I8;
+ t->texelBytes = 1;
+ break;
+ case MESA_FORMAT_A8:
+ textureFormat = TFT_A8;
+ t->texelBytes = 1;
+ break;
+ default:
+ _mesa_problem(imesa->glCtx, "Bad texture format in %s", __FUNCTION__);
+ }
+
+ /* Figure out the size now (and count the levels). Upload won't be done
+ * until later.
+ */
+ width = image->Width * t->texelBytes;
+ for (pitch = 2, log_pitch=1 ; pitch < width ; pitch *= 2 )
+ log_pitch++;
+
+ t->dirty_images = 0;
+ t->bound = 0;
+
+ offset = 0;
+ for ( i = 0 ; i < SAVAGE_TEX_MAXLEVELS && tObj->Image[0][i] ; i++ ) {
+ t->image[i].image = tObj->Image[0][i];
+ t->image[i].offset = offset;
+ t->image[i].internalFormat = textureFormat;
+ t->dirty_images |= (1<<i);
+ offset += t->image[i].image->Height * pitch;
+ pitch = pitch >> 1;
+ }
+
+ t->totalSize = offset;
+ t->max_level = i-1;
+ t->min_level = 0;
+}
+
+void savageDestroyTexObj(savageContextPtr imesa, savageTextureObjectPtr t)
+{
+ if (!t) return;
+
+ /* This is sad - need to sync *in case* we upload a texture
+ * to this newly free memory...
+ */
+ if (t->MemBlock) {
+ mmFreeMem(t->MemBlock);
+ t->MemBlock = 0;
+
+ if (t->age > imesa->dirtyAge)
+ imesa->dirtyAge = t->age;
+ }
+
+ if (t->globj)
+ t->globj->DriverData = 0;
+
+ if (t->bound)
+ imesa->CurrentTexObj[t->bound - 1] = 0;
+
+ remove_from_list(t);
+ free(t);
+}
+
+
+static void savageSwapOutTexObj(savageContextPtr imesa, savageTextureObjectPtr t)
+{
+ if (t->MemBlock) {
+ mmFreeMem(t->MemBlock);
+ t->MemBlock = 0;
+
+ if (t->age > imesa->dirtyAge)
+ imesa->dirtyAge = t->age;
+ }
+
+ t->dirty_images = ~0;
+ move_to_tail(&(imesa->SwappedOut), t);
+}
+
+
+
+/* Upload an image from mesa's internal copy.
+ */
+static void savageUploadTexLevel( savageTextureObjectPtr t, int level )
+{
+ const struct gl_texture_image *image = t->image[level].image;
+
+
+ /* Need triangle (rather than pixel) fallbacks to simulate this using
+ * normal textured triangles.
+ *
+ * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
+ *
+ */
+
+ if(image->Border != 0)
+ fprintf (stderr, "Not supported texture border %d.\n",
+ (int) image->Border);
+
+ savageTileTex(t, level);
+}
+
+
+
+void savagePrintLocalLRU( savageContextPtr imesa , GLuint heap)
+{
+ savageTextureObjectPtr t;
+ int sz = 1 << (imesa->savageScreen->logTextureGranularity[heap]);
+
+ foreach( t, &imesa->TexObjList[heap] ) {
+ if (!t->globj)
+ fprintf(stderr, "Placeholder %d at %x sz %x\n",
+ t->MemBlock->ofs / sz,
+ t->MemBlock->ofs,
+ t->MemBlock->size);
+ else
+ fprintf(stderr, "Texture (bound %d) at %x sz %x\n",
+ t->bound,
+ t->MemBlock->ofs,
+ t->MemBlock->size);
+
+ }
+}
+
+void savagePrintGlobalLRU( savageContextPtr imesa , GLuint heap)
+{
+ int i, j;
+
+ drm_savage_tex_region_t *list = imesa->sarea->texList[heap];
+
+
+ for (i = 0, j = SAVAGE_NR_TEX_REGIONS ; i < SAVAGE_NR_TEX_REGIONS ; i++) {
+ fprintf(stderr, "list[%d] age %d next %d prev %d\n",
+ j, list[j].age, list[j].next, list[j].prev);
+ j = list[j].next;
+ if (j == SAVAGE_NR_TEX_REGIONS) break;
+ }
+
+ if (j != SAVAGE_NR_TEX_REGIONS)
+ fprintf(stderr, "Loop detected in global LRU\n");
+ for (i = 0 ; i < SAVAGE_NR_TEX_REGIONS ; i++)
+ {
+ fprintf(stderr,"list[%d] age %d next %d prev %d\n",
+ i, list[i].age, list[i].next, list[i].prev);
+ }
+}
+
+
+void savageResetGlobalLRU( savageContextPtr imesa, GLuint heap )
+{
+ drm_savage_tex_region_t *list = imesa->sarea->texList[heap];
+ int sz = 1 << imesa->savageScreen->logTextureGranularity[heap];
+ int i;
+
+ /* (Re)initialize the global circular LRU list. The last element
+ * in the array (SAVAGE_NR_TEX_REGIONS) is the sentinal. Keeping it
+ * at the end of the array allows it to be addressed rationally
+ * when looking up objects at a particular location in texture
+ * memory.
+ */
+ for (i = 0 ; (i+1) * sz <= imesa->savageScreen->textureSize[heap]; i++) {
+ list[i].prev = i-1;
+ list[i].next = i+1;
+ list[i].age = 0;
+ }
+
+ i--;
+ list[0].prev = SAVAGE_NR_TEX_REGIONS;
+ list[i].prev = i-1;
+ list[i].next = SAVAGE_NR_TEX_REGIONS;
+ list[SAVAGE_NR_TEX_REGIONS].prev = i;
+ list[SAVAGE_NR_TEX_REGIONS].next = 0;
+ imesa->sarea->texAge[heap] = 0;
+}
+
+
+static void savageUpdateTexLRU( savageContextPtr imesa, savageTextureObjectPtr t )
+{
+ int i;
+ int heap = t->heap;
+ int logsz = imesa->savageScreen->logTextureGranularity[heap];
+ int start = t->MemBlock->ofs >> logsz;
+ int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;
+ drm_savage_tex_region_t *list = imesa->sarea->texList[heap];
+
+ imesa->texAge[heap] = ++imesa->sarea->texAge[heap];
+
+ /* Update our local LRU
+ */
+ move_to_head( &(imesa->TexObjList[heap]), t );
+
+ /* Update the global LRU
+ */
+ for (i = start ; i <= end ; i++) {
+
+ list[i].in_use = 1;
+ list[i].age = imesa->texAge[heap];
+
+ /* remove_from_list(i)
+ */
+ list[(unsigned)list[i].next].prev = list[i].prev;
+ list[(unsigned)list[i].prev].next = list[i].next;
+
+ /* insert_at_head(list, i)
+ */
+ list[i].prev = SAVAGE_NR_TEX_REGIONS;
+ list[i].next = list[SAVAGE_NR_TEX_REGIONS].next;
+ list[(unsigned)list[SAVAGE_NR_TEX_REGIONS].next].prev = i;
+ list[SAVAGE_NR_TEX_REGIONS].next = i;
+ }
+}
+
+
+/* Called for every shared texture region which has increased in age
+ * since we last held the lock.
+ *
+ * Figures out which of our textures have been ejected by other clients,
+ * and pushes a placeholder texture onto the LRU list to represent
+ * the other client's textures.
+ */
+void savageTexturesGone( savageContextPtr imesa,
+ GLuint heap,
+ GLuint offset,
+ GLuint size,
+ GLuint in_use )
+{
+ savageTextureObjectPtr t, tmp;
+
+ foreach_s ( t, tmp, &imesa->TexObjList[heap] ) {
+
+ if (t->MemBlock->ofs >= offset + size ||
+ t->MemBlock->ofs + t->MemBlock->size <= offset)
+ continue;
+
+ /* It overlaps - kick it off. Need to hold onto the currently bound
+ * objects, however.
+ */
+ if (t->bound)
+ savageSwapOutTexObj( imesa, t );
+ else
+ savageDestroyTexObj( imesa, t );
+ }
+
+
+ if (in_use) {
+ t = (savageTextureObjectPtr) calloc(1,sizeof(*t));
+ if (!t) return;
+
+ t->heap = heap;
+ t->MemBlock = mmAllocMem( imesa->texHeap[heap], size, 0, offset);
+ if(!t->MemBlock)
+ {
+ free(t);
+ return;
+ }
+ insert_at_head( &imesa->TexObjList[heap], t );
+ }
+}
+
+
+
+
+
+/* This is called with the lock held. May have to eject our own and/or
+ * other client's texture objects to make room for the upload.
+ */
+int savageUploadTexImages( savageContextPtr imesa, savageTextureObjectPtr t )
+{
+ int heap;
+ int i;
+ int ofs;
+
+ heap = t->heap = SAVAGE_CARD_HEAP;
+
+ /* Do we need to eject LRU texture objects?
+ */
+ if (!t->MemBlock) {
+ while (1)
+ {
+ t->MemBlock = mmAllocMem( imesa->texHeap[heap], t->totalSize, 12, 0 );
+ if (t->MemBlock)
+ break;
+ else
+ {
+ heap = t->heap = SAVAGE_AGP_HEAP;
+ t->MemBlock = mmAllocMem( imesa->texHeap[heap], t->totalSize, 12, 0 );
+
+ if (t->MemBlock)
+ break;
+ }
+
+ if (imesa->TexObjList[heap].prev->bound) {
+ fprintf(stderr, "Hit bound texture in upload\n");
+ savagePrintLocalLRU( imesa,heap );
+ return -1;
+ }
+
+ if (imesa->TexObjList[heap].prev == &(imesa->TexObjList[heap])) {
+ fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize);
+ mmDumpMemInfo( imesa->texHeap[heap] );
+ return -1;
+ }
+
+ savageDestroyTexObj( imesa, imesa->TexObjList[heap].prev );
+ }
+
+ ofs = t->MemBlock->ofs;
+ t->texParams.hwPhysAddress = imesa->savageScreen->textureOffset[heap] + ofs;
+ t->BufAddr = (char *)((GLuint) imesa->savageScreen->texVirtual[heap] + ofs);
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+ }
+
+ /* Let the world know we've used this memory recently.
+ */
+ savageUpdateTexLRU( imesa, t );
+
+ if (t->dirty_images) {
+ if (SAVAGE_DEBUG & DEBUG_VERBOSE_LRU)
+ fprintf(stderr, "*");
+
+ for (i = t->min_level ; i <= t->max_level ; i++)
+ if (t->dirty_images & (1<<i))
+ savageUploadTexLevel( t, i );
+ }
+
+
+ t->dirty_images = 0;
+ return 0;
+}
+
+static void savageTexSetUnit( savageTextureObjectPtr t, GLuint unit )
+{
+ if (t->current_unit == unit) return;
+
+ t->current_unit = unit;
+}
+
+
+
+
+static void savageUpdateTex0State_s4( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ struct gl_texture_object *tObj;
+ savageTextureObjectPtr t;
+ GLuint format;
+ Reg_TexCtrl TexCtrl;
+ Reg_TexBlendCtrl TexBlendCtrl;
+ Reg_TexDescr TexDescr;
+
+ /* disable */
+
+ if (ctx->Texture.Unit[0]._ReallyEnabled == 0) {
+ imesa->Registers.TexDescr.s4.tex0En = GL_FALSE;
+ imesa->Registers.TexBlendCtrl[0].ui = TBC_NoTexMap;
+ imesa->Registers.TexCtrl[0].ui = 0x20f040;
+ imesa->Registers.TexAddr[0].ui = 0;
+ imesa->Registers.changed.ni.fTex0BlendCtrlChanged = GL_TRUE;
+ imesa->Registers.changed.ni.fTex0AddrChanged = GL_TRUE;
+ imesa->Registers.changed.ni.fTexDescrChanged = GL_TRUE;
+ imesa->Registers.changed.ni.fTex0CtrlChanged = GL_TRUE;
+ return;
+ }
+
+ tObj = ctx->Texture.Unit[0]._Current;
+ if (ctx->Texture.Unit[0]._ReallyEnabled != TEXTURE_2D_BIT ||
+ tObj->Image[0][tObj->BaseLevel]->Border > 0) {
+ /* 1D or 3D texturing enabled, or texture border - fallback */
+ FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
+ return;
+ }
+
+ /* Do 2D texture setup */
+
+ t = tObj->DriverData;
+ if (!t) {
+ t = savageAllocTexObj( tObj );
+ if (!t)
+ return;
+ }
+
+ if (t->current_unit != 0)
+ savageTexSetUnit( t, 0 );
+
+ imesa->CurrentTexObj[0] = t;
+ t->bound = 1;
+
+ if (t->dirty_images) {
+ savageSetTexImages(imesa, tObj);
+ savageUploadTexImages(imesa, imesa->CurrentTexObj[0]);
+ }
+
+ if (t->MemBlock)
+ savageUpdateTexLRU( imesa, t );
+
+ TexDescr.ui = imesa->Registers.TexDescr.ui & ~0x01000000;
+ TexCtrl.ui = imesa->Registers.TexCtrl[0].ui;
+ TexBlendCtrl.ui = imesa->Registers.TexBlendCtrl[0].ui;
+
+ format = tObj->Image[0][tObj->BaseLevel]->Format;
+
+ switch (ctx->Texture.Unit[0].EnvMode) {
+ case GL_REPLACE:
+ TexCtrl.s4.clrArg1Invert = GL_FALSE;
+ switch(format)
+ {
+ case GL_LUMINANCE:
+ case GL_RGB:
+ TexBlendCtrl.ui = TBC_Decal;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ case GL_INTENSITY:
+ TexBlendCtrl.ui = TBC_Copy;
+ break;
+
+ case GL_ALPHA:
+ TexBlendCtrl.ui = TBC_CopyAlpha;
+ break;
+ }
+ __HWEnvCombineSingleUnitScale(imesa, 0, 0, &TexBlendCtrl);
+ break;
+
+ case GL_DECAL:
+ TexCtrl.s4.clrArg1Invert = GL_FALSE;
+ switch (format)
+ {
+ case GL_RGB:
+ case GL_LUMINANCE:
+ TexBlendCtrl.ui = TBC_Decal;
+ break;
+
+ case GL_RGBA:
+ case GL_INTENSITY:
+ case GL_LUMINANCE_ALPHA:
+ TexBlendCtrl.ui = TBC_DecalAlpha;
+ break;
+
+ /*
+ GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
+ are undefined with GL_DECAL
+ */
+
+ case GL_ALPHA:
+ TexBlendCtrl.ui = TBC_CopyAlpha;
+ break;
+ }
+ __HWEnvCombineSingleUnitScale(imesa, 0, 0, &TexBlendCtrl);
+ break;
+
+ case GL_MODULATE:
+ TexCtrl.s4.clrArg1Invert = GL_FALSE;
+ TexBlendCtrl.ui = TBC_ModulAlpha;
+ __HWEnvCombineSingleUnitScale(imesa, 0, 0, &TexBlendCtrl);
+ break;
+
+ case GL_BLEND:
+
+ switch (format)
+ {
+ case GL_ALPHA:
+ TexBlendCtrl.ui = TBC_ModulAlpha;
+ TexCtrl.s4.clrArg1Invert = GL_FALSE;
+ break;
+
+ case GL_LUMINANCE:
+ case GL_RGB:
+ TexBlendCtrl.ui = TBC_Blend0;
+ TexDescr.s4.tex1En = GL_TRUE;
+ TexDescr.s4.texBLoopEn = GL_TRUE;
+ TexDescr.s4.tex1Width = TexDescr.s4.tex0Width;
+ TexDescr.s4.tex1Height = TexDescr.s4.tex0Height;
+ TexDescr.s4.tex1Fmt = TexDescr.s4.tex0Fmt;
+
+ if (imesa->Registers.TexAddr[1].ui != imesa->Registers.TexAddr[0].ui)
+ {
+ imesa->Registers.TexAddr[1].ui = imesa->Registers.TexAddr[0].ui;
+ imesa->Registers.changed.ni.fTex1AddrChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexBlendCtrl[1].ui != TBC_Blend1)
+ {
+ imesa->Registers.TexBlendCtrl[1].ui = TBC_Blend1;
+ imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
+ }
+
+ TexCtrl.s4.clrArg1Invert = GL_TRUE;
+ imesa->bTexEn1 = GL_TRUE;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ TexBlendCtrl.ui = TBC_BlendAlpha0;
+ TexDescr.s4.tex1En = GL_TRUE;
+ TexDescr.s4.texBLoopEn = GL_TRUE;
+ TexDescr.s4.tex1Width = TexDescr.s4.tex0Width;
+ TexDescr.s4.tex1Height = TexDescr.s4.tex0Height;
+ TexDescr.s4.tex1Fmt = TexDescr.s4.tex0Fmt;
+
+ if (imesa->Registers.TexAddr[1].ui != imesa->Registers.TexAddr[0].ui)
+ {
+ imesa->Registers.TexAddr[1].ui = imesa->Registers.TexAddr[0].ui;
+ imesa->Registers.changed.ni.fTex1AddrChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexBlendCtrl[1].ui != TBC_BlendAlpha1)
+ {
+ imesa->Registers.TexBlendCtrl[1].ui = TBC_BlendAlpha1;
+ imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
+ }
+
+ TexCtrl.s4.clrArg1Invert = GL_TRUE;
+ imesa->bTexEn1 = GL_TRUE;
+ break;
+
+ case GL_INTENSITY:
+ TexBlendCtrl.ui = TBC_BlendInt0;
+ TexDescr.s4.tex1En = GL_TRUE;
+ TexDescr.s4.texBLoopEn = GL_TRUE;
+ TexDescr.s4.tex1Width = TexDescr.s4.tex0Width;
+ TexDescr.s4.tex1Height = TexDescr.s4.tex0Height;
+ TexDescr.s4.tex1Fmt = TexDescr.s4.tex0Fmt;
+
+ if (imesa->Registers.TexAddr[1].ui != imesa->Registers.TexAddr[0].ui)
+ {
+ imesa->Registers.TexAddr[1].ui = imesa->Registers.TexAddr[0].ui;
+ imesa->Registers.changed.ni.fTex1AddrChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexBlendCtrl[1].ui != TBC_BlendInt1)
+ {
+ imesa->Registers.TexBlendCtrl[1].ui = TBC_BlendInt1;
+ imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
+ }
+ TexCtrl.s4.clrArg1Invert = GL_TRUE;
+ TexCtrl.s4.alphaArg1Invert = GL_TRUE;
+ imesa->bTexEn1 = GL_TRUE;
+ break;
+ }
+ __HWEnvCombineSingleUnitScale(imesa, 0, 0, &TexBlendCtrl);
+ break;
+
+ /*
+ GL_ADD
+ */
+ case GL_ADD:
+ printf("Add\n");
+ TexCtrl.s4.clrArg1Invert = GL_FALSE;
+ TexBlendCtrl.ui = TBC_AddAlpha;
+ __HWEnvCombineSingleUnitScale(imesa, 0, 0, &TexBlendCtrl);
+ break;
+
+#if GL_ARB_texture_env_combine
+ case GL_COMBINE_ARB:
+ __HWParseTexEnvCombine(imesa, 0, &TexCtrl, &TexBlendCtrl);
+ break;
+#endif
+
+ default:
+ fprintf(stderr, "unknown tex env mode");
+ exit(1);
+ break;
+ }
+
+ TexCtrl.s4.uMode = !(t->texParams.sWrapMode & 0x01);
+ TexCtrl.s4.vMode = !(t->texParams.tWrapMode & 0x01);
+
+ switch (t->texParams.minFilter)
+ {
+ case GL_NEAREST:
+ TexCtrl.s4.filterMode = TFM_Point;
+ TexCtrl.s4.mipmapEnable = GL_FALSE;
+ break;
+
+ case GL_LINEAR:
+ TexCtrl.s4.filterMode = TFM_Bilin;
+ TexCtrl.s4.mipmapEnable = GL_FALSE;
+ break;
+
+ case GL_NEAREST_MIPMAP_NEAREST:
+ TexCtrl.s4.filterMode = TFM_Point;
+ TexCtrl.s4.mipmapEnable = GL_TRUE;
+ break;
+
+ case GL_LINEAR_MIPMAP_NEAREST:
+ TexCtrl.s4.filterMode = TFM_Bilin;
+ TexCtrl.s4.mipmapEnable = GL_TRUE;
+ break;
+
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ TexCtrl.s4.filterMode = TFM_Trilin;
+ TexCtrl.s4.mipmapEnable = GL_TRUE;
+ break;
+ }
+
+ if((ctx->Texture.Unit[0].LodBias !=0.0F) && (TexCtrl.s4.dBias != 0))
+ {
+ union {
+ GLfloat f;
+ GLint i;
+ } bias;
+ GLuint ul;
+
+ bias.f = ctx->Texture.Unit[0].LodBias;
+
+ /* if the value is >= 15.9375 determine whether >= 16
+ or <0
+ */
+ if(((bias.i) & 0x7FFFFFFF) >= 0x417F0000)
+ {
+ if((bias.i) & 0x80000000)
+ {
+ ul=0x101;
+ }
+ else
+ {
+ ul=0xff;
+ }
+ }
+ else
+ {
+ ul=(GLuint)(bias.f*16.0);
+ }
+
+ ul &= 0x1FF;
+ TexCtrl.s4.dBias = ul;
+ }
+
+ TexDescr.s4.tex0En = GL_TRUE;
+ TexDescr.s4.tex0Width = t->image[0].image->WidthLog2;
+ TexDescr.s4.tex0Height = t->image[0].image->HeightLog2;
+ TexDescr.s4.tex0Fmt = t->image[0].internalFormat;
+ TexCtrl.s4.dMax = t->max_level;
+
+ if (TexDescr.s4.tex1En)
+ TexDescr.s4.texBLoopEn = GL_TRUE;
+
+ if (imesa->Registers.TexAddr[0].ui != (GLuint)t->texParams.hwPhysAddress)
+ {
+ imesa->Registers.TexAddr[0].ui = (GLuint) t->texParams.hwPhysAddress | 0x2;
+
+ if(t->heap == SAVAGE_AGP_HEAP)
+ imesa->Registers.TexAddr[0].ui |= 0x1;
+
+ imesa->Registers.changed.ni.fTex0AddrChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexCtrl[0].ui != TexCtrl.ui)
+ {
+ imesa->Registers.TexCtrl[0].ui = TexCtrl.ui;
+ imesa->Registers.changed.ni.fTex0CtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexBlendCtrl[0].ui != TexBlendCtrl.ui)
+ {
+ imesa->Registers.TexBlendCtrl[0].ui = TexBlendCtrl.ui;
+ imesa->Registers.changed.ni.fTex0BlendCtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexDescr.ui != TexDescr.ui)
+ {
+ imesa->Registers.TexDescr.ui = TexDescr.ui;
+ imesa->Registers.changed.ni.fTexDescrChanged = GL_TRUE;
+ }
+
+ return;
+}
+static void savageUpdateTex1State_s4( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ struct gl_texture_object *tObj;
+ savageTextureObjectPtr t;
+ GLuint format;
+ Reg_TexCtrl TexCtrl;
+ Reg_TexBlendCtrl TexBlendCtrl;
+ Reg_TexDescr TexDescr;
+
+
+ /* disable */
+ if(imesa->bTexEn1)
+ {
+ imesa->bTexEn1 = GL_FALSE;
+ return;
+ }
+
+ if (ctx->Texture.Unit[1]._ReallyEnabled == 0) {
+ imesa->Registers.TexDescr.s4.tex1En = GL_FALSE;
+ imesa->Registers.TexBlendCtrl[1].ui = TBC_NoTexMap1;
+ imesa->Registers.TexCtrl[1].ui = 0x20f040;
+ imesa->Registers.TexAddr[1].ui = 0;
+ imesa->Registers.TexDescr.s4.texBLoopEn = GL_FALSE;
+ imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
+ imesa->Registers.changed.ni.fTexDescrChanged = GL_TRUE;
+ imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
+ imesa->Registers.changed.ni.fTex1AddrChanged = GL_TRUE;
+ return;
+ }
+
+ tObj = ctx->Texture.Unit[1]._Current;
+
+ if (ctx->Texture.Unit[1]._ReallyEnabled != TEXTURE_2D_BIT ||
+ tObj->Image[0][tObj->BaseLevel]->Border > 0) {
+ /* 1D or 3D texturing enabled, or texture border - fallback */
+ FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
+ return;
+ }
+
+ /* Do 2D texture setup */
+
+ t = tObj->DriverData;
+ if (!t) {
+ t = savageAllocTexObj( tObj );
+ if (!t)
+ return;
+ }
+
+ if (t->current_unit != 1)
+ savageTexSetUnit( t, 1 );
+
+ imesa->CurrentTexObj[1] = t;
+
+ t->bound = 2;
+
+ if (t->dirty_images) {
+ savageSetTexImages(imesa, tObj);
+ savageUploadTexImages(imesa, imesa->CurrentTexObj[1]);
+ }
+
+ if (t->MemBlock)
+ savageUpdateTexLRU( imesa, t );
+
+ TexDescr.ui = imesa->Registers.TexDescr.ui;
+ TexCtrl.ui = imesa->Registers.TexCtrl[1].ui;
+ TexBlendCtrl.ui = imesa->Registers.TexBlendCtrl[1].ui;
+
+ format = tObj->Image[0][tObj->BaseLevel]->Format;
+
+ switch (ctx->Texture.Unit[1].EnvMode) {
+ case GL_REPLACE:
+ TexCtrl.s4.clrArg1Invert = GL_FALSE;
+ switch (format)
+ {
+ case GL_LUMINANCE:
+ case GL_RGB:
+ TexBlendCtrl.ui = TBC_Decal;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ case GL_RGBA:
+ TexBlendCtrl.ui = TBC_Copy;
+ break;
+
+ case GL_ALPHA:
+ TexBlendCtrl.ui = TBC_CopyAlpha1;
+ break;
+ }
+ __HWEnvCombineSingleUnitScale(imesa, 0, 1, &TexBlendCtrl);
+ break;
+ case GL_MODULATE:
+ TexCtrl.s4.clrArg1Invert = GL_FALSE;
+ TexBlendCtrl.ui = TBC_ModulAlpha1;
+ __HWEnvCombineSingleUnitScale(imesa, 0, 1, &TexBlendCtrl);
+ break;
+
+/*#if GL_EXT_texture_env_add*/
+ case GL_ADD:
+ TexCtrl.s4.clrArg1Invert = GL_FALSE;
+ TexBlendCtrl.ui = TBC_AddAlpha1;
+ __HWEnvCombineSingleUnitScale(imesa, 0, 1, &TexBlendCtrl);
+ break;
+/*#endif*/
+
+#if GL_ARB_texture_env_combine
+ case GL_COMBINE_ARB:
+ __HWParseTexEnvCombine(imesa, 1, &TexCtrl, &TexBlendCtrl);
+ break;
+#endif
+
+ case GL_DECAL:
+ TexCtrl.s4.clrArg1Invert = GL_FALSE;
+
+ switch (format)
+ {
+ case GL_LUMINANCE:
+ case GL_RGB:
+ TexBlendCtrl.ui = TBC_Decal1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ case GL_RGBA:
+ TexBlendCtrl.ui = TBC_DecalAlpha1;
+ break;
+
+ /*
+ // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
+ // are undefined with GL_DECAL
+ */
+ case GL_ALPHA:
+ TexBlendCtrl.ui = TBC_CopyAlpha1;
+ break;
+ }
+ __HWEnvCombineSingleUnitScale(imesa, 0, 1, &TexBlendCtrl);
+ break;
+
+ case GL_BLEND:
+ if (format == GL_LUMINANCE)
+ {
+ /*
+ // This is a hack for GLQuake, invert.
+ */
+ TexCtrl.s4.clrArg1Invert = GL_TRUE;
+ TexBlendCtrl.ui = 0;
+ }
+ __HWEnvCombineSingleUnitScale(imesa, 0, 1, &TexBlendCtrl);
+ break;
+
+ default:
+ fprintf(stderr, "unkown tex 1 env mode\n");
+ exit(1);
+ break;
+ }
+
+ TexCtrl.s4.uMode = !(t->texParams.sWrapMode & 0x01);
+ TexCtrl.s4.vMode = !(t->texParams.tWrapMode & 0x01);
+
+ switch (t->texParams.minFilter)
+ {
+ case GL_NEAREST:
+ TexCtrl.s4.filterMode = TFM_Point;
+ TexCtrl.s4.mipmapEnable = GL_FALSE;
+ break;
+
+ case GL_LINEAR:
+ TexCtrl.s4.filterMode = TFM_Bilin;
+ TexCtrl.s4.mipmapEnable = GL_FALSE;
+ break;
+
+ case GL_NEAREST_MIPMAP_NEAREST:
+ TexCtrl.s4.filterMode = TFM_Point;
+ TexCtrl.s4.mipmapEnable = GL_TRUE;
+ break;
+
+ case GL_LINEAR_MIPMAP_NEAREST:
+ TexCtrl.s4.filterMode = TFM_Bilin;
+ TexCtrl.s4.mipmapEnable = GL_TRUE;
+ break;
+
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ TexCtrl.s4.filterMode = TFM_Trilin;
+ TexCtrl.s4.mipmapEnable = GL_TRUE;
+ break;
+ }
+
+ if((ctx->Texture.Unit[1].LodBias !=0.0F)&&(TexCtrl.s4.dBias != 0))
+ {
+ union {
+ GLfloat f;
+ GLint i;
+ } bias;
+ GLuint ul;
+
+ bias.f = ctx->Texture.Unit[1].LodBias;
+
+ /* if the value is >= 15.9375 determine whether >= 16
+ or <0
+ */
+ if(((bias.i) & 0x7FFFFFFF) >= 0x417F0000)
+ {
+ if((bias.i) & 0x80000000)
+ {
+ ul=0x101;
+ }
+ else
+ {
+ ul=0xff;
+ }
+ }
+ else
+ {
+ ul=(GLuint)(bias.f*16.0);
+ }
+
+ ul &= 0x1FF;
+ TexCtrl.s4.dBias = ul;
+ }
+
+ TexDescr.s4.tex1En = GL_TRUE;
+ TexDescr.s4.tex1Width = t->image[0].image->WidthLog2;
+ TexDescr.s4.tex1Height = t->image[0].image->HeightLog2;
+ TexDescr.s4.tex1Fmt = t->image[0].internalFormat;
+ TexCtrl.s4.dMax = t->max_level;
+ TexDescr.s4.texBLoopEn = GL_TRUE;
+
+ if (imesa->Registers.TexAddr[1].ui != (GLuint)t->texParams.hwPhysAddress)
+ {
+ imesa->Registers.TexAddr[1].ui = (GLuint) t->texParams.hwPhysAddress| 2;
+
+ if(t->heap == SAVAGE_AGP_HEAP)
+ imesa->Registers.TexAddr[1].ui |= 0x1;
+
+ /*imesa->Registers.TexAddr[1].ui = (GLuint) t->texParams.hwPhysAddress| 3;*/
+ imesa->Registers.changed.ni.fTex1AddrChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexCtrl[1].ui != TexCtrl.ui)
+ {
+ imesa->Registers.TexCtrl[1].ui = TexCtrl.ui;
+ imesa->Registers.changed.ni.fTex1CtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexBlendCtrl[1].ui != TexBlendCtrl.ui)
+ {
+ imesa->Registers.TexBlendCtrl[1].ui = TexBlendCtrl.ui;
+ imesa->Registers.changed.ni.fTex1BlendCtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexDescr.ui != TexDescr.ui)
+ {
+ imesa->Registers.TexDescr.ui = TexDescr.ui;
+ imesa->Registers.changed.ni.fTexDescrChanged = GL_TRUE;
+ }
+
+}
+static void savageUpdateTexState_s3d( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ struct gl_texture_object *tObj;
+ savageTextureObjectPtr t;
+ GLuint format;
+ Reg_TexCtrl TexCtrl;
+ Reg_DrawCtrl DrawCtrl;
+ Reg_TexDescr TexDescr;
+
+ /* disable */
+ if (ctx->Texture.Unit[0]._ReallyEnabled == 0) {
+ imesa->Registers.TexCtrl[0].ui = 0;
+ imesa->Registers.TexCtrl[0].s3d.texEn = GL_FALSE;
+ imesa->Registers.TexCtrl[0].s3d.dBias = 0x08;
+ imesa->Registers.TexCtrl[0].s3d.texXprEn = GL_TRUE;
+ imesa->Registers.TexAddr[0].ui = 0;
+ imesa->Registers.changed.ni.fTex0AddrChanged = GL_TRUE;
+ imesa->Registers.changed.ni.fTex0CtrlChanged = GL_TRUE;
+ return;
+ }
+
+ tObj = ctx->Texture.Unit[0]._Current;
+ if (ctx->Texture.Unit[0]._ReallyEnabled != TEXTURE_2D_BIT ||
+ tObj->Image[0][tObj->BaseLevel]->Border > 0) {
+ /* 1D or 3D texturing enabled, or texture border - fallback */
+ FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
+ return;
+ }
+
+ /* Do 2D texture setup */
+ t = tObj->DriverData;
+ if (!t) {
+ t = savageAllocTexObj( tObj );
+ if (!t)
+ return;
+ }
+
+ if (t->current_unit != 0)
+ savageTexSetUnit( t, 0 );
+
+ imesa->CurrentTexObj[0] = t;
+ t->bound = 1;
+
+ if (t->dirty_images) {
+ savageSetTexImages(imesa, tObj);
+ savageUploadTexImages(imesa, imesa->CurrentTexObj[0]);
+ }
+
+ if (t->MemBlock)
+ savageUpdateTexLRU( imesa, t );
+
+ TexDescr.ui = imesa->Registers.TexDescr.ui;
+ TexCtrl.ui = imesa->Registers.TexCtrl[0].ui;
+ DrawCtrl.ui = imesa->Registers.DrawCtrl.ui;
+
+ format = tObj->Image[0][tObj->BaseLevel]->Format;
+
+ /* FIXME: copied from utah-glx, probably needs some tuning */
+ switch (ctx->Texture.Unit[0].EnvMode) {
+ case GL_DECAL:
+ DrawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
+ break;
+ case GL_REPLACE:
+ DrawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
+ break;
+ case GL_BLEND: /* FIXIT */
+ case GL_MODULATE:
+ DrawCtrl.ni.texBlendCtrl = SAVAGETBC_MODULATEALPHA_S3D;
+ break;
+ default:
+ fprintf(stderr, "unkown tex env mode\n");
+ /*exit(1);*/
+ break;
+ }
+
+ DrawCtrl.ni.flushPdDestWrites = GL_TRUE;
+ DrawCtrl.ni.flushPdZbufWrites = GL_TRUE;
+
+ /* FIXME: this is how the utah-driver works. I doubt it's the ultimate
+ truth. */
+ TexCtrl.s3d.uWrapEn = 0;
+ TexCtrl.s3d.vWrapEn = 0;
+ if (t->texParams.sWrapMode == GL_CLAMP)
+ TexCtrl.s3d.wrapMode = TAM_Clamp;
+ else
+ TexCtrl.s3d.wrapMode = TAM_Wrap;
+
+ switch (t->texParams.minFilter) {
+ case GL_NEAREST:
+ TexCtrl.s3d.filterMode = TFM_Point;
+ TexCtrl.s3d.mipmapDisable = GL_TRUE;
+ break;
+
+ case GL_LINEAR:
+ TexCtrl.s3d.filterMode = TFM_Bilin;
+ TexCtrl.s3d.mipmapDisable = GL_TRUE;
+ break;
+
+ case GL_NEAREST_MIPMAP_NEAREST:
+ TexCtrl.s3d.filterMode = TFM_Point;
+ TexCtrl.s3d.mipmapDisable = GL_FALSE;
+ break;
+
+ case GL_LINEAR_MIPMAP_NEAREST:
+ TexCtrl.s3d.filterMode = TFM_Bilin;
+ TexCtrl.s3d.mipmapDisable = GL_FALSE;
+ break;
+
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ TexCtrl.s3d.filterMode = TFM_Trilin;
+ TexCtrl.s3d.mipmapDisable = GL_FALSE;
+ break;
+ }
+
+ /* There is no way to specify a maximum mipmap level. We may have to
+ disable mipmapping completely. */
+ /*
+ if (t->max_level < t->image[0].image->WidthLog2 ||
+ t->max_level < t->image[0].image->HeightLog2) {
+ TexCtrl.s3d.mipmapEnable = GL_TRUE;
+ if (TexCtrl.s3d.filterMode == TFM_Trilin)
+ TexCtrl.s3d.filterMode = TFM_Bilin;
+ TexCtrl.s3d.filterMode = TFM_Point;
+ }
+ */
+
+ /* LOD bias makes corruption of small mipmap levels worse on Savage IX
+ * but doesn't show the desired effect with the lodbias mesa demo. */
+ TexCtrl.s3d.dBias = 0;
+
+ TexCtrl.s3d.texEn = GL_TRUE;
+ TexDescr.s3d.texWidth = t->image[0].image->WidthLog2;
+ TexDescr.s3d.texHeight = t->image[0].image->HeightLog2;
+ assert (t->image[0].internalFormat <= 7);
+ TexDescr.s3d.texFmt = t->image[0].internalFormat;
+
+ if (imesa->Registers.TexAddr[0].ni.addr != (GLuint)t->texParams.hwPhysAddress >> 3)
+ {
+ imesa->Registers.TexAddr[0].ni.addr = (GLuint) t->texParams.hwPhysAddress >> 3;
+
+ if(t->heap == SAVAGE_AGP_HEAP) {
+ imesa->Registers.TexAddr[0].ni.inSysTex = 1;
+ imesa->Registers.TexAddr[0].ni.inAGPTex = 1;
+ } else {
+ imesa->Registers.TexAddr[0].ni.inSysTex = 0;
+ imesa->Registers.TexAddr[0].ni.inAGPTex = 1;
+ }
+
+ imesa->Registers.changed.ni.fTex0AddrChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexCtrl[0].ui != TexCtrl.ui)
+ {
+ imesa->Registers.TexCtrl[0].ui = TexCtrl.ui;
+ imesa->Registers.changed.ni.fTex0CtrlChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.TexDescr.ui != TexDescr.ui)
+ {
+ imesa->Registers.TexDescr.ui = TexDescr.ui;
+ imesa->Registers.changed.ni.fTexDescrChanged = GL_TRUE;
+ }
+
+ if (imesa->Registers.DrawCtrl.ui != DrawCtrl.ui)
+ {
+ imesa->Registers.DrawCtrl.ui = DrawCtrl.ui;
+ imesa->Registers.changed.ni.fDrawCtrlChanged = GL_TRUE;
+ }
+}
+
+
+
+static void savageUpdateTextureState_s4( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound = 0;
+ if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->bound = 0;
+ imesa->CurrentTexObj[0] = 0;
+ imesa->CurrentTexObj[1] = 0;
+ FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_FALSE);
+ savageUpdateTex0State_s4( ctx );
+ savageUpdateTex1State_s4( ctx );
+ imesa->dirty |= (SAVAGE_UPLOAD_CTX |
+ SAVAGE_UPLOAD_TEX0 |
+ SAVAGE_UPLOAD_TEX1);
+}
+static void savageUpdateTextureState_s3d( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound = 0;
+ imesa->CurrentTexObj[0] = 0;
+ if (ctx->Texture.Unit[1]._ReallyEnabled) {
+ FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
+ } else {
+ FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_FALSE);
+ savageUpdateTexState_s3d( ctx );
+ imesa->dirty |= (SAVAGE_UPLOAD_CTX |
+ SAVAGE_UPLOAD_TEX0);
+ }
+}
+static void savageUpdateTextureState_first( GLcontext *ctx)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+ if (imesa->savageScreen->chipset <= S3_SAVAGE4) {
+ GetTiledCoordinates16 = GetTiledCoordinates16_4;
+ GetTiledCoordinates32 = GetTiledCoordinates32_4;
+ } else {
+ GetTiledCoordinates16 = GetTiledCoordinates16_8;
+ GetTiledCoordinates32 = GetTiledCoordinates32_8;
+ }
+ if (imesa->savageScreen->chipset >= S3_SAVAGE4)
+ savageUpdateTextureState = savageUpdateTextureState_s4;
+ else
+ savageUpdateTextureState = savageUpdateTextureState_s3d;
+ savageUpdateTextureState (ctx);
+}
+void (*savageUpdateTextureState)( GLcontext *ctx ) =
+ savageUpdateTextureState_first;
+
+
+
+/*****************************************
+ * DRIVER functions
+ *****************************************/
+
+static void savageTexEnv( GLcontext *ctx, GLenum target,
+ GLenum pname, const GLfloat *param )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+
+ if (pname == GL_TEXTURE_ENV_MODE) {
+
+ imesa->new_state |= SAVAGE_NEW_TEXTURE;
+
+ } else if (pname == GL_TEXTURE_ENV_COLOR) {
+
+ struct gl_texture_unit *texUnit =
+ &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ const GLfloat *fc = texUnit->EnvColor;
+ GLuint r, g, b, a, col;
+ CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
+ CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
+ CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
+ CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
+
+ col = ((a << 24) |
+ (r << 16) |
+ (g << 8) |
+ (b << 0));
+
+
+ }
+}
+
+static void savageTexImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ savageTextureObjectPtr t = (savageTextureObjectPtr) texObj->DriverData;
+ if (t) {
+ savageSwapOutTexObj( SAVAGE_CONTEXT(ctx), t );
+ } else {
+ t = savageAllocTexObj(texObj);
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
+ }
+ }
+ _mesa_store_teximage2d( ctx, target, level, internalFormat,
+ width, height, border, format, type,
+ pixels, packing, texObj, texImage );
+ t->dirty_images |= (1 << level);
+ SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
+}
+
+static void savageTexSubImage2D( GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ savageTextureObjectPtr t = (savageTextureObjectPtr) texObj->DriverData;
+ assert( t ); /* this _should_ be true */
+ if (t) {
+ savageSwapOutTexObj( SAVAGE_CONTEXT(ctx), t );
+ } else {
+ t = savageAllocTexObj(texObj);
+ if (!t) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
+ }
+ }
+ _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
+ height, format, type, pixels, packing, texObj,
+ texImage);
+ t->dirty_images |= (1 << level);
+ SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
+}
+
+static void savageTexParameter( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj,
+ GLenum pname, const GLfloat *params )
+{
+ savageTextureObjectPtr t = (savageTextureObjectPtr) tObj->DriverData;
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+
+ if (!t || target != GL_TEXTURE_2D)
+ return;
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ savageSetTexFilter(t,tObj->MinFilter,tObj->MagFilter);
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ savageSetTexWrapping(t,tObj->WrapS,tObj->WrapT);
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ savageSetTexBorderColor(t,tObj->_BorderChan);
+ break;
+
+ default:
+ return;
+ }
+
+ imesa->new_state |= SAVAGE_NEW_TEXTURE;
+}
+
+static void savageBindTexture( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+
+
+ if (imesa->CurrentTexObj[ctx->Texture.CurrentUnit]) {
+ imesa->CurrentTexObj[ctx->Texture.CurrentUnit]->bound = 0;
+ imesa->CurrentTexObj[ctx->Texture.CurrentUnit] = 0;
+ }
+
+ assert( (target != GL_TEXTURE_2D) || (tObj->DriverData != NULL) );
+
+ imesa->new_state |= SAVAGE_NEW_TEXTURE;
+}
+
+static void savageDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
+{
+ savageTextureObjectPtr t = (savageTextureObjectPtr)tObj->DriverData;
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+
+ if (t) {
+
+ if (t->bound) {
+ imesa->CurrentTexObj[t->bound-1] = 0;
+ imesa->new_state |= SAVAGE_NEW_TEXTURE;
+ }
+
+ savageDestroyTexObj(imesa,t);
+ tObj->DriverData=0;
+ }
+ /* Free mipmap images and the texture object itself */
+ _mesa_delete_texture_object(ctx, tObj);
+}
+
+
+static GLboolean savageIsTextureResident( GLcontext *ctx,
+ struct gl_texture_object *t )
+{
+ savageTextureObjectPtr mt;
+
+/* LOCK_HARDWARE; */
+ mt = (savageTextureObjectPtr)t->DriverData;
+/* UNLOCK_HARDWARE; */
+
+ return mt && mt->MemBlock;
+}
+
+
+static struct gl_texture_object *
+savageNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
+{
+ struct gl_texture_object *obj;
+ obj = _mesa_new_texture_object(ctx, name, target);
+ savageAllocTexObj( obj );
+
+ return obj;
+}
+
+void savageDDInitTextureFuncs( struct dd_function_table *functions )
+{
+ functions->TexEnv = savageTexEnv;
+ functions->ChooseTextureFormat = savageChooseTextureFormat;
+ functions->TexImage2D = savageTexImage2D;
+ functions->TexSubImage2D = savageTexSubImage2D;
+ functions->BindTexture = savageBindTexture;
+ functions->NewTextureObject = savageNewTextureObject;
+ functions->DeleteTexture = savageDeleteTexture;
+ functions->IsTextureResident = savageIsTextureResident;
+ functions->TexParameter = savageTexParameter;
+}
diff --git a/src/mesa/drivers/dri/savage/savagetex.h b/src/mesa/drivers/dri/savage/savagetex.h
new file mode 100644
index 0000000000..9ff85e2e32
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagetex.h
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+
+#ifndef SAVAGETEX_INC
+#define SAVAGETEX_INC
+
+#include "mtypes.h"
+#include "mm.h"
+
+#include "savagecontext.h"
+#include "savage_3d_reg.h"
+
+#define VALID_SAVAGE_TEXTURE_OBJECT(tobj) (tobj)
+
+#define SAVAGE_TEX_MAXLEVELS 11
+#define MIN_TILE_CHUNK 8
+#define MIPMAP_CHUNK 4
+
+
+
+/* For shared texture space managment, these texture objects may also
+ * be used as proxies for regions of texture memory containing other
+ * client's textures. Such proxy textures (not to be confused with GL
+ * proxy textures) are subject to the same LRU aging we use for our
+ * own private textures, and thus we have a mechanism where we can
+ * fairly decide between kicking out our own textures and those of
+ * other clients.
+ *
+ * Non-local texture objects have a valid MemBlock to describe the
+ * region managed by the other client, and can be identified by
+ * 't->globj == 0'
+ */
+typedef struct {
+ GLuint sWrapMode;
+ GLuint tWrapMode;
+ GLuint minFilter;
+ GLuint magFilter;
+ GLuint boarderColor;
+ GLuint hwPhysAddress;
+} savage_texture_parameter_t;
+
+struct savage_texture_object_t {
+ struct savage_texture_object_t *next, *prev;
+ struct gl_texture_object *globj;
+ GLuint age;
+
+
+ GLuint texelBytes;
+ GLuint totalSize;
+ GLuint bound;
+ GLuint heap;
+
+ PMemBlock MemBlock;
+ char *BufAddr;
+
+ GLuint min_level;
+ GLuint max_level;
+ GLuint dirty_images;
+
+ struct {
+ const struct gl_texture_image *image;
+ GLuint offset; /* into BufAddr */
+ GLuint height;
+ GLuint internalFormat;
+ } image[SAVAGE_TEX_MAXLEVELS];
+
+ /* Support for multitexture.
+ */
+ GLuint current_unit;
+ savage_texture_parameter_t texParams;
+};
+
+#define SAVAGE_NO_PALETTE 0x0
+#define SAVAGE_USE_PALETTE 0x1
+#define SAVAGE_UPDATE_PALETTE 0x2
+#define SAVAGE_FALLBACK_PALETTE 0x4
+#define __HWEnvCombineSingleUnitScale(imesa, flag0, flag1, TexBlendCtrl)
+#define __HWParseTexEnvCombine(imesa, flag0, TexCtrl, TexBlendCtrl)
+
+
+extern void (*savageUpdateTextureState)( GLcontext *ctx );
+void savageDDInitTextureFuncs( struct dd_function_table *functions );
+
+void savageDestroyTexObj( savageContextPtr imesa, savageTextureObjectPtr t);
+int savageUploadTexImages( savageContextPtr imesa, savageTextureObjectPtr t );
+
+void savageResetGlobalLRU( savageContextPtr imesa , GLuint heap);
+void savageTexturesGone( savageContextPtr imesa, GLuint heap,
+ GLuint start, GLuint end,
+ GLuint in_use );
+
+void savagePrintLocalLRU( savageContextPtr imesa ,GLuint heap);
+void savagePrintGlobalLRU( savageContextPtr imesa ,GLuint heap);
+
+#endif
diff --git a/src/mesa/drivers/dri/savage/savagetris.c b/src/mesa/drivers/dri/savage/savagetris.c
new file mode 100644
index 0000000000..db061d9d39
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagetris.c
@@ -0,0 +1,817 @@
+/* $XFree86$ */ /* -*- c-basic-offset: 3 -*- */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keithw@valinux.com>
+ * Felix Kuehling <fxkuehl@gmx.de>
+ *
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "macros.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "savagetris.h"
+#include "savagestate.h"
+#include "savagetex.h"
+#include "savagevb.h"
+#include "savageioctl.h"
+#include "savage_bci.h"
+
+static void savageRasterPrimitive( GLcontext *ctx, GLuint prim );
+static void savageRenderPrimitive( GLcontext *ctx, GLenum prim );
+
+/***********************************************************************
+ * Emit primitives *
+ ***********************************************************************/
+
+static __inline__ GLuint * savage_send_one_vertex(savageContextPtr imesa, savageVertexPtr v, GLuint * vb, GLuint start, GLuint size)
+{
+ GLuint j;
+ for (j = start ; j < size ; j++)
+ {
+ WRITE_CMD(vb, v->ui[j],GLuint);
+ }
+ return vb;
+}
+
+static void __inline__ savage_draw_triangle( savageContextPtr imesa,
+ savageVertexPtr v0,
+ savageVertexPtr v1,
+ savageVertexPtr v2 )
+{
+ GLuint vertsize = imesa->vertex_size;
+#if SAVAGEDEBUG
+ GLuint *vb = savageDMAAlloc (imesa, 3 * vertsize + 1 + 8);
+#else
+ GLuint *vb = savageDMAAlloc (imesa, 4 * vertsize + 1);
+#endif
+
+ imesa->DrawPrimitiveCmd &=
+ ~(SAVAGE_HW_TRIANGLE_TYPE| SAVAGE_HW_TRIANGLE_CONT);
+ WRITE_CMD(vb,SAVAGE_DRAW_PRIMITIVE(3, imesa->DrawPrimitiveCmd&imesa->DrawPrimitiveMask, 0),GLuint);
+
+ vb = savage_send_one_vertex(imesa, v0, vb, 0, vertsize);
+ vb = savage_send_one_vertex(imesa, v1, vb, 0, vertsize);
+ vb = savage_send_one_vertex(imesa, v2, vb, 0, vertsize);
+
+#if SAVAGEDEBUG
+ {
+ GLuint x0,y0,w,h;
+ x0 = (GLuint)imesa->drawX;
+ y0 = (GLuint)imesa->drawY;
+ w = (GLuint)imesa->driDrawable->w;
+ h = (GLuint)imesa->driDrawable->h;
+
+ (*vb) = 0x4BCC00C0;
+ vb++;
+ (*vb) = imesa->savageScreen->backOffset;
+ vb++;
+ (*vb) = imesa->savageScreen->backBitmapDesc;
+ vb++;
+ (*vb) = (y0<<16)|x0;
+ vb++;
+ (*vb) = 0x0;
+ vb++;
+ (*vb) = (h<<16)|w;
+ vb++;
+ }
+#endif
+ savageDMACommit (imesa, vb);
+}
+
+static __inline__ void savage_draw_point( savageContextPtr imesa,
+ savageVertexPtr tmp )
+{
+ GLfloat sz = imesa->glCtx->Point._Size * .5;
+ int vertsize = imesa->vertex_size;
+ GLuint *vb = savageDMAAlloc (imesa, 4 * vertsize + 1);
+ const GLfloat x = tmp->v.x;
+ const GLfloat y = tmp->v.y;
+
+ imesa->DrawPrimitiveCmd &=
+ ~(SAVAGE_HW_TRIANGLE_TYPE | SAVAGE_HW_TRIANGLE_CONT);
+ imesa->DrawPrimitiveCmd |= SAVAGE_HW_TRIANGLE_FAN;
+
+ WRITE_CMD(vb, SAVAGE_DRAW_PRIMITIVE(4, imesa->DrawPrimitiveCmd&imesa->DrawPrimitiveMask, 0),GLuint);
+
+ WRITE_CMD(vb, x - sz, GLfloat);
+ WRITE_CMD(vb, y - sz, GLfloat);
+ vb = savage_send_one_vertex(imesa, tmp, vb, 2, vertsize);
+
+ WRITE_CMD(vb, x + sz, GLfloat);
+ WRITE_CMD(vb, y - sz, GLfloat);
+ vb = savage_send_one_vertex(imesa, tmp, vb, 2, vertsize);
+
+ WRITE_CMD(vb, x + sz, GLfloat);
+ WRITE_CMD(vb, y + sz, GLfloat);
+ vb = savage_send_one_vertex(imesa, tmp, vb, 2, vertsize);
+
+ WRITE_CMD(vb, x - sz, GLfloat);
+ WRITE_CMD(vb, y + sz, GLfloat);
+ vb = savage_send_one_vertex(imesa, tmp, vb, 2, vertsize);
+
+ savageDMACommit (imesa, vb);
+}
+
+
+static __inline__ void savage_draw_line( savageContextPtr imesa,
+ savageVertexPtr v0,
+ savageVertexPtr v1 )
+{
+ GLuint vertsize = imesa->vertex_size;
+ GLuint *vb = savageDMAAlloc (imesa, 4 * vertsize + 1);
+ GLfloat dx, dy, ix, iy;
+ GLfloat width = imesa->glCtx->Line._Width;
+
+ imesa->DrawPrimitiveCmd &=
+ ~(SAVAGE_HW_TRIANGLE_TYPE | SAVAGE_HW_TRIANGLE_CONT);
+ imesa->DrawPrimitiveCmd |= SAVAGE_HW_TRIANGLE_FAN;
+ WRITE_CMD(vb, SAVAGE_DRAW_PRIMITIVE(4, imesa->DrawPrimitiveCmd&imesa->DrawPrimitiveMask, 0),GLuint);
+
+ dx = v0->v.x - v1->v.x;
+ dy = v0->v.y - v1->v.y;
+
+ ix = width * .5; iy = 0;
+ if (dx * dx > dy * dy) {
+ iy = ix; ix = 0;
+ }
+
+ WRITE_CMD(vb, (v0->v.x - ix), GLfloat);
+ WRITE_CMD(vb, (v0->v.y - iy), GLfloat);
+ vb = savage_send_one_vertex(imesa, v0, vb, 2, vertsize);
+
+ WRITE_CMD(vb, (v1->v.x - ix), GLfloat);
+ WRITE_CMD(vb, (v1->v.y - iy), GLfloat);
+ vb = savage_send_one_vertex(imesa, v1, vb, 2, vertsize);
+
+ WRITE_CMD(vb, (v1->v.x + ix), GLfloat);
+ WRITE_CMD(vb, (v1->v.y + iy), GLfloat);
+ vb = savage_send_one_vertex(imesa, v1, vb, 2, vertsize);
+
+ WRITE_CMD(vb, (v0->v.x + ix), GLfloat);
+ WRITE_CMD(vb, (v0->v.y + iy), GLfloat);
+ vb = savage_send_one_vertex(imesa, v0, vb, 2, vertsize);
+
+ savageDMACommit (imesa, vb);
+}
+
+static void __inline__ savage_draw_quad( savageContextPtr imesa,
+ savageVertexPtr v0,
+ savageVertexPtr v1,
+ savageVertexPtr v2,
+ savageVertexPtr v3 )
+{
+ GLuint vertsize = imesa->vertex_size;
+ GLuint *vb = savageDMAAlloc (imesa, 6 * vertsize + 1);
+
+ imesa->DrawPrimitiveCmd &=
+ ~(SAVAGE_HW_TRIANGLE_TYPE | SAVAGE_HW_TRIANGLE_CONT);
+ WRITE_CMD(vb, SAVAGE_DRAW_PRIMITIVE(6, imesa->DrawPrimitiveCmd&imesa->DrawPrimitiveMask, 0),GLuint);
+
+ vb = savage_send_one_vertex(imesa, v0, vb, 0, vertsize);
+ vb = savage_send_one_vertex(imesa, v1, vb, 0, vertsize);
+ vb = savage_send_one_vertex(imesa, v3, vb, 0, vertsize);
+ vb = savage_send_one_vertex(imesa, v1, vb, 0, vertsize);
+ vb = savage_send_one_vertex(imesa, v2, vb, 0, vertsize);
+ vb = savage_send_one_vertex(imesa, v3, vb, 0, vertsize);
+
+ savageDMACommit (imesa, vb);
+}
+
+/***********************************************************************
+ * Macros for t_dd_tritmp.h to draw basic primitives *
+ ***********************************************************************/
+
+#define TRI( a, b, c ) \
+do { \
+ if (DO_FALLBACK) \
+ imesa->draw_tri( imesa, a, b, c ); \
+ else \
+ savage_draw_triangle( imesa, a, b, c ); \
+} while (0)
+
+#define QUAD( a, b, c, d ) \
+do { \
+ if (DO_FALLBACK) { \
+ imesa->draw_tri( imesa, a, b, d ); \
+ imesa->draw_tri( imesa, b, c, d ); \
+ } else \
+ savage_draw_quad( imesa, a, b, c, d ); \
+} while (0)
+
+#define LINE( v0, v1 ) \
+do { \
+ if (DO_FALLBACK) \
+ imesa->draw_line( imesa, v0, v1 ); \
+ else \
+ savage_draw_line( imesa, v0, v1 ); \
+} while (0)
+
+#define POINT( v0 ) \
+do { \
+ if (DO_FALLBACK) \
+ imesa->draw_point( imesa, v0 ); \
+ else \
+ savage_draw_point( imesa, v0 ); \
+} while (0)
+
+
+/***********************************************************************
+ * Build render functions from dd templates *
+ ***********************************************************************/
+
+#define SAVAGE_OFFSET_BIT 0x1
+#define SAVAGE_TWOSIDE_BIT 0x2
+#define SAVAGE_UNFILLED_BIT 0x4
+#define SAVAGE_FALLBACK_BIT 0x8
+#define SAVAGE_MAX_TRIFUNC 0x10
+
+
+static struct {
+ points_func points;
+ line_func line;
+ triangle_func triangle;
+ quad_func quad;
+} rast_tab[SAVAGE_MAX_TRIFUNC];
+
+
+#define DO_FALLBACK (IND & SAVAGE_FALLBACK_BIT)
+#define DO_OFFSET (IND & SAVAGE_OFFSET_BIT)
+#define DO_UNFILLED (IND & SAVAGE_UNFILLED_BIT)
+#define DO_TWOSIDE (IND & SAVAGE_TWOSIDE_BIT)
+#define DO_FLAT 0
+#define DO_TRI 1
+#define DO_QUAD 1
+#define DO_LINE 1
+#define DO_POINTS 1
+#define DO_FULL_QUAD 1
+
+#define HAVE_RGBA 1
+#define HAVE_SPEC 1
+#define HAVE_BACK_COLORS 0
+#define HAVE_HW_FLATSHADE 1
+#define VERTEX savageVertex
+#define TAB rast_tab
+
+#define DEPTH_SCALE imesa->depth_scale
+#define UNFILLED_TRI unfilled_tri
+#define UNFILLED_QUAD unfilled_quad
+#define VERT_X(_v) _v->v.x
+#define VERT_Y(_v) _v->v.y
+#define VERT_Z(_v) _v->v.z
+#define AREA_IS_CCW( a ) (a > 0)
+#define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
+
+#define SAVAGE_COLOR( dst, src ) \
+do { \
+ dst[0] = src[2]; \
+ dst[1] = src[1]; \
+ dst[2] = src[0]; \
+ dst[3] = src[3]; \
+} while (0)
+
+#define SAVAGE_SPEC( dst, src ) \
+do { \
+ dst[0] = src[2]; \
+ dst[1] = src[1]; \
+ dst[2] = src[0]; \
+} while (0)
+
+#define VERT_SET_RGBA( v, c ) SAVAGE_COLOR( v->ub4[coloroffset], c )
+#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
+#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
+#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
+
+#define VERT_SET_SPEC( v, c ) if (havespec) SAVAGE_SPEC( v->ub4[5], c )
+#define VERT_COPY_SPEC( v0, v1 ) if (havespec) COPY_3V(v0->ub4[5], v1->ub4[5])
+#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
+#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
+
+#define LOCAL_VARS(n) \
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
+ GLuint color[n], spec[n]; \
+ GLuint coloroffset = 4/*(rmesa->vertex_size == 4 ? 3 : 4)*/; \
+ GLboolean havespec = 1/*(rmesa->vertex_size == 4 ? 0 : 1)*/; \
+ (void) color; (void) spec; (void) coloroffset; (void) havespec;
+
+/***********************************************************************
+ * Helpers for rendering unfilled primitives *
+ ***********************************************************************/
+
+#define RASTERIZE(x)
+#define RENDER_PRIMITIVE imesa->render_primitive
+#define IND SAVAGE_FALLBACK_BIT
+#define TAG(x) x
+#include "tnl_dd/t_dd_unfilled.h"
+#undef IND
+
+
+/***********************************************************************
+ * Generate GL render functions *
+ ***********************************************************************/
+
+
+#define IND (0)
+#define TAG(x) x
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
+#define TAG(x) x##_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
+#define TAG(x) x##_twoside_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_FALLBACK_BIT)
+#define TAG(x) x##_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
+#define TAG(x) x##_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_FALLBACK_BIT)
+#define TAG(x) x##_twoside_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
+#define TAG(x) x##_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
+#define TAG(x) x##_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
+#define TAG(x) x##_twoside_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT| \
+ SAVAGE_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+
+static void init_rast_tab( void )
+{
+ init();
+ init_offset();
+ init_twoside();
+ init_twoside_offset();
+ init_unfilled();
+ init_offset_unfilled();
+ init_twoside_unfilled();
+ init_twoside_offset_unfilled();
+ init_fallback();
+ init_offset_fallback();
+ init_twoside_fallback();
+ init_twoside_offset_fallback();
+ init_unfilled_fallback();
+ init_offset_unfilled_fallback();
+ init_twoside_unfilled_fallback();
+ init_twoside_offset_unfilled_fallback();
+}
+
+
+
+/***********************************************************************
+ * Rasterization fallback helpers *
+ ***********************************************************************/
+
+
+/* This code is hit only when a mix of accelerated and unaccelerated
+ * primitives are being drawn, and only for the unaccelerated
+ * primitives.
+ */
+static void
+savage_fallback_tri( savageContextPtr imesa,
+ savageVertexPtr v0,
+ savageVertexPtr v1,
+ savageVertexPtr v2 )
+{
+ GLcontext *ctx = imesa->glCtx;
+ SWvertex v[3];
+ savage_translate_vertex( ctx, v0, &v[0] );
+ savage_translate_vertex( ctx, v1, &v[1] );
+ savage_translate_vertex( ctx, v2, &v[2] );
+ _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
+}
+
+
+static void
+savage_fallback_line( savageContextPtr imesa,
+ savageVertexPtr v0,
+ savageVertexPtr v1 )
+{
+ GLcontext *ctx = imesa->glCtx;
+ SWvertex v[2];
+ savage_translate_vertex( ctx, v0, &v[0] );
+ savage_translate_vertex( ctx, v1, &v[1] );
+ _swrast_Line( ctx, &v[0], &v[1] );
+}
+
+
+static void
+savage_fallback_point( savageContextPtr imesa,
+ savageVertexPtr v0 )
+{
+ GLcontext *ctx = imesa->glCtx;
+ SWvertex v[1];
+ savage_translate_vertex( ctx, v0, &v[0] );
+ _swrast_Point( ctx, &v[0] );
+}
+
+
+
+/**********************************************************************/
+/* Render unclipped begin/end objects */
+/**********************************************************************/
+
+#define VERT(x) (savageVertexPtr)(savageVerts + (x * vertsize * sizeof(int)))
+#define RENDER_POINTS( start, count ) \
+ for ( ; start < count ; start++) \
+ savage_draw_point( imesa, VERT(start) )
+#define RENDER_LINE( v0, v1 ) \
+ savage_draw_line( imesa, VERT(v0), VERT(v1) )
+#define RENDER_TRI( v0, v1, v2 ) \
+ savage_draw_triangle( imesa, VERT(v0), VERT(v1), VERT(v2) )
+#define RENDER_QUAD( v0, v1, v2, v3 ) \
+ savage_draw_quad( imesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
+#define INIT(x) do { \
+ if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
+ savageRenderPrimitive( ctx, x ); \
+ /*SAVAGE_CONTEXT(ctx)->render_primitive = x;*/ \
+} while (0)
+#undef LOCAL_VARS
+#define LOCAL_VARS \
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
+ const GLuint vertsize = imesa->vertex_size; \
+ const char *savageVerts = (char *)imesa->verts; \
+ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
+ (void) elt;
+#define RESET_STIPPLE
+#define RESET_OCCLUSION
+#define PRESERVE_VB_DEFS
+#define ELT(x) (x)
+#define TAG(x) savage_##x##_verts
+#include "tnl/t_vb_rendertmp.h"
+#undef ELT
+#undef TAG
+#define TAG(x) savage_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Render clipped primitives */
+/**********************************************************************/
+
+static void savageRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
+ GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ /* Render the new vertices as an unclipped polygon.
+ */
+ {
+ GLuint *tmp = VB->Elts;
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+ }
+}
+
+static void savageRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+/*
+static void savageFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
+ GLuint n )
+{
+ r128ContextPtr rmesa = R128_CONTEXT( ctx );
+ GLuint vertsize = rmesa->vertex_size;
+ GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
+ GLubyte *r128verts = (GLubyte *)rmesa->verts;
+ const GLuint shift = rmesa->vertex_stride_shift;
+ const GLuint *start = (const GLuint *)VERT(elts[0]);
+ int i,j;
+
+ rmesa->num_verts += (n-2) * 3;
+
+ for (i = 2 ; i < n ; i++) {
+ COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
+ COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
+ COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
+ }
+}
+*/
+
+
+
+/**********************************************************************/
+/* Choose render functions */
+/**********************************************************************/
+
+#define _SAVAGE_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
+ _DD_NEW_LINE_SMOOTH | \
+ _DD_NEW_POINT_SMOOTH | \
+ _DD_NEW_TRI_SMOOTH | \
+ _DD_NEW_TRI_UNFILLED | \
+ _DD_NEW_TRI_LIGHT_TWOSIDE | \
+ _DD_NEW_TRI_OFFSET) \
+
+/* original driver didn't have DD_POINT_SMOOTH. really needed? */
+#define POINT_FALLBACK (DD_POINT_SMOOTH)
+#define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
+#define TRI_FALLBACK (DD_TRI_SMOOTH)
+#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
+#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
+
+
+static void savageChooseRenderState(GLcontext *ctx)
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ GLuint flags = ctx->_TriangleCaps;
+ GLuint index = 0;
+
+ if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
+ imesa->draw_point = savage_draw_point;
+ imesa->draw_line = savage_draw_line;
+ imesa->draw_tri = savage_draw_triangle;
+
+ if (flags & ANY_RASTER_FLAGS) {
+ if (flags & DD_TRI_LIGHT_TWOSIDE) index |= SAVAGE_TWOSIDE_BIT;
+ if (flags & DD_TRI_OFFSET) index |= SAVAGE_OFFSET_BIT;
+ if (flags & DD_TRI_UNFILLED) index |= SAVAGE_UNFILLED_BIT;
+ }
+
+ /* Hook in fallbacks for specific primitives.
+ */
+ if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
+ if (flags & POINT_FALLBACK) imesa->draw_point = savage_fallback_point;
+ if (flags & LINE_FALLBACK) imesa->draw_line = savage_fallback_line;
+ if (flags & TRI_FALLBACK) imesa->draw_tri = savage_fallback_tri;
+ index |= SAVAGE_FALLBACK_BIT;
+ }
+ }
+
+ if (index != imesa->RenderIndex) {
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Points = rast_tab[index].points;
+ tnl->Driver.Render.Line = rast_tab[index].line;
+ tnl->Driver.Render.Triangle = rast_tab[index].triangle;
+ tnl->Driver.Render.Quad = rast_tab[index].quad;
+
+ if (index == 0) {
+ tnl->Driver.Render.PrimTabVerts = savage_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = savage_render_tab_elts;
+ tnl->Driver.Render.ClippedLine = rast_tab[index].line;
+ tnl->Driver.Render.ClippedPolygon = savageRenderClippedPoly/*r128FastRenderClippedPoly*/;
+ } else {
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.ClippedLine = savageRenderClippedLine;
+ tnl->Driver.Render.ClippedPolygon = savageRenderClippedPoly;
+ }
+
+ imesa->RenderIndex = index;
+ }
+}
+
+/**********************************************************************/
+/* Validate state at pipeline start */
+/**********************************************************************/
+
+static void savageRunPipeline( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+
+ if (imesa->new_state)
+ savageDDUpdateHwState( ctx );
+
+ if (!imesa->Fallback && imesa->new_gl_state) {
+ if (imesa->new_gl_state & _SAVAGE_NEW_VERTEX_STATE)
+ savageChooseVertexState( ctx );
+
+ if (imesa->new_gl_state & _SAVAGE_NEW_RENDER_STATE)
+ savageChooseRenderState( ctx );
+
+ imesa->new_gl_state = 0;
+ }
+
+ _tnl_run_pipeline( ctx );
+}
+
+/**********************************************************************/
+/* High level hooks for t_vb_render.c */
+/**********************************************************************/
+
+static GLenum reduced_prim[GL_POLYGON+1] = {
+ GL_POINTS,
+ GL_LINES,
+ GL_LINES,
+ GL_LINES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES
+};
+
+/* This is called when Mesa switches between rendering triangle
+ * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
+ * and lines, points and bitmaps.
+ *
+ * As the r128 uses triangles to render lines and points, it is
+ * necessary to turn off hardware culling when rendering these
+ * primitives.
+ */
+
+static void savageRasterPrimitive( GLcontext *ctx, GLuint prim )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+
+ FLUSH_BATCH( imesa );
+
+ /* Update culling */
+ if (imesa->raster_primitive != prim)
+ imesa->dirty |= SAVAGE_UPLOAD_CTX;
+
+ imesa->raster_primitive = prim;
+#if 0
+ if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple)
+ {
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+ mmesa->setup.dwgctl &= ~(0xf<<20);
+ if (mmesa->raster_primitive == GL_TRIANGLES)
+ mmesa->setup.dwgctl |= mmesa->poly_stipple;
+ }
+#endif
+}
+
+static void savageRenderPrimitive( GLcontext *ctx, GLenum prim )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ GLuint rprim = reduced_prim[prim];
+
+ imesa->render_primitive = prim;
+
+ if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
+ return;
+
+ if (imesa->raster_primitive != rprim) {
+ savageRasterPrimitive( ctx, rprim );
+ }
+}
+
+
+static void savageRenderStart( GLcontext *ctx )
+{
+ /* Check for projective texturing. Make sure all texcoord
+ * pointers point to something. (fix in mesa?)
+ */
+ savageCheckTexSizes( ctx );
+
+ if (!SAVAGE_CONTEXT(ctx)->Fallback) {
+ /* Update hardware state and get the lock */
+ savageDDRenderStart( ctx );
+ }
+}
+
+static void savageRenderFinish( GLcontext *ctx )
+{
+ /* Release the lock */
+ savageDDRenderEnd( ctx );
+
+ if (SAVAGE_CONTEXT(ctx)->RenderIndex & SAVAGE_FALLBACK_BIT)
+ _swrast_flush( ctx );
+}
+
+
+/**********************************************************************/
+/* Transition to/from hardware rasterization. */
+/**********************************************************************/
+
+void savageFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ GLuint oldfallback = imesa->Fallback;
+
+ if (mode) {
+ imesa->Fallback |= bit;
+ if (oldfallback == 0) {
+ /* the first fallback */
+ LOCK_HARDWARE(SAVAGE_CONTEXT(ctx));
+ FLUSH_BATCH( imesa );
+ UNLOCK_HARDWARE(SAVAGE_CONTEXT(ctx));
+ _swsetup_Wakeup( ctx );
+ imesa->RenderIndex = ~0;
+ }
+ }
+ else {
+ imesa->Fallback &= ~bit;
+ if (oldfallback == bit) {
+ /* the last fallback */
+ _swrast_flush( ctx );
+ tnl->Driver.Render.Start = savageRenderStart;
+ tnl->Driver.Render.PrimitiveNotify = savageRenderPrimitive;
+ tnl->Driver.Render.Finish = savageRenderFinish;
+ tnl->Driver.Render.BuildVertices = savageBuildVertices;
+ imesa->new_gl_state |= (_SAVAGE_NEW_RENDER_STATE|
+ _SAVAGE_NEW_VERTEX_STATE);
+ }
+ }
+}
+
+
+/**********************************************************************/
+/* Initialization. */
+/**********************************************************************/
+
+void savageInitTriFuncs( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ static int firsttime = 1;
+
+ if (firsttime) {
+ init_rast_tab();
+ firsttime = 0;
+ }
+
+ tnl->Driver.RunPipeline = savageRunPipeline;
+ tnl->Driver.Render.Start = savageRenderStart;
+ tnl->Driver.Render.Finish = savageRenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = savageRenderPrimitive;
+ tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
+ tnl->Driver.Render.BuildVertices = savageBuildVertices;
+
+/* r128Fallback( ctx, 0x100000, 1 ); */
+}
diff --git a/src/mesa/drivers/dri/savage/savagetris.h b/src/mesa/drivers/dri/savage/savagetris.h
new file mode 100644
index 0000000000..00803e7ff3
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagetris.h
@@ -0,0 +1,49 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tris.h,v 1.4 2001/01/08 01:07:24 martin Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keithw@valinux.com>
+ * Felix Kuehling <fxkuehl@gmx.de>
+ *
+ */
+
+#ifndef __R128_TRIS_H__
+#define __R128_TRIS_H__
+
+#include "mtypes.h"
+
+extern void savageInitTriFuncs( GLcontext *ctx );
+
+
+extern void savageFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+#define FALLBACK( ctx, bit, mode ) savageFallback( ctx, bit, mode )
+
+
+#endif /* __R128_TRIS_H__ */
diff --git a/src/mesa/drivers/dri/savage/savagevb.c b/src/mesa/drivers/dri/savage/savagevb.c
new file mode 100644
index 0000000000..f0f4f4c43d
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagevb.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@valinux.com>
+ * Felix Kuehling <fxkuehl@gmx.de>
+ */
+/* $XFree86$ */
+
+#include "savagecontext.h"
+#include "savagevb.h"
+#include "savagetris.h"
+#include "savageioctl.h"
+#include "savagecontext.h"
+#include "savage_bci.h"
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "colormac.h"
+
+#include "tnl/t_context.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast/swrast.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#define SAVAGE_TEX1_BIT 0x1
+#define SAVAGE_TEX0_BIT 0x2
+#define SAVAGE_RGBA_BIT 0x4
+#define SAVAGE_SPEC_BIT 0x8
+#define SAVAGE_FOG_BIT 0x10
+#define SAVAGE_XYZW_BIT 0x20
+#define SAVAGE_PTEX_BIT 0x40
+#define SAVAGE_MAX_SETUP 0x80
+
+static struct {
+ void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
+ interp_func interp;
+ copy_pv_func copy_pv;
+ GLboolean (*check_tex_sizes)( GLcontext *ctx );
+ GLuint vertex_size;
+ GLuint vertex_format;
+} setup_tab[SAVAGE_MAX_SETUP];
+
+/* savage supports vertices without specular color, but this is not supported
+ * by the vbtmp. have to check if/how tiny vertices work. */
+#define TINY_VERTEX_FORMAT 0
+#define NOTEX_VERTEX_FORMAT (SAVAGE_HW_NO_UV0|SAVAGE_HW_NO_UV1)
+#define TEX0_VERTEX_FORMAT (SAVAGE_HW_NO_UV1)
+#define TEX1_VERTEX_FORMAT (0)
+#define PROJ_TEX1_VERTEX_FORMAT 0
+#define TEX2_VERTEX_FORMAT 0
+#define TEX3_VERTEX_FORMAT 0
+#define PROJ_TEX3_VERTEX_FORMAT 0
+
+#define DO_XYZW (IND & SAVAGE_XYZW_BIT)
+#define DO_RGBA (IND & SAVAGE_RGBA_BIT)
+#define DO_SPEC (IND & SAVAGE_SPEC_BIT)
+#define DO_FOG (IND & SAVAGE_FOG_BIT)
+#define DO_TEX0 (IND & SAVAGE_TEX0_BIT)
+#define DO_TEX1 (IND & SAVAGE_TEX1_BIT)
+#define DO_TEX2 0
+#define DO_TEX3 0
+#define DO_PTEX (IND & SAVAGE_PTEX_BIT)
+
+
+#define VERTEX savageVertex
+#define LOCALVARS savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+#define GET_VIEWPORT_MAT() imesa->hw_viewport
+#define GET_TEXSOURCE(n) n
+#define GET_VERTEX_FORMAT() (imesa->DrawPrimitiveCmd & \
+ (SAVAGE_HW_NO_UV0|SAVAGE_HW_NO_UV1))
+#define GET_VERTEX_STORE() imesa->verts
+#define GET_VERTEX_SIZE() (imesa->vertex_size * sizeof(int))
+
+#define HAVE_HW_VIEWPORT 0
+#define HAVE_HW_DIVIDE 0
+#define HAVE_RGBA_COLOR 0
+#define HAVE_TINY_VERTICES 0
+#define HAVE_NOTEX_VERTICES 1
+#define HAVE_TEX0_VERTICES 1
+#define HAVE_TEX1_VERTICES 1
+#define HAVE_TEX2_VERTICES 0
+#define HAVE_TEX3_VERTICES 0
+#define HAVE_PTEX_VERTICES 0
+
+#define UNVIEWPORT_VARS \
+ const GLfloat dx = - imesa->drawX - SUBPIXEL_X; \
+ const GLfloat dy = (imesa->driDrawable->h + \
+ imesa->drawY + SUBPIXEL_Y); \
+ const GLfloat sz = 1.0 / imesa->depth_scale
+
+#define UNVIEWPORT_X(x) x + dx;
+#define UNVIEWPORT_Y(y) - y + dy;
+#define UNVIEWPORT_Z(z) z * sz;
+
+#define PTEX_FALLBACK() (void)imesa, FALLBACK(ctx, SAVAGE_FALLBACK_TEXTURE, 1)
+
+
+#define INTERP_VERTEX (void)imesa, setup_tab[SAVAGE_CONTEXT(ctx)->SetupIndex].interp
+#define COPY_PV_VERTEX (void)imesa, setup_tab[SAVAGE_CONTEXT(ctx)->SetupIndex].copy_pv
+
+
+/***********************************************************************
+ * Generate pv-copying and translation functions *
+ ***********************************************************************/
+
+#define TAG(x) savage_##x
+#include "tnl_dd/t_dd_vb.c"
+
+/***********************************************************************
+ * Generate vertex emit and interp functions *
+ ***********************************************************************/
+
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT)
+#define TAG(x) x##_wg
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_SPEC_BIT)
+#define TAG(x) x##_wgs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_TEX0_BIT)
+#define TAG(x) x##_wgt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT)
+#define TAG(x) x##_wgt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_TEX0_BIT|SAVAGE_PTEX_BIT)
+#define TAG(x) x##_wgpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_SPEC_BIT|SAVAGE_TEX0_BIT)
+#define TAG(x) x##_wgst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_SPEC_BIT|SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT)
+#define TAG(x) x##_wgst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_SPEC_BIT|SAVAGE_TEX0_BIT|SAVAGE_PTEX_BIT)
+#define TAG(x) x##_wgspt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT)
+#define TAG(x) x##_wgf
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_SPEC_BIT)
+#define TAG(x) x##_wgfs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_TEX0_BIT)
+#define TAG(x) x##_wgft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT)
+#define TAG(x) x##_wgft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_TEX0_BIT|SAVAGE_PTEX_BIT)
+#define TAG(x) x##_wgfpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_SPEC_BIT|SAVAGE_TEX0_BIT)
+#define TAG(x) x##_wgfst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_SPEC_BIT|SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT)
+#define TAG(x) x##_wgfst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_SPEC_BIT|SAVAGE_TEX0_BIT|SAVAGE_PTEX_BIT)
+#define TAG(x) x##_wgfspt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_TEX0_BIT)
+#define TAG(x) x##_t0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT)
+#define TAG(x) x##_t0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_FOG_BIT)
+#define TAG(x) x##_f
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_FOG_BIT|SAVAGE_TEX0_BIT)
+#define TAG(x) x##_ft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_FOG_BIT|SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT)
+#define TAG(x) x##_ft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT)
+#define TAG(x) x##_g
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_SPEC_BIT)
+#define TAG(x) x##_gs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_TEX0_BIT)
+#define TAG(x) x##_gt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT)
+#define TAG(x) x##_gt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_SPEC_BIT|SAVAGE_TEX0_BIT)
+#define TAG(x) x##_gst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_SPEC_BIT|SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT)
+#define TAG(x) x##_gst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT)
+#define TAG(x) x##_gf
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_SPEC_BIT)
+#define TAG(x) x##_gfs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_TEX0_BIT)
+#define TAG(x) x##_gft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT)
+#define TAG(x) x##_gft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_SPEC_BIT|SAVAGE_TEX0_BIT)
+#define TAG(x) x##_gfst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (SAVAGE_RGBA_BIT|SAVAGE_FOG_BIT|SAVAGE_SPEC_BIT|SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT)
+#define TAG(x) x##_gfst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+
+static void init_setup_tab( void )
+{
+ init_wg();
+ init_wgs();
+ init_wgt0();
+ init_wgt0t1();
+ init_wgpt0();
+ init_wgst0();
+ init_wgst0t1();
+ init_wgspt0();
+ init_wgf();
+ init_wgfs();
+ init_wgft0();
+ init_wgft0t1();
+ init_wgfpt0();
+ init_wgfst0();
+ init_wgfst0t1();
+ init_wgfspt0();
+ init_t0();
+ init_t0t1();
+ init_f();
+ init_ft0();
+ init_ft0t1();
+ init_g();
+ init_gs();
+ init_gt0();
+ init_gt0t1();
+ init_gst0();
+ init_gst0t1();
+ init_gf();
+ init_gfs();
+ init_gft0();
+ init_gft0t1();
+ init_gfst0();
+ init_gfst0t1();
+}
+
+
+
+
+void savagePrintSetupFlags(char *msg, GLuint flags )
+{
+ fprintf(stderr, "%s: %d %s%s%s%s%s%s\n",
+ msg,
+ (int)flags,
+ (flags & SAVAGE_XYZW_BIT) ? " xyzw," : "",
+ (flags & SAVAGE_RGBA_BIT) ? " rgba," : "",
+ (flags & SAVAGE_SPEC_BIT) ? " spec," : "",
+ (flags & SAVAGE_FOG_BIT) ? " fog," : "",
+ (flags & SAVAGE_TEX0_BIT) ? " tex-0," : "",
+ (flags & SAVAGE_TEX1_BIT) ? " tex-1," : "");
+}
+
+
+void savageCheckTexSizes( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ /*fprintf(stderr, "%s\n", __FUNCTION__);*/
+
+ if (!setup_tab[imesa->SetupIndex].check_tex_sizes(ctx)) {
+ imesa->SetupIndex |= SAVAGE_PTEX_BIT;
+ imesa->SetupNewInputs = ~0;
+
+ if (!imesa->Fallback &&
+ !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ tnl->Driver.Render.Interp = setup_tab[imesa->SetupIndex].interp;
+ tnl->Driver.Render.CopyPV = setup_tab[imesa->SetupIndex].copy_pv;
+ }
+ if (imesa->Fallback)
+ tnl->Driver.Render.Start(ctx);
+ }
+}
+
+
+void savageBuildVertices( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint newinputs )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+ GLuint stride = imesa->vertex_size * sizeof(int);
+ GLubyte *v = ((GLubyte *)imesa->verts + (start * stride));
+
+ newinputs |= imesa->SetupNewInputs;
+ imesa->SetupNewInputs = 0;
+
+ if (!newinputs)
+ return;
+
+ if (newinputs & VERT_BIT_POS) {
+ setup_tab[imesa->SetupIndex].emit( ctx, start, count, v, stride );
+ } else {
+ GLuint ind = 0;
+
+ if (newinputs & VERT_BIT_COLOR0)
+ ind |= SAVAGE_RGBA_BIT;
+
+ if (newinputs & VERT_BIT_COLOR1)
+ ind |= SAVAGE_SPEC_BIT;
+
+ if (newinputs & VERT_BIT_TEX0)
+ ind |= SAVAGE_TEX0_BIT;
+
+ if (newinputs & VERT_BIT_TEX1)
+ ind |= SAVAGE_TEX0_BIT|SAVAGE_TEX1_BIT;
+
+ if (newinputs & VERT_BIT_FOG)
+ ind |= SAVAGE_FOG_BIT;
+
+ if (imesa->SetupIndex & SAVAGE_PTEX_BIT)
+ ind = ~0;
+
+ ind &= imesa->SetupIndex;
+
+ if (ind) {
+ setup_tab[ind].emit( ctx, start, count, v, stride );
+ }
+ }
+}
+
+
+void savageChooseVertexState( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint ind = SAVAGE_XYZW_BIT|SAVAGE_RGBA_BIT;
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+ ind |= SAVAGE_SPEC_BIT;
+
+ if (ctx->Fog.Enabled)
+ ind |= SAVAGE_FOG_BIT;
+
+ if (ctx->Texture._EnabledUnits & 0x2) {
+ if (ctx->Texture._EnabledUnits & 0x1) {
+ ind |= SAVAGE_TEX1_BIT|SAVAGE_TEX0_BIT;
+ }
+ else {
+ ind |= SAVAGE_TEX0_BIT;
+ }
+ }
+ else if (ctx->Texture._EnabledUnits & 0x1) {
+ ind |= SAVAGE_TEX0_BIT;
+ }
+
+ imesa->SetupIndex = ind;
+
+ if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
+ tnl->Driver.Render.Interp = savage_interp_extras;
+ tnl->Driver.Render.CopyPV = savage_copy_pv_extras;
+ } else {
+ tnl->Driver.Render.Interp = setup_tab[ind].interp;
+ tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
+ }
+
+ if (setup_tab[ind].vertex_format != GET_VERTEX_FORMAT()) {
+ imesa->DrawPrimitiveCmd = setup_tab[ind].vertex_format;
+ imesa->vertex_size = setup_tab[ind].vertex_size;
+ }
+}
+
+
+
+void savageInitVB( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ GLuint size = TNL_CONTEXT(ctx)->vb.Size;
+
+ imesa->verts = (GLubyte *)ALIGN_MALLOC(size * sizeof(savageVertex), 32);
+
+ {
+ static int firsttime = 1;
+ if (firsttime) {
+ init_setup_tab();
+ firsttime = 0;
+ }
+ }
+
+ imesa->DrawPrimitiveCmd = setup_tab[0].vertex_format;
+ imesa->vertex_size = setup_tab[0].vertex_size;
+
+ if (imesa->savageScreen->chipset >= S3_SAVAGE4)
+ imesa->DrawPrimitiveMask = ~0;
+ else
+ imesa->DrawPrimitiveMask = ~SAVAGE_HW_NO_UV1;
+}
+
+
+void savageFreeVB( GLcontext *ctx )
+{
+ savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+ if (imesa->verts) {
+ ALIGN_FREE(imesa->verts);
+ imesa->verts = 0;
+ }
+}
+
diff --git a/src/mesa/drivers/dri/savage/savagevb.h b/src/mesa/drivers/dri/savage/savagevb.h
new file mode 100644
index 0000000000..9ee2bd9cc7
--- /dev/null
+++ b/src/mesa/drivers/dri/savage/savagevb.h
@@ -0,0 +1,62 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgavb.h,v 1.6 2001/04/10 16:07:51 dawes Exp $ */
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@valinux.com>
+ * Felix Kuehling <fxkuehl@gmx.de>
+ */
+
+#ifndef SAVAGEVB_INC
+#define SAVAGEVB_INC
+
+#include "mtypes.h"
+#include "savagecontext.h"
+#include "swrast/swrast.h"
+
+#define _SAVAGE_NEW_VERTEX_STATE (_NEW_TEXTURE | \
+ _DD_NEW_SEPARATE_SPECULAR | \
+ _DD_NEW_TRI_UNFILLED | \
+ _DD_NEW_TRI_LIGHT_TWOSIDE | \
+ _NEW_FOG)
+
+
+extern void savageChooseVertexState( GLcontext *ctx );
+extern void savageCheckTexSizes( GLcontext *ctx );
+extern void savageBuildVertices( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint newinputs );
+
+extern void savagePrintSetupFlags(char *msg, GLuint flags );
+
+extern void savageInitVB( GLcontext *ctx );
+extern void savageFreeVB( GLcontext *ctx );
+
+extern void savage_translate_vertex(GLcontext *ctx,
+ const savageVertex *src,
+ SWvertex *dst);
+
+extern void savage_print_vertex( GLcontext *ctx, const savageVertex *v );
+
+#endif