DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/voodoo_data.h
00001 /***************************************************************************/
00002 /*        Portion of this software comes with the following license:       */
00003 /***************************************************************************/
00004 /*
00005 
00006     Copyright Aaron Giles
00007     All rights reserved.
00008 
00009     Redistribution and use in source and binary forms, with or without
00010     modification, are permitted provided that the following conditions are
00011     met:
00012 
00013         * Redistributions of source code must retain the above copyright
00014           notice, this list of conditions and the following disclaimer.
00015         * Redistributions in binary form must reproduce the above copyright
00016           notice, this list of conditions and the following disclaimer in
00017           the documentation and/or other materials provided with the
00018           distribution.
00019         * Neither the name 'MAME' nor the names of its contributors may be
00020           used to endorse or promote products derived from this software
00021           without specific prior written permission.
00022 
00023     THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
00024     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00026     DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
00027     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00029     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00031     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00032     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033     POSSIBILITY OF SUCH DAMAGE.
00034 
00035 ***************************************************************************/
00036 
00037 /*************************************************************************
00038 
00039     3dfx Voodoo Graphics SST-1/2 emulator
00040 
00041     emulator by Aaron Giles
00042 
00043 **************************************************************************/
00044 
00045 
00046 #ifndef DOSBOX_VOODOO_DATA_H
00047 #define DOSBOX_VOODOO_DATA_H
00048 
00049 
00050 /*************************************
00051  *
00052  *  Misc. constants
00053  *
00054  *************************************/
00055 
00056 /* enumeration specifying which model of Voodoo we are emulating */
00057 enum
00058 {
00059         VOODOO_1,
00060         VOODOO_1_DTMU,
00061         VOODOO_2,
00062         MAX_VOODOO_TYPES
00063 };
00064 
00065 
00066 /* maximum number of TMUs */
00067 #define MAX_TMU                                 2
00068 
00069 /* maximum number of rasterizers */
00070 #define MAX_RASTERIZERS                 1024
00071 
00072 /* size of the rasterizer hash table */
00073 #define RASTER_HASH_SIZE                97
00074 
00075 /* flags for LFB writes */
00076 #define LFB_RGB_PRESENT                 1
00077 #define LFB_ALPHA_PRESENT               2
00078 #define LFB_DEPTH_PRESENT               4
00079 #define LFB_DEPTH_PRESENT_MSW   8
00080 
00081 /* flags for the register access array */
00082 #define REGISTER_READ                   0x01            /* reads are allowed */
00083 #define REGISTER_WRITE                  0x02            /* writes are allowed */
00084 #define REGISTER_PIPELINED              0x04            /* writes are pipelined */
00085 #define REGISTER_FIFO                   0x08            /* writes go to FIFO */
00086 #define REGISTER_WRITETHRU              0x10            /* writes are valid even for CMDFIFO */
00087 
00088 /* shorter combinations to make the table smaller */
00089 #define REG_R                                   (REGISTER_READ)
00090 #define REG_W                                   (REGISTER_WRITE)
00091 #define REG_WT                                  (REGISTER_WRITE | REGISTER_WRITETHRU)
00092 #define REG_RW                                  (REGISTER_READ | REGISTER_WRITE)
00093 #define REG_RWT                                 (REGISTER_READ | REGISTER_WRITE | REGISTER_WRITETHRU)
00094 #define REG_RP                                  (REGISTER_READ | REGISTER_PIPELINED)
00095 #define REG_WP                                  (REGISTER_WRITE | REGISTER_PIPELINED)
00096 #define REG_RWP                                 (REGISTER_READ | REGISTER_WRITE | REGISTER_PIPELINED)
00097 #define REG_RWPT                                (REGISTER_READ | REGISTER_WRITE | REGISTER_PIPELINED | REGISTER_WRITETHRU)
00098 #define REG_RF                                  (REGISTER_READ | REGISTER_FIFO)
00099 #define REG_WF                                  (REGISTER_WRITE | REGISTER_FIFO)
00100 #define REG_RWF                                 (REGISTER_READ | REGISTER_WRITE | REGISTER_FIFO)
00101 #define REG_RPF                                 (REGISTER_READ | REGISTER_PIPELINED | REGISTER_FIFO)
00102 #define REG_WPF                                 (REGISTER_WRITE | REGISTER_PIPELINED | REGISTER_FIFO)
00103 #define REG_RWPF                                (REGISTER_READ | REGISTER_WRITE | REGISTER_PIPELINED | REGISTER_FIFO)
00104 
00105 /* lookup bits is the log2 of the size of the reciprocal/log table */
00106 #define RECIPLOG_LOOKUP_BITS    9
00107 
00108 /* input precision is how many fraction bits the input value has; this is a 64-bit number */
00109 #define RECIPLOG_INPUT_PREC             32
00110 
00111 /* lookup precision is how many fraction bits each table entry contains */
00112 #define RECIPLOG_LOOKUP_PREC    22
00113 
00114 /* output precision is how many fraction bits the result should have */
00115 #define RECIP_OUTPUT_PREC               15
00116 #define LOG_OUTPUT_PREC                 8
00117 
00118 
00119 
00120 /*************************************
00121  *
00122  *  Dithering tables
00123  *
00124  *************************************/
00125 
00126 static const UINT8 dither_matrix_4x4[16] =
00127 {
00128          0,  8,  2, 10,
00129         12,  4, 14,  6,
00130          3, 11,  1,  9,
00131         15,  7, 13,  5
00132 };
00133 
00134 static const UINT8 dither_matrix_2x2[16] =
00135 {
00136          2, 10,  2, 10,
00137         14,  6, 14,  6,
00138          2, 10,  2, 10,
00139         14,  6, 14,  6
00140 };
00141 
00142 
00143 
00144 /*************************************
00145  *
00146  *  Macros for extracting pixels
00147  *
00148  *************************************/
00149 
00150 #define EXTRACT_565_TO_888(val, a, b, c)                                        \
00151         (a) = (int)((((unsigned int)(val) >> 8u) & 0xf8u) | (((unsigned int)(val) >> 13u) & 0x07u));    \
00152         (b) = (int)((((unsigned int)(val) >> 3u) & 0xfcu) | (((unsigned int)(val) >>  9u) & 0x03u));    \
00153         (c) = (int)((((unsigned int)(val) << 3u) & 0xf8u) | (((unsigned int)(val) >>  2u) & 0x07u));    \
00154 
00155 #define EXTRACT_x555_TO_888(val, a, b, c)                                       \
00156         (a) = (int)((((unsigned int)(val) >> 7u) & 0xf8u) | (((unsigned int)(val) >> 12u) & 0x07u));    \
00157         (b) = (int)((((unsigned int)(val) >> 2u) & 0xf8u) | (((unsigned int)(val) >>  7u) & 0x07u));    \
00158         (c) = (int)((((unsigned int)(val) << 3u) & 0xf8u) | (((unsigned int)(val) >>  2u) & 0x07u));    \
00159 
00160 #define EXTRACT_555x_TO_888(val, a, b, c)                                       \
00161         (a) = (int)((((unsigned int)(val) >> 8u) & 0xf8u) | (((unsigned int)(val) >> 13u) & 0x07u));    \
00162         (b) = (int)((((unsigned int)(val) >> 3u) & 0xf8u) | (((unsigned int)(val) >>  8u) & 0x07u));    \
00163         (c) = (int)((((unsigned int)(val) << 2u) & 0xf8u) | (((unsigned int)(val) >>  3u) & 0x07u));    \
00164 
00165 #define EXTRACT_1555_TO_8888(val, a, b, c, d)                           \
00166         (a) = (int)(((unsigned int)(val) >> 15u) & 0xffu);                                              \
00167         EXTRACT_x555_TO_888(val, b, c, d)                                               \
00168 
00169 #define EXTRACT_5551_TO_8888(val, a, b, c, d)                           \
00170         EXTRACT_555x_TO_888(val, a, b, c)                                               \
00171         (d) = (int)(((unsigned int)(val) & 0x0001u) ? 0xffu : 0x00u);                                   \
00172 
00173 #define EXTRACT_x888_TO_888(val, a, b, c)                                       \
00174         (a) = (int)(((unsigned int)(val) >> 16u) & 0xffu);                                                              \
00175         (b) = (int)(((unsigned int)(val) >>  8u) & 0xffu);                                                              \
00176         (c) = (int)(((unsigned int)(val) >>  0u) & 0xffu);                                                              \
00177 
00178 #define EXTRACT_888x_TO_888(val, a, b, c)                                       \
00179         (a) = (int)(((unsigned int)(val) >> 24u) & 0xffu);                                                              \
00180         (b) = (int)(((unsigned int)(val) >> 16u) & 0xffu);                                                              \
00181         (c) = (int)(((unsigned int)(val) >>  8u) & 0xffu);                                                              \
00182 
00183 #define EXTRACT_8888_TO_8888(val, a, b, c, d)                           \
00184         (a) = (int)(((unsigned int)(val) >> 24u) & 0xffu);                                                              \
00185         (b) = (int)(((unsigned int)(val) >> 16u) & 0xffu);                                                              \
00186         (c) = (int)(((unsigned int)(val) >>  8u) & 0xffu);                                                              \
00187         (d) = (int)(((unsigned int)(val) >>  0u) & 0xffu);                                                              \
00188 
00189 #define EXTRACT_4444_TO_8888(val, a, b, c, d)                           \
00190         (a) = (int)((((unsigned int)(val) >> 8u) & 0xf0u) | (((unsigned int)(val) >> 12u) & 0x0fu));    \
00191         (b) = (int)((((unsigned int)(val) >> 4u) & 0xf0u) | (((unsigned int)(val) >>  8u) & 0x0fu));    \
00192         (c) = (int)((((unsigned int)(val) >> 0u) & 0xf0u) | (((unsigned int)(val) >>  4u) & 0x0fu));    \
00193         (d) = (int)((((unsigned int)(val) << 4u) & 0xf0u) | (((unsigned int)(val) >>  0u) & 0x0fu));    \
00194 
00195 #define EXTRACT_332_TO_888(val, a, b, c)                                        \
00196         (a) = (int)((((unsigned int)(val) >> 0u) & 0xe0u) | (((unsigned int)(val) >> 3u) & 0x1cu) | (((unsigned int)(val) >> 6u) & 0x03u)); \
00197         (b) = (int)((((unsigned int)(val) << 3u) & 0xe0u) | (((unsigned int)(val) >> 0u) & 0x1cu) | (((unsigned int)(val) >> 3u) & 0x03u)); \
00198         (c) = (int)((((unsigned int)(val) << 6u) & 0xc0u) | (((unsigned int)(val) << 4u) & 0x30u) | (((unsigned int)(val) << 2u) & 0x0cu) | (((unsigned int)(val) << 0u) & 0x03u)); \
00199 
00200 
00201 
00202 /*************************************
00203  *
00204  *  Misc. macros
00205  *
00206  *************************************/
00207 
00208 /* macro for clamping a value between minimum and maximum values */
00209 #define CLAMP(val,min,max)              do { if ((val) < (min)) { (val) = (min); } else if ((val) > (max)) { (val) = (max); } } while (0)
00210 
00211 /* macro to compute the base 2 log for LOD calculations */
00212 #define LOGB2(x)                                (log((double)(x)) / log(2.0))
00213 
00214 
00215 
00216 /*************************************
00217  *
00218  *  Macros for extracting bitfields
00219  *
00220  *************************************/
00221 
00222 #define INITEN_ENABLE_HW_INIT(val)                      (((val) >> 0) & 1)
00223 #define INITEN_ENABLE_PCI_FIFO(val)                     (((val) >> 1) & 1)
00224 #define INITEN_REMAP_INIT_TO_DAC(val)           (((val) >> 2) & 1)
00225 #define INITEN_ENABLE_SNOOP0(val)                       (((val) >> 4) & 1)
00226 #define INITEN_SNOOP0_MEMORY_MATCH(val)         (((val) >> 5) & 1)
00227 #define INITEN_SNOOP0_READWRITE_MATCH(val)      (((val) >> 6) & 1)
00228 #define INITEN_ENABLE_SNOOP1(val)                       (((val) >> 7) & 1)
00229 #define INITEN_SNOOP1_MEMORY_MATCH(val)         (((val) >> 8) & 1)
00230 #define INITEN_SNOOP1_READWRITE_MATCH(val)      (((val) >> 9) & 1)
00231 #define INITEN_SLI_BUS_OWNER(val)                       (((val) >> 10) & 1)
00232 #define INITEN_SLI_ODD_EVEN(val)                        (((val) >> 11) & 1)
00233 #define INITEN_SECONDARY_REV_ID(val)            (((val) >> 12) & 0xf)   /* voodoo 2 only */
00234 #define INITEN_MFCTR_FAB_ID(val)                        (((val) >> 16) & 0xf)   /* voodoo 2 only */
00235 #define INITEN_ENABLE_PCI_INTERRUPT(val)        (((val) >> 20) & 1)             /* voodoo 2 only */
00236 #define INITEN_PCI_INTERRUPT_TIMEOUT(val)       (((val) >> 21) & 1)             /* voodoo 2 only */
00237 #define INITEN_ENABLE_NAND_TREE_TEST(val)       (((val) >> 22) & 1)             /* voodoo 2 only */
00238 #define INITEN_ENABLE_SLI_ADDRESS_SNOOP(val) (((val) >> 23) & 1)        /* voodoo 2 only */
00239 #define INITEN_SLI_SNOOP_ADDRESS(val)           (((val) >> 24) & 0xff)  /* voodoo 2 only */
00240 
00241 #define FBZCP_CC_RGBSELECT(val)                         (((val) >> 0) & 3)
00242 #define FBZCP_CC_ASELECT(val)                           (((val) >> 2) & 3)
00243 #define FBZCP_CC_LOCALSELECT(val)                       (((val) >> 4) & 1)
00244 #define FBZCP_CCA_LOCALSELECT(val)                      (((val) >> 5) & 3)
00245 #define FBZCP_CC_LOCALSELECT_OVERRIDE(val)      (((val) >> 7) & 1)
00246 #define FBZCP_CC_ZERO_OTHER(val)                        (((val) >> 8) & 1)
00247 #define FBZCP_CC_SUB_CLOCAL(val)                        (((val) >> 9) & 1)
00248 #define FBZCP_CC_MSELECT(val)                           (((val) >> 10) & 7)
00249 #define FBZCP_CC_REVERSE_BLEND(val)                     (((val) >> 13) & 1)
00250 #define FBZCP_CC_ADD_ACLOCAL(val)                       (((val) >> 14) & 3)
00251 #define FBZCP_CC_INVERT_OUTPUT(val)                     (((val) >> 16) & 1)
00252 #define FBZCP_CCA_ZERO_OTHER(val)                       (((val) >> 17) & 1)
00253 #define FBZCP_CCA_SUB_CLOCAL(val)                       (((val) >> 18) & 1)
00254 #define FBZCP_CCA_MSELECT(val)                          (((val) >> 19) & 7)
00255 #define FBZCP_CCA_REVERSE_BLEND(val)            (((val) >> 22) & 1)
00256 #define FBZCP_CCA_ADD_ACLOCAL(val)                      (((val) >> 23) & 3)
00257 #define FBZCP_CCA_INVERT_OUTPUT(val)            (((val) >> 25) & 1)
00258 #define FBZCP_CCA_SUBPIXEL_ADJUST(val)          (((val) >> 26) & 1)
00259 #define FBZCP_TEXTURE_ENABLE(val)                       (((val) >> 27) & 1)
00260 #define FBZCP_RGBZW_CLAMP(val)                          (((val) >> 28) & 1)             /* voodoo 2 only */
00261 #define FBZCP_ANTI_ALIAS(val)                           (((val) >> 29) & 1)             /* voodoo 2 only */
00262 
00263 #define ALPHAMODE_ALPHATEST(val)                        (((val) >> 0) & 1)
00264 #define ALPHAMODE_ALPHAFUNCTION(val)            (((val) >> 1) & 7)
00265 #define ALPHAMODE_ALPHABLEND(val)                       (((val) >> 4) & 1)
00266 #define ALPHAMODE_ANTIALIAS(val)                        (((val) >> 5) & 1)
00267 #define ALPHAMODE_SRCRGBBLEND(val)                      (((val) >> 8) & 15)
00268 #define ALPHAMODE_DSTRGBBLEND(val)                      (((val) >> 12) & 15)
00269 #define ALPHAMODE_SRCALPHABLEND(val)            (((val) >> 16) & 15)
00270 #define ALPHAMODE_DSTALPHABLEND(val)            (((val) >> 20) & 15)
00271 #define ALPHAMODE_ALPHAREF(val)                         (((val) >> 24) & 0xff)
00272 
00273 #define FOGMODE_ENABLE_FOG(val)                         (((val) >> 0) & 1)
00274 #define FOGMODE_FOG_ADD(val)                            (((val) >> 1) & 1)
00275 #define FOGMODE_FOG_MULT(val)                           (((val) >> 2) & 1)
00276 #define FOGMODE_FOG_ZALPHA(val)                         (((val) >> 3) & 3)
00277 #define FOGMODE_FOG_CONSTANT(val)                       (((val) >> 5) & 1)
00278 #define FOGMODE_FOG_DITHER(val)                         (((val) >> 6) & 1)              /* voodoo 2 only */
00279 #define FOGMODE_FOG_ZONES(val)                          (((val) >> 7) & 1)              /* voodoo 2 only */
00280 
00281 #define FBZMODE_ENABLE_CLIPPING(val)            (((val) >> 0) & 1)
00282 #define FBZMODE_ENABLE_CHROMAKEY(val)           (((val) >> 1) & 1)
00283 #define FBZMODE_ENABLE_STIPPLE(val)                     (((val) >> 2) & 1)
00284 #define FBZMODE_WBUFFER_SELECT(val)                     (((val) >> 3) & 1)
00285 #define FBZMODE_ENABLE_DEPTHBUF(val)            (((val) >> 4) & 1)
00286 #define FBZMODE_DEPTH_FUNCTION(val)                     (((val) >> 5) & 7)
00287 #define FBZMODE_ENABLE_DITHERING(val)           (((val) >> 8) & 1)
00288 #define FBZMODE_RGB_BUFFER_MASK(val)            (((val) >> 9) & 1)
00289 #define FBZMODE_AUX_BUFFER_MASK(val)            (((val) >> 10) & 1)
00290 #define FBZMODE_DITHER_TYPE(val)                        (((val) >> 11) & 1)
00291 #define FBZMODE_STIPPLE_PATTERN(val)            (((val) >> 12) & 1)
00292 #define FBZMODE_ENABLE_ALPHA_MASK(val)          (((val) >> 13) & 1)
00293 #define FBZMODE_DRAW_BUFFER(val)                        (((val) >> 14) & 3)
00294 #define FBZMODE_ENABLE_DEPTH_BIAS(val)          (((val) >> 16) & 1)
00295 #define FBZMODE_Y_ORIGIN(val)                           (((val) >> 17) & 1)
00296 #define FBZMODE_ENABLE_ALPHA_PLANES(val)        (((val) >> 18) & 1)
00297 #define FBZMODE_ALPHA_DITHER_SUBTRACT(val)      (((val) >> 19) & 1)
00298 #define FBZMODE_DEPTH_SOURCE_COMPARE(val)       (((val) >> 20) & 1)
00299 #define FBZMODE_DEPTH_FLOAT_SELECT(val)         (((val) >> 21) & 1)             /* voodoo 2 only */
00300 
00301 #define LFBMODE_WRITE_FORMAT(val)                       (((val) >> 0) & 0xf)
00302 #define LFBMODE_WRITE_BUFFER_SELECT(val)        (((val) >> 4) & 3)
00303 #define LFBMODE_READ_BUFFER_SELECT(val)         (((val) >> 6) & 3)
00304 #define LFBMODE_ENABLE_PIXEL_PIPELINE(val)      (((val) >> 8) & 1)
00305 #define LFBMODE_RGBA_LANES(val)                         (((val) >> 9) & 3)
00306 #define LFBMODE_WORD_SWAP_WRITES(val)           (((val) >> 11) & 1)
00307 #define LFBMODE_BYTE_SWIZZLE_WRITES(val)        (((val) >> 12) & 1)
00308 #define LFBMODE_Y_ORIGIN(val)                           (((val) >> 13) & 1)
00309 #define LFBMODE_WRITE_W_SELECT(val)                     (((val) >> 14) & 1)
00310 #define LFBMODE_WORD_SWAP_READS(val)            (((val) >> 15) & 1)
00311 #define LFBMODE_BYTE_SWIZZLE_READS(val)         (((val) >> 16) & 1)
00312 
00313 #define CHROMARANGE_BLUE_EXCLUSIVE(val)         (((val) >> 24) & 1)
00314 #define CHROMARANGE_GREEN_EXCLUSIVE(val)        (((val) >> 25) & 1)
00315 #define CHROMARANGE_RED_EXCLUSIVE(val)          (((val) >> 26) & 1)
00316 #define CHROMARANGE_UNION_MODE(val)                     (((val) >> 27) & 1)
00317 #define CHROMARANGE_ENABLE(val)                         (((val) >> 28) & 1)
00318 
00319 #define FBIINIT0_VGA_PASSTHRU(val)                      (((val) >> 0) & 1)
00320 #define FBIINIT0_GRAPHICS_RESET(val)            (((val) >> 1) & 1)
00321 #define FBIINIT0_FIFO_RESET(val)                        (((val) >> 2) & 1)
00322 #define FBIINIT0_SWIZZLE_REG_WRITES(val)        (((val) >> 3) & 1)
00323 #define FBIINIT0_STALL_PCIE_FOR_HWM(val)        (((val) >> 4) & 1)
00324 #define FBIINIT0_PCI_FIFO_LWM(val)                      (((val) >> 6) & 0x1f)
00325 #define FBIINIT0_LFB_TO_MEMORY_FIFO(val)        (((val) >> 11) & 1)
00326 #define FBIINIT0_TEXMEM_TO_MEMORY_FIFO(val) (((val) >> 12) & 1)
00327 #define FBIINIT0_ENABLE_MEMORY_FIFO(val)        (((val) >> 13) & 1)
00328 #define FBIINIT0_MEMORY_FIFO_HWM(val)           (((val) >> 14) & 0x7ff)
00329 #define FBIINIT0_MEMORY_FIFO_BURST(val)         (((val) >> 25) & 0x3f)
00330 
00331 #define FBIINIT1_PCI_DEV_FUNCTION(val)          (((val) >> 0) & 1)
00332 #define FBIINIT1_PCI_WRITE_WAIT_STATES(val)     (((val) >> 1) & 1)
00333 #define FBIINIT1_MULTI_SST1(val)                        (((val) >> 2) & 1)              /* not on voodoo 2 */
00334 #define FBIINIT1_ENABLE_LFB(val)                        (((val) >> 3) & 1)
00335 #define FBIINIT1_X_VIDEO_TILES(val)                     (((val) >> 4) & 0xf)
00336 #define FBIINIT1_VIDEO_TIMING_RESET(val)        (((val) >> 8) & 1)
00337 #define FBIINIT1_SOFTWARE_OVERRIDE(val)         (((val) >> 9) & 1)
00338 #define FBIINIT1_SOFTWARE_HSYNC(val)            (((val) >> 10) & 1)
00339 #define FBIINIT1_SOFTWARE_VSYNC(val)            (((val) >> 11) & 1)
00340 #define FBIINIT1_SOFTWARE_BLANK(val)            (((val) >> 12) & 1)
00341 #define FBIINIT1_DRIVE_VIDEO_TIMING(val)        (((val) >> 13) & 1)
00342 #define FBIINIT1_DRIVE_VIDEO_BLANK(val)         (((val) >> 14) & 1)
00343 #define FBIINIT1_DRIVE_VIDEO_SYNC(val)          (((val) >> 15) & 1)
00344 #define FBIINIT1_DRIVE_VIDEO_DCLK(val)          (((val) >> 16) & 1)
00345 #define FBIINIT1_VIDEO_TIMING_VCLK(val)         (((val) >> 17) & 1)
00346 #define FBIINIT1_VIDEO_CLK_2X_DELAY(val)        (((val) >> 18) & 3)
00347 #define FBIINIT1_VIDEO_TIMING_SOURCE(val)       (((val) >> 20) & 3)
00348 #define FBIINIT1_ENABLE_24BPP_OUTPUT(val)       (((val) >> 22) & 1)
00349 #define FBIINIT1_ENABLE_SLI(val)                        (((val) >> 23) & 1)
00350 #define FBIINIT1_X_VIDEO_TILES_BIT5(val)        (((val) >> 24) & 1)             /* voodoo 2 only */
00351 #define FBIINIT1_ENABLE_EDGE_FILTER(val)        (((val) >> 25) & 1)
00352 #define FBIINIT1_INVERT_VID_CLK_2X(val)         (((val) >> 26) & 1)
00353 #define FBIINIT1_VID_CLK_2X_SEL_DELAY(val)      (((val) >> 27) & 3)
00354 #define FBIINIT1_VID_CLK_DELAY(val)                     (((val) >> 29) & 3)
00355 #define FBIINIT1_DISABLE_FAST_READAHEAD(val) (((val) >> 31) & 1)
00356 
00357 #define FBIINIT2_DISABLE_DITHER_SUB(val)        (((val) >> 0) & 1)
00358 #define FBIINIT2_DRAM_BANKING(val)                      (((val) >> 1) & 1)
00359 #define FBIINIT2_ENABLE_TRIPLE_BUF(val)         (((val) >> 4) & 1)
00360 #define FBIINIT2_ENABLE_FAST_RAS_READ(val)      (((val) >> 5) & 1)
00361 #define FBIINIT2_ENABLE_GEN_DRAM_OE(val)        (((val) >> 6) & 1)
00362 #define FBIINIT2_ENABLE_FAST_READWRITE(val)     (((val) >> 7) & 1)
00363 #define FBIINIT2_ENABLE_PASSTHRU_DITHER(val) (((val) >> 8) & 1)
00364 #define FBIINIT2_SWAP_BUFFER_ALGORITHM(val)     (((val) >> 9) & 3)
00365 #define FBIINIT2_VIDEO_BUFFER_OFFSET(val)       (((val) >> 11) & 0x1ff)
00366 #define FBIINIT2_ENABLE_DRAM_BANKING(val)       (((val) >> 20) & 1)
00367 #define FBIINIT2_ENABLE_DRAM_READ_FIFO(val)     (((val) >> 21) & 1)
00368 #define FBIINIT2_ENABLE_DRAM_REFRESH(val)       (((val) >> 22) & 1)
00369 #define FBIINIT2_REFRESH_LOAD_VALUE(val)        (((val) >> 23) & 0x1ff)
00370 
00371 #define FBIINIT3_TRI_REGISTER_REMAP(val)        (((val) >> 0) & 1)
00372 #define FBIINIT3_VIDEO_FIFO_THRESH(val)         (((val) >> 1) & 0x1f)
00373 #define FBIINIT3_DISABLE_TMUS(val)                      (((val) >> 6) & 1)
00374 #define FBIINIT3_FBI_MEMORY_TYPE(val)           (((val) >> 8) & 7)
00375 #define FBIINIT3_VGA_PASS_RESET_VAL(val)        (((val) >> 11) & 1)
00376 #define FBIINIT3_HARDCODE_PCI_BASE(val)         (((val) >> 12) & 1)
00377 #define FBIINIT3_FBI2TREX_DELAY(val)            (((val) >> 13) & 0xf)
00378 #define FBIINIT3_TREX2FBI_DELAY(val)            (((val) >> 17) & 0x1f)
00379 #define FBIINIT3_YORIGIN_SUBTRACT(val)          (((val) >> 22) & 0x3ff)
00380 
00381 #define FBIINIT4_PCI_READ_WAITS(val)            (((val) >> 0) & 1)
00382 #define FBIINIT4_ENABLE_LFB_READAHEAD(val)      (((val) >> 1) & 1)
00383 #define FBIINIT4_MEMORY_FIFO_LWM(val)           (((val) >> 2) & 0x3f)
00384 #define FBIINIT4_MEMORY_FIFO_START_ROW(val)     (((val) >> 8) & 0x3ff)
00385 #define FBIINIT4_MEMORY_FIFO_STOP_ROW(val)      (((val) >> 18) & 0x3ff)
00386 #define FBIINIT4_VIDEO_CLOCKING_DELAY(val)      (((val) >> 29) & 7)             /* voodoo 2 only */
00387 
00388 #define FBIINIT5_DISABLE_PCI_STOP(val)          (((val) >> 0) & 1)              /* voodoo 2 only */
00389 #define FBIINIT5_PCI_SLAVE_SPEED(val)           (((val) >> 1) & 1)              /* voodoo 2 only */
00390 #define FBIINIT5_DAC_DATA_OUTPUT_WIDTH(val)     (((val) >> 2) & 1)              /* voodoo 2 only */
00391 #define FBIINIT5_DAC_DATA_17_OUTPUT(val)        (((val) >> 3) & 1)              /* voodoo 2 only */
00392 #define FBIINIT5_DAC_DATA_18_OUTPUT(val)        (((val) >> 4) & 1)              /* voodoo 2 only */
00393 #define FBIINIT5_GENERIC_STRAPPING(val)         (((val) >> 5) & 0xf)    /* voodoo 2 only */
00394 #define FBIINIT5_BUFFER_ALLOCATION(val)         (((val) >> 9) & 3)              /* voodoo 2 only */
00395 #define FBIINIT5_DRIVE_VID_CLK_SLAVE(val)       (((val) >> 11) & 1)             /* voodoo 2 only */
00396 #define FBIINIT5_DRIVE_DAC_DATA_16(val)         (((val) >> 12) & 1)             /* voodoo 2 only */
00397 #define FBIINIT5_VCLK_INPUT_SELECT(val)         (((val) >> 13) & 1)             /* voodoo 2 only */
00398 #define FBIINIT5_MULTI_CVG_DETECT(val)          (((val) >> 14) & 1)             /* voodoo 2 only */
00399 #define FBIINIT5_SYNC_RETRACE_READS(val)        (((val) >> 15) & 1)             /* voodoo 2 only */
00400 #define FBIINIT5_ENABLE_RHBORDER_COLOR(val)     (((val) >> 16) & 1)             /* voodoo 2 only */
00401 #define FBIINIT5_ENABLE_LHBORDER_COLOR(val)     (((val) >> 17) & 1)             /* voodoo 2 only */
00402 #define FBIINIT5_ENABLE_BVBORDER_COLOR(val)     (((val) >> 18) & 1)             /* voodoo 2 only */
00403 #define FBIINIT5_ENABLE_TVBORDER_COLOR(val)     (((val) >> 19) & 1)             /* voodoo 2 only */
00404 #define FBIINIT5_DOUBLE_HORIZ(val)                      (((val) >> 20) & 1)             /* voodoo 2 only */
00405 #define FBIINIT5_DOUBLE_VERT(val)                       (((val) >> 21) & 1)             /* voodoo 2 only */
00406 #define FBIINIT5_ENABLE_16BIT_GAMMA(val)        (((val) >> 22) & 1)             /* voodoo 2 only */
00407 #define FBIINIT5_INVERT_DAC_HSYNC(val)          (((val) >> 23) & 1)             /* voodoo 2 only */
00408 #define FBIINIT5_INVERT_DAC_VSYNC(val)          (((val) >> 24) & 1)             /* voodoo 2 only */
00409 #define FBIINIT5_ENABLE_24BIT_DACDATA(val)      (((val) >> 25) & 1)             /* voodoo 2 only */
00410 #define FBIINIT5_ENABLE_INTERLACING(val)        (((val) >> 26) & 1)             /* voodoo 2 only */
00411 #define FBIINIT5_DAC_DATA_18_CONTROL(val)       (((val) >> 27) & 1)             /* voodoo 2 only */
00412 #define FBIINIT5_RASTERIZER_UNIT_MODE(val)      (((val) >> 30) & 3)             /* voodoo 2 only */
00413 
00414 #define FBIINIT6_WINDOW_ACTIVE_COUNTER(val)     (((val) >> 0) & 7)              /* voodoo 2 only */
00415 #define FBIINIT6_WINDOW_DRAG_COUNTER(val)       (((val) >> 3) & 0x1f)   /* voodoo 2 only */
00416 #define FBIINIT6_SLI_SYNC_MASTER(val)           (((val) >> 8) & 1)              /* voodoo 2 only */
00417 #define FBIINIT6_DAC_DATA_22_OUTPUT(val)        (((val) >> 9) & 3)              /* voodoo 2 only */
00418 #define FBIINIT6_DAC_DATA_23_OUTPUT(val)        (((val) >> 11) & 3)             /* voodoo 2 only */
00419 #define FBIINIT6_SLI_SYNCIN_OUTPUT(val)         (((val) >> 13) & 3)             /* voodoo 2 only */
00420 #define FBIINIT6_SLI_SYNCOUT_OUTPUT(val)        (((val) >> 15) & 3)             /* voodoo 2 only */
00421 #define FBIINIT6_DAC_RD_OUTPUT(val)                     (((val) >> 17) & 3)             /* voodoo 2 only */
00422 #define FBIINIT6_DAC_WR_OUTPUT(val)                     (((val) >> 19) & 3)             /* voodoo 2 only */
00423 #define FBIINIT6_PCI_FIFO_LWM_RDY(val)          (((val) >> 21) & 0x7f)  /* voodoo 2 only */
00424 #define FBIINIT6_VGA_PASS_N_OUTPUT(val)         (((val) >> 28) & 3)             /* voodoo 2 only */
00425 #define FBIINIT6_X_VIDEO_TILES_BIT0(val)        (((val) >> 30) & 1)             /* voodoo 2 only */
00426 
00427 #define FBIINIT7_GENERIC_STRAPPING(val)         (((val) >> 0) & 0xff)   /* voodoo 2 only */
00428 #define FBIINIT7_CMDFIFO_ENABLE(val)            (((val) >> 8) & 1)              /* voodoo 2 only */
00429 #define FBIINIT7_CMDFIFO_MEMORY_STORE(val)      (((val) >> 9) & 1)              /* voodoo 2 only */
00430 #define FBIINIT7_DISABLE_CMDFIFO_HOLES(val)     (((val) >> 10) & 1)             /* voodoo 2 only */
00431 #define FBIINIT7_CMDFIFO_READ_THRESH(val)       (((val) >> 11) & 0x1f)  /* voodoo 2 only */
00432 #define FBIINIT7_SYNC_CMDFIFO_WRITES(val)       (((val) >> 16) & 1)             /* voodoo 2 only */
00433 #define FBIINIT7_SYNC_CMDFIFO_READS(val)        (((val) >> 17) & 1)             /* voodoo 2 only */
00434 #define FBIINIT7_RESET_PCI_PACKER(val)          (((val) >> 18) & 1)             /* voodoo 2 only */
00435 #define FBIINIT7_ENABLE_CHROMA_STUFF(val)       (((val) >> 19) & 1)             /* voodoo 2 only */
00436 #define FBIINIT7_CMDFIFO_PCI_TIMEOUT(val)       (((val) >> 20) & 0x7f)  /* voodoo 2 only */
00437 #define FBIINIT7_ENABLE_TEXTURE_BURST(val)      (((val) >> 27) & 1)             /* voodoo 2 only */
00438 
00439 #define TEXMODE_ENABLE_PERSPECTIVE(val)         (((val) >> 0) & 1)
00440 #define TEXMODE_MINIFICATION_FILTER(val)        (((val) >> 1) & 1)
00441 #define TEXMODE_MAGNIFICATION_FILTER(val)       (((val) >> 2) & 1)
00442 #define TEXMODE_CLAMP_NEG_W(val)                        (((val) >> 3) & 1)
00443 #define TEXMODE_ENABLE_LOD_DITHER(val)          (((val) >> 4) & 1)
00444 #define TEXMODE_NCC_TABLE_SELECT(val)           (((val) >> 5) & 1)
00445 #define TEXMODE_CLAMP_S(val)                            (((val) >> 6) & 1)
00446 #define TEXMODE_CLAMP_T(val)                            (((val) >> 7) & 1)
00447 #define TEXMODE_FORMAT(val)                                     (((val) >> 8) & 0xf)
00448 #define TEXMODE_TC_ZERO_OTHER(val)                      (((val) >> 12) & 1)
00449 #define TEXMODE_TC_SUB_CLOCAL(val)                      (((val) >> 13) & 1)
00450 #define TEXMODE_TC_MSELECT(val)                         (((val) >> 14) & 7)
00451 #define TEXMODE_TC_REVERSE_BLEND(val)           (((val) >> 17) & 1)
00452 #define TEXMODE_TC_ADD_ACLOCAL(val)                     (((val) >> 18) & 3)
00453 #define TEXMODE_TC_INVERT_OUTPUT(val)           (((val) >> 20) & 1)
00454 #define TEXMODE_TCA_ZERO_OTHER(val)                     (((val) >> 21) & 1)
00455 #define TEXMODE_TCA_SUB_CLOCAL(val)                     (((val) >> 22) & 1)
00456 #define TEXMODE_TCA_MSELECT(val)                        (((val) >> 23) & 7)
00457 #define TEXMODE_TCA_REVERSE_BLEND(val)          (((val) >> 26) & 1)
00458 #define TEXMODE_TCA_ADD_ACLOCAL(val)            (((val) >> 27) & 3)
00459 #define TEXMODE_TCA_INVERT_OUTPUT(val)          (((val) >> 29) & 1)
00460 #define TEXMODE_TRILINEAR(val)                          (((val) >> 30) & 1)
00461 #define TEXMODE_SEQ_8_DOWNLD(val)                       (((val) >> 31) & 1)
00462 
00463 #define TEXLOD_LODMIN(val)                                      (((val) >> 0) & 0x3f)
00464 #define TEXLOD_LODMAX(val)                                      (((val) >> 6) & 0x3f)
00465 #define TEXLOD_LODBIAS(val)                                     (((val) >> 12) & 0x3f)
00466 #define TEXLOD_LOD_ODD(val)                                     (((val) >> 18) & 1)
00467 #define TEXLOD_LOD_TSPLIT(val)                          (((val) >> 19) & 1)
00468 #define TEXLOD_LOD_S_IS_WIDER(val)                      (((val) >> 20) & 1)
00469 #define TEXLOD_LOD_ASPECT(val)                          (((val) >> 21) & 3)
00470 #define TEXLOD_LOD_ZEROFRAC(val)                        (((val) >> 23) & 1)
00471 #define TEXLOD_TMULTIBASEADDR(val)                      (((val) >> 24) & 1)
00472 #define TEXLOD_TDATA_SWIZZLE(val)                       (((val) >> 25) & 1)
00473 #define TEXLOD_TDATA_SWAP(val)                          (((val) >> 26) & 1)
00474 #define TEXLOD_TDIRECT_WRITE(val)                       (((val) >> 27) & 1)             /* Voodoo 2 only */
00475 
00476 #define TEXDETAIL_DETAIL_MAX(val)                       (((val) >> 0) & 0xff)
00477 #define TEXDETAIL_DETAIL_BIAS(val)                      (((val) >> 8) & 0x3f)
00478 #define TEXDETAIL_DETAIL_SCALE(val)                     (((val) >> 14) & 7)
00479 #define TEXDETAIL_RGB_MIN_FILTER(val)           (((val) >> 17) & 1)             /* Voodoo 2 only */
00480 #define TEXDETAIL_RGB_MAG_FILTER(val)           (((val) >> 18) & 1)             /* Voodoo 2 only */
00481 #define TEXDETAIL_ALPHA_MIN_FILTER(val)         (((val) >> 19) & 1)             /* Voodoo 2 only */
00482 #define TEXDETAIL_ALPHA_MAG_FILTER(val)         (((val) >> 20) & 1)             /* Voodoo 2 only */
00483 #define TEXDETAIL_SEPARATE_RGBA_FILTER(val)     (((val) >> 21) & 1)             /* Voodoo 2 only */
00484 
00485 #define TREXINIT_SEND_TMU_CONFIG(val)           (((val) >> 18) & 1)
00486 
00487 
00488 /*************************************
00489  *
00490  *  Core types
00491  *
00492  *************************************/
00493 
00494 typedef struct _voodoo_state voodoo_state;
00495 typedef struct _poly_extra_data poly_extra_data;
00496 
00497 typedef UINT32 rgb_t;
00498 
00499 typedef struct _rgba rgba;
00500 #define LSB_FIRST
00501 struct _rgba
00502 {
00503 #ifdef LSB_FIRST
00504         UINT8                           b, g, r, a;
00505 #else
00506         UINT8                           a, r, g, b;
00507 #endif
00508 };
00509 
00510 
00511 typedef union _voodoo_reg voodoo_reg;
00512 union _voodoo_reg
00513 {
00514         INT32                           i;
00515         UINT32                          u;
00516         float                           f;
00517         rgba                            rgb;
00518 };
00519 
00520 
00521 typedef voodoo_reg rgb_union;
00522 
00523 
00524 /* note that this structure is an even 64 bytes long */
00525 typedef struct _stats_block stats_block;
00526 struct _stats_block
00527 {
00528         INT32                           pixels_in;                              /* pixels in statistic */
00529         INT32                           pixels_out;                             /* pixels out statistic */
00530         INT32                           chroma_fail;                    /* chroma test fail statistic */
00531         INT32                           zfunc_fail;                             /* z function test fail statistic */
00532         INT32                           afunc_fail;                             /* alpha function test fail statistic */
00533         INT32                           clip_fail;                              /* clipping fail statistic */
00534         INT32                           stipple_count;                  /* stipple statistic */
00535         INT32                           filler[64/4 - 7];               /* pad this structure to 64 bytes */
00536 };
00537 
00538 
00539 typedef struct _fifo_state fifo_state;
00540 struct _fifo_state
00541 {
00542         INT32                           size;                                   /* size of the FIFO */
00543 };
00544 
00545 
00546 typedef struct _pci_state pci_state;
00547 struct _pci_state
00548 {
00549         fifo_state                      fifo;                                   /* PCI FIFO */
00550         UINT32                          init_enable;                    /* initEnable value */
00551         bool                            op_pending;                             /* true if an operation is pending */
00552 };
00553 
00554 
00555 typedef struct _ncc_table ncc_table;
00556 struct _ncc_table
00557 {
00558         bool                            dirty;                                  /* is the texel lookup dirty? */
00559         voodoo_reg *            reg;                                    /* pointer to our registers */
00560         INT32                           ir[4], ig[4], ib[4];    /* I values for R,G,B */
00561         INT32                           qr[4], qg[4], qb[4];    /* Q values for R,G,B */
00562         INT32                           y[16];                                  /* Y values */
00563         rgb_t *                         palette;                                /* pointer to associated RGB palette */
00564         rgb_t *                         palettea;                               /* pointer to associated ARGB palette */
00565         rgb_t                           texel[256];                             /* texel lookup */
00566 };
00567 
00568 
00569 typedef struct _tmu_state tmu_state;
00570 struct _tmu_state
00571 {
00572         UINT8 *                         ram;                                    /* pointer to our RAM */
00573         UINT32                          mask;                                   /* mask to apply to pointers */
00574         voodoo_reg *            reg;                                    /* pointer to our register base */
00575         bool                            regdirty;                               /* true if the LOD/mode/base registers have changed */
00576 
00577         UINT32                          texaddr_mask;                   /* mask for texture address */
00578         UINT8                           texaddr_shift;                  /* shift for texture address */
00579 
00580         INT64                           starts, startt;                 /* starting S,T (14.18) */
00581         INT64                           startw;                                 /* starting W (2.30) */
00582         INT64                           dsdx, dtdx;                             /* delta S,T per X */
00583         INT64                           dwdx;                                   /* delta W per X */
00584         INT64                           dsdy, dtdy;                             /* delta S,T per Y */
00585         INT64                           dwdy;                                   /* delta W per Y */
00586 
00587         INT32                           lodmin, lodmax;                 /* min, max LOD values */
00588         INT32                           lodbias;                                /* LOD bias */
00589         UINT32                          lodmask;                                /* mask of available LODs */
00590         UINT32                          lodoffset[9];                   /* offset of texture base for each LOD */
00591         INT32                           detailmax;                              /* detail clamp */
00592         INT32                           detailbias;                             /* detail bias */
00593         UINT8                           detailscale;                    /* detail scale */
00594 
00595         UINT32                          wmask;                                  /* mask for the current texture width */
00596         UINT32                          hmask;                                  /* mask for the current texture height */
00597 
00598         UINT8                           bilinear_mask;                  /* mask for bilinear resolution (0xf0 for V1, 0xff for V2) */
00599 
00600         ncc_table                       ncc[2];                                 /* two NCC tables */
00601 
00602         rgb_t *                         lookup;                                 /* currently selected lookup */
00603         rgb_t *                         texel[16];                              /* texel lookups for each format */
00604 
00605         rgb_t                           palette[256];                   /* palette lookup table */
00606         rgb_t                           palettea[256];                  /* palette+alpha lookup table */
00607 };
00608 
00609 
00610 typedef struct _tmu_shared_state tmu_shared_state;
00611 struct _tmu_shared_state
00612 {
00613         rgb_t                           rgb332[256];                    /* RGB 3-3-2 lookup table */
00614         rgb_t                           alpha8[256];                    /* alpha 8-bit lookup table */
00615         rgb_t                           int8[256];                              /* intensity 8-bit lookup table */
00616         rgb_t                           ai44[256];                              /* alpha, intensity 4-4 lookup table */
00617 
00618         rgb_t                           rgb565[65536];                  /* RGB 5-6-5 lookup table */
00619         rgb_t                           argb1555[65536];                /* ARGB 1-5-5-5 lookup table */
00620         rgb_t                           argb4444[65536];                /* ARGB 4-4-4-4 lookup table */
00621 };
00622 
00623 
00624 typedef struct _setup_vertex setup_vertex;
00625 struct _setup_vertex
00626 {
00627         float                           x, y;                                   /* X, Y coordinates */
00628         float                           a, r, g, b;                             /* A, R, G, B values */
00629         float                           z, wb;                                  /* Z and broadcast W values */
00630         float                           w0, s0, t0;                             /* W, S, T for TMU 0 */
00631         float                           w1, s1, t1;                             /* W, S, T for TMU 1 */
00632 };
00633 
00634 
00635 typedef struct _fbi_state fbi_state;
00636 struct _fbi_state
00637 {
00638         UINT8 *                         ram;                                    /* pointer to frame buffer RAM */
00639         UINT32                          mask;                                   /* mask to apply to pointers */
00640         UINT32                          rgboffs[3];                             /* word offset to 3 RGB buffers */
00641         UINT32                          auxoffs;                                /* word offset to 1 aux buffer */
00642 
00643         UINT8                           frontbuf;                               /* front buffer index */
00644         UINT8                           backbuf;                                /* back buffer index */
00645 
00646         UINT32                          yorigin;                                /* Y origin subtract value */
00647 
00648         UINT32                          width;                                  /* width of current frame buffer */
00649         UINT32                          height;                                 /* height of current frame buffer */
00650 //      UINT32                          xoffs;                                  /* horizontal offset (back porch) */
00651 //      UINT32                          yoffs;                                  /* vertical offset (back porch) */
00652 //      UINT32                          vsyncscan;                              /* vertical sync scanline */
00653         UINT32                          rowpixels;                              /* pixels per row */
00654         UINT32                          tile_width;                             /* width of video tiles */
00655         UINT32                          tile_height;                    /* height of video tiles */
00656         UINT32                          x_tiles;                                /* number of tiles in the X direction */
00657 
00658         UINT8                           vblank;                                 /* VBLANK state */
00659         bool                            vblank_dont_swap;               /* don't actually swap when we hit this point */
00660         bool                            vblank_flush_pending;
00661 
00662         /* triangle setup info */
00663         INT16                           ax, ay;                                 /* vertex A x,y (12.4) */
00664         INT16                           bx, by;                                 /* vertex B x,y (12.4) */
00665         INT16                           cx, cy;                                 /* vertex C x,y (12.4) */
00666         INT32                           startr, startg, startb, starta; /* starting R,G,B,A (12.12) */
00667         INT32                           startz;                                 /* starting Z (20.12) */
00668         INT64                           startw;                                 /* starting W (16.32) */
00669         INT32                           drdx, dgdx, dbdx, dadx; /* delta R,G,B,A per X */
00670         INT32                           dzdx;                                   /* delta Z per X */
00671         INT64                           dwdx;                                   /* delta W per X */
00672         INT32                           drdy, dgdy, dbdy, dady; /* delta R,G,B,A per Y */
00673         INT32                           dzdy;                                   /* delta Z per Y */
00674         INT64                           dwdy;                                   /* delta W per Y */
00675 
00676         stats_block                     lfb_stats;                              /* LFB-access statistics */
00677 
00678         UINT8                           sverts;                                 /* number of vertices ready */
00679         setup_vertex            svert[3];                               /* 3 setup vertices */
00680 
00681         fifo_state                      fifo;                                   /* framebuffer memory fifo */
00682 
00683         UINT8                           fogblend[64];                   /* 64-entry fog table */
00684         UINT8                           fogdelta[64];                   /* 64-entry fog table */
00685         UINT8                           fogdelta_mask;                  /* mask for for delta (0xff for V1, 0xfc for V2) */
00686 
00687 //      rgb_t                           clut[512];                              /* clut gamma data */
00688 };
00689 
00690 
00691 typedef struct _dac_state dac_state;
00692 struct _dac_state
00693 {
00694         UINT8                           reg[8];                                 /* 8 registers */
00695         UINT8                           read_result;                    /* pending read result */
00696 };
00697 
00698 
00699 typedef struct _raster_info raster_info;
00700 struct _raster_info
00701 {
00702         struct _raster_info *next;                                      /* pointer to next entry with the same hash */
00703         poly_draw_scanline_func callback;                       /* callback pointer */
00704         bool                            is_generic;                             /* true if this is one of the generic rasterizers */
00705         UINT8                           display;                                /* display index */
00706         UINT32                          hits;                                   /* how many hits (pixels) we've used this for */
00707         UINT32                          polys;                                  /* how many polys we've used this for */
00708         UINT32                          eff_color_path;                 /* effective fbzColorPath value */
00709         UINT32                          eff_alpha_mode;                 /* effective alphaMode value */
00710         UINT32                          eff_fog_mode;                   /* effective fogMode value */
00711         UINT32                          eff_fbz_mode;                   /* effective fbzMode value */
00712         UINT32                          eff_tex_mode_0;                 /* effective textureMode value for TMU #0 */
00713         UINT32                          eff_tex_mode_1;                 /* effective textureMode value for TMU #1 */
00714 
00715         bool                            shader_ready;
00716         UINT32                          so_shader_program;
00717         UINT32                          so_vertex_shader;
00718         UINT32                          so_fragment_shader;
00719         INT32*                          shader_ulocations;
00720 };
00721 
00722 
00723 struct _poly_extra_data
00724 {
00725         voodoo_state *          state;                                  /* pointer back to the voodoo state */
00726         raster_info *           info;                                   /* pointer to rasterizer information */
00727 
00728         INT16                           ax, ay;                                 /* vertex A x,y (12.4) */
00729         INT32                           startr, startg, startb, starta; /* starting R,G,B,A (12.12) */
00730         INT32                           startz;                                 /* starting Z (20.12) */
00731         INT64                           startw;                                 /* starting W (16.32) */
00732         INT32                           drdx, dgdx, dbdx, dadx; /* delta R,G,B,A per X */
00733         INT32                           dzdx;                                   /* delta Z per X */
00734         INT64                           dwdx;                                   /* delta W per X */
00735         INT32                           drdy, dgdy, dbdy, dady; /* delta R,G,B,A per Y */
00736         INT32                           dzdy;                                   /* delta Z per Y */
00737         INT64                           dwdy;                                   /* delta W per Y */
00738 
00739         INT64                           starts0, startt0;               /* starting S,T (14.18) */
00740         INT64                           startw0;                                /* starting W (2.30) */
00741         INT64                           ds0dx, dt0dx;                   /* delta S,T per X */
00742         INT64                           dw0dx;                                  /* delta W per X */
00743         INT64                           ds0dy, dt0dy;                   /* delta S,T per Y */
00744         INT64                           dw0dy;                                  /* delta W per Y */
00745         INT32                           lodbase0;                               /* used during rasterization */
00746 
00747         INT64                           starts1, startt1;               /* starting S,T (14.18) */
00748         INT64                           startw1;                                /* starting W (2.30) */
00749         INT64                           ds1dx, dt1dx;                   /* delta S,T per X */
00750         INT64                           dw1dx;                                  /* delta W per X */
00751         INT64                           ds1dy, dt1dy;                   /* delta S,T per Y */
00752         INT64                           dw1dy;                                  /* delta W per Y */
00753         INT32                           lodbase1;                               /* used during rasterization */
00754 
00755         UINT16                          dither[16];                             /* dither matrix, for fastfill */
00756 
00757         Bitu                            texcount;
00758         Bitu                            r_fbzColorPath;
00759         Bitu                            r_fbzMode;
00760         Bitu                            r_alphaMode;
00761         Bitu                            r_fogMode;
00762         INT32                           r_textureMode0;
00763         INT32                           r_textureMode1;
00764 };
00765 
00766 
00767 /* typedef struct _voodoo_state voodoo_state; -- declared above */
00768 struct _voodoo_state
00769 {
00770         UINT8                           type;                                   /* type of system */
00771         UINT8                           chipmask;                               /* mask for which chips are available */
00772 
00773         voodoo_reg                      reg[0x400];                             /* raw registers */
00774         const UINT8 *           regaccess;                              /* register access array */
00775         const char *const *     regnames;                               /* register names array */
00776         bool                            alt_regmap;                             /* enable alternate register map? */
00777 
00778         pci_state                       pci;                                    /* PCI state */
00779         dac_state                       dac;                                    /* DAC state */
00780 
00781         fbi_state                       fbi;                                    /* FBI states */
00782         tmu_state                       tmu[MAX_TMU];                   /* TMU states */
00783         tmu_shared_state        tmushare;                               /* TMU shared state */
00784 
00785         stats_block     *               thread_stats;                   /* per-thread statistics */
00786 
00787         int                                     next_rasterizer;                /* next rasterizer index */
00788         raster_info                     rasterizer[MAX_RASTERIZERS];    /* array of rasterizers */
00789         raster_info *           raster_hash[RASTER_HASH_SIZE];  /* hash table of rasterizers */
00790 
00791         bool                            send_config;
00792         UINT32                          tmu_config;
00793 
00794         bool                            ogl;
00795         bool                            ogl_dimchange;
00796         bool                            clock_enabled;
00797         bool                            output_on;
00798         bool                            active;
00799 };
00800 
00801 
00802 
00803 /*************************************
00804  *
00805  *  Inline FIFO management
00806  *
00807  *************************************/
00808 
00809 INLINE INT32 fifo_space(fifo_state *f)
00810 {
00811         INT32 items = 0;
00812         if (items < 0)
00813                 items += f->size;
00814         return f->size - 1 - items;
00815 }
00816 
00817 
00818 INLINE UINT8 count_leading_zeros(UINT32 value)
00819 {
00820         INT32 result;
00821 
00822 #if defined(_MSC_VER) && defined(_M_IX86)
00823     __asm
00824     {
00825         bsr   eax,value
00826         jnz   skip
00827         mov   eax,63
00828     skip:
00829         xor   eax,31
00830         mov   result,eax
00831     }
00832 #else
00833         result = 32;
00834         while(value > 0) {
00835                 result--;
00836                 value >>= 1;
00837         }
00838 #endif
00839 
00840         return (UINT8)result;
00841 }
00842 
00843 /*************************************
00844  *
00845  *  Computes a fast 16.16 reciprocal
00846  *  of a 16.32 value; used for
00847  *  computing 1/w in the rasterizer.
00848  *
00849  *  Since it is trivial to also
00850  *  compute log2(1/w) = -log2(w) at
00851  *  the same time, we do that as well
00852  *  to 16.8 precision for LOD
00853  *  calculations.
00854  *
00855  *  On a Pentium M, this routine is
00856  *  20% faster than a 64-bit integer
00857  *  divide and also produces the log
00858  *  for free.
00859  *
00860  *************************************/
00861 
00862 INLINE INT64 fast_reciplog(INT64 value, INT32 *log2)
00863 {
00864         extern UINT32 voodoo_reciplog[];
00865         UINT32 temp, rlog;
00866         UINT32 interp;
00867         UINT32 *table;
00868         UINT64 recip;
00869         bool neg = false;
00870         int lz, exp = 0;
00871 
00872         /* always work with unsigned numbers */
00873         if (value < 0)
00874         {
00875                 value = -value;
00876                 neg = true;
00877         }
00878 
00879         /* if we've spilled out of 32 bits, push it down under 32 */
00880         if (value & LONGTYPE(0xffff00000000))
00881         {
00882                 temp = (UINT32)(value >> 16);
00883                 exp -= 16;
00884         }
00885         else
00886                 temp = (UINT32)value;
00887 
00888         /* if the resulting value is 0, the reciprocal is infinite */
00889         if (GCC_UNLIKELY(temp == 0))
00890         {
00891                 *log2 = 1000 << LOG_OUTPUT_PREC;
00892                 return neg ? 0x80000000 : 0x7fffffff;
00893         }
00894 
00895         /* determine how many leading zeros in the value and shift it up high */
00896         lz = count_leading_zeros(temp);
00897         temp <<= lz;
00898         exp += lz;
00899 
00900         /* compute a pointer to the table entries we want */
00901         /* math is a bit funny here because we shift one less than we need to in order */
00902         /* to account for the fact that there are two UINT32's per table entry */
00903         table = &voodoo_reciplog[(temp >> (31 - RECIPLOG_LOOKUP_BITS - 1)) & ((2 << RECIPLOG_LOOKUP_BITS) - 2)];
00904 
00905         /* compute the interpolation value */
00906         interp = (temp >> (31 - RECIPLOG_LOOKUP_BITS - 8)) & 0xff;
00907 
00908         /* do a linear interpolatation between the two nearest table values */
00909         /* for both the log and the reciprocal */
00910         rlog = (table[1] * (0x100 - interp) + table[3] * interp) >> 8;
00911         recip = (table[0] * (0x100 - interp) + table[2] * interp) >> 8;
00912 
00913         /* the log result is the fractional part of the log; round it to the output precision */
00914         rlog = (rlog + (1 << (RECIPLOG_LOOKUP_PREC - LOG_OUTPUT_PREC - 1))) >> (RECIPLOG_LOOKUP_PREC - LOG_OUTPUT_PREC);
00915 
00916         /* the exponent is the non-fractional part of the log; normally, we would subtract it from rlog */
00917         /* but since we want the log(1/value) = -log(value), we subtract rlog from the exponent */
00918         *log2 = (INT32)((((int)exp - ((int)31 - (int)RECIPLOG_INPUT_PREC)) << (int)LOG_OUTPUT_PREC) - (int)rlog);
00919 
00920         /* adjust the exponent to account for all the reciprocal-related parameters to arrive at a final shift amount */
00921         exp += (RECIP_OUTPUT_PREC - RECIPLOG_LOOKUP_PREC) - (31 - RECIPLOG_INPUT_PREC);
00922 
00923         /* shift by the exponent */
00924         if (exp < 0)
00925                 recip >>= -exp;
00926         else
00927                 recip <<= exp;
00928 
00929         /* on the way out, apply the original sign to the reciprocal */
00930         return neg ? -(INT64)recip : (INT64)recip;
00931 }
00932 
00933 
00934 
00935 /*************************************
00936  *
00937  *  Float-to-int conversions
00938  *
00939  *************************************/
00940 
00941 INLINE INT32 float_to_int32(UINT32 data, int fixedbits)
00942 {
00943         int exponent = ((int)((data >> 23u) & 0xffu) - 127 - 23 + fixedbits);
00944         INT32 result = (INT32)(data & 0x7fffff) | 0x800000;
00945         if (exponent < 0)
00946         {
00947                 if (exponent > -32)
00948                         result >>= -exponent;
00949                 else
00950                         result = 0;
00951         }
00952         else
00953         {
00954                 if (exponent < 32)
00955                         result <<= exponent;
00956                 else
00957                         result = 0x7fffffff;
00958         }
00959         if (data & 0x80000000)
00960                 result = -result;
00961         return result;
00962 }
00963 
00964 
00965 INLINE INT64 float_to_int64(UINT32 data, int fixedbits)
00966 {
00967         int exponent = (int)((data >> 23) & 0xff) - 127 - 23 + fixedbits;
00968         INT64 result = (INT64)(data & 0x7fffff) | 0x800000;
00969         if (exponent < 0)
00970         {
00971                 if (exponent > -64)
00972                         result >>= -exponent;
00973                 else
00974                         result = 0;
00975         }
00976         else
00977         {
00978                 if (exponent < 64)
00979                         result <<= exponent;
00980                 else
00981                         result = LONGTYPE(0x7fffffffffffffff);
00982         }
00983         if (data & 0x80000000)
00984                 result = -result;
00985         return result;
00986 }
00987 
00988 
00989 
00990 /*************************************
00991  *
00992  *  Rasterizer inlines
00993  *
00994  *************************************/
00995 
00996 INLINE UINT32 normalize_color_path(UINT32 eff_color_path)
00997 {
00998         /* ignore the subpixel adjust and texture enable flags */
00999         eff_color_path &= ~((1u << 26u) | (1u << 27u));
01000 
01001         return eff_color_path;
01002 }
01003 
01004 
01005 INLINE UINT32 normalize_alpha_mode(UINT32 eff_alpha_mode)
01006 {
01007         /* always ignore alpha ref value */
01008         eff_alpha_mode &= ~(0xffu << 24u);
01009 
01010         /* if not doing alpha testing, ignore the alpha function and ref value */
01011         if (!ALPHAMODE_ALPHATEST(eff_alpha_mode))
01012                 eff_alpha_mode &= ~(7u << 1u);
01013 
01014         /* if not doing alpha blending, ignore the source and dest blending factors */
01015         if (!ALPHAMODE_ALPHABLEND(eff_alpha_mode))
01016                 eff_alpha_mode &= ~((15u << 8u) | (15u << 12u) | (15u << 16u) | (15u << 20u));
01017 
01018         return eff_alpha_mode;
01019 }
01020 
01021 
01022 INLINE UINT32 normalize_fog_mode(UINT32 eff_fog_mode)
01023 {
01024         /* if not doing fogging, ignore all the other fog bits */
01025         if (!FOGMODE_ENABLE_FOG(eff_fog_mode))
01026                 eff_fog_mode = 0;
01027 
01028         return eff_fog_mode;
01029 }
01030 
01031 
01032 INLINE UINT32 normalize_fbz_mode(UINT32 eff_fbz_mode)
01033 {
01034         /* ignore the draw buffer */
01035         eff_fbz_mode &= ~(3u << 14u);
01036 
01037         return eff_fbz_mode;
01038 }
01039 
01040 
01041 INLINE UINT32 normalize_tex_mode(UINT32 eff_tex_mode)
01042 {
01043         /* ignore the NCC table and seq_8_downld flags */
01044         eff_tex_mode &= ~((1u << 5u) | (1u << 31u));
01045 
01046         /* classify texture formats into 3 format categories */
01047         if (TEXMODE_FORMAT(eff_tex_mode) < 8)
01048                 eff_tex_mode = (eff_tex_mode & ~(0xfu << 8u)) | (0u << 8u);
01049         else if (TEXMODE_FORMAT(eff_tex_mode) >= 10 && TEXMODE_FORMAT(eff_tex_mode) <= 12)
01050                 eff_tex_mode = (eff_tex_mode & ~(0xfu << 8u)) | (10u << 8u);
01051         else
01052                 eff_tex_mode = (eff_tex_mode & ~(0xfu << 8u)) | (8u << 8u);
01053 
01054         return eff_tex_mode;
01055 }
01056 
01057 
01058 INLINE UINT32 compute_raster_hash(const raster_info *info)
01059 {
01060         UINT32 hash;
01061 
01062         /* make a hash */
01063         hash = info->eff_color_path;
01064         hash = (hash << 1u) | (hash >> 31u);
01065         hash ^= info->eff_fbz_mode;
01066         hash = (hash << 1u) | (hash >> 31u);
01067         hash ^= info->eff_alpha_mode;
01068         hash = (hash << 1u) | (hash >> 31u);
01069         hash ^= info->eff_fog_mode;
01070         hash = (hash << 1u) | (hash >> 31u);
01071         hash ^= info->eff_tex_mode_0;
01072         hash = (hash << 1u) | (hash >> 31u);
01073         hash ^= info->eff_tex_mode_1;
01074 
01075         return hash % RASTER_HASH_SIZE;
01076 }
01077 
01078 
01079 
01080 /*************************************
01081  *
01082  *  Dithering macros
01083  *
01084  *************************************/
01085 
01086 /* note that these equations and the dither matrixes have
01087    been confirmed to be exact matches to the real hardware */
01088 #define DITHER_RB(val,dith)     ((((val) << 1) - ((val) >> 4) + ((val) >> 7) + (dith)) >> 1)
01089 #define DITHER_G(val,dith)      ((((val) << 2) - ((val) >> 4) + ((val) >> 6) + (dith)) >> 2)
01090 
01091 #define DECLARE_DITHER_POINTERS                                                                                                 \
01092         const UINT8 *dither_lookup = NULL;                                                                                      \
01093         const UINT8 *dither4 = NULL;                                                                                            \
01094         const UINT8 *dither = NULL                                                                                                      \
01095 
01096 #define DECLARE_DITHER_POINTERS_NO_DITHER_VAR                                                                                           \
01097         const UINT8 *dither_lookup = NULL;                                                                                      \
01098 
01099 #define COMPUTE_DITHER_POINTERS(FBZMODE, YY)                                                                    \
01100 do                                                                                                                                                              \
01101 {                                                                                                                                                               \
01102         /* compute the dithering pointers */                                                                            \
01103         if (FBZMODE_ENABLE_DITHERING(FBZMODE))                                                                          \
01104         {                                                                                                                                                       \
01105                 dither4 = &dither_matrix_4x4[((YY) & 3) * 4];                                                   \
01106                 if (FBZMODE_DITHER_TYPE(FBZMODE) == 0)                                                                  \
01107                 {                                                                                                                                               \
01108                         dither = dither4;                                                                                                       \
01109                         dither_lookup = &dither4_lookup[(YY & 3) << 11];                                        \
01110                 }                                                                                                                                               \
01111                 else                                                                                                                                    \
01112                 {                                                                                                                                               \
01113                         dither = &dither_matrix_2x2[((YY) & 3) * 4];                                            \
01114                         dither_lookup = &dither2_lookup[(YY & 3) << 11];                                        \
01115                 }                                                                                                                                               \
01116         }                                                                                                                                                       \
01117 }                                                                                                                                                               \
01118 while (0)
01119 
01120 #define COMPUTE_DITHER_POINTERS_NO_DITHER_VAR(FBZMODE, YY)                                                                      \
01121 do                                                                                                                                                              \
01122 {                                                                                                                                                               \
01123         /* compute the dithering pointers */                                                                            \
01124         if (FBZMODE_ENABLE_DITHERING(FBZMODE))                                                                          \
01125         {                                                                                                                                                       \
01126                 if (FBZMODE_DITHER_TYPE(FBZMODE) == 0)                                                                  \
01127                 {                                                                                                                                               \
01128                         dither_lookup = &dither4_lookup[(YY & 3) << 11];                                        \
01129                 }                                                                                                                                               \
01130                 else                                                                                                                                    \
01131                 {                                                                                                                                               \
01132                         dither_lookup = &dither2_lookup[(YY & 3) << 11];                                        \
01133                 }                                                                                                                                               \
01134         }                                                                                                                                                       \
01135 }                                                                                                                                                               \
01136 while (0)
01137 
01138 #define APPLY_DITHER(FBZMODE, XX, DITHER_LOOKUP, RR, GG, BB)                                    \
01139 do                                                                                                                                                              \
01140 {                                                                                                                                                               \
01141         /* apply dithering */                                                                                                           \
01142         if (FBZMODE_ENABLE_DITHERING(FBZMODE))                                                                          \
01143         {                                                                                                                                                       \
01144                 /* look up the dither value from the appropriate matrix */                              \
01145                 const UINT8 *dith = &DITHER_LOOKUP[((XX) & 3) << 1];                                    \
01146                                                                                                                                                                 \
01147                 /* apply dithering to R,G,B */                                                                                  \
01148                 (RR) = dith[((RR) << 3) + 0];                                                                                   \
01149                 (GG) = dith[((GG) << 3) + 1];                                                                                   \
01150                 (BB) = dith[((BB) << 3) + 0];                                                                                   \
01151         }                                                                                                                                                       \
01152         else                                                                                                                                            \
01153         {                                                                                                                                                       \
01154                 (RR) >>= 3;                                                                                                                             \
01155                 (GG) >>= 2;                                                                                                                             \
01156                 (BB) >>= 3;                                                                                                                             \
01157         }                                                                                                                                                       \
01158 }                                                                                                                                                               \
01159 while (0)
01160 
01161 
01162 
01163 /*************************************
01164  *
01165  *  Clamping macros
01166  *
01167  *************************************/
01168 
01169 #define CLAMPED_ARGB(ITERR, ITERG, ITERB, ITERA, FBZCP, RESULT)                                 \
01170 do                                                                                                                                                              \
01171 {                                                                                                                                                               \
01172         r = (INT32)(ITERR) >> 12;                                                                                               \
01173         g = (INT32)(ITERG) >> 12;                                                                                               \
01174         b = (INT32)(ITERB) >> 12;                                                                                               \
01175         a = (INT32)(ITERA) >> 12;                                                                                               \
01176                                                                                                                                                                 \
01177         if (FBZCP_RGBZW_CLAMP(FBZCP) == 0)                                                                                      \
01178         {                                                                                                                                                       \
01179                 r &= 0xfff;                                                                                                                             \
01180                 RESULT.rgb.r = r;                                                                                                               \
01181                 if (r == 0xfff)                                                                                                                 \
01182                         RESULT.rgb.r = 0;                                                                                                       \
01183                 else if (r == 0x100)                                                                                                    \
01184                         RESULT.rgb.r = 0xff;                                                                                            \
01185                                                                                                                                                                 \
01186                 g &= 0xfff;                                                                                                                             \
01187                 RESULT.rgb.g = g;                                                                                                               \
01188                 if (g == 0xfff)                                                                                                                 \
01189                         RESULT.rgb.g = 0;                                                                                                       \
01190                 else if (g == 0x100)                                                                                                    \
01191                         RESULT.rgb.g = 0xff;                                                                                            \
01192                                                                                                                                                                 \
01193                 b &= 0xfff;                                                                                                                             \
01194                 RESULT.rgb.b = b;                                                                                                               \
01195                 if (b == 0xfff)                                                                                                                 \
01196                         RESULT.rgb.b = 0;                                                                                                       \
01197                 else if (b == 0x100)                                                                                                    \
01198                         RESULT.rgb.b = 0xff;                                                                                            \
01199                                                                                                                                                                 \
01200                 a &= 0xfff;                                                                                                                             \
01201                 RESULT.rgb.a = a;                                                                                                               \
01202                 if (a == 0xfff)                                                                                                                 \
01203                         RESULT.rgb.a = 0;                                                                                                       \
01204                 else if (a == 0x100)                                                                                                    \
01205                         RESULT.rgb.a = 0xff;                                                                                            \
01206         }                                                                                                                                                       \
01207         else                                                                                                                                            \
01208         {                                                                                                                                                       \
01209                 RESULT.rgb.r = (r < 0) ? 0 : (r > 0xff) ? 0xff : (UINT8)r;                              \
01210                 RESULT.rgb.g = (g < 0) ? 0 : (g > 0xff) ? 0xff : (UINT8)g;                              \
01211                 RESULT.rgb.b = (b < 0) ? 0 : (b > 0xff) ? 0xff : (UINT8)b;                              \
01212                 RESULT.rgb.a = (a < 0) ? 0 : (a > 0xff) ? 0xff : (UINT8)a;                              \
01213         }                                                                                                                                                       \
01214 }                                                                                                                                                               \
01215 while (0)
01216 
01217 
01218 #define CLAMPED_Z(ITERZ, FBZCP, RESULT)                                                                                 \
01219 do                                                                                                                                                              \
01220 {                                                                                                                                                               \
01221         (RESULT) = (INT32)(ITERZ) >> 12;                                                                                        \
01222         if (FBZCP_RGBZW_CLAMP(FBZCP) == 0)                                                                                      \
01223         {                                                                                                                                                       \
01224                 (RESULT) &= 0xfffff;                                                                                                    \
01225                 if ((RESULT) == 0xfffff)                                                                                                \
01226                         (RESULT) = 0;                                                                                                           \
01227                 else if ((RESULT) == 0x10000)                                                                                   \
01228                         (RESULT) = 0xffff;                                                                                                      \
01229                 else                                                                                                                                    \
01230                         (RESULT) &= 0xffff;                                                                                                     \
01231         }                                                                                                                                                       \
01232         else                                                                                                                                            \
01233         {                                                                                                                                                       \
01234                 CLAMP((RESULT), 0, 0xffff);                                                                                             \
01235         }                                                                                                                                                       \
01236 }                                                                                                                                                               \
01237 while (0)
01238 
01239 
01240 #define CLAMPED_W(ITERW, FBZCP, RESULT)                                                                                 \
01241 do                                                                                                                                                              \
01242 {                                                                                                                                                               \
01243         (RESULT) = (INT16)((ITERW) >> 32);                                                                                      \
01244         if (FBZCP_RGBZW_CLAMP(FBZCP) == 0)                                                                                      \
01245         {                                                                                                                                                       \
01246                 (RESULT) &= 0xffff;                                                                                                             \
01247                 if ((RESULT) == 0xffff)                                                                                                 \
01248                         (RESULT) = 0;                                                                                                           \
01249                 else if ((RESULT) == 0x100)                                                                                             \
01250                         (RESULT) = 0xff;                                                                                                        \
01251                 (RESULT) &= 0xff;                                                                                                               \
01252         }                                                                                                                                                       \
01253         else                                                                                                                                            \
01254         {                                                                                                                                                       \
01255                 CLAMP((RESULT), 0, 0xff);                                                                                               \
01256         }                                                                                                                                                       \
01257 }                                                                                                                                                               \
01258 while (0)
01259 
01260 
01261 
01262 /*************************************
01263  *
01264  *  Chroma keying macro
01265  *
01266  *************************************/
01267 
01268 #define APPLY_CHROMAKEY(VV, STATS, FBZMODE, COLOR)                                                              \
01269 do                                                                                                                                                              \
01270 {                                                                                                                                                               \
01271         if (FBZMODE_ENABLE_CHROMAKEY(FBZMODE))                                                                          \
01272         {                                                                                                                                                       \
01273                 /* non-range version */                                                                                                 \
01274                 if (!CHROMARANGE_ENABLE((VV)->reg[chromaRange].u))                                              \
01275                 {                                                                                                                                               \
01276                         if (((COLOR.u ^ (VV)->reg[chromaKey].u) & 0xffffff) == 0)                       \
01277                         {                                                                                                                                       \
01278                                 (STATS)->chroma_fail++;                                                                                 \
01279                                 goto skipdrawdepth;                                                                                             \
01280                         }                                                                                                                                       \
01281                 }                                                                                                                                               \
01282                                                                                                                                                                 \
01283                 /* tricky range version */                                                                                              \
01284                 else                                                                                                                                    \
01285                 {                                                                                                                                               \
01286                         INT32 low, high, test;                                                                                          \
01287                         int results = 0;                                                                                                        \
01288                                                                                                                                                                 \
01289                         /* check blue */                                                                                                        \
01290                         low = (VV)->reg[chromaKey].rgb.b;                                                                       \
01291                         high = (VV)->reg[chromaRange].rgb.b;                                                            \
01292                         test = COLOR.rgb.b;                                                                                                     \
01293                         results = (test >= low && test <= high);                                                        \
01294                         results ^= (int)(CHROMARANGE_BLUE_EXCLUSIVE((VV)->reg[chromaRange].u)); \
01295                         results <<= 1;                                                                                                          \
01296                                                                                                                                                                 \
01297                         /* check green */                                                                                                       \
01298                         low = (VV)->reg[chromaKey].rgb.g;                                                                       \
01299                         high = (VV)->reg[chromaRange].rgb.g;                                                            \
01300                         test = COLOR.rgb.g;                                                                                                     \
01301                         results |= (test >= low && test <= high);                                                       \
01302                         results ^= (int)(CHROMARANGE_GREEN_EXCLUSIVE((VV)->reg[chromaRange].u));        \
01303                         results <<= 1;                                                                                                          \
01304                                                                                                                                                                 \
01305                         /* check red */                                                                                                         \
01306                         low = (VV)->reg[chromaKey].rgb.r;                                                                       \
01307                         high = (VV)->reg[chromaRange].rgb.r;                                                            \
01308                         test = COLOR.rgb.r;                                                                                                     \
01309                         results |= (test >= low && test <= high);                                                       \
01310                         results ^= (int)(CHROMARANGE_RED_EXCLUSIVE((VV)->reg[chromaRange].u));          \
01311                                                                                                                                                                 \
01312                         /* final result */                                                                                                      \
01313                         if (CHROMARANGE_UNION_MODE((VV)->reg[chromaRange].u))                           \
01314                         {                                                                                                                                       \
01315                                 if (results != 0)                                                                                               \
01316                                 {                                                                                                                               \
01317                                         (STATS)->chroma_fail++;                                                                         \
01318                                         goto skipdrawdepth;                                                                                     \
01319                                 }                                                                                                                               \
01320                         }                                                                                                                                       \
01321                         else                                                                                                                            \
01322                         {                                                                                                                                       \
01323                                 if (results == 7)                                                                                               \
01324                                 {                                                                                                                               \
01325                                         (STATS)->chroma_fail++;                                                                         \
01326                                         goto skipdrawdepth;                                                                                     \
01327                                 }                                                                                                                               \
01328                         }                                                                                                                                       \
01329                 }                                                                                                                                               \
01330         }                                                                                                                                                       \
01331 }                                                                                                                                                               \
01332 while (0)
01333 
01334 
01335 
01336 /*************************************
01337  *
01338  *  Alpha masking macro
01339  *
01340  *************************************/
01341 
01342 #define APPLY_ALPHAMASK(VV, STATS, FBZMODE, AA)                                                                 \
01343 do                                                                                                                                                              \
01344 {                                                                                                                                                               \
01345         if (FBZMODE_ENABLE_ALPHA_MASK(FBZMODE))                                                                         \
01346         {                                                                                                                                                       \
01347                 if (((AA) & 1) == 0)                                                                                                    \
01348                 {                                                                                                                                               \
01349                         (STATS)->afunc_fail++;                                                                                          \
01350                         goto skipdrawdepth;                                                                                                     \
01351                 }                                                                                                                                               \
01352         }                                                                                                                                                       \
01353 }                                                                                                                                                               \
01354 while (0)
01355 
01356 
01357 
01358 /*************************************
01359  *
01360  *  Alpha testing macro
01361  *
01362  *************************************/
01363 
01364 #define APPLY_ALPHATEST(VV, STATS, ALPHAMODE, AA)                                                               \
01365 do                                                                                                                                                              \
01366 {                                                                                                                                                               \
01367         if (ALPHAMODE_ALPHATEST(ALPHAMODE))                                                                                     \
01368         {                                                                                                                                                       \
01369                 UINT8 alpharef = (VV)->reg[alphaMode].rgb.a;                                                    \
01370                 switch (ALPHAMODE_ALPHAFUNCTION(ALPHAMODE))                                                             \
01371                 {                                                                                                                                               \
01372                         case 0:         /* alphaOP = never */                                                                   \
01373                                 (STATS)->afunc_fail++;                                                                                  \
01374                                 goto skipdrawdepth;                                                                                             \
01375                                                                                                                                                                 \
01376                         case 1:         /* alphaOP = less than */                                                               \
01377                                 if ((AA) >= alpharef)                                                                                   \
01378                                 {                                                                                                                               \
01379                                         (STATS)->afunc_fail++;                                                                          \
01380                                         goto skipdrawdepth;                                                                                     \
01381                                 }                                                                                                                               \
01382                                 break;                                                                                                                  \
01383                                                                                                                                                                 \
01384                         case 2:         /* alphaOP = equal */                                                                   \
01385                                 if ((AA) != alpharef)                                                                                   \
01386                                 {                                                                                                                               \
01387                                         (STATS)->afunc_fail++;                                                                          \
01388                                         goto skipdrawdepth;                                                                                     \
01389                                 }                                                                                                                               \
01390                                 break;                                                                                                                  \
01391                                                                                                                                                                 \
01392                         case 3:         /* alphaOP = less than or equal */                                              \
01393                                 if ((AA) > alpharef)                                                                                    \
01394                                 {                                                                                                                               \
01395                                         (STATS)->afunc_fail++;                                                                          \
01396                                         goto skipdrawdepth;                                                                                     \
01397                                 }                                                                                                                               \
01398                                 break;                                                                                                                  \
01399                                                                                                                                                                 \
01400                         case 4:         /* alphaOP = greater than */                                                    \
01401                                 if ((AA) <= alpharef)                                                                                   \
01402                                 {                                                                                                                               \
01403                                         (STATS)->afunc_fail++;                                                                          \
01404                                         goto skipdrawdepth;                                                                                     \
01405                                 }                                                                                                                               \
01406                                 break;                                                                                                                  \
01407                                                                                                                                                                 \
01408                         case 5:         /* alphaOP = not equal */                                                               \
01409                                 if ((AA) == alpharef)                                                                                   \
01410                                 {                                                                                                                               \
01411                                         (STATS)->afunc_fail++;                                                                          \
01412                                         goto skipdrawdepth;                                                                                     \
01413                                 }                                                                                                                               \
01414                                 break;                                                                                                                  \
01415                                                                                                                                                                 \
01416                         case 6:         /* alphaOP = greater than or equal */                                   \
01417                                 if ((AA) < alpharef)                                                                                    \
01418                                 {                                                                                                                               \
01419                                         (STATS)->afunc_fail++;                                                                          \
01420                                         goto skipdrawdepth;                                                                                     \
01421                                 }                                                                                                                               \
01422                                 break;                                                                                                                  \
01423                                                                                                                                                                 \
01424                         case 7:         /* alphaOP = always */                                                                  \
01425                                 break;                                                                                                                  \
01426                 }                                                                                                                                               \
01427         }                                                                                                                                                       \
01428 }                                                                                                                                                               \
01429 while (0)
01430 
01431 
01432 
01433 /*************************************
01434  *
01435  *  Alpha blending macro
01436  *
01437  *************************************/
01438 
01439 #define APPLY_ALPHA_BLEND(FBZMODE, ALPHAMODE, XX, DITHER, RR, GG, BB, AA)               \
01440 do                                                                                                                                                              \
01441 {                                                                                                                                                               \
01442         if (ALPHAMODE_ALPHABLEND(ALPHAMODE))                                                                            \
01443         {                                                                                                                                                       \
01444                 int dpix = dest[XX];                                                                                                    \
01445                 int dr, dg, db;                                                         \
01446                 EXTRACT_565_TO_888(dpix, dr, dg, db);                                   \
01447                 int da = (FBZMODE_ENABLE_ALPHA_PLANES(FBZMODE) && depth) ? depth[XX] : 0xff;            \
01448                 int sr = (RR);                                                                                                                  \
01449                 int sg = (GG);                                                                                                                  \
01450                 int sb = (BB);                                                                                                                  \
01451                 int sa = (AA);                                                                                                                  \
01452                 int ta;                                                                                                                                 \
01453                                                                                                                                                                 \
01454                 /* apply dither subtraction */                                                                                  \
01455                 if ((FBZMODE_ALPHA_DITHER_SUBTRACT(FBZMODE)) && DITHER)                                 \
01456                 {                                                                                                                                               \
01457                         /* look up the dither value from the appropriate matrix */                      \
01458                         int dith = DITHER[(XX) & 3];                                                                            \
01459                                                                                                                                                                 \
01460                         /* subtract the dither value */                                                                         \
01461                         dr = ((dr << 1) + 15 - dith) >> 1;                                                                      \
01462                         dg = ((dg << 2) + 15 - dith) >> 2;                                                                      \
01463                         db = ((db << 1) + 15 - dith) >> 1;                                                                      \
01464                 }                                                                                                                                               \
01465                                                                                                                                                                 \
01466                 /* compute source portion */                                                                                    \
01467                 switch (ALPHAMODE_SRCRGBBLEND(ALPHAMODE))                                                               \
01468                 {                                                                                                                                               \
01469                         default:        /* reserved */                                                                                  \
01470                         case 0:         /* AZERO */                                                                                             \
01471                                 (RR) = (GG) = (BB) = 0;                                                                                 \
01472                                 break;                                                                                                                  \
01473                                                                                                                                                                 \
01474                         case 1:         /* ASRC_ALPHA */                                                                                \
01475                                 (RR) = (sr * (sa + 1)) >> 8;                                                                    \
01476                                 (GG) = (sg * (sa + 1)) >> 8;                                                                    \
01477                                 (BB) = (sb * (sa + 1)) >> 8;                                                                    \
01478                                 break;                                                                                                                  \
01479                                                                                                                                                                 \
01480                         case 2:         /* A_COLOR */                                                                                   \
01481                                 (RR) = (sr * (dr + 1)) >> 8;                                                                    \
01482                                 (GG) = (sg * (dg + 1)) >> 8;                                                                    \
01483                                 (BB) = (sb * (db + 1)) >> 8;                                                                    \
01484                                 break;                                                                                                                  \
01485                                                                                                                                                                 \
01486                         case 3:         /* ADST_ALPHA */                                                                                \
01487                                 (RR) = (sr * (da + 1)) >> 8;                                                                    \
01488                                 (GG) = (sg * (da + 1)) >> 8;                                                                    \
01489                                 (BB) = (sb * (da + 1)) >> 8;                                                                    \
01490                                 break;                                                                                                                  \
01491                                                                                                                                                                 \
01492                         case 4:         /* AONE */                                                                                              \
01493                                 break;                                                                                                                  \
01494                                                                                                                                                                 \
01495                         case 5:         /* AOMSRC_ALPHA */                                                                              \
01496                                 (RR) = (sr * (0x100 - sa)) >> 8;                                                                \
01497                                 (GG) = (sg * (0x100 - sa)) >> 8;                                                                \
01498                                 (BB) = (sb * (0x100 - sa)) >> 8;                                                                \
01499                                 break;                                                                                                                  \
01500                                                                                                                                                                 \
01501                         case 6:         /* AOM_COLOR */                                                                                 \
01502                                 (RR) = (sr * (0x100 - dr)) >> 8;                                                                \
01503                                 (GG) = (sg * (0x100 - dg)) >> 8;                                                                \
01504                                 (BB) = (sb * (0x100 - db)) >> 8;                                                                \
01505                                 break;                                                                                                                  \
01506                                                                                                                                                                 \
01507                         case 7:         /* AOMDST_ALPHA */                                                                              \
01508                                 (RR) = (sr * (0x100 - da)) >> 8;                                                                \
01509                                 (GG) = (sg * (0x100 - da)) >> 8;                                                                \
01510                                 (BB) = (sb * (0x100 - da)) >> 8;                                                                \
01511                                 break;                                                                                                                  \
01512                                                                                                                                                                 \
01513                         case 15:        /* ASATURATE */                                                                                 \
01514                                 ta = (sa < (0x100 - da)) ? sa : (0x100 - da);                                   \
01515                                 (RR) = (sr * (ta + 1)) >> 8;                                                                    \
01516                                 (GG) = (sg * (ta + 1)) >> 8;                                                                    \
01517                                 (BB) = (sb * (ta + 1)) >> 8;                                                                    \
01518                                 break;                                                                                                                  \
01519                 }                                                                                                                                               \
01520                                                                                                                                                                 \
01521                 /* add in dest portion */                                                                                               \
01522                 switch (ALPHAMODE_DSTRGBBLEND(ALPHAMODE))                                                               \
01523                 {                                                                                                                                               \
01524                         default:        /* reserved */                                                                                  \
01525                         case 0:         /* AZERO */                                                                                             \
01526                                 break;                                                                                                                  \
01527                                                                                                                                                                 \
01528                         case 1:         /* ASRC_ALPHA */                                                                                \
01529                                 (RR) += (dr * (sa + 1)) >> 8;                                                                   \
01530                                 (GG) += (dg * (sa + 1)) >> 8;                                                                   \
01531                                 (BB) += (db * (sa + 1)) >> 8;                                                                   \
01532                                 break;                                                                                                                  \
01533                                                                                                                                                                 \
01534                         case 2:         /* A_COLOR */                                                                                   \
01535                                 (RR) += (dr * (sr + 1)) >> 8;                                                                   \
01536                                 (GG) += (dg * (sg + 1)) >> 8;                                                                   \
01537                                 (BB) += (db * (sb + 1)) >> 8;                                                                   \
01538                                 break;                                                                                                                  \
01539                                                                                                                                                                 \
01540                         case 3:         /* ADST_ALPHA */                                                                                \
01541                                 (RR) += (dr * (da + 1)) >> 8;                                                                   \
01542                                 (GG) += (dg * (da + 1)) >> 8;                                                                   \
01543                                 (BB) += (db * (da + 1)) >> 8;                                                                   \
01544                                 break;                                                                                                                  \
01545                                                                                                                                                                 \
01546                         case 4:         /* AONE */                                                                                              \
01547                                 (RR) += dr;                                                                                                             \
01548                                 (GG) += dg;                                                                                                             \
01549                                 (BB) += db;                                                                                                             \
01550                                 break;                                                                                                                  \
01551                                                                                                                                                                 \
01552                         case 5:         /* AOMSRC_ALPHA */                                                                              \
01553                                 (RR) += (dr * (0x100 - sa)) >> 8;                                                               \
01554                                 (GG) += (dg * (0x100 - sa)) >> 8;                                                               \
01555                                 (BB) += (db * (0x100 - sa)) >> 8;                                                               \
01556                                 break;                                                                                                                  \
01557                                                                                                                                                                 \
01558                         case 6:         /* AOM_COLOR */                                                                                 \
01559                                 (RR) += (dr * (0x100 - sr)) >> 8;                                                               \
01560                                 (GG) += (dg * (0x100 - sg)) >> 8;                                                               \
01561                                 (BB) += (db * (0x100 - sb)) >> 8;                                                               \
01562                                 break;                                                                                                                  \
01563                                                                                                                                                                 \
01564                         case 7:         /* AOMDST_ALPHA */                                                                              \
01565                                 (RR) += (dr * (0x100 - da)) >> 8;                                                               \
01566                                 (GG) += (dg * (0x100 - da)) >> 8;                                                               \
01567                                 (BB) += (db * (0x100 - da)) >> 8;                                                               \
01568                                 break;                                                                                                                  \
01569                                                                                                                                                                 \
01570                         case 15:        /* A_COLORBEFOREFOG */                                                                  \
01571                                 (RR) += (dr * (prefogr + 1)) >> 8;                                                              \
01572                                 (GG) += (dg * (prefogg + 1)) >> 8;                                                              \
01573                                 (BB) += (db * (prefogb + 1)) >> 8;                                                              \
01574                                 break;                                                                                                                  \
01575                 }                                                                                                                                               \
01576                                                                                                                                                                 \
01577                 /* blend the source alpha */                                                                                    \
01578                 (AA) = 0;                                                                                                                               \
01579                 if (ALPHAMODE_SRCALPHABLEND(ALPHAMODE) == 4)                                                    \
01580                         (AA) = sa;                                                                                                                      \
01581                                                                                                                                                                 \
01582                 /* blend the dest alpha */                                                                                              \
01583                 if (ALPHAMODE_DSTALPHABLEND(ALPHAMODE) == 4)                                                    \
01584                         (AA) += da;                                                                                                                     \
01585                                                                                                                                                                 \
01586                 /* clamp */                                                                                                                             \
01587                 CLAMP((RR), 0x00, 0xff);                                                                                                \
01588                 CLAMP((GG), 0x00, 0xff);                                                                                                \
01589                 CLAMP((BB), 0x00, 0xff);                                                                                                \
01590                 CLAMP((AA), 0x00, 0xff);                                                                                                \
01591         }                                                                                                                                                       \
01592 }                                                                                                                                                               \
01593 while (0)
01594 
01595 
01596 
01597 /*************************************
01598  *
01599  *  Fogging macro
01600  *
01601  *************************************/
01602 
01603 #define APPLY_FOGGING(VV, FOGMODE, FBZCP, XX, DITHER4, RR, GG, BB, ITERZ, ITERW, ITERAXXX)      \
01604 do                                                                                                                                                              \
01605 {                                                                                                                                                               \
01606         if (FOGMODE_ENABLE_FOG(FOGMODE))                                                                                        \
01607         {                                                                                                                                                       \
01608                 rgb_union fogcolor = (VV)->reg[fogColor];                                                               \
01609                 INT32 fr, fg, fb;                                                                                                               \
01610                                                                                                                                                                 \
01611                 /* constant fog bypasses everything else */                                                             \
01612                 if (FOGMODE_FOG_CONSTANT(FOGMODE))                                                                              \
01613                 {                                                                                                                                               \
01614                         fr = fogcolor.rgb.r;                                                                                            \
01615                         fg = fogcolor.rgb.g;                                                                                            \
01616                         fb = fogcolor.rgb.b;                                                                                            \
01617                 }                                                                                                                                               \
01618                                                                                                                                                                 \
01619                 /* non-constant fog comes from several sources */                                               \
01620                 else                                                                                                                                    \
01621                 {                                                                                                                                               \
01622                         INT32 fogblend = 0;                                                                                                     \
01623                                                                                                                                                                 \
01624                         /* if fog_add is zero, we start with the fog color */                           \
01625                         if (FOGMODE_FOG_ADD(FOGMODE) == 0)                                                                      \
01626                         {                                                                                                                                       \
01627                                 fr = fogcolor.rgb.r;                                                                                    \
01628                                 fg = fogcolor.rgb.g;                                                                                    \
01629                                 fb = fogcolor.rgb.b;                                                                                    \
01630                         }                                                                                                                                       \
01631                         else                                                                                                                            \
01632                                 fr = fg = fb = 0;                                                                                               \
01633                                                                                                                                                                 \
01634                         /* if fog_mult is zero, we subtract the incoming color */                       \
01635                         if (FOGMODE_FOG_MULT(FOGMODE) == 0)                                                                     \
01636                         {                                                                                                                                       \
01637                                 fr -= (RR);                                                                                                             \
01638                                 fg -= (GG);                                                                                                             \
01639                                 fb -= (BB);                                                                                                             \
01640                         }                                                                                                                                       \
01641                                                                                                                                                                 \
01642                         /* fog blending mode */                                                                                         \
01643                         switch (FOGMODE_FOG_ZALPHA(FOGMODE))                                                            \
01644                         {                                                                                                                                       \
01645                                 case 0:         /* fog table */                                                                         \
01646                                 {                                                                                                                               \
01647                                         INT32 delta = (VV)->fbi.fogdelta[fogdepth >> 10];                               \
01648                                         INT32 deltaval;                                                                                         \
01649                                                                                                                                                                 \
01650                                         /* perform the multiply against lower 8 bits of wfloat */       \
01651                                         deltaval = (delta & (VV)->fbi.fogdelta_mask) *                          \
01652                                                                 ((fogdepth >> 2) & 0xff);                                                       \
01653                                                                                                                                                                 \
01654                                         /* fog zones allow for negating this value */                           \
01655                                         if (FOGMODE_FOG_ZONES(FOGMODE) && (delta & 2))                          \
01656                                                 deltaval = -deltaval;                                                                   \
01657                                         deltaval >>= 6;                                                                                         \
01658                                                                                                                                                                 \
01659                                         /* apply dither */                                                                                      \
01660                                         if (FOGMODE_FOG_DITHER(FOGMODE))                                                        \
01661                                                 if (DITHER4)                                                                                    \
01662                                                         deltaval += DITHER4[(XX) & 3];                                          \
01663                                         deltaval >>= 4;                                                                                         \
01664                                                                                                                                                                 \
01665                                         /* add to the blending factor */                                                        \
01666                                         fogblend = (VV)->fbi.fogblend[fogdepth >> 10] + deltaval;               \
01667                                         break;                                                                                                          \
01668                                 }                                                                                                                               \
01669                                                                                                                                                                 \
01670                                 case 1:         /* iterated A */                                                                        \
01671                                         fogblend = ITERAXXX.rgb.a;                                                                      \
01672                                         break;                                                                                                          \
01673                                                                                                                                                                 \
01674                                 case 2:         /* iterated Z */                                                                        \
01675                                         CLAMPED_Z((ITERZ), FBZCP, fogblend);                                            \
01676                                         fogblend >>= 8;                                                                                         \
01677                                         break;                                                                                                          \
01678                                                                                                                                                                 \
01679                                 case 3:         /* iterated W - Voodoo 2 only */                                        \
01680                                         CLAMPED_W((ITERW), FBZCP, fogblend);                                            \
01681                                         break;                                                                                                          \
01682                         }                                                                                                                                       \
01683                                                                                                                                                                 \
01684                         /* perform the blend */                                                                                         \
01685                         fogblend++;                                                                                                                     \
01686                         fr = (fr * fogblend) >> 8;                                                                                      \
01687                         fg = (fg * fogblend) >> 8;                                                                                      \
01688                         fb = (fb * fogblend) >> 8;                                                                                      \
01689                 }                                                                                                                                               \
01690                                                                                                                                                                 \
01691                 /* if fog_mult is 0, we add this to the original color */                               \
01692                 if (FOGMODE_FOG_MULT(FOGMODE) == 0)                                                                             \
01693                 {                                                                                                                                               \
01694                         (RR) += fr;                                                                                                                     \
01695                         (GG) += fg;                                                                                                                     \
01696                         (BB) += fb;                                                                                                                     \
01697                 }                                                                                                                                               \
01698                                                                                                                                                                 \
01699                 /* otherwise this just becomes the new color */                                                 \
01700                 else                                                                                                                                    \
01701                 {                                                                                                                                               \
01702                         (RR) = fr;                                                                                                                      \
01703                         (GG) = fg;                                                                                                                      \
01704                         (BB) = fb;                                                                                                                      \
01705                 }                                                                                                                                               \
01706                                                                                                                                                                 \
01707                 /* clamp */                                                                                                                             \
01708                 CLAMP((RR), 0x00, 0xff);                                                                                                \
01709                 CLAMP((GG), 0x00, 0xff);                                                                                                \
01710                 CLAMP((BB), 0x00, 0xff);                                                                                                \
01711         }                                                                                                                                                       \
01712 }                                                                                                                                                               \
01713 while (0)
01714 
01715 
01716 
01717 /*************************************
01718  *
01719  *  Texture pipeline macro
01720  *
01721  *************************************/
01722 
01723 #define TEXTURE_PIPELINE(TT, XX, DITHER4, TEXMODE, COTHER, LOOKUP, LODBASE, ITERS, ITERT, ITERW, RESULT) \
01724 do                                                                                                                                                              \
01725 {                                                                                                                                                               \
01726         INT32 blendr, blendg, blendb, blenda;                                                                           \
01727         INT32 tr, tg, tb, ta;                                                                                                           \
01728         INT32 s, t, lod, ilod;                                                                                                          \
01729         INT64 oow;                                                                                                                                      \
01730         INT32 smax, tmax;                                                                                                                       \
01731         UINT32 texbase;                                                                                                                         \
01732         rgb_union c_local;                                                                                                                      \
01733                                                                                                                                                                 \
01734         /* determine the S/T/LOD values for this texture */                                                     \
01735         if (TEXMODE_ENABLE_PERSPECTIVE(TEXMODE))                                                                        \
01736         {                                                                                                                                                       \
01737                 oow = fast_reciplog((ITERW), &lod);                                                                             \
01738                 s = (INT32)((oow * (ITERS)) >> 29);                                                                             \
01739                 t = (INT32)((oow * (ITERT)) >> 29);                                                                             \
01740                 lod = (LODBASE);                                                                                                                \
01741         }                                                                                                                                                       \
01742         else                                                                                                                                            \
01743         {                                                                                                                                                       \
01744                 s = (INT32)((ITERS) >> 14);                                                                                             \
01745                 t = (INT32)((ITERT) >> 14);                                                                                             \
01746                 lod = (LODBASE);                                                                                                                \
01747         }                                                                                                                                                       \
01748                                                                                                                                                                 \
01749         /* clamp W */                                                                                                                           \
01750         if (TEXMODE_CLAMP_NEG_W(TEXMODE) && (ITERW) < 0)                                                        \
01751                 s = t = 0;                                                                                                                              \
01752                                                                                                                                                                 \
01753         /* clamp the LOD */                                                                                                                     \
01754         lod += (TT)->lodbias;                                                                                                           \
01755         if (TEXMODE_ENABLE_LOD_DITHER(TEXMODE))                                                                         \
01756                 if (DITHER4)                                                                                                                    \
01757                         lod += DITHER4[(XX) & 3] << 4;                                                                          \
01758         if (lod < (TT)->lodmin)                                                                                                         \
01759                 lod = (TT)->lodmin;                                                                                                             \
01760         if (lod > (TT)->lodmax)                                                                                                         \
01761                 lod = (TT)->lodmax;                                                                                                             \
01762                                                                                                                                                                 \
01763         /* now the LOD is in range; if we don't own this LOD, take the next one */      \
01764         ilod = lod >> 8;                                                                                                                        \
01765         if (!(((TT)->lodmask >> ilod) & 1))                                                                                     \
01766                 ilod++;                                                                                                                                 \
01767                                                                                                                                                                 \
01768         /* fetch the texture base */                                                                                            \
01769         texbase = (TT)->lodoffset[ilod];                                                                                        \
01770                                                                                                                                                                 \
01771         /* compute the maximum s and t values at this LOD */                                            \
01772         smax = (INT32)((TT)->wmask >> ilod);                                                                                                    \
01773         tmax = (INT32)((TT)->hmask >> ilod);                                                                                                    \
01774                                                                                                                                                                 \
01775         /* determine whether we are point-sampled or bilinear */                                        \
01776         if ((lod == (TT)->lodmin && !TEXMODE_MAGNIFICATION_FILTER(TEXMODE)) ||          \
01777                 (lod != (TT)->lodmin && !TEXMODE_MINIFICATION_FILTER(TEXMODE)))                 \
01778         {                                                                                                                                                       \
01779                 /* point sampled */                                                                                                             \
01780                                                                                                                                                                 \
01781                 UINT32 texel0;                                                                                                                  \
01782                                                                                                                                                                 \
01783                 /* adjust S/T for the LOD and strip off the fractions */                                \
01784                 s >>= ilod + 18;                                                                                                                \
01785                 t >>= ilod + 18;                                                                                                                \
01786                                                                                                                                                                 \
01787                 /* clamp/wrap S/T if necessary */                                                                               \
01788                 if (TEXMODE_CLAMP_S(TEXMODE))                                                                                   \
01789                         CLAMP(s, 0, smax);                                                                                                      \
01790                 if (TEXMODE_CLAMP_T(TEXMODE))                                                                                   \
01791                         CLAMP(t, 0, tmax);                                                                                                      \
01792                 s &= smax;                                                                                                                              \
01793                 t &= tmax;                                                                                                                              \
01794                 t *= smax + 1;                                                                                                                  \
01795                                                                                                                                                                 \
01796                 /* fetch texel data */                                                                                                  \
01797                 if (TEXMODE_FORMAT(TEXMODE) < 8)                                                                                \
01798                 {                                                                                                                                               \
01799                         texel0 = *(UINT8 *)&(TT)->ram[(unsigned long)((unsigned long)texbase + (unsigned long)t + (unsigned long)s) & (TT)->mask];              \
01800                         c_local.u = (LOOKUP)[texel0];                                                                           \
01801                 }                                                                                                                                               \
01802                 else                                                                                                                                    \
01803                 {                                                                                                                                               \
01804                         texel0 = *(UINT16 *)&(TT)->ram[(unsigned long)((unsigned long)texbase + 2ul*((unsigned long)t + (unsigned long)s)) & (TT)->mask];       \
01805                         if (TEXMODE_FORMAT(TEXMODE) >= 10 && TEXMODE_FORMAT(TEXMODE) <= 12)     \
01806                                 c_local.u = (LOOKUP)[texel0];                                                                   \
01807                         else                                                                                                                            \
01808                                 c_local.u = ((LOOKUP)[texel0 & 0xff] & 0xffffff) |                              \
01809                                                         ((texel0 & 0xff00) << 16);                                                      \
01810                 }                                                                                                                                               \
01811         }                                                                                                                                                       \
01812         else                                                                                                                                            \
01813         {                                                                                                                                                       \
01814                 /* bilinear filtered */                                                                                                 \
01815                                                                                                                                                                 \
01816                 UINT32 texel0, texel1, texel2, texel3;                                                                  \
01817                 UINT8 sfrac, tfrac;                                                                                                             \
01818                 INT32 s1, t1;                                                                                                                   \
01819                                                                                                                                                                 \
01820                 /* adjust S/T for the LOD and strip off all but the low 8 bits of */    \
01821                 /* the fraction */                                                                                                              \
01822                 s >>= ilod + 10;                                                                                                                \
01823                 t >>= ilod + 10;                                                                                                                \
01824                                                                                                                                                                 \
01825                 /* also subtract 1/2 texel so that (0.5,0.5) = a full (0,0) texel */    \
01826                 s -= 0x80;                                                                                                                              \
01827                 t -= 0x80;                                                                                                                              \
01828                                                                                                                                                                 \
01829                 /* extract the fractions */                                                                                             \
01830                 sfrac = (UINT8)(s & (TT)->bilinear_mask);                                                               \
01831                 tfrac = (UINT8)(t & (TT)->bilinear_mask);                                                               \
01832                                                                                                                                                                 \
01833                 /* now toss the rest */                                                                                                 \
01834                 s >>= 8;                                                                                                                                \
01835                 t >>= 8;                                                                                                                                \
01836                 s1 = s + 1;                                                                                                                             \
01837                 t1 = t + 1;                                                                                                                             \
01838                                                                                                                                                                 \
01839                 /* clamp/wrap S/T if necessary */                                                                               \
01840                 if (TEXMODE_CLAMP_S(TEXMODE))                                                                                   \
01841                 {                                                                                                                                               \
01842                         CLAMP(s, 0, smax);                                                                                                      \
01843                         CLAMP(s1, 0, smax);                                                                                                     \
01844                 }                                                                                                                                               \
01845                 if (TEXMODE_CLAMP_T(TEXMODE))                                                                                   \
01846                 {                                                                                                                                               \
01847                         CLAMP(t, 0, tmax);                                                                                                      \
01848                         CLAMP(t1, 0, tmax);                                                                                                     \
01849                 }                                                                                                                                               \
01850                 s &= smax;                                                                                                                              \
01851                 s1 &= smax;                                                                                                                             \
01852                 t &= tmax;                                                                                                                              \
01853                 t1 &= tmax;                                                                                                                             \
01854                 t *= smax + 1;                                                                                                                  \
01855                 t1 *= smax + 1;                                                                                                                 \
01856                                                                                                                                                                 \
01857                 /* fetch texel data */                                                                                                  \
01858                 if (TEXMODE_FORMAT(TEXMODE) < 8)                                                                                \
01859                 {                                                                                                                                               \
01860                         texel0 = *(UINT8 *)&(TT)->ram[((unsigned long)texbase + (unsigned long)t + (unsigned long)s) & (TT)->mask];             \
01861                         texel1 = *(UINT8 *)&(TT)->ram[((unsigned long)texbase + (unsigned long)t + (unsigned long)s1) & (TT)->mask];            \
01862                         texel2 = *(UINT8 *)&(TT)->ram[((unsigned long)texbase + (unsigned long)t1 + (unsigned long)s) & (TT)->mask];            \
01863                         texel3 = *(UINT8 *)&(TT)->ram[((unsigned long)texbase + (unsigned long)t1 + (unsigned long)s1) & (TT)->mask];   \
01864                         texel0 = (LOOKUP)[texel0];                                                                                      \
01865                         texel1 = (LOOKUP)[texel1];                                                                                      \
01866                         texel2 = (LOOKUP)[texel2];                                                                                      \
01867                         texel3 = (LOOKUP)[texel3];                                                                                      \
01868                 }                                                                                                                                               \
01869                 else                                                                                                                                    \
01870                 {                                                                                                                                               \
01871                         texel0 = *(UINT16 *)&(TT)->ram[((unsigned long)texbase + 2ul*((unsigned long)t + (unsigned long)s)) & (TT)->mask];      \
01872                         texel1 = *(UINT16 *)&(TT)->ram[((unsigned long)texbase + 2ul*((unsigned long)t + (unsigned long)s1)) & (TT)->mask];\
01873                         texel2 = *(UINT16 *)&(TT)->ram[((unsigned long)texbase + 2ul*((unsigned long)t1 + (unsigned long)s)) & (TT)->mask];\
01874                         texel3 = *(UINT16 *)&(TT)->ram[((unsigned long)texbase + 2ul*((unsigned long)t1 + (unsigned long)s1)) & (TT)->mask];\
01875                         if (TEXMODE_FORMAT(TEXMODE) >= 10 && TEXMODE_FORMAT(TEXMODE) <= 12)     \
01876                         {                                                                                                                                       \
01877                                 texel0 = (LOOKUP)[texel0];                                                                              \
01878                                 texel1 = (LOOKUP)[texel1];                                                                              \
01879                                 texel2 = (LOOKUP)[texel2];                                                                              \
01880                                 texel3 = (LOOKUP)[texel3];                                                                              \
01881                         }                                                                                                                                       \
01882                         else                                                                                                                            \
01883                         {                                                                                                                                       \
01884                                 texel0 = ((LOOKUP)[texel0 & 0xff] & 0xffffff) |                                 \
01885                                                         ((texel0 & 0xff00) << 16);                                                      \
01886                                 texel1 = ((LOOKUP)[texel1 & 0xff] & 0xffffff) |                                 \
01887                                                         ((texel1 & 0xff00) << 16);                                                      \
01888                                 texel2 = ((LOOKUP)[texel2 & 0xff] & 0xffffff) |                                 \
01889                                                         ((texel2 & 0xff00) << 16);                                                      \
01890                                 texel3 = ((LOOKUP)[texel3 & 0xff] & 0xffffff) |                                 \
01891                                                         ((texel3 & 0xff00) << 16);                                                      \
01892                         }                                                                                                                                       \
01893                 }                                                                                                                                               \
01894                                                                                                                                                                 \
01895                 /* weigh in each texel */                                                                                               \
01896                 c_local.u = rgba_bilinear_filter(texel0, texel1, texel2, texel3, sfrac, tfrac);\
01897         }                                                                                                                                                       \
01898                                                                                                                                                                 \
01899         /* select zero/other for RGB */                                                                                         \
01900         if (!TEXMODE_TC_ZERO_OTHER(TEXMODE))                                                                            \
01901         {                                                                                                                                                       \
01902                 tr = COTHER.rgb.r;                                                                                                              \
01903                 tg = COTHER.rgb.g;                                                                                                              \
01904                 tb = COTHER.rgb.b;                                                                                                              \
01905         }                                                                                                                                                       \
01906         else                                                                                                                                            \
01907                 tr = tg = tb = 0;                                                                                                               \
01908                                                                                                                                                                 \
01909         /* select zero/other for alpha */                                                                                       \
01910         if (!TEXMODE_TCA_ZERO_OTHER(TEXMODE))                                                                           \
01911                 ta = COTHER.rgb.a;                                                                                                              \
01912         else                                                                                                                                            \
01913                 ta = 0;                                                                                                                                 \
01914                                                                                                                                                                 \
01915         /* potentially subtract c_local */                                                                                      \
01916         if (TEXMODE_TC_SUB_CLOCAL(TEXMODE))                                                                                     \
01917         {                                                                                                                                                       \
01918                 tr -= c_local.rgb.r;                                                                                                    \
01919                 tg -= c_local.rgb.g;                                                                                                    \
01920                 tb -= c_local.rgb.b;                                                                                                    \
01921         }                                                                                                                                                       \
01922         if (TEXMODE_TCA_SUB_CLOCAL(TEXMODE))                                                                            \
01923                 ta -= c_local.rgb.a;                                                                                                    \
01924                                                                                                                                                                 \
01925         /* blend RGB */                                                                                                                         \
01926         switch (TEXMODE_TC_MSELECT(TEXMODE))                                                                            \
01927         {                                                                                                                                                       \
01928                 default:        /* reserved */                                                                                          \
01929                 case 0:         /* zero */                                                                                                      \
01930                         blendr = blendg = blendb = 0;                                                                           \
01931                         break;                                                                                                                          \
01932                                                                                                                                                                 \
01933                 case 1:         /* c_local */                                                                                           \
01934                         blendr = c_local.rgb.r;                                                                                         \
01935                         blendg = c_local.rgb.g;                                                                                         \
01936                         blendb = c_local.rgb.b;                                                                                         \
01937                         break;                                                                                                                          \
01938                                                                                                                                                                 \
01939                 case 2:         /* a_other */                                                                                           \
01940                         blendr = blendg = blendb = COTHER.rgb.a;                                                        \
01941                         break;                                                                                                                          \
01942                                                                                                                                                                 \
01943                 case 3:         /* a_local */                                                                                           \
01944                         blendr = blendg = blendb = c_local.rgb.a;                                                       \
01945                         break;                                                                                                                          \
01946                                                                                                                                                                 \
01947                 case 4:         /* LOD (detail factor) */                                                                       \
01948                         if ((TT)->detailbias <= lod)                                                                            \
01949                                 blendr = blendg = blendb = 0;                                                                   \
01950                         else                                                                                                                            \
01951                         {                                                                                                                                       \
01952                                 blendr = ((((TT)->detailbias - lod) << (TT)->detailscale) >> 8);\
01953                                 if (blendr > (TT)->detailmax)                                                                   \
01954                                         blendr = (TT)->detailmax;                                                                       \
01955                                 blendg = blendb = blendr;                                                                               \
01956                         }                                                                                                                                       \
01957                         break;                                                                                                                          \
01958                                                                                                                                                                 \
01959                 case 5:         /* LOD fraction */                                                                                      \
01960                         blendr = blendg = blendb = lod & 0xff;                                                          \
01961                         break;                                                                                                                          \
01962         }                                                                                                                                                       \
01963                                                                                                                                                                 \
01964         /* blend alpha */                                                                                                                       \
01965         switch (TEXMODE_TCA_MSELECT(TEXMODE))                                                                           \
01966         {                                                                                                                                                       \
01967                 default:        /* reserved */                                                                                          \
01968                 case 0:         /* zero */                                                                                                      \
01969                         blenda = 0;                                                                                                                     \
01970                         break;                                                                                                                          \
01971                                                                                                                                                                 \
01972                 case 1:         /* c_local */                                                                                           \
01973                         blenda = c_local.rgb.a;                                                                                         \
01974                         break;                                                                                                                          \
01975                                                                                                                                                                 \
01976                 case 2:         /* a_other */                                                                                           \
01977                         blenda = COTHER.rgb.a;                                                                                          \
01978                         break;                                                                                                                          \
01979                                                                                                                                                                 \
01980                 case 3:         /* a_local */                                                                                           \
01981                         blenda = c_local.rgb.a;                                                                                         \
01982                         break;                                                                                                                          \
01983                                                                                                                                                                 \
01984                 case 4:         /* LOD (detail factor) */                                                                       \
01985                         if ((TT)->detailbias <= lod)                                                                            \
01986                                 blenda = 0;                                                                                                             \
01987                         else                                                                                                                            \
01988                         {                                                                                                                                       \
01989                                 blenda = ((((TT)->detailbias - lod) << (TT)->detailscale) >> 8);\
01990                                 if (blenda > (TT)->detailmax)                                                                   \
01991                                         blenda = (TT)->detailmax;                                                                       \
01992                         }                                                                                                                                       \
01993                         break;                                                                                                                          \
01994                                                                                                                                                                 \
01995                 case 5:         /* LOD fraction */                                                                                      \
01996                         blenda = lod & 0xff;                                                                                            \
01997                         break;                                                                                                                          \
01998         }                                                                                                                                                       \
01999                                                                                                                                                                 \
02000         /* reverse the RGB blend */                                                                                                     \
02001         if (!TEXMODE_TC_REVERSE_BLEND(TEXMODE))                                                                         \
02002         {                                                                                                                                                       \
02003                 blendr ^= 0xff;                                                                                                                 \
02004                 blendg ^= 0xff;                                                                                                                 \
02005                 blendb ^= 0xff;                                                                                                                 \
02006         }                                                                                                                                                       \
02007                                                                                                                                                                 \
02008         /* reverse the alpha blend */                                                                                           \
02009         if (!TEXMODE_TCA_REVERSE_BLEND(TEXMODE))                                                                        \
02010                 blenda ^= 0xff;                                                                                                                 \
02011                                                                                                                                                                 \
02012         /* do the blend */                                                                                                                      \
02013         tr = (tr * (blendr + 1)) >> 8;                                                                                          \
02014         tg = (tg * (blendg + 1)) >> 8;                                                                                          \
02015         tb = (tb * (blendb + 1)) >> 8;                                                                                          \
02016         ta = (ta * (blenda + 1)) >> 8;                                                                                          \
02017                                                                                                                                                                 \
02018         /* add clocal or alocal to RGB */                                                                                       \
02019         switch (TEXMODE_TC_ADD_ACLOCAL(TEXMODE))                                                                        \
02020         {                                                                                                                                                       \
02021                 case 3:         /* reserved */                                                                                          \
02022                 case 0:         /* nothing */                                                                                           \
02023                         break;                                                                                                                          \
02024                                                                                                                                                                 \
02025                 case 1:         /* add c_local */                                                                                       \
02026                         tr += c_local.rgb.r;                                                                                            \
02027                         tg += c_local.rgb.g;                                                                                            \
02028                         tb += c_local.rgb.b;                                                                                            \
02029                         break;                                                                                                                          \
02030                                                                                                                                                                 \
02031                 case 2:         /* add_alocal */                                                                                        \
02032                         tr += c_local.rgb.a;                                                                                            \
02033                         tg += c_local.rgb.a;                                                                                            \
02034                         tb += c_local.rgb.a;                                                                                            \
02035                         break;                                                                                                                          \
02036         }                                                                                                                                                       \
02037                                                                                                                                                                 \
02038         /* add clocal or alocal to alpha */                                                                                     \
02039         if (TEXMODE_TCA_ADD_ACLOCAL(TEXMODE))                                                                           \
02040                 ta += c_local.rgb.a;                                                                                                    \
02041                                                                                                                                                                 \
02042         /* clamp */                                                                                                                                     \
02043         RESULT.rgb.r = (tr < 0) ? 0 : (tr > 0xff) ? 0xff : (UINT8)tr;                           \
02044         RESULT.rgb.g = (tg < 0) ? 0 : (tg > 0xff) ? 0xff : (UINT8)tg;                           \
02045         RESULT.rgb.b = (tb < 0) ? 0 : (tb > 0xff) ? 0xff : (UINT8)tb;                           \
02046         RESULT.rgb.a = (ta < 0) ? 0 : (ta > 0xff) ? 0xff : (UINT8)ta;                           \
02047                                                                                                                                                                 \
02048         /* invert */                                                                                                                            \
02049         if (TEXMODE_TC_INVERT_OUTPUT(TEXMODE))                                                                          \
02050                 RESULT.u ^= 0x00ffffff;                                                                                                 \
02051         if (TEXMODE_TCA_INVERT_OUTPUT(TEXMODE))                                                                         \
02052                 RESULT.rgb.a ^= 0xff;                                                                                                   \
02053 }                                                                                                                                                               \
02054 while (0)
02055 
02056 
02057 
02058 /*************************************
02059  *
02060  *  Pixel pipeline macros
02061  *
02062  *************************************/
02063 
02064 #define PIXEL_PIPELINE_BEGIN(VV, XX, YY, FBZCOLORPATH, FBZMODE, ITERZ, ITERW)   \
02065 do                                                                                                                                                              \
02066 {                                                                                                                                                               \
02067         INT32 depthval, wfloat, fogdepth, biasdepth;                                                                                                            \
02068         INT32 prefogr, prefogg, prefogb;                                                                                        \
02069         INT32 r, g, b, a;                                                                                                                       \
02070                                                                                                                                                                 \
02071         /* apply clipping */                                                                                                            \
02072         /* note that for perf reasons, we assume the caller has done clipping */        \
02073                                                                                                                                                                 \
02074         /* handle stippling */                                                                                                          \
02075         if (FBZMODE_ENABLE_STIPPLE(FBZMODE))                                                                            \
02076         {                                                                                                                                                       \
02077                 /* rotate mode */                                                                                                               \
02078                 if (FBZMODE_STIPPLE_PATTERN(FBZMODE) == 0)                                                              \
02079                 {                                                                                                                                               \
02080                         (VV)->reg[stipple].u = ((VV)->reg[stipple].u << 1) | ((VV)->reg[stipple].u >> 31);\
02081                         if (((VV)->reg[stipple].u & 0x80000000) == 0)                                           \
02082                         {                                                                                                                                       \
02083                                 goto skipdrawdepth;                                                                                             \
02084                         }                                                                                                                                       \
02085                 }                                                                                                                                               \
02086                                                                                                                                                                 \
02087                 /* pattern mode */                                                                                                              \
02088                 else                                                                                                                                    \
02089                 {                                                                                                                                               \
02090                         int stipple_index = (((YY) & 3) << 3) | (~(XX) & 7);                            \
02091                         if ((((VV)->reg[stipple].u >> stipple_index) & 1) == 0)                         \
02092                         {                                                                                                                                       \
02093                                 goto skipdrawdepth;                                                                                             \
02094                         }                                                                                                                                       \
02095                 }                                                                                                                                               \
02096         }                                                                                                                                                       \
02097                                                                                                                                                                 \
02098         /* compute "floating point" W value (used for depth and fog) */                         \
02099         if ((ITERW) & LONGTYPE(0xffff00000000))                                                                                 \
02100                 wfloat = 0x0000;                                                                                                                \
02101         else                                                                                                                                            \
02102         {                                                                                                                                                       \
02103                 UINT32 temp = (UINT32)(ITERW);                                                                                  \
02104                 if ((temp & 0xffff0000) == 0)                                                                                   \
02105                         wfloat = 0xffff;                                                                                                        \
02106                 else                                                                                                                                    \
02107                 {                                                                                                                                               \
02108                         int exp = count_leading_zeros(temp);                                                            \
02109                         wfloat = (INT32)(((unsigned int)exp << 12) | ((~temp >> (19 - exp)) & 0xfff)) + 1;                      \
02110                 }                                                                                                                                               \
02111         }                                                                                                                                                       \
02112         fogdepth = wfloat;                                                         \
02113         /* add the bias for fog selection*/                                         \
02114         if (FBZMODE_ENABLE_DEPTH_BIAS(FBZMODE))                                     \
02115         {                                                                           \
02116                 fogdepth += (INT16)(VV)->reg[zaColor].u;                                \
02117                 CLAMP(fogdepth, 0, 0xffff);                                             \
02118         }                                                                           \
02119                                                                                                                                                                 \
02120         /* compute depth value (W or Z) for this pixel */                           \
02121         if (FBZMODE_WBUFFER_SELECT(FBZMODE) == 0)                                   \
02122         {                                                                           \
02123                 CLAMPED_Z(ITERZ, FBZCOLORPATH, depthval);                               \
02124         }                                                                           \
02125         else if (FBZMODE_DEPTH_FLOAT_SELECT(FBZMODE) == 0)                          \
02126                 depthval = wfloat;                                                      \
02127         else                                                                        \
02128         {                                                                           \
02129                 if ((ITERZ) & 0xf0000000l)                                               \
02130                         depthval = 0x0000;                                                  \
02131                 else                                                                    \
02132                 {                                                                       \
02133                         UINT32 temp = (UINT32)(ITERZ << 4);                             \
02134                         if (!(temp & 0xffff0000u))                                                           \
02135                                 depthval = 0xffff;                                              \
02136                         else                                                                \
02137                         {                                                                   \
02138                                 int exp = count_leading_zeros(temp);                            \
02139                                 depthval = (INT32)(((unsigned int)exp << 12) | ((~temp >> (19 - exp)) & 0xfff)) + 1; \
02140                         }                                                                   \
02141                 }                                                                       \
02142         }                                                                            \
02143         /* add the bias */                                                          \
02144         biasdepth = depthval;                                                     \
02145         if (FBZMODE_ENABLE_DEPTH_BIAS(FBZMODE))                                     \
02146         {                                                                           \
02147                 biasdepth += (INT16)(VV)->reg[zaColor].u;                                \
02148                 CLAMP(biasdepth, 0, 0xffff);                                             \
02149         }                                                                                                                       \
02150 
02151 
02152 #define DEPTH_TEST(VV, STATS, XX, FBZMODE)    \
02153 do                                                                              \
02154 {                                                                               \
02155         /* handle depth buffer testing */                                           \
02156         if (FBZMODE_ENABLE_DEPTHBUF(FBZMODE))                                       \
02157         {                                                                           \
02158                 INT32 depthsource;                                                      \
02159                                                                                                                                                                 \
02160                 /* the source depth is either the iterated W/Z+bias or a */             \
02161                 /* constant value */                                                    \
02162                 if (FBZMODE_DEPTH_SOURCE_COMPARE(FBZMODE) == 0)                         \
02163                         depthsource = biasdepth;                                             \
02164                 else                                                                    \
02165                         depthsource = (UINT16)(VV)->reg[zaColor].u;                         \
02166                                                                                                                                                                 \
02167                 /* test against the depth buffer */                                     \
02168                 switch (FBZMODE_DEPTH_FUNCTION(FBZMODE))                                \
02169                 {                                                                       \
02170                         case 0:     /* depthOP = never */                                   \
02171                                 (STATS)->zfunc_fail++;                                          \
02172                                 goto skipdrawdepth;                                             \
02173                                                                                                                                                                 \
02174                         case 1:     /* depthOP = less than */                               \
02175                                 if (depthsource >= depth[XX])                                   \
02176                                 {                                                               \
02177                                         (STATS)->zfunc_fail++;                                      \
02178                                         goto skipdrawdepth;                                         \
02179                                 }                                                               \
02180                                 break;                                                          \
02181                                                                                                                                                                 \
02182                         case 2:     /* depthOP = equal */                                   \
02183                                 if (depthsource != depth[XX])                                   \
02184                                 {                                                               \
02185                                         (STATS)->zfunc_fail++;                                      \
02186                                         goto skipdrawdepth;                                         \
02187                                 }                                                               \
02188                                 break;                                                          \
02189                                                                                                                                                                 \
02190                         case 3:     /* depthOP = less than or equal */                      \
02191                                 if (depthsource > depth[XX])                                    \
02192                                 {                                                               \
02193                                         (STATS)->zfunc_fail++;                                      \
02194                                         goto skipdrawdepth;                                         \
02195                                 }                                                               \
02196                                 break;                                                          \
02197                                                                                                                                                                 \
02198                         case 4:     /* depthOP = greater than */                            \
02199                                 if (depthsource <= depth[XX])                                   \
02200                                 {                                                               \
02201                                         (STATS)->zfunc_fail++;                                      \
02202                                         goto skipdrawdepth;                                         \
02203                                 }                                                               \
02204                                 break;                                                          \
02205                                                                                                                                                                 \
02206                         case 5:     /* depthOP = not equal */                               \
02207                                 if (depthsource == depth[XX])                                   \
02208                                 {                                                               \
02209                                         (STATS)->zfunc_fail++;                                      \
02210                                         goto skipdrawdepth;                                         \
02211                                 }                                                               \
02212                                 break;                                                          \
02213                                                                                                                                                                 \
02214                         case 6:     /* depthOP = greater than or equal */                   \
02215                                 if (depthsource < depth[XX])                                    \
02216                                 {                                                               \
02217                                         (STATS)->zfunc_fail++;                                      \
02218                                         goto skipdrawdepth;                                         \
02219                                 }                                                               \
02220                                 break;                                                          \
02221                                                                                                                                                                 \
02222                         case 7:     /* depthOP = always */                                  \
02223                                 break;                                                          \
02224                 }                                                                       \
02225         }                                                                       \
02226 }                                                                               \
02227 while (0)
02228 
02229 
02230 #define PIXEL_PIPELINE_MODIFY(VV, DITHER, DITHER4, XX, FBZMODE, FBZCOLORPATH, ALPHAMODE, FOGMODE, ITERZ, ITERW, ITERAXXX) \
02231                                                                                                                                                                 \
02232         /* perform fogging */                                                                                                           \
02233         prefogr = r;                                                                                                                            \
02234         prefogg = g;                                                                                                                            \
02235         prefogb = b;                                                                                                                            \
02236         APPLY_FOGGING(VV, FOGMODE, FBZCOLORPATH, XX, DITHER4, r, g, b,                          \
02237                                         ITERZ, ITERW, ITERAXXX);                                                                        \
02238                                                                                                                                                                 \
02239         /* perform alpha blending */                                                                                            \
02240         APPLY_ALPHA_BLEND(FBZMODE, ALPHAMODE, XX, DITHER, r, g, b, a);
02241 
02242 
02243 #define PIXEL_PIPELINE_FINISH(VV, DITHER_LOOKUP, XX, dest, depth, FBZMODE)              \
02244                                                                                                                                                                 \
02245         /* write to framebuffer */                                                                                                      \
02246         if (FBZMODE_RGB_BUFFER_MASK(FBZMODE))                                                                           \
02247         {                                                                                                                                                       \
02248                 /* apply dithering */                                                                                                   \
02249                 APPLY_DITHER(FBZMODE, XX, DITHER_LOOKUP, r, g, b);                                              \
02250                 dest[XX] = (UINT16)((r << 11) | (g << 5) | b);                                                  \
02251         }                                                                                                                                                       \
02252                                                                                                                                                                 \
02253         /* write to aux buffer */                                                                                                       \
02254         if (depth && FBZMODE_AUX_BUFFER_MASK(FBZMODE))                                                          \
02255         {                                                                                                                                                       \
02256                 if (FBZMODE_ENABLE_ALPHA_PLANES(FBZMODE) == 0)                                                  \
02257                         depth[XX] = (UINT16)biasdepth;                                                                          \
02258                 else                                                                                                                                    \
02259                         depth[XX] = (UINT16)a;                                                                                          \
02260         }
02261 
02262 #define PIXEL_PIPELINE_END(STATS)                                                                                               \
02263                                                                                                                                                                 \
02264         /* track pixel writes to the frame buffer regardless of mask */                         \
02265         (STATS)->pixels_out++;                                                                                                          \
02266                                                                                                                                                                 \
02267 skipdrawdepth:                                                                                                                                  \
02268         ;                                                                                                                                                       \
02269 }                                                                                                                                                               \
02270 while (0)
02271 
02272 #endif