diff options
Diffstat (limited to 'xc/extras/Mesa/src/FX')
29 files changed, 16230 insertions, 0 deletions
diff --git a/xc/extras/Mesa/src/FX/X86/fx_3dnow_fastpath.S b/xc/extras/Mesa/src/FX/X86/fx_3dnow_fastpath.S new file mode 100644 index 000000000..e032942be --- /dev/null +++ b/xc/extras/Mesa/src/FX/X86/fx_3dnow_fastpath.S @@ -0,0 +1,82 @@ +#include "../../X86/assyntax.h" + +#define SETUP_RGBA 0x1 +#define SETUP_TMU0 0x2 +#define SETUP_TMU1 0x4 + + +/* Pack either rgba or texture into the remaining half of a 32 byte vertex. + */ +#define CLIP_R 24 +#define CLIP_G 16 +#define CLIP_B 20 +#define CLIP_A 28 /* defined inf fxdrv.h */ + +#define CLIP_S0 16 +#define CLIP_T0 20 +#define CLIP_S1 24 +#define CLIP_T1 28 + +#define SIZE 4 +#define TYPE (0) +#define TAG(x) x +#include "fx_3dnow_fasttmp.h" + +#define SIZE 8 +#define TYPE (SETUP_RGBA) +#define TAG(x) CONCAT(x,_RGBA) +#include "fx_3dnow_fasttmp.h" + +#define SIZE 6 +#define TYPE (SETUP_TMU0) +#define TAG(x) CONCAT(x,_TMU0) +#include "fx_3dnow_fasttmp.h" + +#define SIZE 8 +#define TYPE (SETUP_TMU0|SETUP_TMU1) +#define TAG(x) CONCAT(x,_TMU0_TMU1) +#include "fx_3dnow_fasttmp.h" + +#undef CLIP_S1 +#undef CLIP_T1 +#define CLIP_S1 16 +#define CLIP_T1 20 + +#define SIZE 6 +#define TYPE (SETUP_TMU1) +#define TAG(x) CONCAT(x,_TMU1) +#include "fx_3dnow_fasttmp.h" + +/* These three need to use a full 64 byte clip-space vertex. + */ +#undef CLIP_S0 +#undef CLIP_T0 +#undef CLIP_S1 +#undef CLIP_T1 + +#define CLIP_S0 32 +#define CLIP_T0 36 +#define CLIP_S1 40 +#define CLIP_T1 44 + +#define SIZE 10 +#define TYPE (SETUP_RGBA|SETUP_TMU0) +#define TAG(x) CONCAT(x,_RGBA_TMU0) +#include "fx_3dnow_fasttmp.h" + +#define SIZE 12 +#define TYPE (SETUP_RGBA|SETUP_TMU0|SETUP_TMU1) +#define TAG(x) CONCAT(x,_RGBA_TMU0_TMU1) +#include "fx_3dnow_fasttmp.h" + +#undef CLIP_S1 +#undef CLIP_T1 +#define CLIP_S1 32 +#define CLIP_T1 36 + +#define SIZE 10 +#define TYPE (SETUP_RGBA|SETUP_TMU1) +#define TAG(x) CONCAT(x,_RGBA_TMU1) +#include "fx_3dnow_fasttmp.h" + + diff --git a/xc/extras/Mesa/src/FX/X86/fx_3dnow_fasttmp.h b/xc/extras/Mesa/src/FX/X86/fx_3dnow_fasttmp.h new file mode 100644 index 000000000..fff802dd6 --- /dev/null +++ b/xc/extras/Mesa/src/FX/X86/fx_3dnow_fasttmp.h @@ -0,0 +1,325 @@ + + SEG_TEXT + +#if !defined(NASM_ASSEMBLER) && !defined(MASM_ASSEMBLER) +#define _TAGLLBL(a) CONCAT(.L,a) +#define TAGLLBL(a) _TAGLLBL(TAG(a)) +#else +#define TAGLLBL(a) TAG(a) +#endif + +#define TAG_GLNAME(x) TAG( GLNAME(x) ) + + + +#if !GLIDE3 + +#define GR_VERTEX_X_OFFSET 0 +#define GR_VERTEX_Y_OFFSET 4 +#define GR_VERTEX_Z_OFFSET 8 +#define GR_VERTEX_R_OFFSET 12 +#define GR_VERTEX_G_OFFSET 16 +#define GR_VERTEX_B_OFFSET 20 +#define GR_VERTEX_OOZ_OFFSET 24 +#define GR_VERTEX_A_OFFSET 28 +#define GR_VERTEX_OOW_OFFSET 32 + +#else /* GLIDE3 */ + +#define GR_VERTEX_X_OFFSET 0 +#define GR_VERTEX_Y_OFFSET 4 +#define GR_VERTEX_OOZ_OFFSET 8 +#define GR_VERTEX_OOW_OFFSET 12 +#define GR_VERTEX_R_OFFSET 16 +#define GR_VERTEX_G_OFFSET 20 +#define GR_VERTEX_B_OFFSET 24 +#define GR_VERTEX_A_OFFSET 28 +#define GR_VERTEX_Z_OFFSET 32 + +#endif /* GLIDE3 */ + +#define GR_VERTEX_SOW_TMU0_OFFSET 36 +#define GR_VERTEX_TOW_TMU0_OFFSET 40 +#define GR_VERTEX_OOW_TMU0_OFFSET 44 +#define GR_VERTEX_SOW_TMU1_OFFSET 48 +#define GR_VERTEX_TOW_TMU1_OFFSET 52 +#define GR_VERTEX_OOW_TMU1_OFFSET 56 + + + + +/*#define MAT_SX 0 */ /* accessed by REGIND !! */ +#define MAT_SY 20 +#define MAT_SZ 40 +#define MAT_TX 48 +#define MAT_TY 52 +#define MAT_TZ 56 + + + + +/* Do viewport map, device scale and perspective projection. + * + * void project_verts( GLfloat *first, + * GLfloat *last, + * const GLfloat *m, + * GLuint stride ) + * + * + * Rearrange fxVertices to look like grVertices. + */ + +ALIGNTEXT16 +GLOBL TAG_GLNAME( fx_3dnow_project_vertices ) +TAG_GLNAME( fx_3dnow_project_vertices ): + + PUSH_L ( EBP ) + + MOV_L ( REGOFF(8, ESP), ECX ) /* first_vert */ + MOV_L ( REGOFF(12, ESP), EDX ) /* last_vert */ + + CMP_L ( ECX, EDX ) + JE ( TAGLLBL(FXPV_end) ) + + FEMMS + + PREFETCH ( REGIND(ECX) ) /* fetch the first vertex */ + + MOV_L ( REGOFF(16, ESP), EBP ) /* matrix */ + MOV_L ( REGOFF(20, ESP), EAX ) /* stride */ + + MOVD ( REGOFF(MAT_TX, EBP), MM6 ) /* | tx */ + PUNPCKLDQ ( REGOFF(MAT_TY, EBP), MM6 ) /* ty | tx */ + +#if !defined(FX_V2) + MOV_L ( CONST(0x49400000), REGOFF(-8, ESP) ) /* snapper */ + MOV_L ( CONST(0x49400000), REGOFF(-4, ESP) ) /* snapper */ +#endif + + MOVQ ( REGOFF(-8, ESP), MM4 ) /* snapper | snapper */ + PFADD ( MM4, MM6 ) /* ty+snapper | tx+snapper */ + + MOVD ( REGIND(EBP), MM5 ) + PUNPCKLDQ ( REGOFF(MAT_SY, EBP), MM5 ) /* vsy | vsx */ + + MOVD ( REGOFF(MAT_SZ, EBP), MM1 ) /* | vsz */ + + +ALIGNTEXT32 +TAGLLBL(FXPV_loop_start): + + PREFETCH ( REGOFF(64, ECX) ) /* fetch the next-ish vertex */ + + + MOVD ( REGOFF(12, ECX), MM0 ) /* | f[3] */ + PFRCP ( MM0, MM0 ) /* oow = 1/f[3] */ + + MOVD ( REGOFF(12, ECX), MM7 ) /* | f[3] */ + PFRCPIT1 ( MM0, MM7 ) + PFRCPIT2 ( MM0, MM7 ) /* oow | oow */ + + PUNPCKLDQ ( MM7, MM7 ) + + +#if (TYPE & SETUP_RGBA) + MOVD ( REGOFF(CLIP_R, ECX ), MM0 ) /* f[RCOORD] = f[CLIP_R]; */ + MOVD ( MM0, REGOFF(GR_VERTEX_R_OFFSET, ECX) ) +#endif + +#if (TYPE & SETUP_TMU1) + MOVQ ( REGOFF(CLIP_S1, ECX), MM0 ) /* f[S1COORD] = f[CLIP_S1] * oow */ + PFMUL ( MM7, MM0 ) /* f[T1COORD] = f[CLIP_T1] * oow */ + MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU1_OFFSET, ECX) ) +#endif + + +#if (TYPE & SETUP_TMU0) + MOVQ ( REGOFF(CLIP_S0, ECX), MM0 ) /* f[S0COORD] = f[CLIP_S0] * oow */ + PFMUL ( MM7, MM0 ) /* f[T0COORD] = f[CLIP_T0] * oow */ + MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU0_OFFSET, ECX) ) +#endif + + + + + +/* DO_SETUP_XYZ */ + + MOVQ ( REGIND(ECX), MM2 ) /* f[1] | f[0] */ + PFMUL ( MM7, MM2 ) /* f[1] * oow | f[0] * oow */ + + MOVD ( REGOFF(8, ECX), MM3 ) /* | f[2] */ + PFMUL ( MM7, MM3 ) /* | f[2] * oow */ + + MOVD ( REGOFF(MAT_TZ, EBP), MM0 ) /* | vtz */ + PFMUL ( MM1, MM3 ) /* | f[2] *= vsz */ + + PFADD ( MM0, MM3 ) /* | f[2] += vtz */ + PFMUL ( MM5, MM2 ) /* f[1] *= vsy | f[0] *= vsx */ + + PFADD ( MM6, MM2 ) /* f[1] += vty | f[0] += vtx */ + +#if !defined(FX_V2) + PFSUB ( MM4, MM2 ) /* f[0,1] -= snapper */ +#endif + + MOVQ ( MM2, REGOFF(GR_VERTEX_X_OFFSET, ECX) ) + MOVD ( MM3, REGOFF(GR_VERTEX_OOZ_OFFSET, ECX) ) + + +/* end of DO_SETUP_XYZ */ + + MOVD ( MM7, REGOFF(GR_VERTEX_OOW_OFFSET, ECX) ) /* f[OOWCOORD] = oow */ + ADD_L ( EAX, ECX ) /* f += stride */ + + CMP_L ( ECX, EDX ) /* stall??? */ + JA ( TAGLLBL(FXPV_loop_start) ) + +TAGLLBL(FXPV_end): + FEMMS + POP_L ( EBP ) + RET + + + + + + + +/* void project_verts( GLfloat *first, + * GLfloat *last, + * const GLfloat *m, + * GLuint stride, + * const GLubyte *mask ) + * + */ + +ALIGNTEXT16 +GLOBL TAG_GLNAME( fx_3dnow_project_clipped_vertices ) +TAG_GLNAME( fx_3dnow_project_clipped_vertices ): + + PUSH_L ( EBP ) + + MOV_L ( REGOFF(8, ESP), ECX ) /* first FXDRIVER(VB)->verts*/ + MOV_L ( REGOFF(12, ESP), EDX ) /* last FXDRIVER(VB)->last_vert */ + + FEMMS + + PUSH_L ( EDI ) + PUSH_L ( ESI ) + + PREFETCH ( REGIND(ECX) ) /* fetch the first vertex */ + + MOV_L ( REGOFF(24, ESP), EBP ) /* mat ctx->Viewport.WindowMap.M */ + MOV_L ( REGOFF(28, ESP), EAX ) /* stride */ + MOV_L ( REGOFF(32, ESP), ESI ) /* VB->ClipMask */ + + MOVD ( REGOFF(MAT_TX, EBP), MM6 ) /* | tx */ + PUNPCKLDQ ( REGOFF(MAT_TY, EBP), MM6 ) /* ty | tx */ + +#if !defined(FX_V2) + MOV_L ( CONST(0x49400000), REGOFF(-8, ESP) ) /* snapper */ + MOV_L ( CONST(0x49400000), REGOFF(-4, ESP) ) /* snapper */ +#endif + + MOVQ ( REGOFF(-8, ESP), MM4 ) /* snapper | snapper */ + PFADD ( MM4, MM6 ) /* ty+snapper | tx+snapper */ + + MOVD ( REGIND(EBP), MM5 ) + PUNPCKLDQ ( REGOFF(MAT_SY, EBP), MM5 ) /* vsy | vsx */ + + MOVD ( REGOFF(MAT_SZ, EBP), MM1 ) /* | vsz */ + + + +ALIGNTEXT32 +TAGLLBL(FXPCV_loop_start): + + PREFETCH ( REGOFF(64, ECX) ) /* fetch the next-ish vertex */ + + CMP_B ( CONST(0), REGIND(ESI) ) + JNE ( TAGLLBL(FXPCV_skip) ) + + MOVD ( REGOFF(12, ECX), MM0) /* | f[3] */ + PFRCP ( MM0, MM0 ) /* oow = 1/f[3] */ + + MOVD ( REGOFF(12, ECX), MM7) /* | f[3] */ + PFRCPIT1 ( MM0, MM7 ) + PFRCPIT2 ( MM0, MM7 ) /* oow | oow */ + + PUNPCKLDQ ( MM7, MM7 ) + + +#if (TYPE & SETUP_RGBA) + MOVD ( REGOFF(CLIP_R, ECX ), MM0 ) /* f[RCOORD] = f[CLIP_R]; */ + MOVD ( MM0, REGOFF(GR_VERTEX_R_OFFSET, ECX) ) +#endif + +#if (TYPE & SETUP_TMU1) + MOVQ ( REGOFF(CLIP_S1, ECX), MM0 ) /* f[S1COORD] = f[CLIP_S1] * oow */ + PFMUL ( MM7, MM0 ) /* f[T1COORD] = f[CLIP_T1] * oow */ + MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU1_OFFSET, ECX) ) +#endif + + +#if (TYPE & SETUP_TMU0) + MOVQ ( REGOFF(CLIP_S0, ECX), MM0 ) /* f[S0COORD] = f[CLIP_S0] * oow */ + PFMUL ( MM7, MM0 ) /* f[T0COORD] = f[CLIP_T0] * oow */ + MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU0_OFFSET, ECX) ) +#endif + + + + +/* DO_SETUP_XYZ */ + + MOVQ ( REGIND(ECX), MM2 ) /* f[1] | f[0] */ + PFMUL ( MM7, MM2 ) /* f[1] * oow | f[0] * oow */ + + MOVD ( REGOFF(8, ECX), MM3 ) /* | f[2] */ + PFMUL ( MM7, MM3 ) /* | f[2] * oow */ + + MOVD ( REGOFF(MAT_TZ, EBP), MM0 ) /* | vtz */ + PFMUL ( MM1, MM3 ) /* | f[2] *= vsz */ + + PFADD ( MM0, MM3 ) /* | f[2] += vtz */ + PFMUL ( MM5, MM2 ) /* f[1] *= vsy | f[0] *= vsx */ + + PFADD ( MM6, MM2 ) /* f[1] += vty | f[0] += vtx */ + +#if !defined(FX_V2) + PFSUB ( MM4, MM2 ) /* f[0,1] -= snapper */ +#endif + + MOVQ ( MM2, REGOFF(GR_VERTEX_X_OFFSET, ECX) ) + MOVD ( MM3, REGOFF(GR_VERTEX_OOZ_OFFSET, ECX) ) + + +/* end of DO_SETUP_XYZ */ + + MOVD ( MM7, REGOFF(GR_VERTEX_OOW_OFFSET, ECX) ) /* f[OOWCOORD] = oow */ + +TAGLLBL(FXPCV_skip): + ADD_L ( EAX, ECX ) /* f += stride */ + + INC_L ( ESI ) /* next ClipMask */ + CMP_L ( ECX, EDX ) + JA ( TAGLLBL(FXPCV_loop_start) ) + + POP_L ( ESI ) + POP_L ( EDI ) + +TAGLLBL(FXPCV_end): + FEMMS + POP_L ( EBP ) + RET + + + +#undef TYPE +#undef TAG +#undef SIZE +#undef _TAGLLBL +#undef TAGLLBL +#undef TAG_GLNAME + diff --git a/xc/extras/Mesa/src/FX/fxapi.c b/xc/extras/Mesa/src/FX/fxapi.c new file mode 100644 index 000000000..ec956958f --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxapi.c @@ -0,0 +1,1428 @@ +/* -*- mode: C; tab-width:8; -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* fxapi.c - 3Dfx VooDoo/Mesa interface */ + + +/******************************************************************** + * + * Function names: + * fxMesa.... (The driver API) + * fxDD.... (Mesa device driver functions) + * fxTM.... (Texture manager functions) + * fxSetup.... (Voodoo units setup functions) + * fx.... (Internal driver functions) + * + * Data type names: + * fxMesa.... (Public driver data types) + * tfx.... (Private driver data types) + * + ******************************************************************** + * + * V0.30 - David Bucciarelli (davibu@tin.it) Humanware s.r.l. + * - introduced a new MESA_GLX_FX related behavior + * - the Glide fog table was built in a wrong way (using + * gu* Glide function). Added the code for building the + * table following the OpenGL specs. Thanks to Steve Baker + * for highlighting the problem. + * - fixed few problems in my and Keith's fxDDClear code + * - merged my code with the Keith's one + * - used the new BlendFunc Mesa device driver function + * - used the new AlphaFunc Mesa device driver function + * - used the new Enable Mesa device driver function + * - fixed a bug related to fog in the Mesa core. Fog + * were applied two times: at vertex level and at fragment + * level (thanks to Steve Baker for reporting the problem) + * - glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE) now works + * (thanks to Jiri Pop for reporting the problem) + * - the driver works fine with OpenGL Unreal + * - fixed a bug in the Mesa core clipping code (related + * to the q texture coordinate) + * - introduced the support for the q texture coordinate + * + * Keith Whitwell (keithw@cableinet.co.uk) + * - optimized the driver and written all the new code + * required by the new Mesa-3.1 device driver API + * and by the new Mesa-3.1 core changes + * - written the cva support and many other stuff + * + * Brian Paul (brian_paul@avid.com) Avid Technology + * - fixed display list share bug for MESA_GLX_FX = window/fullscreen + * - fixed glClear/gl...Mask related problem + * + * Bert Schoenwaelder (bert@prinz-atm.CS.Uni-Magdeburg.De) + * - the driver is now able to sleep when waiting for the completation + * of multiple swapbuffer operations instead of wasting + * CPU time (NOTE: you must uncomment the lines in the + * fxMesaSwapBuffers function in order to enable this option) + * + * Eero Pajarre (epajarre@koti.tpo.fi) + * - enabled the macro FLOAT_COLOR_TO_UBYTE_COLOR under + * windows + * - written an asm x86 optimized float->integer conversions + * for windows + * + * Theodore Jump (tjump@cais.com) + * - fixed a small problem in the __wglMonitor function of the + * wgl emulator + * - written the in-window-rendering hack support for windows + * and Vooodoo1/2 cards + * + * V0.29 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - included in Mesa-3.0 + * - now glGetString(GL_RENDERER) returns more information + * about the hardware configuration: "Mesa Glide <version> + * <Voodoo_Graphics|Voodoo_Rush|UNKNOWN> <num> CARD/<num> FB/ + * <num> TM/<num> TMU/<NOSLI|SLI>" + * where: <num> CARD is the card used for the current context, + * <num> FB is the number of MB for the framebuffer, + * <num> TM is the number of MB for the texture memory, + * <num> TMU is the number of TMU. You can try to run + * Mesa/demos/glinfo in order to have an example of the + * output + * - fixed a problem of the WGL emulator with the + * OpenGL Optimizer 1.1 (thanks to Erwin Coumans for + * the bug report) + * - fixed some bug in the fxwgl.c code (thanks to + * Peter Pettersson for a patch and a bug report) + * + * Theodore Jump (tjump@cais.com) + * - written the SST_DUALHEAD support in the WGL emulator + * + * Daryll Strauss (daryll@harlot.rb.ca.us) + * - fixed the Voodoo Rush support for the in window rendering + * + * V0.28 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - the only supported multitexture functions are GL_MODULATE + * for texture set 0 and GL_MODULATE for texture set 1. In + * all other cases, the driver falls back to pure software + * rendering + * - written the support for the new GL_EXT_multitexture + * - written the DD_MAX_TEXTURE_COORD_SETS support in the + * fxDDGetParameteri() function + * - the driver falls back to pure software rendering when + * texture mapping function is GL_BLEND + * + * V0.27 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - inluded in the Mesa-3.0beta5 + * - written a smal extension (GL_FXMESA_global_texture_lod_bias) in + * order to expose the LOD bias related Glide function + * - fixed a bug fxDDWriteMonoRGBAPixels() + * - the driver is now able to fallback to software rendering in + * any case not directly supported by the hardware + * - written the support for enabling/disabling dithering + * - the in-window-rendering hack now works with any X11 screen + * depth + * - fixed a problem related to color/depth/alpha buffer clears + * - fixed a problem when clearing buffer for a context with the + * alpha buffer + * - fixed a problem in the fxTMReloadSubMipMapLevel() function, + * I have forget a "break;" (thanks to Joe Waters for the bug report) + * - fixed a problem in the color format for the in window + * rendering hack + * - written the fxDDReadRGBAPixels function + * - written the fxDDDepthTestPixelsGeneric function + * - written the fxDDDepthTestSpanGeneric function + * - written the fxDDWriteMonoRGBAPixels function + * - written the fxDDWriteRGBAPixels function + * - removed the multitexture emulation code for Voodoo board + * with only one TMU + * + * Chris Prince <cprince@cs.washington.edu> + * - fixed a new bug in the wglUseFontBitmaps code + * + * Ralf Knoesel (rknoesel@Stormfront.com) + * - fixed a bug in the wglUseFontBitmaps code + * + * Rune Hasvold (runeh@ifi.uio.no) + * - fixed a problem related to the aux usage in the fxBestResolution + * function + * - fixed the order of pixel formats in the WGL emulator + * + * Fredrik Hubinette (hubbe@hubbe.net) + * - the driver shutdown the Glide for most common signals + * + * V0.26 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - included in the Mesa-3.0beta4 + * - fixed a problem related to a my optimization for the Rune's + * pixel-span optimization + * - fixed a problem related to fxDDSetNearFar() and ctx->ProjectionMatrixType + * (thanks to Ben "Ctrl-Alt-Delete" and the Raul Alonso's ssystem) + * - fixed a small bug in the Rune's pixel-span optimization + * - fixed a problem with GL_CCW (thanks to Curt Olson for and example + * of the problem) + * - grVertex setup code is now ready for the internal thread support + * - fixed a no used optimization with clipped vertices in + * grVertex setup code + * - fixed a problem in the GL_LIGHT_MODEL_TWO_SIDE support (thanks + * to Patrick H. Madden for a complete example of the bug) + * + * Rune Hasvold (runeh@ifi.uio.no) + * - highly optimized the driver functions for writing pixel + * span (2-3 times faster !) + * + * Axel W. Volley (volley@acm.org) Krauss-Maffei Wehrtechnik + * - written the fxDDReadDepthSpanFloat() and fxDDReadDepthSpanInt() + * functions + * + * V0.25 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - fixed a problem with Voodoo boards with only one TMU + * - fixed a bug in the fxMesaCreateContext() + * - now the GL_FRONT_AND_BACK works fine also with + * the alpha buffer and/or antialiasing + * - written the support for GL_FRONT_AND_BACK drawing but + * it doesn't works with the alpha buffer and/or antialiasing + * - fixed some bug in the Mesa core for glCopyTexSubImage + * and glCopyTexImage functions (thanks to Mike Connell + * for an example of the problem) + * - make some small optimizations in the Mesa core in order + * to save same driver call and state change for not very + * well written applications + * - introduced the NEW_DRVSTATE and make other optimizations + * for minimizing state changes + * - made a lot of optimizations in order to minimize state + * changes + * - it isn't more possible to create a context with the + * depth buffer and the stancil buffer (it isn't yet supported) + * - now the partial support for the Multitexture extension + * works with Quake2 for windows + * - vertex snap is not longer used for the Voodoo2 (FX_V2 + * must be defined) + * - done a lot of cleanup in the fxsetup.c file + * - now the partial support for the Multitexture extension + * works with GLQuake for windows + * + * Dieter Nuetzel (nuetzel@kogs.informatik.uni-hamburg.de) University of Hamburg + * - fixed a problem in the asm code for Linux of the fxvsetup.c file + * highlighted by the binutils-2.8.1.0.29. 'fildw' asm instruction + * changed in 'fild' + * + * Kevin Hester (kevinh@glassworks.net) + * - written the wglUseFontBitmaps() function in the WGL emulator + * + * V0.24 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - now the drive always uses per fragment fog + * - written a small optimization in the points drawing function + * - written the support for trilinear filtering with 2 TMUs + * - written the first partial support for the Multitexture extension. + * This task is quite hard because the color combine units work after + * the two texture combine units and not before as required by the + * Multitexture extension + * - written a workaround in fxBestResolution() in order to solve a + * problem with bzflag (it asks for 1x1 window !) + * - changed the fxBestResolution() behavior. It now returns the larger + * screen resolution supported by the hardware (instead of 640x480) + * when it is unable to find an appropriate resolution that is large + * enough for the requested size + * - the driver is now able to use also the texture memory attached to + * second TMU + * - the texture memory manager is now able to work with two TMUs and + * store texture maps in the memory attached to TMU0, TMU1 or to split + * the mimpmap levels across TMUs in order to support trilinear filtering + * - I have bought a Voodoo2 board ! + * - the amount of frambuffer ram is now doubled when an SLI configuration + * is detected + * - solved a problem related to the fxDDTexParam() and fxTexInvalidate() + * functions (thanks to Rune Hasvold for highlighting the problem) + * - done some cleanup in the fxvsetup.c file, written + * the FXVSETUP_FUNC macro + * - done a lot of cleanup in data types and field names + * + * Rune Hasvold (runeh@ifi.uio.no) + * - written the support for a right management of the auxiliary buffer. + * You can now use an 800x600 screen without the depth and alpha + * buffer + * - written the support for a new pixel format (without the depth + * and alpha buffer) in the WGL emulator + * - fixed a bug in the window version of the GLUT (it was ever asking + * for depth buffer) + * + * V0.23 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - included in the Mesa-3.0beta2 release + * - written the support for the OpenGL 1.2 GL_TEXTURE_BASE_LEVEL + * and GL_TEXTURE_MAX_LEVEL + * - rewritten several functions for a more clean support of texture + * mapping and in order to solve some bug + * - the accumulation buffer works (it is bit slow beacuase it requires + * to read/write from/to the Voodoo frame buffer but it works) + * - fixed a bug in the fxDDReadRGBASpan driver function (the R and + * B channels were read in the wrong order). Thanks to Jason Heym + * for highlighting the problem + * - written the support for multiple contexts on multiple boards. + * you can now use the Mesa/Voodoo with multiple Voodoo Graphics + * boards (for example with multiple screens or an HMD) + * - the fxBestResolution() now check all available resolutions + * and it is able to check the amount of framebuffer memory + * before return a resolution + * - modified the GLX/X11 driver in order to support all the + * resolution available + * - changed all function names. They should be now a bit more + * readable + * - written the Glide grVertex setup code for two TMU or + * for Multitexture support with emulationa dn one TMU + * - written the support for the new Mesa driver + * function GetParametri + * - small optimization/clean up in the texbind() function + * - fixed a FPU precision problem for glOrtho and texture + * mapping (thanks to Antti Juhani Huovilainen for an example + * of the problem) + * - written some small SGI OpenGL emulation code for the wgl, + * the OpenGL Optimizer and Cosmo3D work fine under windows ! + * - moved the point/line/triangle/quad support in the fxmesa7.c + * - fixed a bug in the clear_color_depth() (thanks to Henk Kok + * for an example of the problem) + * - written a small workaround for Linux GLQuake, it asks + * for the alpha buffer and the depth buffer at the some time + * (but it never uses the alpha buffer) + * - checked the antialiasing points, lines and polygons support. + * It works fine + * - written the support for standard OpenGL antialiasing using + * blending. Lines support works fine (tested with BZflag) + * while I have still to check the polygons and points support + * - written the support for the alpha buffer. The driver is now + * able to use the Voodoo auxiliary buffer as an alpha buffer + * instead of a depth buffer. Also all the OpenGL blending + * modes are now supported. But you can't request a context + * with an alpha buffer AND a depth buffer at the some time + * (this is an hardware limitation) + * - written the support for switching between the fullscreen + * rendering and the in-window-rendering hack on the fly + * + * Rune Hasvold (runeh@ifi.uio.no) + * - fixed a bug in the texparam() function + * + * Brian Paul (brianp@elastic.avid.com) Avid Technology + * - sources accomodated for the new Mesa 3.0beta1 + * + * V0.22 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - included with some v0.23 bug fix in the final release + * of the Mesa-2.6 + * - written the support for the MESA_WGL_FX env. var. but + * not tested because I have only Voodoo Graphics boards + * - fixed a bug in the backface culling code + * (thanks to David Farrell for an example of the problem) + * - fixed the "Quake2 elevator" bug + * - GL_POLYGONS with 3/4 vertices are now drawn as + * GL_TRIANLGES/GL_QUADS (a small optimization for GLQuake) + * - fixed a bug in fxmesa6.h for GL_LINE_LOOP + * - fixed a NearFarStack bug in the Mesa when applications + * directly call glLoadMatrix to load a projection matrix + * - done some cleanup in the fxmesa2.c file + * - the driver no longer translates the texture maps + * when the Mesa internal format and the Voodoo + * format are the some (usefull for 1 byte texture maps + * where the driver can directly use the Mesa texture + * map). Also the amount of used memory is halfed + * - fixed a bug for GL_DECAL and GL_RGBA + * - fixed a bug in the clear_color_depth() + * - tested the v0.22 with the Mesa-2.6beta2. Impressive + * performances improvement thanks to the new Josh's + * asm code (+10fps in the isosurf demo, +5fps in GLQuake + * TIMEREFRESH) + * - written a optimized version of the RenderVB Mesa driver + * function. The Voodoo driver is now able to upload polygons + * in the most common cases at a very good speed. Good + * performance improvement for large set of small polygons + * - optimized the asm code for setting up the color information + * in the Glide grVertex structure + * - fixed a bug in the fxmesa2.c asm code (the ClipMask[] + * wasn't working) + * + * Josh Vanderhoof (joshv@planet.net) + * - removed the flush() function because it isn't required + * - limited the maximum number of swapbuffers in the Voodoo + * commands FIFO (controlled by the env. var. MESA_FX_SWAP_PENDING) + * + * Holger Kleemiss (holger.kleemiss@metronet.de) STN Atlas Elektronik GmbH + * - applied some patch for the Voodoo Rush + * + * V0.21 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - the driver is now able to take advantage of the ClipMask[], + * ClipOrMask and ClipAndMask information also under Windows + * - introduced a new function in the Mesa driver interface + * ClearColorAndDepth(). Now the glClear() function is + * 2 times faster (!) when you have to clear the color buffer + * and the depth buffer at some time + * - written the first version of the fxRenderVB() driver + * function + * - optimized the glTexImage() path + * - removed the fxMesaTextureUsePalette() support + * - fixed a bug in the points support (thanks to David Farrell + * for an example of the problem) + * - written the optimized path for glSubTexImage(), + * introduced a new function in the Mesa driver interface + * TexSubImage(...) + * - fixed a bug for glColorMask and glDepthMask + * - the wbuffer is not more used. The Voodoo driver uses + * a standard 16bit zbuffer in all cases. It is more consistent + * and now GLQuake and GLQuake2test work also with a GL_ZTRICK 0 + * - the driver is now able to take advantage of the ClipMask[], + * ClipOrMask and ClipAndMask information (under Linux); + * - rewritten the setup_fx_units() function, now the texture + * mapping support is compliant to the OpenGL specs (GL_BLEND + * support is still missing). The LinuxGLQuake console correctly + * fade in/out and transparent water of GLQuake2test works fine + * - written the support for the env. var. FX_GLIDE_SWAPINTERVAL + * - found a bug in the Mesa core. There is a roundup problem for + * color values out of the [0.0,1.0] range + * + * Wonko <matt@khm.de> + * - fixed a Voodoo Rush related problem in the fxwgl.c + * + * Daryll Strauss <daryll@harlot.rb.ca.us> + * - written the scissor test support + * + * V0.20 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - written the closetmmanger() function in order to free all the memory + * allocated by the Texture Memory Manager (it will be useful + * when the support for multiple contexts/boards will be ready) + * - now the Voodoo driver runs without printing any information, + * define the env. var. MESA_FX_INFO if you want to read some + * information about the hardware and some statistic + * - written a small workaround for the "GLQuake multiplayer white box bug" + * in the setup_fx_units() funxtions. I'm already rewriting + * this function because it is the source of nearly all the current + * Voodoo driver problems + * - fixed the GLQuake texture misalignment problem (the texture + * coordinates must be scaled between 0.0 and 256.0 and not + * between 0.0 and 255.0) + * - written the support for the GL_EXT_shared_texture_palette + * - some small change for supporting the automatic building of the + * OpenGL32.dll under the Windows platform + * - the redefinition of a mipmap level is now a LOT faster. This path + * is used by GLQuake for dynamic lighting with some call to glTexSubImage2D() + * - the texture memory is now managed a set of 2MB blocks so + * texture maps can't be allocated on a 2MB boundary. The new Pure3D + * needs this kind of support (and probably any other Voodoo Graphics + * board with more than 2MB of texture memory) + * + * Brian Paul (brianp@elastic.avid.com) Avid Technology + * - added write_monocolor_span(), fixed bug in write_color_span() + * - added test for stenciling in choosepoint/line/triangle functions + * + * Joe Waters (falc@attila.aegistech.com) Aegis + * - written the support for the env. var. SST_SCREENREFRESH + * + * V0.19 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - written the 3Dfx Global Palette extension for GLQuake + * - written the support for the GL_EXT_paletted_texture (it works only with GL_RGBA + * palettes and the alpha value is ignored ... this is a limitation of the + * the current Glide version and Voodoo hardware) + * - fixed the amount of memory allocated for 8bit textures + * - merged the under construction v0.19 driver with the Mesa 2.5 + * - finally written the support for deleting textures + * - introduced a new powerful texture memory manager: the texture memory + * is used as a cache of the set of all defined texture maps. You can + * now define several MB of texture maps also with a 2MB of texture memory + * (the texture memory manager will do automatically all the swap out/swap in + * work). The new texture memory manager has also + * solved a lot of other bugs/no specs compliance/problems + * related to the texture memory usage. The texture + * manager code is inside the new fxmesa3.c file + * - broken the fxmesa.c file in two files (fxmesa1.c and fxmesa2.c) + * and done some code cleanup + * - now is possible to redefine texture mipmap levels already defined + * - fixed a problem with the amount of texture memory allocated for textures + * with not all mipmap levels defined + * - fixed a small problem with single buffer rendering + * + * Brian Paul (brianp@elastic.avid.com) Avid Technology + * - read/write_color_span() now use front/back buffer correctly + * - create GLvisual with 5,6,5 bits per pixel, not 8,8,8 + * - removed a few ^M characters from fxmesa2.c file + * + * V0.18 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - the Mesa-2.4beta3 is finally using the driver quads support (the + * previous Mesa versions have never taken any advantage from the quads support !) + * - tested with the Glide 2.4 for Win + * - ported all asm code to Linux + * - ported the v0.18 to Linux (without asm code) + * - back to Linux !!! + * - optimized the SETUP macro (no more vertex snap for points and lines) + * - optimized the SETUP macro (added one argument) + * - the Mesa/Voodoo is now 20/30% for points, lines and small triangles ! + * - performance improvement setting VBSIZE to 72 + * - the GrVertex texture code is now written in asm + * - the GrVertex zbuffer code is now written in asm + * - the GrVertex wbuffer code is now written in asm + * - the GrVertex gouraud code is now written in asm + * - the GrVertex snap code is now written in asm + * - changed the 8bit compressed texture maps in 8bit palette texture maps + * support (it has the some advantage of compressed texture maps without the + * problem of a fixed NCC table for all mipmap levels) + * - written the support for 8bit compressed texture maps (but texture maps with + * more than one mipmap level aren't working fine) + * - finnaly everthing is working fine in MesaQuake ! + * - fixed a bug in the computation of texture mapping coordinates (I have found + * the bug thanks to MesaQuake !) + * - written the GL_REPLACE support (mainly for MesaQuake) + * - written the support for textures with not all mipmap levels defined + * - rewritten all the Texture memory stuff + * - written the MesaQuake support (define MESAQUAKE) + * - working with a ZBuffer if glOrtho or not int the default glDepthRange, + * otherwise working with the WBuffer + * written the glDepthRange support + * + * Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l. + * - written the fxCloseHardware() and the fxQuaryHardware() (mainly + * for the VoodooWGL emulator) + * + * Brian Paul (brianp@elastic.avid.com) Avid Technology + * - implemented read/write_color_span() so glRead/DrawPixels() works + * - now needs Glide 2.3 or later. Removed GLIDE_FULL_SCREEN and call to grSstOpen() + * + * V0.17 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - optimized the bitmap support (66% faster) + * - tested with the Mesa 2.3beta2 + * + * Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l. + * - solved a problem with the drawbitmap() and the Voodoo Rush + * (GR_ORIGIN_LOWER_LEFT did not work with the Stingray) + * + * Brian Paul (brianp@elastic.avid.com) Avid Technology + * - linux stuff + * - general code clean-up + * - added attribList parameter to fxMesaCreateContext() + * - single buffering works now + * - VB colors are now GLubytes, removed ColorShift stuff + * + * Paul Metzger + * - linux stuff + * + * V0.16 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - written the quadfunc support (no performance improvement) + * - written the support for the new Mesa 2.3beta1 driver interface (Wow ! It is faaaster) + * - rewritten the glBitmap support for the Glide 2.3 (~35% slower !) + * - written the glBitmap support for the most common case (fonts) + * + * Jack Palevich + * - Glide 2.3 porting + * + * Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l. + * - extended the fxMesaCreateContext() and fxMesaCreateBestContext() + * functions in order to support also the Voodoo Rush + * - tested with the Hercules Stingray 128/3D (The rendering in a window works !) + * + * V0.15 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - written the GL_LUMINANCE_ALPHA support + * - written the GL_ALPHA support + * - written the GL_LUMINANCE support + * - now SETUP correctly set color for mono color sequences + * - written the 9x1,10x1,...,1x9,1x10,... texture map ratio support + * - written the no square texture map support + * - the fog table is no more rebuilt inside setup_fx_units() each time + * + * Henri Fousse (arnaud@pobox.oleane.com) Thomson Training & Simulation + * - written (not yet finished: no texture mapping) support for glOrtho + * - some change to setup functions + * - the fog support is now fully compatible with the standard OpenGL + * - rewritten several parts of the driver in order to take + * advantage of meshes (40% faster !!!) + * + * V0.14 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - now glAlphaFunc() works + * - now glDepthMask() works + * - solved a mipmap problem when using more than one texture + * - moved ti, texid and wscale inside the fxMesaContext (now we can + * easy support more ctx and more boards) + * - the management of the fxMesaContext was completly broken ! + * - solved several problems about Alpha and texture Alpha + * - 4 (RGBA) texture channels supported + * - setting the default color to white + * + * Henri Fousse (arnaud@pobox.oleane.com) Thomson Training & Simulation + * - small change to fxMesaCreateContext() and fxMesaMakeCurrent() + * - written the fog support + * - setting the default clear color to black + * - written cleangraphics() for the onexit() function + * - written fxMesaCreateBestContext() + * + * V0.13 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - now glBlendFunc() works for all glBlendFunc without DST_ALPHA + * (because the alpha buffer is not yet implemented) + * - now fxMesaCreateContext() accept resolution and refresh rate + * - fixed a bug for texture mapping: the w (alias z) must be set + * also without depth buffer + * - fixed a bug for texture image with width!=256 + * - written texparam() + * - written all point, line and triangle functions for all possible supported + * contexts and the driver is slight faster with points, lines and small triangles + * - fixed a small bug in fx/fxmesa.h (glOrtho) + * + * V0.12 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - glDepthFunc supported + * - introduced a trick to discover the far plane distance + * (see fxMesaSetFar and fx/fxmesa.h) + * - now the wbuffer works with homogeneous coordinate (and it + * doesn't work with a glOrtho projection :) + * - solved several problems with homogeneous coordinate and texture mapping + * - fixed a bug in all line functions + * - fixed a clear framebuffer bug + * - solved a display list/teximg problem (but use + * glBindTexture: it is several times faster) + * + * V0.11 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - introduced texture mapping support (not yet finished !) + * - tested with Mesa2.2b6 + * - the driver is faster + * - written glFlush/glFinish + * - the driver print a lot of info about the Glide lib + * + * v0.1 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l. + * - Initial revision + * + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) +#include "fxdrv.h" + +static fxMesaContext fxMesaCurrentCtx=NULL; + +/* + * Status of 3Dfx hardware initialization + */ + +static int glbGlideInitialized=0; +static int glb3DfxPresent=0; +static int glbTotNumCtx=0; + +GrHwConfiguration glbHWConfig; +int glbCurrentBoard=0; + + +#if defined(__WIN32__) +static int cleangraphics(void) +{ + glbTotNumCtx=1; + fxMesaDestroyContext(fxMesaCurrentCtx); + + return 0; +} +#elif defined(__linux__) +static void cleangraphics(void) +{ + glbTotNumCtx=1; + fxMesaDestroyContext(fxMesaCurrentCtx); +} + +static void cleangraphics_handler(int s) +{ + fprintf(stderr,"fxmesa: Received a not handled signal %d\n",s); + + cleangraphics(); +/* abort(); */ + exit(1); +} +#endif + + +/* + * Select the Voodoo board to use when creating + * a new context. + */ +GLboolean GLAPIENTRY fxMesaSelectCurrentBoard(int n) +{ + fxQueryHardware(); + + if((n<0) || (n>=glbHWConfig.num_sst)) + return GL_FALSE; + + glbCurrentBoard=n; + + return GL_TRUE; +} + + +fxMesaContext GLAPIENTRY fxMesaGetCurrentContext(void) +{ + return fxMesaCurrentCtx; +} + + +void GLAPIENTRY fxMesaSetNearFar(GLfloat n, GLfloat f) +{ + if(fxMesaCurrentCtx) + fxDDSetNearFar(fxMesaCurrentCtx->glCtx,n,f); +} + + +/* + * The 3Dfx Global Palette extension for GLQuake. + * More a trick than a real extesion, use the shared global + * palette extension. + */ +extern void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *pal); /* silence warning */ +void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *pal) +{ + fxMesaContext fxMesa =fxMesaCurrentCtx; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + int i; + + fprintf(stderr,"fxmesa: gl3DfxSetPaletteEXT()\n"); + + for(i=0;i<256;i++) + fprintf(stderr,"%x\n",pal[i]); + } + + if(fxMesa) { + fxMesa->haveGlobalPaletteTexture=1; + + FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,(GuTexPalette *)pal); + if (fxMesa->haveTwoTMUs) + FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,(GuTexPalette *)pal); + } +} + + +static GrScreenResolution_t fxBestResolution(int width, int height, int aux) +{ + static int resolutions[][5]={ + { 320, 200, GR_RESOLUTION_320x200, 2, 2 }, + { 320, 240, GR_RESOLUTION_320x240, 2, 2 }, + { 512, 384, GR_RESOLUTION_512x384, 2, 2 }, + { 640, 400, GR_RESOLUTION_640x400, 2, 2 }, + { 640, 480, GR_RESOLUTION_640x480, 2, 2 }, + { 800, 600, GR_RESOLUTION_800x600, 4, 2 }, + { 960, 720, GR_RESOLUTION_960x720, 6, 4 } +#ifdef GR_RESOLUTION_1024x768 + ,{ 1024, 768, GR_RESOLUTION_1024x768, 8, 4 } +#endif +#ifdef GR_RESOLUTION_1280x1024 + ,{ 1280, 1024, GR_RESOLUTION_1280x1024, 8, 8 } +#endif +#ifdef GR_RESOLUTION_1600x1200 + ,{ 1600, 1200, GR_RESOLUTION_1600x1200, 16, 8 } +#endif + }; + int NUM_RESOLUTIONS = sizeof(resolutions) / (sizeof(int)*5); + int i,fbmem; + GrScreenResolution_t lastvalidres=resolutions[4][2]; + + fxQueryHardware(); + + if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) { + fbmem=glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam; + + if(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect) + fbmem*=2; + } else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96) + fbmem=glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam; + else + fbmem=2; + + /* A work around for BZFlag */ + + if((width==1) && (height==1)) { + width=640; + height=480; + } + + for(i=0;i<NUM_RESOLUTIONS;i++) + if(resolutions[i][4-aux]<=fbmem) { + if((width<=resolutions[i][0]) && (height<=resolutions[i][1])) + return resolutions[i][2]; + + lastvalidres=resolutions[i][2]; + } + + return lastvalidres; +} + + +fxMesaContext GLAPIENTRY fxMesaCreateBestContext(GLuint win,GLint width, GLint height, + const GLint attribList[]) +{ + GrScreenRefresh_t refresh; + int i; + int res,aux; + refresh=GR_REFRESH_75Hz; + + if(getenv("SST_SCREENREFRESH")) { + if(!strcmp(getenv("SST_SCREENREFRESH"),"60")) + refresh=GR_REFRESH_60Hz; + if(!strcmp(getenv("SST_SCREENREFRESH"),"70")) + refresh=GR_REFRESH_70Hz; + if(!strcmp(getenv("SST_SCREENREFRESH"),"72")) + refresh=GR_REFRESH_72Hz; + if(!strcmp(getenv("SST_SCREENREFRESH"),"75")) + refresh=GR_REFRESH_75Hz; + if(!strcmp(getenv("SST_SCREENREFRESH"),"80")) + refresh=GR_REFRESH_80Hz; + if(!strcmp(getenv("SST_SCREENREFRESH"),"85")) + refresh=GR_REFRESH_85Hz; + if(!strcmp(getenv("SST_SCREENREFRESH"),"90")) + refresh=GR_REFRESH_90Hz; + if(!strcmp(getenv("SST_SCREENREFRESH"),"100")) + refresh=GR_REFRESH_100Hz; + if(!strcmp(getenv("SST_SCREENREFRESH"),"120")) + refresh=GR_REFRESH_120Hz; + } + + aux=0; + for(i=0;attribList[i]!=FXMESA_NONE;i++) + if((attribList[i]==FXMESA_ALPHA_SIZE) || + (attribList[i]==FXMESA_DEPTH_SIZE)) { + if(attribList[++i]>0) { + aux=1; + break; + } + } + + res=fxBestResolution(width,height,aux); + + return fxMesaCreateContext(win,res,refresh,attribList); +} + + +#if 0 +void fxsignals() +{ + signal(SIGINT,SIG_IGN); + signal(SIGHUP,SIG_IGN); + signal(SIGPIPE,SIG_IGN); + signal(SIGFPE,SIG_IGN); + signal(SIGBUS,SIG_IGN); + signal(SIGILL,SIG_IGN); + signal(SIGSEGV,SIG_IGN); + signal(SIGTERM,SIG_IGN); +} +#endif + +/* + * Create a new FX/Mesa context and return a handle to it. + */ +fxMesaContext GLAPIENTRY fxMesaCreateContext(GLuint win, + GrScreenResolution_t res, + GrScreenRefresh_t ref, + const GLint attribList[]) +{ + fxMesaContext fxMesa = NULL; + int i,type; + int aux; + GLboolean doubleBuffer=GL_FALSE; + GLboolean alphaBuffer=GL_FALSE; + GLboolean verbose=GL_FALSE; + GLint depthSize=0; + GLint stencilSize=0; + GLint accumSize=0; + GLcontext *shareCtx = NULL; + GLcontext *ctx = 0; + /*FX_GrContext_t glideContext = 0;*/ + char *errorstr; + GLboolean useBGR; + char *system = NULL; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxMesaCreateContext() Start\n"); + } + + if(getenv("MESA_FX_INFO")) + verbose=GL_TRUE; + + aux=0; + i=0; + while(attribList[i]!=FXMESA_NONE) { + switch (attribList[i]) { + case FXMESA_DOUBLEBUFFER: + doubleBuffer=GL_TRUE; + break; + case FXMESA_ALPHA_SIZE: + i++; + alphaBuffer=attribList[i]>0; + if(alphaBuffer) + aux=1; + break; + case FXMESA_DEPTH_SIZE: + i++; + depthSize=attribList[i]; + if(depthSize) { + aux=1; + depthSize = 16; + } + break; + case FXMESA_STENCIL_SIZE: + i++; + stencilSize=attribList[i]; + break; + case FXMESA_ACCUM_SIZE: + i++; + accumSize=attribList[i]; + break; + /* XXX ugly hack here for sharing display lists */ +#define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with xmesa1.c! */ + case FXMESA_SHARE_CONTEXT: + i++; + { + const void *vPtr = &attribList[i]; + GLcontext **ctx = (GLcontext **) vPtr; + shareCtx = *ctx; + } + break; + default: + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxMesaCreateContext() End (defualt)\n"); + } + return NULL; + } + i++; + } + + /* A workaround for Linux GLQuake */ + if(depthSize && alphaBuffer) + alphaBuffer=0; + + if ((type=fxQueryHardware()) < 0) { + fprintf(stderr,"fx Driver: ERROR no Voodoo1/2 Graphics or Voodoo Rush !\n"); + return NULL; + } + + if(type==GR_SSTTYPE_VOODOO) + win=0; + + grSstSelect(glbCurrentBoard); + + fxMesa=(fxMesaContext)calloc(1,sizeof(struct tfxMesaContext)); + if(!fxMesa) { + errorstr = "malloc"; + goto errorhandler; + } + + if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) + fxMesa->haveTwoTMUs=(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx > 1); + else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96) + fxMesa->haveTwoTMUs=(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx > 1); + else + fxMesa->haveTwoTMUs=GL_FALSE; + + fxMesa->haveDoubleBuffer=doubleBuffer; + fxMesa->haveAlphaBuffer=alphaBuffer; + fxMesa->haveGlobalPaletteTexture=GL_FALSE; + fxMesa->haveZBuffer=depthSize ? 16 : 0; + fxMesa->verbose=verbose; + fxMesa->board=glbCurrentBoard; + + + fxMesa->glideContext = FX_grSstWinOpen((FxU32)win,res,ref, +#if FXMESA_USE_ARGB + GR_COLORFORMAT_ARGB, +#else + GR_COLORFORMAT_ABGR, +#endif + GR_ORIGIN_LOWER_LEFT, + 2,aux); + if (!fxMesa->glideContext){ + errorstr = "grSstWinOpen"; + goto errorhandler; + } + + /* + * Pixel tables are use during pixel read-back + * Either initialize them for RGB or BGR order. + */ +#if FXMESA_USE_ARGB + useBGR = GL_FALSE; /* Force RGB pixel order */ + system = "FXMESA_USE_ARGB"; +#else + if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_VOODOO) { + /* jk991130 - Voodoo 3s don't use BGR. Query the # of TMUs + * as Voodoo3s have 2 TMUs on board, Banshee has only 1 + * bk000413 - another suggestion from Joseph Kain is using + * VendorID 0x121a for all 3dfx boards + * DeviceID VG 1/V2 2/VB 3/V3 5 + * For now we cehck for known BGR devices, and presume + * everything else to be a V3/RGB. + */ + GrVoodooConfig_t *voodoo; + voodoo = &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig; + + if (voodoo->nTexelfx == 1) { + /* Voodoo1 or Banshee */ + useBGR = GL_TRUE; + system = "Voodoo1"; + } + else if (voodoo->nTexelfx == 2 && + voodoo->fbiRev == 260 && + voodoo->tmuConfig[0].tmuRev == 4 && + (voodoo->tmuConfig[0].tmuRam == 2 || + voodoo->tmuConfig[0].tmuRam == 4)) { + /* Voodoo 2 */ + useBGR = GL_TRUE; + system = "Voodoo2"; + } + else if (voodoo->nTexelfx == 2 && + voodoo->fbiRev == 2 && + voodoo->tmuConfig[0].tmuRev == 1 && + voodoo->tmuConfig[0].tmuRam == 4) { + /* Quantum3D Obsidian 50/100 */ + useBGR = GL_TRUE; + system = "Quantum3D Obsidian"; + } + else + /* Brian + * (voodoo->nTexelfx == 2 && + * voodoo->fbiRev == 0 && + * voodoo->tmuConfig[0].tmuRev == 148441048 && + * voodoo->tmuConfig[0].tmuRam == 3) + * Bernd + * (voodoo->nTexelfx == 2 && + * voodoo->fbiRev == 69634 && + * voodoo->tmuConfig[0].tmuRev == 69634 && + * voodoo->tmuConfig[0].tmuRam == 2 ) + */ + { + /* Presumed Voodoo3 */ + useBGR = GL_FALSE; + system = "Voodoo3"; + } + if (getenv("MESA_FX_INFO")) { + printf("Voodoo: Texelfx: %d / FBI Rev.: %d / TMU Rev.: %d / TMU RAM: %d\n", + voodoo->nTexelfx, + voodoo->fbiRev, + voodoo->tmuConfig[0].tmuRev, + voodoo->tmuConfig[0].tmuRam ); + } + } + else { + useBGR = GL_FALSE; /* use RGB pixel order otherwise */ + system = "non-voodoo"; + } +#endif /*FXMESA_USE_ARGB*/ + + if (getenv("MESA_FX_INFO")) + printf("Voodoo pixel order: %s (%s)\n", useBGR ? "BGR" : "RGB", system); + + fxInitPixelTables(fxMesa, useBGR); + + fxMesa->width=FX_grSstScreenWidth(); + fxMesa->height=FX_grSstScreenHeight(); + + fxMesa->clipMinX = 0; + fxMesa->clipMaxX = fxMesa->width; + fxMesa->clipMinY = 0; + fxMesa->clipMaxY = fxMesa->height; + + fxMesa->screen_width = fxMesa->width; + fxMesa->screen_height = fxMesa->height; + fxMesa->x_offset = 0; + fxMesa->y_offset = 0; + fxMesa->y_delta = 0; + + fxMesa->needClip = 0; + + if(verbose) + fprintf(stderr,"Voodoo Glide screen size: %dx%d\n", + (int)FX_grSstScreenWidth(),(int)FX_grSstScreenHeight()); + + fxMesa->glVis=gl_create_visual(GL_TRUE, /* RGB mode */ + alphaBuffer, + doubleBuffer, + GL_FALSE, /* stereo */ + depthSize, /* depth_size */ + stencilSize, /* stencil_size */ + accumSize, /* accum_size */ + 0, /* index bits */ + 5,6,5,0); /* RGBA bits */ + if (!fxMesa->glVis) { + errorstr = "gl_create_visual"; + goto errorhandler; + } + + ctx = fxMesa->glCtx=gl_create_context(fxMesa->glVis, + shareCtx, /* share list context */ + (void *) fxMesa, GL_TRUE); + if (!ctx) { + errorstr = "gl_create_context"; + goto errorhandler; + } + + + if (!fxDDInitFxMesaContext( fxMesa )) { + errorstr = "fxDDInitFxMesaContext failed"; + goto errorhandler; + } + + + fxMesa->glBuffer=gl_create_framebuffer(fxMesa->glVis, + GL_FALSE, /* no software depth */ + fxMesa->glVis->StencilBits > 0, + fxMesa->glVis->AccumRedBits > 0, + fxMesa->glVis->AlphaBits > 0 ); + if (!fxMesa->glBuffer) { + errorstr = "gl_create_framebuffer"; + goto errorhandler; + } + + glbTotNumCtx++; + + /* install signal handlers */ +#if defined(__linux__) + /* Only install if environment var. is not set. */ + if (fxMesa->glCtx->CatchSignals && !getenv("MESA_FX_NO_SIGNALS")) { + signal(SIGINT,cleangraphics_handler); + signal(SIGHUP,cleangraphics_handler); + signal(SIGPIPE,cleangraphics_handler); + signal(SIGFPE,cleangraphics_handler); + signal(SIGBUS,cleangraphics_handler); + signal(SIGILL,cleangraphics_handler); + signal(SIGSEGV,cleangraphics_handler); + signal(SIGTERM,cleangraphics_handler); + } +#endif + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxMesaCreateContext() End\n"); + } + + return fxMesa; + + errorhandler: + if (fxMesa) { + if (fxMesa->glideContext) + FX_grSstWinClose(fxMesa->glideContext); + fxMesa->glideContext = 0; + + if (fxMesa->state) + free(fxMesa->state); + if (fxMesa->fogTable) + free(fxMesa->fogTable); + if (fxMesa->glBuffer) + gl_destroy_framebuffer(fxMesa->glBuffer); + if (fxMesa->glVis) + gl_destroy_visual(fxMesa->glVis); + if (fxMesa->glCtx) + gl_destroy_context(fxMesa->glCtx); + free(fxMesa); + } + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxMesaCreateContext() End (%s)\n",errorstr); + } + return NULL; +} + + +/* + * Function to set the new window size in the context (mainly for the Voodoo Rush) + */ +void GLAPIENTRY fxMesaUpdateScreenSize(fxMesaContext fxMesa) +{ + fxMesa->width=FX_grSstScreenWidth(); + fxMesa->height=FX_grSstScreenHeight(); +} + + +/* + * Destroy the given FX/Mesa context. + */ +void GLAPIENTRY fxMesaDestroyContext(fxMesaContext fxMesa) +{ + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxMesaDestroyContext()\n"); + } + + if(fxMesa) { + gl_destroy_visual(fxMesa->glVis); + gl_destroy_context(fxMesa->glCtx); + gl_destroy_framebuffer(fxMesa->glBuffer); + + glbTotNumCtx--; + + fxCloseHardware(); + FX_grSstWinClose(fxMesa->glideContext); + + if(fxMesa->verbose) { + fprintf(stderr,"Misc Stats:\n"); + fprintf(stderr," # swap buffer: %u\n",fxMesa->stats.swapBuffer); + + if(!fxMesa->stats.swapBuffer) + fxMesa->stats.swapBuffer=1; + + fprintf(stderr,"Textures Stats:\n"); + fprintf(stderr," Free texture memory on TMU0: %d:\n",fxMesa->freeTexMem[FX_TMU0]); + if(fxMesa->haveTwoTMUs) + fprintf(stderr," Free texture memory on TMU1: %d:\n",fxMesa->freeTexMem[FX_TMU1]); + fprintf(stderr," # request to TMM to upload a texture objects: %u\n", + fxMesa->stats.reqTexUpload); + fprintf(stderr," # request to TMM to upload a texture objects per swapbuffer: %.2f\n", + fxMesa->stats.reqTexUpload/(float)fxMesa->stats.swapBuffer); + fprintf(stderr," # texture objects uploaded: %u\n", + fxMesa->stats.texUpload); + fprintf(stderr," # texture objects uploaded per swapbuffer: %.2f\n", + fxMesa->stats.texUpload/(float)fxMesa->stats.swapBuffer); + fprintf(stderr," # MBs uploaded to texture memory: %.2f\n", + fxMesa->stats.memTexUpload/(float)(1<<20)); + fprintf(stderr," # MBs uploaded to texture memory per swapbuffer: %.2f\n", + (fxMesa->stats.memTexUpload/(float)fxMesa->stats.swapBuffer)/(float)(1<<20)); + } + if (fxMesa->state) + free(fxMesa->state); + if (fxMesa->fogTable) + free(fxMesa->fogTable); + fxTMClose(fxMesa); + + free(fxMesa); + } + + if(fxMesa==fxMesaCurrentCtx) + fxMesaCurrentCtx=NULL; +} + + +/* + * Make the specified FX/Mesa context the current one. + */ +void GLAPIENTRY fxMesaMakeCurrent(fxMesaContext fxMesa) +{ + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) Start\n"); + } + + if(!fxMesa) { + gl_make_current(NULL,NULL); + fxMesaCurrentCtx=NULL; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxMesaMakeCurrent(NULL) End\n"); + } + + return; + } + + /* if this context is already the current one, we can return early */ + if (fxMesaCurrentCtx == fxMesa + && fxMesaCurrentCtx->glCtx == gl_get_current_context()) { + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxMesaMakeCurrent(fxMesaCurrentCtx==fxMesa) End\n"); + } + + return; + } + + if(fxMesaCurrentCtx) + grGlideGetState((GrState*)fxMesaCurrentCtx->state); + + fxMesaCurrentCtx=fxMesa; + + grSstSelect(fxMesa->board); + grGlideSetState((GrState*)fxMesa->state); + + gl_make_current(fxMesa->glCtx,fxMesa->glBuffer); + + fxSetupDDPointers(fxMesa->glCtx); + + /* The first time we call MakeCurrent we set the initial viewport size */ + if(fxMesa->glCtx->Viewport.Width==0) + gl_Viewport(fxMesa->glCtx,0,0,fxMesa->width,fxMesa->height); + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) End\n"); + } +} + + +#if 0 +static void QueryCounters(void) +{ + static GLuint prevPassed = 0; + static GLuint prevFailed = 0; + GLuint failed, passed; + GrSstPerfStats_t st; + + FX_grSstPerfStats(&st); + failed = st.zFuncFail - st.aFuncFail - st.chromaFail; + passed = st.pixelsIn - failed; + printf("failed: %d passed: %d\n", failed - prevFailed, passed - prevPassed); + + prevPassed = passed; + prevFailed = failed; +} +#endif + + +/* + * Swap front/back buffers for current context if double buffered. + */ +void GLAPIENTRY fxMesaSwapBuffers(void) +{ + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: ------------------------------- fxMesaSwapBuffers() -------------------------------\n"); + } + + if(fxMesaCurrentCtx) { + FLUSH_VB( fxMesaCurrentCtx->glCtx, "swap buffers" ); + + if(fxMesaCurrentCtx->haveDoubleBuffer) { + + grBufferSwap(fxMesaCurrentCtx->swapInterval); + + /* + * Don't allow swap buffer commands to build up! + */ + while(FX_grGetInteger(FX_PENDING_BUFFERSWAPS)>fxMesaCurrentCtx->maxPendingSwapBuffers) + /* The driver is able to sleep when waiting for the completation + of multiple swapbuffer operations instead of wasting + CPU time (NOTE: you must uncomment the following line in the + in order to enable this option) */ + /* usleep(10000); */ + ; + + fxMesaCurrentCtx->stats.swapBuffer++; + } + } +} + + +/* + * Query 3Dfx hardware presence/kind + */ +int GLAPIENTRY fxQueryHardware(void) +{ + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxQueryHardware() Start\n"); + } + + if (!glbGlideInitialized) { + grGlideInit(); + if (FX_grSstQueryHardware(&glbHWConfig)) { + grSstSelect(glbCurrentBoard); + glb3DfxPresent = 1; + + if (getenv("MESA_FX_INFO")) { + char buf[80]; + + FX_grGlideGetVersion(buf); + fprintf(stderr, "Voodoo Using Glide V%s\n", buf); + fprintf(stderr, "Voodoo Number of boards: %d\n", glbHWConfig.num_sst); + + if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_VOODOO) { + GrVoodooConfig_t *voodoo; + voodoo = &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig; + + fprintf(stderr, "Voodoo Framebuffer RAM: %d\n", + voodoo->sliDetect ? (voodoo->fbRam*2) : voodoo->fbRam); + fprintf(stderr, "Voodoo Number of TMUs: %d\n", voodoo->nTexelfx); + fprintf(stderr, "Voodoo fbRam: %d\n", voodoo->fbRam); + fprintf(stderr, "Voodoo fbiRev: %d\n", voodoo->fbiRev); + + fprintf(stderr,"Voodoo SLI detected: %d\n", voodoo->sliDetect); + } + else if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_SST96) { + GrSst96Config_t *sst96; + sst96 = &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config; + fprintf(stderr, "Voodoo Framebuffer RAM: %d\n", sst96->fbRam); + fprintf(stderr, "Voodoo Number of TMUs: %d\n", sst96->nTexelfx); + } + + } + } + else { + glb3DfxPresent = 0; + } + + glbGlideInitialized = 1; + +#if defined(__WIN32__) + onexit((_onexit_t)cleangraphics); +#elif defined(__linux__) + /* Only register handler if environment variable is not defined. */ + if (!getenv("MESA_FX_NO_SIGNALS")) { + atexit(cleangraphics); + } +#endif + } + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxQueryHardware() End (voodooo)\n"); + } + + return glbHWConfig.SSTs[glbCurrentBoard].type; +} + + +/* + * Shutdown Glide library + */ +void GLAPIENTRY fxCloseHardware(void) +{ + if (glbGlideInitialized) { + if (getenv("MESA_FX_INFO")) { + GrSstPerfStats_t st; + + FX_grSstPerfStats(&st); + fprintf(stderr,"Pixels Stats:\n"); + fprintf(stderr," # pixels processed (minus buffer clears): %u\n",(unsigned)st.pixelsIn); + fprintf(stderr," # pixels not drawn due to chroma key test failure: %u\n",(unsigned)st.chromaFail); + fprintf(stderr," # pixels not drawn due to depth test failure: %u\n",(unsigned)st.zFuncFail); + fprintf(stderr," # pixels not drawn due to alpha test failure: %u\n",(unsigned)st.aFuncFail); + fprintf(stderr," # pixels drawn (including buffer clears and LFB writes): %u\n",(unsigned)st.pixelsOut); + } + + if (glbTotNumCtx == 0) { + grGlideShutdown(); + glbGlideInitialized = 0; + } + } +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ +extern int gl_fx_dummy_function_api(void); +int gl_fx_dummy_function_api(void) +{ + return 0; +} + +#endif /* FX */ diff --git a/xc/extras/Mesa/src/FX/fxclip.c b/xc/extras/Mesa/src/FX/fxclip.c new file mode 100644 index 000000000..7067516be --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxclip.c @@ -0,0 +1,554 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" +#include "mmath.h" +#include "macros.h" +#include "vector.h" +#include "types.h" + + +#if 0 && defined(__i386__) +#define NEGATIVE(f) ((*(int *)&f) < 0) +#define DIFFERENT_SIGNS(a,b) (((*(int *)&a)^(*(int *)&b)) < 0) +#else +#define NEGATIVE(f) (f < 0) +#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) +#endif + +#define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) ) + + +#define CLIP(sgn,v) \ +do { \ + GLuint out = in ^ 1; \ + GLfloat **indata = inlist[in]; \ + GrVertex **inverts = vertlist[in]; \ + GrVertex **outverts = vertlist[out]; \ + GLfloat **outdata = inlist[in = out]; \ + GLfloat *J = indata[n-1]; \ + GLfloat dpJ = (sgn J[v]) + J[3]; \ + GLuint nr = n; \ + \ + for (i = n = 0 ; i < nr ; i++) { \ + GLfloat *I = indata[i]; \ + GLfloat dpI = (sgn I[v]) + I[3]; \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLuint j; \ + GLfloat t = dpI / (dpI - dpJ); \ + outverts[n] = 0; \ + outdata[n++] = store; \ + store[3] = LINTERP(t, I[3], J[3]); \ + store[v] = - sgn store[3]; \ + if (v != 0) store[0] = LINTERP(t, I[0], J[0]); \ + if (v != 1) store[1] = LINTERP(t, I[1], J[1]); \ + if (v != 2) store[2] = LINTERP(t, I[2], J[2]); \ + store += 4; \ + for (j = 4 ; j < sz ; j+=4,store+=4) { \ + store[0] = LINTERP(t, I[j], J[j] ); \ + store[1] = LINTERP(t, I[j+1], J[j+1] ); \ + store[2] = LINTERP(t, I[j+2], J[j+2] ); \ + store[3] = LINTERP(t, I[j+3], J[j+3] ); \ + } \ + } \ + \ + if (!NEGATIVE(dpI)) { \ + outverts[n] = inverts[i]; \ + outdata[n++] = I; \ + } \ + \ + \ + J = I; \ + dpJ = dpI; \ + } \ + \ + if (n < 3) return 0; \ +} while (0) + + +/* Originally used this for the viewclip planes as well, as in + * CLIP(-1,0,0,1), which was just as fast, but tended to lead to + * cracks. I haven't figured out exactly why this is, but the above + * code only really differs in the way it sets store[v] to +- w. + */ +#define UCLIP(a,b,c,d) \ +do { \ + GLuint out = in ^ 1; \ + GLfloat **indata = inlist[in]; \ + GrVertex **inverts = vertlist[in]; \ + GrVertex **outverts = vertlist[out]; \ + GLfloat **outdata = inlist[in = out]; \ + GLfloat *J = indata[n-1]; \ + GLfloat dpJ = DOT4V(J,a,b,c,d); \ + GLuint nr = n; \ + \ + for (i = n = 0 ; i < nr ; i++) { \ + GLfloat *I = indata[i]; \ + GLfloat dpI = DOT4V(I,a,b,c,d); \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLuint j; \ + GLfloat t = dpI / (dpI - dpJ); \ + outverts[n] = 0; \ + outdata[n++] = store; \ + for (j = 0 ; j < sz ; j+=4,store+=4) { \ + store[0] = LINTERP(t, I[j], J[j] ); \ + store[1] = LINTERP(t, I[j+1], J[j+1] ); \ + store[2] = LINTERP(t, I[j+2], J[j+2] ); \ + store[3] = LINTERP(t, I[j+3], J[j+3] ); \ + } \ + } \ + \ + if (!NEGATIVE(dpI)) { \ + outverts[n] = inverts[i]; \ + outdata[n++] = I; \ + } \ + \ + \ + J = I; \ + dpJ = dpI; \ + } \ + \ + if (n < 3) return 0; \ +} while (0) + + + +/* Data parameter is organized as 4 clip coordinates followed by an + * arbitary number (sz-4) of additional data. The three original + * vertices are packed together at the start, and there is room for at + * least VB_MAX_CLIPPED_VERTS vertices of the same size in this + * storage. + * + */ +static INLINE GLuint fx_clip_triangle( GLcontext *ctx, + GLfloat *inoutlist[], + GrVertex **verts, + GLuint sz, + GLuint mask ) +{ + GLuint n = 3; + GLfloat *store = inoutlist[n-1] + sz; + GLfloat *vlist[VB_MAX_CLIPPED_VERTS]; + GrVertex *verts2[VB_MAX_CLIPPED_VERTS]; + GLfloat **inlist[2]; + GrVertex **vertlist[2]; + GLuint in = 0; + GLuint i; + + inlist[0] = inoutlist; + inlist[1] = vlist; + + vertlist[0] = verts; + vertlist[1] = verts2; + + if (mask & CLIP_ALL_BITS) + { + if (mask & CLIP_RIGHT_BIT) + CLIP(-,0); + + if (mask & CLIP_LEFT_BIT) + CLIP(+,0); + + if (mask & CLIP_TOP_BIT) + CLIP(-,1); + + if (mask & CLIP_BOTTOM_BIT) + CLIP(+,1); + + if (mask & CLIP_FAR_BIT) + CLIP(-,2); + + if (mask & CLIP_NEAR_BIT) + CLIP(+,2); + } + + if (mask & CLIP_USER_BIT) { + GLuint bit; + GLfloat (*plane)[4] = &ctx->Transform.ClipUserPlane[0]; + for (bit = 0x100 ; bit < mask ; plane++, bit *= 2) { + if (mask & bit) { + GLfloat a = plane[0][0]; + GLfloat b = plane[0][1]; + GLfloat c = plane[0][2]; + GLfloat d = plane[0][3]; + UCLIP(a,b,c,d); + } + } + } + + if (inlist[in] != inoutlist) + for (i = 0 ; i < n ; i++) { + inoutlist[i] = inlist[in][i]; + verts[i] = verts2[i]; + } + + return n; +} + + + +static INLINE GLuint fx_view_clip_triangle( GLcontext *ctx, + GLfloat *inoutlist[], + GrVertex **verts, + GLuint sz, + GLubyte mask ) +{ + GLuint n = 3; + GLfloat *store = inoutlist[n-1] + sz; + GLfloat *vlist[VB_MAX_CLIPPED_VERTS]; + GrVertex *verts2[VB_MAX_CLIPPED_VERTS]; + GLfloat **inlist[2]; + GrVertex **vertlist[2]; + GLuint in = 0; + GLuint i; + + inlist[0] = inoutlist; + inlist[1] = vlist; + + vertlist[0] = verts; + vertlist[1] = verts2; + + if (mask & CLIP_RIGHT_BIT) + CLIP(-,0); + + if (mask & CLIP_LEFT_BIT) + CLIP(+,0); + + if (mask & CLIP_TOP_BIT) + CLIP(-,1); + + if (mask & CLIP_BOTTOM_BIT) + CLIP(+,1); + + if (mask & CLIP_FAR_BIT) + CLIP(-,2); + + if (mask & CLIP_NEAR_BIT) + CLIP(+,2); + + if (inlist[in] != inoutlist) + for (i = 0 ; i < n ; i++) { + inoutlist[i] = inlist[in][i]; + verts[i] = verts2[i]; + } + + return n; +} + + + +#undef CLIP + +#define CLIP(x,y,z,w) \ +do { \ + GLfloat dpI = DOT4V(I,x,y,z,w); \ + GLfloat dpJ = DOT4V(J,x,y,z,w); \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLuint j; \ + GLfloat t = dpI / (dpI - dpJ); \ + GLfloat *tmp = store; \ + \ + for (j = 0 ; j < sz ; j+=2) { \ + *store++ = LINTERP(t, I[j], J[j] ); \ + *store++ = LINTERP(t, I[j+1], J[j+1] ); \ + } \ + \ + if (NEGATIVE(dpI)) \ + I = tmp; \ + else \ + J = tmp; \ + \ + } \ + else if (NEGATIVE(dpI)) \ + return 0; \ + \ +} while (0) + + +static GLuint fx_clip_line( GLcontext *ctx, + GLfloat *inoutlist[], + GLuint sz, + GLubyte clipor ) +{ + GLfloat *I = inoutlist[0]; + GLfloat *J = inoutlist[1]; + GLfloat *store = J + sz; + + if (clipor & CLIP_ALL_BITS) + { + if (clipor & CLIP_LEFT_BIT) + CLIP(1,0,0,1); + + if (clipor & CLIP_RIGHT_BIT) + CLIP(-1,0,0,1); + + if (clipor & CLIP_TOP_BIT) + CLIP(0,-1,0,1); + + if (clipor & CLIP_BOTTOM_BIT) + CLIP(0,1,0,1); + + if (clipor & CLIP_FAR_BIT) + CLIP(0,0,-1,1); + + if (clipor & CLIP_NEAR_BIT) + CLIP(0,0,1,1); + } + + if (clipor & CLIP_USER_BIT) { + GLuint i; + for (i = 0 ; i < MAX_CLIP_PLANES ; i++) { + if (ctx->Transform.ClipEnabled[i]) { + GLfloat a = ctx->Transform.ClipUserPlane[i][0]; + GLfloat b = ctx->Transform.ClipUserPlane[i][1]; + GLfloat c = ctx->Transform.ClipUserPlane[i][2]; + GLfloat d = ctx->Transform.ClipUserPlane[i][3]; + CLIP(a,b,c,d); + } + } + } + + inoutlist[0] = I; + inoutlist[1] = J; + + return 2; +} + + + + + + +#if defined(FX_V2) + +#define VARS_XYZW \ + GLfloat vsx = mat[MAT_SX]; \ + GLfloat vsy = mat[MAT_SY]; \ + GLfloat vsz = mat[MAT_SZ]; \ + GLfloat vtx = mat[MAT_TX]; \ + GLfloat vty = mat[MAT_TY]; \ + GLfloat vtz = mat[MAT_TZ]; + +#define DO_SETUP_XYZW \ +{ \ + GLfloat oow = 1.0 / data[3]; \ + v->x = data[0]*oow*vsx + vtx; \ + v->y = data[1]*oow*vsy + vty; \ + v->ooz = data[2]*oow*vsz + vtz; \ + v->oow = oow; \ +} +#else + +#if defined(DRIVERTS) + +#define VARS_XYZW \ + GLfloat vsx = mat[MAT_SX]; \ + GLfloat vsy = mat[MAT_SY]; \ + GLfloat vsz = mat[MAT_SZ]; \ + GLfloat vtx = mat[MAT_TX]+fxMesa->x_offset; \ + GLfloat vty = mat[MAT_TY]+fxMesa->y_delta; \ + GLfloat vtz = mat[MAT_TZ]; + +#define DO_SETUP_XYZW \ +{ \ + GLfloat oow = 1.0 / data[3]; \ + v->x = data[0]*oow*vsx + vtx; \ + v->y = data[1]*oow*vsy + vty; \ + v->ooz = data[2]*oow*vsz + vtz; \ + v->oow = oow; \ +} + +#else +#define VARS_XYZW \ + GLfloat vsx = mat[MAT_SX]; \ + GLfloat vsy = mat[MAT_SY]; \ + GLfloat vsz = mat[MAT_SZ]; \ + const GLfloat snapper = (3L << 18); \ + GLfloat snap_tx = mat[MAT_TX] + snapper; \ + GLfloat snap_ty = mat[MAT_TY] + snapper; \ + GLfloat vtz = mat[MAT_TZ]; + +#define DO_SETUP_XYZW \ +{ \ + GLfloat oow = 1.0 / data[3]; \ + v->x = data[0]*oow*vsx + snap_tx; \ + v->y = data[1]*oow*vsy + snap_ty; \ + v->ooz = data[2]*oow*vsz + vtz; \ + v->oow = oow; \ + v->x -= snapper; \ + v->y -= snapper; \ +} + +#endif +#endif + +#define COPY_XYZW_STRIDE \ + { GLfloat *clip = VEC_ELT(VB->ClipPtr, GLfloat, e); \ + COPY_4FV(out, clip); } + +#define VARS_RGBA + +#define COPY_RGBA_STRIDE \ + { GLubyte *color = VEC_ELT(VB->ColorPtr, GLubyte, e); \ + UBYTE_RGBA_TO_FLOAT_255_RGBA((out+4), color); } + +#if FX_USE_PARGB +#define DO_SETUP_RGBA \ + GET_PARGB(v) = (((int)data[4+3]) << 24) | \ + (((int)data[4+0]) << 16) | \ + (((int)data[4+1]) << 8) | \ + (((int)data[4+2]) << 0); +#else +#define DO_SETUP_RGBA \ + v->r = data[4+0]; \ + v->g = data[4+1]; \ + v->b = data[4+2]; \ + v->a = data[4+3]; +#endif /* FX_USE_PARGB */ + +#define VARS_TMU0 \ + struct gl_texture_unit *t0 = &ctx->Texture.Unit[tmu0_source]; \ + GLfloat sScale0 = fxTMGetTexInfo(t0->Current)->sScale; \ + GLfloat tScale0 = fxTMGetTexInfo(t0->Current)->tScale; \ + + +#define COPY_TMU0_STRIDE(offset) \ + { GLfloat *tc0 = VEC_ELT(tc0_vec, GLfloat, e); \ + COPY_2V((out+offset), tc0); } + + +#define DO_SETUP_TMU0(offset) \ + v->tmuvtx[0].sow = data[offset+0]*sScale0*v->oow; \ + v->tmuvtx[0].tow = data[offset+1]*tScale0*v->oow; + +#define VARS_TMU1 \ + struct gl_texture_unit *t1 = &ctx->Texture.Unit[tmu1_source]; \ + GLfloat sScale1 = fxTMGetTexInfo(t1->Current)->sScale; \ + GLfloat tScale1 = fxTMGetTexInfo(t1->Current)->tScale; + +#define COPY_TMU1_STRIDE(offset) \ + { GLfloat *tc1 = VEC_ELT(tc1_vec, GLfloat, e); \ + COPY_2V((out+offset), tc1); } + + +#define DO_SETUP_TMU1(offset) \ + v->tmuvtx[1].sow = data[offset+0]*sScale1*v->oow; \ + v->tmuvtx[1].tow = data[offset+1]*tScale1*v->oow; + +#define COPY_NIL(offset) ASSIGN_2V((out+offset), 0, 0); + +#define IND 0 +#define TAG(x) x##_nil +#include "fxcliptmp.h" + +#define IND SETUP_RGBA +#define TAG(x) x##_RGBA +#include "fxcliptmp.h" + +#define IND SETUP_TMU0 +#define TAG(x) x##_TMU0 +#include "fxcliptmp.h" + +#define IND (SETUP_TMU0|SETUP_TMU1) +#define TAG(x) x##_TMU0_TMU1 +#include "fxcliptmp.h" + +#define IND (SETUP_RGBA|SETUP_TMU0) +#define TAG(x) x##_RGBA_TMU0 +#include "fxcliptmp.h" + +#define IND (SETUP_RGBA|SETUP_TMU0|SETUP_TMU1) +#define TAG(x) x##_RGBA_TMU0_TMU1 +#include "fxcliptmp.h" + +tfxTriViewClipFunc fxTriViewClipTab[0x8]; +tfxTriClipFunc fxTriClipStrideTab[0x8]; +tfxLineClipFunc fxLineClipTab[0x8]; + + +void fxDDClipInit() +{ + fxTriViewClipTab[0] = fx_tri_view_clip_nil; + fxTriViewClipTab[SETUP_RGBA] = fx_tri_view_clip_RGBA; + fxTriViewClipTab[SETUP_TMU0] = fx_tri_view_clip_TMU0; + fxTriViewClipTab[SETUP_TMU0|SETUP_TMU1] = fx_tri_view_clip_TMU0_TMU1; + fxTriViewClipTab[SETUP_RGBA|SETUP_TMU0] = fx_tri_view_clip_RGBA_TMU0; + fxTriViewClipTab[SETUP_RGBA|SETUP_TMU0|SETUP_TMU1] = fx_tri_view_clip_RGBA_TMU0_TMU1; + + fxTriClipStrideTab[0] = fx_tri_clip_stride_nil; + fxTriClipStrideTab[SETUP_RGBA] = fx_tri_clip_stride_RGBA; + fxTriClipStrideTab[SETUP_TMU0] = fx_tri_clip_stride_TMU0; + fxTriClipStrideTab[SETUP_TMU0|SETUP_TMU1] = fx_tri_clip_stride_TMU0_TMU1; + fxTriClipStrideTab[SETUP_RGBA|SETUP_TMU0] = fx_tri_clip_stride_RGBA_TMU0; + fxTriClipStrideTab[SETUP_RGBA|SETUP_TMU0|SETUP_TMU1] = fx_tri_clip_stride_RGBA_TMU0_TMU1; + + fxLineClipTab[0] = fx_line_clip_nil; + fxLineClipTab[SETUP_RGBA] = fx_line_clip_RGBA; + fxLineClipTab[SETUP_TMU0] = fx_line_clip_TMU0; + fxLineClipTab[SETUP_TMU0|SETUP_TMU1] = fx_line_clip_TMU0_TMU1; + fxLineClipTab[SETUP_RGBA|SETUP_TMU0] = fx_line_clip_RGBA_TMU0; + fxLineClipTab[SETUP_RGBA|SETUP_TMU0|SETUP_TMU1] = fx_line_clip_RGBA_TMU0_TMU1; +} + +#else + +/* + * Need this to provide at least one external definition. + */ +int gl_fxclip_dummy(void) +{ + return 0; +} + +#endif diff --git a/xc/extras/Mesa/src/FX/fxcliptmp.h b/xc/extras/Mesa/src/FX/fxcliptmp.h new file mode 100644 index 000000000..82beeda6a --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxcliptmp.h @@ -0,0 +1,346 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#define V1 VARS_XYZW +#define S1 DO_SETUP_XYZW +#define T1 COPY_XYZW_STRIDE +#define Z1 4 + +#if (IND & SETUP_RGBA) +#define V2 V1 VARS_RGBA +#define S2 S1 DO_SETUP_RGBA +#define T2 T1 COPY_RGBA_STRIDE +#define Z2 (Z1 + 4) +#else +#define V2 V1 +#define S2 S1 +#define T2 T1 +#define Z2 Z1 +#endif + +#if (IND & SETUP_TMU0) +#define V3 V2 VARS_TMU0 +#define S3 S2 DO_SETUP_TMU0(Z2) +#define T3 T2 COPY_TMU0_STRIDE(Z2) +#define Z3 (Z2 + 2) +#else +#define V3 V2 +#define S3 S2 +#define T3 T2 +#define Z3 Z2 +#endif + +#if (IND & SETUP_TMU1) +#define V4 V3 VARS_TMU1 +#define S4 S3 DO_SETUP_TMU1(Z3) +#define T4 T3 COPY_TMU1_STRIDE(Z3) +#define Z4 (Z3 + 2) +#else +#define V4 V3 +#define S4 S3 +#define T4 T3 +#define Z4 Z3 +#endif + +#if (Z4 & 2) +#define SIZE (Z4+2) +#define COPY_STRIDE T4 COPY_NIL(Z4) +#else +#define SIZE Z4 +#define COPY_STRIDE T4 +#endif + +#define VARS V4 +#define SETUP S4 + +#define DRAW_LINE(tmp0, tmp1, width) \ + do { \ + GrVertex verts[4]; \ + float dx, dy, ix, iy; \ + \ + dx = tmp0->x - tmp1->x; \ + dy = tmp0->y - tmp1->y; \ + \ + if (dx * dx > dy * dy) { \ + iy = width * .5; \ + ix = 0; \ + } else { \ + iy = 0; \ + ix = width * .5; \ + } \ + \ + verts[0] = *tmp0; \ + verts[1] = *tmp0; \ + verts[2] = *tmp1; \ + verts[3] = *tmp1; \ + \ + verts[0].x = tmp0->x - ix; \ + verts[0].y = tmp0->y - iy; \ + \ + verts[1].x = tmp0->x + ix; \ + verts[1].y = tmp0->y + iy; \ + \ + verts[2].x = tmp1->x + ix; \ + verts[2].y = tmp1->y + iy; \ + \ + verts[3].x = tmp1->x - ix; \ + verts[3].y = tmp1->y - iy; \ + \ + FX_grDrawPolygonVertexList(4, verts); \ + } while (0) + +static void TAG(fx_tri_view_clip)( struct vertex_buffer *VB, + GLuint v[], + GLubyte mask ) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + GLfloat data[VB_MAX_CLIPPED_VERTS*12]; + GLfloat *vlist[VB_MAX_CLIPPED_VERTS]; + GrVertex *verts[VB_MAX_CLIPPED_VERTS]; + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + GLfloat *out = data; + GLfloat *mat = ctx->Viewport.WindowMap.m; + GLuint i, n; + GLubyte *clipmask = VB->ClipMask; + + GLuint tmu0_source = fxMesa->tmu_source[0]; + GLuint tmu1_source = fxMesa->tmu_source[1]; + GLvector4f *tc0_vec = VB->TexCoordPtr[tmu0_source]; + GLvector4f *tc1_vec = VB->TexCoordPtr[tmu1_source]; + + (void) fxMesa; + (void) tmu0_source; (void) tc0_vec; + (void) tmu1_source; (void) tc1_vec; + + for (i = 0 ; i < 3 ; i++) { + GLuint e = v[i]; + verts[i] = 0; + if (!clipmask[e]) verts[i] = (GrVertex *)gWin[e].f; + vlist[i] = out; + COPY_STRIDE; + out += SIZE; + } + + if ((n = fx_view_clip_triangle( ctx, vlist, verts, SIZE, mask )) >= 3) + { + GrVertex tmp[VB_MAX_CLIPPED_VERTS]; + GrVertex *v = tmp, *v2, *v3; + VARS; + + for (i = 0 ; i < n ; i++) + if (!verts[i]) { + GLfloat *data = vlist[i]; + SETUP; + verts[i] = v++; + } + + v = verts[0]; + v2 = verts[1]; + v3 = verts[2]; + + for (i = 2 ; i < n ; v2 = v3, v3=verts[++i]) + FX_grDrawTriangle(v, v2, v3); + } +} + + + + + +static void TAG(fx_tri_clip_stride)( struct vertex_buffer *VB, + GLuint v[], + GLuint mask ) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + GLfloat data[VB_MAX_CLIPPED_VERTS*12]; + GLfloat *vlist[VB_MAX_CLIPPED_VERTS]; + GrVertex *verts[VB_MAX_CLIPPED_VERTS]; + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + GLfloat *out = data; + GLfloat *mat = ctx->Viewport.WindowMap.m; + GLuint i, n; + GLubyte *clipmask = VB->ClipMask; + + GLuint tmu0_source = fxMesa->tmu_source[0]; + GLuint tmu1_source = fxMesa->tmu_source[1]; + GLvector4f *tc0_vec = VB->TexCoordPtr[tmu0_source]; + GLvector4f *tc1_vec = VB->TexCoordPtr[tmu1_source]; + + (void) fxMesa; + (void) tmu0_source; (void) tc0_vec; + (void) tmu1_source; (void) tc1_vec; + + for (i = 0 ; i < 3 ; i++) { + GLuint e = v[i]; + verts[i] = 0; + if (!clipmask[e]) verts[i] = (GrVertex *)gWin[e].f; + vlist[i] = out; + COPY_STRIDE; + out += SIZE; + } + + if (VB->ClipPtr->size < 4) { + vlist[0][3] = vlist[1][3] = vlist[2][3] = 1.0; + if (VB->ClipPtr->size == 2) + vlist[0][2] = vlist[1][2] = vlist[2][2] = 0.0; + } + + if ((n = fx_clip_triangle( ctx, vlist, verts, SIZE, mask )) >= 3) + { + GrVertex tmp[VB_MAX_CLIPPED_VERTS]; + GrVertex *v = tmp, *v2, *v3; + VARS; + + for (i = 0 ; i < n ; i++) + if (!verts[i]) { + GLfloat *data = vlist[i]; + SETUP; + verts[i] = v++; + } + + v = verts[0]; + v2 = verts[1]; + v3 = verts[2]; + + for (i = 2 ; i < n ; v2 = v3, v3=verts[++i]) + FX_grDrawTriangle(v, v2, v3); + } +} + + + +static void TAG(fx_line_clip)( struct vertex_buffer *VB, + GLuint v1, GLuint v2, + GLubyte mask ) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + GLfloat data[VB_MAX_CLIPPED_VERTS*12]; + GLfloat *vlist[VB_MAX_CLIPPED_VERTS]; + GLfloat *out = data; + GLfloat *mat = ctx->Viewport.WindowMap.m; + GLfloat w = ctx->Line.Width*.5; + GLuint e, n; + + GLuint tmu0_source = fxMesa->tmu_source[0]; + GLuint tmu1_source = fxMesa->tmu_source[1]; + GLvector4f *tc0_vec = VB->TexCoordPtr[tmu0_source]; + GLvector4f *tc1_vec = VB->TexCoordPtr[tmu1_source]; + + VARS; + + (void) fxMesa; + (void) tmu0_source; (void) tc0_vec; + (void) tmu1_source; (void) tc1_vec; + + vlist[0] = out; + e = v1; + COPY_STRIDE; + out += SIZE; + + vlist[1] = out; + e = v2; + COPY_STRIDE; + out += SIZE; + + if (VB->ClipPtr->size < 4) { + vlist[0][3] = vlist[1][3] = 1.0; + if (VB->ClipPtr->size == 2) + vlist[0][2] = vlist[1][2] = 0.0; + } + + if ((n = fx_clip_line( ctx, vlist, SIZE, mask )) != 0) + { + GrVertex gWin[2]; + GrVertex *v; + GLfloat *data; + + v = gWin; + data = vlist[0]; + SETUP; + + v++; + data = vlist[1]; + SETUP; + + DRAW_LINE(gWin, v, w); + } +} + + + +#undef V1 +#undef S1 +#undef C1 +#undef Z1 +#undef T1 + +#undef V2 +#undef S2 +#undef C2 +#undef Z2 +#undef T2 + +#undef V3 +#undef S3 +#undef C3 +#undef Z3 +#undef T3 + +#undef V4 +#undef S4 +#undef C4 +#undef Z4 +#undef T4 + +#undef VARS +#undef SETUP +#undef COPY +#undef COPY_STRIDE +#undef SIZE +#undef IND +#undef TAG diff --git a/xc/extras/Mesa/src/FX/fxcva.c b/xc/extras/Mesa/src/FX/fxcva.c new file mode 100644 index 000000000..188210add --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxcva.c @@ -0,0 +1,513 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* fxcva.c - the CVA related code */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" +#include "mmath.h" +#include "vbindirect.h" +#include "pb.h" +#include "fxvsetup.h" +#include "pipeline.h" +#include "stages.h" + +#define PRIM_POINTS 0 +#define PRIM_LINES 1 +#define PRIM_TRIS 2 +#define PRIM_CULLED 3 + + +static GLuint reduce_prim[GL_POLYGON+2] = { + PRIM_POINTS, + PRIM_LINES, + PRIM_LINES, + PRIM_LINES, + PRIM_TRIS, + PRIM_TRIS, + PRIM_TRIS, + PRIM_TRIS, + PRIM_TRIS, + PRIM_TRIS, + PRIM_CULLED +}; + +typedef void (*mergefunc)( struct vertex_buffer *cvaVB, + struct vertex_buffer *VB, + const struct gl_prim_state *state, + GLuint start, + GLuint count ); + +static void fxCvaRenderNoop( struct vertex_buffer *cvaVB, + struct vertex_buffer *VB, + const struct gl_prim_state *state, + GLuint start, + GLuint count ) +{ +} + +static INLINE void fxRenderClippedTriangle2( struct vertex_buffer *VB, + GLuint v1, GLuint v2, GLuint v3 ) +{ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + GLubyte *clipmask = VB->ClipMask; + GLubyte mask = clipmask[v1] | clipmask[v2] | clipmask[v3]; + + if (!mask) { + FX_grDrawTriangle((GrVertex *)gWin[v1].f, + (GrVertex *)gWin[v2].f, + (GrVertex *)gWin[v3].f); + } else if (!(clipmask[v1]&clipmask[v2]&clipmask[v3]&CLIP_ALL_BITS)) { + GLuint n; + GLuint vlist[VB_MAX_CLIPPED_VERTS]; + ASSIGN_3V(vlist, v1, v2, v3); + + n = (VB->ctx->poly_clip_tab[VB->ClipPtr->size])( VB, 3, vlist, mask ); + if (n >= 3) { + GLuint i, j0 = vlist[0]; + for (i=2;i<n;i++) { + FX_grDrawTriangle((GrVertex *)gWin[j0].f, + (GrVertex *)gWin[vlist[i-1]].f, + (GrVertex *)gWin[vlist[i]].f); + } + } + } +} + + +static mergefunc merge_and_render_tab[2][MAX_MERGABLE][PRIM_CULLED+1]; + + +/* +#define CVA_VARS_RGBA \ + GLubyte (*color)[4] = VB->ColorPtr->data; \ + GLubyte (*cva_color)[4] = (cvaVB->ColorPtr = cvaVB->LitColor[0])->data; +*/ + +#define CVA_VARS_RGBA \ + GLubyte (*color)[4] = VB->ColorPtr->data; \ + GLubyte (*cva_color)[4] = cvaVB->ColorPtr->data; + + + +#undef DO_SETUP_RGBA +#if FX_USE_PARGB +#define DO_SETUP_RGBA \ +{ \ + GLubyte *col = color[i]; \ + GET_PARGB(v)= ((col[3] << 24) | \ + (col[0] << 16) | \ + (col[1] << 8) | \ + (col[2])); \ +} +#else +#define DO_SETUP_RGBA \ +{ \ + GLubyte *col = color[i]; \ + v[GR_VERTEX_R_OFFSET]=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \ + v[GR_VERTEX_G_OFFSET]=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \ + v[GR_VERTEX_B_OFFSET]=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \ + v[GR_VERTEX_A_OFFSET]=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \ +} +#endif /* FX_USE_PARGB */ + + +#define CVA_VARS_TMU0 \ + VARS_TMU0 \ + GLfloat (*cva_tex0)[4] = (cvaVB->TexCoordPtr[tmu0_source] = cvaVB->store.TexCoord[tmu0_source])->data; + +#define CVA_VARS_TMU1 \ + VARS_TMU1 \ + GLfloat (*cva_tex1)[4] = (cvaVB->TexCoordPtr[tmu1_source] = cvaVB->store.TexCoord[tmu1_source])->data; + + +#define INIT_RGBA (void) cva_color; +#define INIT_TMU0 (void) cva_tex0; (void) tmu0_stride; (void) tmu0_sz; +#define INIT_TMU1 (void) cva_tex1; (void) tmu1_stride; (void) tmu1_sz; + + +#define DRAW_POINT FX_grDrawPoint( (GrVertex *)v ) +#define DRAW_LINE FX_grDrawLine( (GrVertex *)v, (GrVertex *)prev_v ) +#define DRAW_TRI FX_grDrawTriangle( (GrVertex *)gWin[l[0]].f, (GrVertex *)gWin[l[1]].f, (GrVertex *)v ) +#define DRAW_TRI2 FX_grDrawTriangle( vl[0], vl[1], vl[2] ) +#define CLIP_LINE fxRenderClippedLine( cvaVB, e, prev ) +#define CLIP_OR_DRAW_TRI fxRenderClippedTriangle2( cvaVB, l[0], l[1], e ) +#define DIRECT 1 + +#define TAG(x) x +#define IDX 0 +#define VARS +#define INIT +#define INCR +#define MERGE_RAST +#define MERGE_VB +#include "fxcvatmp.h" + +#define TAG(x) x##RGBA +#define IDX SETUP_RGBA +#define VARS CVA_VARS_RGBA +#define INIT INIT_RGBA +#define INCR +#define MERGE_RAST DO_SETUP_RGBA +#define MERGE_VB COPY_4UBV(cva_color[e], color[i]) +#include "fxcvatmp.h" + +#define TAG(x) x##T0 +#define IDX SETUP_TMU0 +#define VARS CVA_VARS_TMU0 +#define INIT INIT_TMU0 +#define INCR , tmu0_data+=4 +#define MERGE_RAST DO_SETUP_TMU0 +#define MERGE_VB COPY_2FV(cva_tex0[e], tmu0_data) +#include "fxcvatmp.h" + +#define TAG(x) x##T1 +#define IDX SETUP_TMU1 +#define VARS CVA_VARS_TMU1 +#define INIT INIT_TMU1 +#define INCR , tmu1_data+=4 +#define MERGE_RAST DO_SETUP_TMU1 +#define MERGE_VB COPY_2FV(cva_tex1[e], tmu1_data) +#include "fxcvatmp.h" + +#define TAG(x) x##T0T1 +#define IDX SETUP_TMU0|SETUP_TMU1 +#define VARS CVA_VARS_TMU0 CVA_VARS_TMU1 +#define INIT INIT_TMU0 INIT_TMU1 +#define INCR , tmu0_data+=4 , tmu1_data+=4 +#define MERGE_RAST DO_SETUP_TMU0 DO_SETUP_TMU1 +#define MERGE_VB COPY_2FV(cva_tex0[e], tmu0_data); \ + COPY_2FV(cva_tex1[e], tmu1_data); +#include "fxcvatmp.h" + +#define TAG(x) x##RGBAT0 +#define IDX SETUP_RGBA|SETUP_TMU0 +#define VARS CVA_VARS_RGBA CVA_VARS_TMU0 +#define INIT INIT_RGBA INIT_TMU0 +#define INCR , tmu0_data+=4 +#define MERGE_RAST DO_SETUP_RGBA; DO_SETUP_TMU0 +#define MERGE_VB COPY_2FV(cva_tex0[e], tmu0_data); \ + COPY_4UBV(cva_color[e], color[i]); +#include "fxcvatmp.h" + +#define TAG(x) x##RGBAT1 +#define IDX SETUP_RGBA|SETUP_TMU1 +#define VARS CVA_VARS_RGBA CVA_VARS_TMU1 +#define INIT INIT_RGBA INIT_TMU1 +#define INCR , tmu1_data+=4 +#define MERGE_RAST DO_SETUP_RGBA; DO_SETUP_TMU1 +#define MERGE_VB COPY_2FV(cva_tex1[e], tmu1_data); \ + COPY_4UBV(cva_color[e], color[i]); +#include "fxcvatmp.h" + +#define TAG(x) x##RGBAT0T1 +#define IDX SETUP_RGBA|SETUP_TMU0|SETUP_TMU1 +#define VARS CVA_VARS_RGBA CVA_VARS_TMU0 CVA_VARS_TMU1 +#define INIT INIT_RGBA INIT_TMU0 INIT_TMU1 +#define INCR , tmu0_data+=4 , tmu1_data+=4 +#define MERGE_RAST DO_SETUP_RGBA; DO_SETUP_TMU0 DO_SETUP_TMU1 +#define MERGE_VB COPY_2FV(cva_tex0[e], tmu0_data); \ + COPY_2FV(cva_tex1[e], tmu1_data); \ + COPY_4UBV(cva_color[e], color[i]); +#include "fxcvatmp.h" + + + +#undef DRAW_POINT +#undef DRAW_LINE +#undef DRAW_TRI +#undef CLIP_LINE +#undef CLIP_OR_DRAW_TRI +#undef DIRECT + +#define DRAW_POINT ctx->Driver.PointsFunc( ctx, e, e ) +#define DRAW_LINE ctx->Driver.LineFunc( ctx, e, prev, e ) +#define DRAW_TRI ctx->TriangleFunc( ctx, l[0], l[1], e, e ) +#define CLIP_LINE gl_render_clipped_line( ctx, e, prev ) +#define CLIP_OR_DRAW_TRI \ +do { \ + if (clip[l[0]] | clip[l[1]] | clip[e]) { \ + if (!(clip[l[0]] & clip[l[1]] & clip[e] & CLIP_ALL_BITS)) { \ + COPY_3V(vlist, l); \ + gl_render_clipped_triangle( ctx, 3, vlist, e ); \ + } \ + } \ + else ctx->TriangleFunc( ctx, l[0], l[1], e, e ); \ +} while (0) + + +#define DIRECT 0 + +#define TAG(x) x##_indirect +#define IDX 0 +#define VARS +#define INIT +#define INCR +#define MERGE_RAST +#define MERGE_VB +#include "fxcvatmp.h" + +#define TAG(x) x##RGBA_indirect +#define IDX SETUP_RGBA +#define VARS CVA_VARS_RGBA +#define INIT INIT_RGBA +#define INCR +#define MERGE_RAST DO_SETUP_RGBA +#define MERGE_VB COPY_4UBV(cva_color[e], color[i]) +#include "fxcvatmp.h" + +#define TAG(x) x##T0_indirect +#define IDX SETUP_TMU0 +#define VARS CVA_VARS_TMU0 +#define INIT INIT_TMU0 +#define INCR , tmu0_data+=4 +#define MERGE_RAST DO_SETUP_TMU0 +#define MERGE_VB COPY_2FV(cva_tex0[e], tmu0_data) +#include "fxcvatmp.h" + +#define TAG(x) x##T1_indirect +#define IDX SETUP_TMU1 +#define VARS CVA_VARS_TMU1 +#define INIT INIT_TMU1 +#define INCR , tmu1_data+=4 +#define MERGE_RAST DO_SETUP_TMU1 +#define MERGE_VB COPY_2FV(cva_tex1[e], tmu1_data) +#include "fxcvatmp.h" + +#define TAG(x) x##T0T1_indirect +#define IDX SETUP_TMU0|SETUP_TMU1 +#define VARS CVA_VARS_TMU0 CVA_VARS_TMU1 +#define INIT INIT_TMU0 INIT_TMU1 +#define INCR , tmu0_data+=4 , tmu1_data+=4 +#define MERGE_RAST DO_SETUP_TMU0 DO_SETUP_TMU1 +#define MERGE_VB COPY_2FV(cva_tex0[e], tmu0_data); \ + COPY_2FV(cva_tex1[e], tmu1_data); +#include "fxcvatmp.h" + +#define TAG(x) x##RGBAT0_indirect +#define IDX SETUP_RGBA|SETUP_TMU0 +#define VARS CVA_VARS_RGBA CVA_VARS_TMU0 +#define INIT INIT_RGBA INIT_TMU0 +#define INCR , tmu0_data+=4 +#define MERGE_RAST DO_SETUP_RGBA; DO_SETUP_TMU0 +#define MERGE_VB COPY_2FV(cva_tex0[e], tmu0_data); \ + COPY_4UBV(cva_color[e], color[i]); +#include "fxcvatmp.h" + +#define TAG(x) x##RGBAT1_indirect +#define IDX SETUP_RGBA|SETUP_TMU1 +#define VARS CVA_VARS_RGBA CVA_VARS_TMU1 +#define INIT INIT_RGBA INIT_TMU1 +#define INCR , tmu1_data+=4 +#define MERGE_RAST DO_SETUP_RGBA; DO_SETUP_TMU1 +#define MERGE_VB COPY_2FV(cva_tex1[e], tmu1_data); \ + COPY_4UBV(cva_color[e], color[i]); +#include "fxcvatmp.h" + +#define TAG(x) x##RGBAT0T1_indirect +#define IDX SETUP_RGBA|SETUP_TMU0|SETUP_TMU1 +#define VARS CVA_VARS_RGBA CVA_VARS_TMU0 CVA_VARS_TMU1 +#define INIT INIT_RGBA INIT_TMU0 INIT_TMU1 +#define INCR , tmu0_data+=4 , tmu1_data+=4 +#define MERGE_RAST DO_SETUP_RGBA DO_SETUP_TMU0 DO_SETUP_TMU1 +#define MERGE_VB COPY_2FV(cva_tex0[e], tmu0_data); \ + COPY_2FV(cva_tex1[e], tmu1_data); \ + COPY_4UBV(cva_color[e], color[i]); +#include "fxcvatmp.h" + + + + +void fxDDCvaInit() +{ + /* Call grDrawTriangle et al */ + init_cva(); + init_cvaT0(); + init_cvaT1(); + init_cvaT0T1(); + init_cvaRGBA(); + init_cvaRGBAT0(); + init_cvaRGBAT1(); + init_cvaRGBAT0T1(); + + /* Call ctx->TriangleFunc and friends */ + init_cva_indirect(); + init_cvaT0_indirect(); + init_cvaT1_indirect(); + init_cvaT0T1_indirect(); + init_cvaRGBA_indirect(); + init_cvaRGBAT0_indirect(); + init_cvaRGBAT1_indirect(); + init_cvaRGBAT0T1_indirect(); +} + + +void fxDDCheckMergeAndRender( GLcontext *ctx, struct gl_pipeline_stage *d ) +{ + GLuint inputs = ctx->RenderFlags & ~ctx->CVA.pre.outputs; + + if (!(ctx->TriangleCaps & DD_TRI_UNFILLED) && + (ctx->Array.Summary & VERT_OBJ_ANY)) + { + d->inputs = (VERT_SETUP_PART | VERT_ELT | inputs); + d->outputs = 0; + d->type = PIPE_IMMEDIATE; + } + +/* gl_print_vert_flags("merge&render inputs", d->inputs); */ +} + + +extern void fxPointSmooth(GLcontext *ctx, GLuint first, GLuint last); +extern void fxLineSmooth(GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv); +extern void fxTriangleSmooth(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, + GLuint pv); +extern const char *gl_prim_name[]; + + +/* static GLboolean edge_flag[GL_POLYGON+2] = { 0,0,0,0,1,0,0,1,0,1,0 }; */ + +void fxDDMergeAndRender( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + struct vertex_buffer *cvaVB = ctx->CVA.VB; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + GLuint i, next, prim; + GLuint parity = VB->Parity; + GLuint count = VB->Count; + const struct gl_prim_state *state; + mergefunc func; + struct vertex_buffer *saved_vb = ctx->VB; + GLuint inputs = ctx->RenderFlags & ~ctx->CVA.pre.outputs; + GLuint flags = 0; + GLuint direct = (fxMesa->render_index == 0); + mergefunc (*tab)[PRIM_CULLED+1] = merge_and_render_tab[direct]; + GLuint p = 0; + + if (fxMesa->new_state) + fxSetupFXUnits(ctx); + + + /* May actually contain elements not present in fxMesa->setupindex, + * eg RGBA when flat shading. These need to be copied into the cva + * VB so that funcs like fxTriangleFlat will be able to reach them. + * + * This leads to some duplication of effort in the merge funcs. + */ + if (inputs & VERT_RGBA) { + cvaVB->ColorPtr = cvaVB->Color[0] = cvaVB->LitColor[0]; + cvaVB->Color[1] = cvaVB->LitColor[1]; + flags |= SETUP_RGBA; + } + + if (inputs & VERT_TEX0_ANY) { + cvaVB->TexCoordPtr[0] = cvaVB->store.TexCoord[0]; + flags |= fxMesa->tex_dest[0]; + } + + if (inputs & VERT_TEX1_ANY) { + cvaVB->TexCoordPtr[1] = cvaVB->store.TexCoord[1]; + flags |= fxMesa->tex_dest[1]; + } +#if 0 + fxPrintSetupFlags("FX cva merge & render", flags); +#endif + + if (cvaVB->ClipOrMask) + gl_import_client_data( cvaVB, ctx->RenderFlags, + VEC_WRITABLE|VEC_GOOD_STRIDE ); + + ctx->VB = cvaVB; + + do { + for ( i= VB->CopyStart ; i < count ; parity = 0, i = next ) + { + prim = VB->Primitive[i]; + next = VB->NextPrimitive[i]; + + state = gl_prim_state_machine[prim][parity]; + func = tab[flags][reduce_prim[prim]]; + func( cvaVB, VB, state, i, next ); + + if ( ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE ) + { + cvaVB->Specular = cvaVB->Spec[0]; + cvaVB->ColorPtr = cvaVB->Color[0]; + cvaVB->IndexPtr = cvaVB->Index[0]; + } + } + } while (ctx->Driver.MultipassFunc && + ctx->Driver.MultipassFunc( VB, ++p )); + + + + if (ctx->PB->count > 0) + gl_flush_pb(ctx); + + ctx->VB = saved_vb; +} + + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_cva(void) +{ + return 0; +} + + +#endif /* FX */ diff --git a/xc/extras/Mesa/src/FX/fxcva.h b/xc/extras/Mesa/src/FX/fxcva.h new file mode 100644 index 000000000..f809ec010 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxcva.h @@ -0,0 +1,70 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifndef _FXCVA_H_ +#define _FXCVA_H_ + + + +extern GLboolean fxMergeAndRenderCVA( struct vertex_buffer *VB, + struct vertex_buffer *cvaVB ); + + + +extern void fxRenderCVAElements( struct vertex_buffer *VB, + GLenum mode, + GLuint *elts, + GLuint n ); + + +extern GLboolean fxCheckCVA( GLcontext *ctx ); + + +extern void fxPrecalcCVA( struct vertex_buffer *VB ); + + + +#endif + diff --git a/xc/extras/Mesa/src/FX/fxcvatmp.h b/xc/extras/Mesa/src/FX/fxcvatmp.h new file mode 100644 index 000000000..801dc0edd --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxcvatmp.h @@ -0,0 +1,262 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +static void TAG(cva_render_points)( struct vertex_buffer *cvaVB, + struct vertex_buffer *VB, + const struct gl_prim_state *state, + GLuint start, + GLuint count ) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + fxVertex *gWin = FX_DRIVER_DATA(cvaVB)->verts; + const GLuint *elt = VB->EltPtr->data; + GLuint i; + + VARS; + INIT; + (void) fxMesa; + + if (cvaVB->ClipOrMask) { + const GLubyte *clip = cvaVB->ClipMask; + for (i = start ; i < count ; i++ INCR) { + GLuint e = elt[i]; + if (!clip[e]) { + GLfloat *v = gWin[e].f; (void) v; + if (!DIRECT) { MERGE_VB; } + MERGE_RAST; + DRAW_POINT; + } + } + } else { + for (i = start ; i < count ; i++ INCR) { + GLuint e = elt[i]; + GLfloat *v = gWin[e].f; (void) v; + if (!DIRECT) { MERGE_VB; } + MERGE_RAST; + DRAW_POINT; + } + } +} + +static void TAG(cva_render_lines)( struct vertex_buffer *cvaVB, + struct vertex_buffer *VB, + const struct gl_prim_state *state, + GLuint start, + GLuint count ) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + fxVertex *gWin = FX_DRIVER_DATA(cvaVB)->verts; + const GLuint *elt = VB->EltPtr->data; + GLuint i; + + VARS; + INIT; + (void) fxMesa; + + if (cvaVB->ClipOrMask) { + const GLubyte *clip = cvaVB->ClipMask; + GLuint prev = 0; + GLfloat *prev_v = 0; + + (void) ctx; + + for (i = start ; i < count ; i++ INCR) { + GLuint e = elt[i]; + GLfloat *v = gWin[e].f; + + MERGE_VB; + + if (!clip[e]) + MERGE_RAST; + + if (state->draw) { + if (clip[e] | clip[prev]) + CLIP_LINE; + else + DRAW_LINE; + } + + prev = e; + prev_v = v; + state = state->next; + } + if (state->finish_loop) { + GLuint e = elt[start]; + GLfloat *v = gWin[e].f; (void) v; + + if (!DIRECT) { MERGE_VB; } + MERGE_RAST; + + if (clip[e] | clip[prev]) + CLIP_LINE; + else + DRAW_LINE; + } + } else { + GLuint prev = 0; + GLfloat *prev_v = 0; + + for (i = start ; i < count ; i++ INCR) { + GLuint e = elt[i]; + GLfloat *v = gWin[e].f; + + if (!DIRECT) { MERGE_VB; } + MERGE_RAST; + if (state->draw) DRAW_LINE; + prev = e; + prev_v = v; + state = state->next; + } + if (state->finish_loop) { + GLuint e = elt[start]; + GLfloat *v = gWin[e].f; (void) v; + + if (!DIRECT) { MERGE_VB; } + MERGE_RAST; + DRAW_LINE; + } + } +} + + +static void TAG(cva_render_tris)( struct vertex_buffer *cvaVB, + struct vertex_buffer *VB, + const struct gl_prim_state *state, + GLuint start, + GLuint count ) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + fxVertex *gWin = FX_DRIVER_DATA(cvaVB)->verts; + const GLuint *elt = VB->EltPtr->data; + GLuint i; + VARS; + INIT; + (void) fxMesa; + + if (cvaVB->ClipOrMask) { + GLuint vlist[VB_MAX_CLIPPED_VERTS]; + GLuint l[3]; + const GLubyte *clip = cvaVB->ClipMask; + + (void) vlist; + + for (i = start ; i < count ; i++ INCR) { + GLuint e = l[2] = elt[i]; + GLfloat *v = gWin[e].f; (void) v; + + MERGE_VB; /* needed for clip-interp */ + + if (!clip[e]) { + MERGE_RAST; + } + + if (state->draw) + CLIP_OR_DRAW_TRI; + + + l[0] = l[state->v0]; + l[1] = l[state->v1]; + state = state->next; + } + } else if (DIRECT) { + GrVertex *vl[3]; + for (i = start ; i < count ; i++ INCR) { + GLuint e = elt[i]; + GLfloat *v = gWin[elt[i]].f; + + vl[2] = (GrVertex *)v; + + (void) v; + (void) e; + + MERGE_RAST; + + if (state->draw) + DRAW_TRI2; + + vl[0] = vl[state->v0]; + vl[1] = vl[state->v1]; + state = state->next; + } + } else { + GLuint l[3]; + for (i = start ; i < count ; i++ INCR) { + GLuint e = l[2] = elt[i]; + GLfloat *v = gWin[e].f; (void) v; + + MERGE_VB; /* needed for ctx->trianglefunc? */ + MERGE_RAST; + + if (state->draw) + DRAW_TRI; + + l[0] = l[state->v0]; + l[1] = l[state->v1]; + state = state->next; + } + } +} + + +static void TAG(init_cva)( void ) +{ + merge_and_render_tab[DIRECT][IDX][PRIM_POINTS] = TAG(cva_render_points); + merge_and_render_tab[DIRECT][IDX][PRIM_LINES] = TAG(cva_render_lines); + merge_and_render_tab[DIRECT][IDX][PRIM_TRIS] = TAG(cva_render_tris); + merge_and_render_tab[DIRECT][IDX][PRIM_CULLED] = fxCvaRenderNoop; +} + + +#undef IDX +#undef MERGE_RAST +#undef MERGE_VB +#undef VARS +#undef INIT +#undef INCR +#undef TAG + diff --git a/xc/extras/Mesa/src/FX/fxdd.c b/xc/extras/Mesa/src/FX/fxdd.c new file mode 100644 index 000000000..fc8bbb824 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxdd.c @@ -0,0 +1,1189 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* fxdd.c - 3Dfx VooDoo Mesa device driver functions */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "image.h" +#include "types.h" +#include "fxdrv.h" +#include "enums.h" +#include "extensions.h" +#include "pb.h" + +/* These lookup table are used to extract RGB values in [0,255] from + * 16-bit pixel values. + */ +GLubyte FX_PixelToR[0x10000]; +GLubyte FX_PixelToG[0x10000]; +GLubyte FX_PixelToB[0x10000]; + + +/* + * Initialize the FX_PixelTo{RGB} arrays. + * Input: bgrOrder - if TRUE, pixels are in BGR order, else RGB order. + */ +void fxInitPixelTables(fxMesaContext fxMesa, GLboolean bgrOrder) +{ + GLuint pixel; + + fxMesa->bgrOrder=bgrOrder; + for (pixel = 0; pixel <= 0xffff; pixel++) { + GLuint r, g, b; + if (bgrOrder) { + r = (pixel & 0x001F) << 3; + g = (pixel & 0x07E0) >> 3; + b = (pixel & 0xF800) >> 8; + } + else { + r = (pixel & 0xF800) >> 8; + g = (pixel & 0x07E0) >> 3; + b = (pixel & 0x001F) << 3; + } + r = r * 255 / 0xF8; /* fill in low-order bits */ + g = g * 255 / 0xFC; + b = b * 255 / 0xF8; + FX_PixelToR[pixel] = r; + FX_PixelToG[pixel] = g; + FX_PixelToB[pixel] = b; + } +} + + +/**********************************************************************/ +/***** Miscellaneous functions *****/ +/**********************************************************************/ + +/* Enalbe/Disable dithering */ +static void fxDDDither(GLcontext *ctx, GLboolean enable) +{ + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDDither()\n"); + } + + if (enable) { + FX_grDitherMode(GR_DITHER_4x4); + } else { + FX_grDitherMode(GR_DITHER_DISABLE); + } +} + + +/* Return buffer size information */ +static void fxDDBufferSize(GLcontext *ctx, GLuint *width, GLuint *height) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDBufferSize(...) Start\n"); + } + + *width=fxMesa->width; + *height=fxMesa->height; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDBufferSize(...) End\n"); + } +} + + +/* Set current drawing color */ +static void fxDDSetColor(GLcontext *ctx, GLubyte red, GLubyte green, + GLubyte blue, GLubyte alpha ) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLubyte col[4]; + ASSIGN_4V( col, red, green, blue, alpha ); + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDSetColor(%d,%d,%d,%d)\n",red,green,blue,alpha); + } + + fxMesa->color=FXCOLOR4(col); +} + + +/* Implements glClearColor() */ +static void fxDDClearColor(GLcontext *ctx, GLubyte red, GLubyte green, + GLubyte blue, GLubyte alpha ) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLubyte col[4]; + + + + ASSIGN_4V( col, red, green, blue, 255 ); + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",red,green,blue,alpha); + } + + fxMesa->clearC=FXCOLOR4( col ); + fxMesa->clearA=alpha; +} + + +/* Clear the color and/or depth buffers */ +static GLbitfield fxDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint x, GLint y, GLint width, GLint height ) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); + const FxU16 clearD = (FxU16) (ctx->Depth.Clear * 0xffff); + GLbitfield softwareMask = mask & (DD_STENCIL_BIT | DD_ACCUM_BIT); + + /* we can't clear stencil or accum buffers */ + mask &= ~(DD_STENCIL_BIT | DD_ACCUM_BIT); + + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDClear(%d,%d,%d,%d)\n", (int) x, (int) y, + (int) width, (int) height); + } + + if (colorMask != 0xffffffff) { + /* do masked color buffer clears in software */ + softwareMask |= (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)); + mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT); + } + + /* + * This could probably be done fancier but doing each possible case + * explicitly is less error prone. + */ + switch (mask) { + case DD_BACK_LEFT_BIT | DD_DEPTH_BIT: + /* back buffer & depth */ + FX_grDepthMask(FXTRUE); + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD); + if (!ctx->Depth.Mask) { + FX_grDepthMask(FXFALSE); + } + break; + case DD_FRONT_LEFT_BIT | DD_DEPTH_BIT: + /* XXX it appears that the depth buffer isn't cleared when + * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set. + * This is a work-around/ + */ + /* clear depth */ + FX_grDepthMask(FXTRUE); + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + FX_grColorMask(FXFALSE,FXFALSE); + FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD); + /* clear front */ + FX_grColorMask(FXTRUE, ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer); + FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER); + FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD); + break; + case DD_BACK_LEFT_BIT: + /* back buffer only */ + FX_grDepthMask(FXFALSE); + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD); + if (ctx->Depth.Mask) { + FX_grDepthMask(FXTRUE); + } + break; + case DD_FRONT_LEFT_BIT: + /* front buffer only */ + FX_grDepthMask(FXFALSE); + FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER); + FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD); + if (ctx->Depth.Mask) { + FX_grDepthMask(FXTRUE); + } + break; + case DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT: + /* front and back */ + FX_grDepthMask(FXFALSE); + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD); + FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER); + FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD); + if (ctx->Depth.Mask) { + FX_grDepthMask(FXTRUE); + } + break; + case DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | DD_DEPTH_BIT: + /* clear front */ + FX_grDepthMask(FXFALSE); + FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER); + FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD); + /* clear back and depth */ + FX_grDepthMask(FXTRUE); + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD); + if (!ctx->Depth.Mask) { + FX_grDepthMask(FXFALSE); + } + break; + case DD_DEPTH_BIT: + /* just the depth buffer */ + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + FX_grColorMask(FXFALSE,FXFALSE); + FX_grDepthMask(FXTRUE); + FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD); + FX_grColorMask(FXTRUE, ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer); + if (ctx->Color.DrawDestMask & FRONT_LEFT_BIT) + FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER); + if (!ctx->Depth.Test || !ctx->Depth.Mask) + FX_grDepthMask(FXFALSE); + break; + default: + /* error */ + ; + } + + return softwareMask; +} + + +/* Set the buffer used for drawing */ +/* XXX support for separate read/draw buffers hasn't been tested */ +static GLboolean fxDDSetDrawBuffer(GLcontext *ctx, GLenum mode) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDSetBuffer(%x)\n", (int) mode); + } + + if (mode == GL_FRONT_LEFT) { + fxMesa->currentFB = GR_BUFFER_FRONTBUFFER; + FX_grRenderBuffer(fxMesa->currentFB); + return GL_TRUE; + } + else if (mode == GL_BACK_LEFT) { + fxMesa->currentFB = GR_BUFFER_BACKBUFFER; + FX_grRenderBuffer(fxMesa->currentFB); + return GL_TRUE; + } + else if (mode == GL_NONE) { + FX_grColorMask(FXFALSE,FXFALSE); + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + + +/* Set the buffer used for reading */ +/* XXX support for separate read/draw buffers hasn't been tested */ +static void fxDDSetReadBuffer(GLcontext *ctx, GLframebuffer *buffer, + GLenum mode ) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + (void) buffer; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDSetBuffer(%x)\n", (int) mode); + } + + if (mode == GL_FRONT_LEFT) { + fxMesa->currentFB = GR_BUFFER_FRONTBUFFER; + FX_grRenderBuffer(fxMesa->currentFB); + } + else if (mode == GL_BACK_LEFT) { + fxMesa->currentFB = GR_BUFFER_BACKBUFFER; + FX_grRenderBuffer(fxMesa->currentFB); + } +} + + +#ifdef XF86DRI +/* test if window coord (px,py) is visible */ +static GLboolean inClipRects(fxMesaContext fxMesa, int px, int py) +{ + int i; + for (i=0; i<fxMesa->numClipRects; i++) { + if ((px>=fxMesa->pClipRects[i].x1) && + (px<fxMesa->pClipRects[i].x2) && + (py>=fxMesa->pClipRects[i].y1) && + (py<fxMesa->pClipRects[i].y2)) return GL_TRUE; + } + return GL_FALSE; +} +#endif + + +static GLboolean fxDDDrawBitmap(GLcontext *ctx, GLint px, GLint py, + GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GrLfbInfo_t info; + FxU16 color; + const struct gl_pixelstore_attrib *finalUnpack; + struct gl_pixelstore_attrib scissoredUnpack; + + /* check if there's any raster operations enabled which we can't handle */ + if (ctx->RasterMask & (ALPHATEST_BIT | + BLEND_BIT | + DEPTH_BIT | + FOG_BIT | + LOGIC_OP_BIT | + SCISSOR_BIT | + STENCIL_BIT | + MASKING_BIT | + ALPHABUF_BIT | + MULTI_DRAW_BIT)) + return GL_FALSE; + + if (ctx->Scissor.Enabled) { + /* This is a bit tricky, but by carefully adjusting the px, py, + * width, height, skipPixels and skipRows values we can do + * scissoring without special code in the rendering loop. + */ + + /* we'll construct a new pixelstore struct */ + finalUnpack = &scissoredUnpack; + scissoredUnpack = *unpack; + if (scissoredUnpack.RowLength == 0) + scissoredUnpack.RowLength = width; + + /* clip left */ + if (px < ctx->Scissor.X) { + scissoredUnpack.SkipPixels += (ctx->Scissor.X - px); + width -= (ctx->Scissor.X - px); + px = ctx->Scissor.X; + } + /* clip right */ + if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) { + width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width)); + } + /* clip bottom */ + if (py < ctx->Scissor.Y) { + scissoredUnpack.SkipRows += (ctx->Scissor.Y - py); + height -= (ctx->Scissor.Y - py); + py = ctx->Scissor.Y; + } + /* clip top */ + if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) { + height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height)); + } + + if (width <= 0 || height <= 0) + return GL_TRUE; /* totally scissored away */ + } + else { + finalUnpack = unpack; + } + + /* compute pixel value */ + { + GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0f); + GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0f); + GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0f); + /*GLint a = (GLint)(ctx->Current.RasterColor[3]*255.0f);*/ + if (fxMesa->bgrOrder) + color = (FxU16) + ( ((FxU16)0xf8 & b) << (11-3)) | + ( ((FxU16)0xfc & g) << (5-3+1)) | + ( ((FxU16)0xf8 & r) >> 3); + else + color = (FxU16) + ( ((FxU16)0xf8 & r) << (11-3)) | + ( ((FxU16)0xfc & g) << (5-3+1)) | + ( ((FxU16)0xf8 & b) >> 3); + } + + info.size = sizeof(info); + if (!FX_grLfbLock(GR_LFB_WRITE_ONLY, + fxMesa->currentFB, + GR_LFBWRITEMODE_565, + GR_ORIGIN_UPPER_LEFT, + FXFALSE, + &info)) { +#ifndef FX_SILENT + fprintf(stderr,"fx Driver: error locking the linear frame buffer\n"); +#endif + return GL_TRUE; + } + +#ifdef XF86DRI +#define INSIDE(c, x, y) inClipRects((c), (x), (y)) +#else +#define INSIDE(c, x, y) (1) +#endif + + { + const GLint winX = fxMesa->x_offset; + const GLint winY = fxMesa->y_offset + fxMesa->height - 1; + /* The dest stride depends on the hardware and whether we're drawing + * to the front or back buffer. This compile-time test seems to do + * the job for now. + */ +#ifdef XF86DRI + const GLint dstStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT) + ? (fxMesa->screen_width) : (info.strideInBytes / 2); +#else + const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */ +#endif + GLint row; + /* compute dest address of bottom-left pixel in bitmap */ + GLushort *dst = (GLushort *) info.lfbPtr + + (winY - py) * dstStride + + (winX + px); + + for (row = 0; row < height; row++) { + const GLubyte *src = (const GLubyte *) _mesa_image_address( finalUnpack, + bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 ); + if (finalUnpack->LsbFirst) { + /* least significan bit first */ + GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7); + GLint col; + for (col=0; col<width; col++) { + if (*src & mask) { + if (INSIDE(fxMesa, winX + px + col, winY - py - row)) + dst[col] = color; + } + if (mask == 128U) { + src++; + mask = 1U; + } + else { + mask = mask << 1; + } + } + if (mask != 1) + src++; + } + else { + /* most significan bit first */ + GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7); + GLint col; + for (col=0; col<width; col++) { + if (*src & mask) { + if (INSIDE(fxMesa, winX + px + col, winY - py - row)) + dst[col] = color; + } + if (mask == 1U) { + src++; + mask = 128U; + } + else { + mask = mask >> 1; + } + } + if (mask != 128) + src++; + } + dst -= dstStride; + } + } + +#undef INSIDE + + FX_grLfbUnlock(GR_LFB_WRITE_ONLY,fxMesa->currentFB); + return GL_TRUE; +} + + +static GLboolean fxDDReadPixels( GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *packing, + GLvoid *dstImage ) +{ + if (ctx->Pixel.ScaleOrBiasRGBA || ctx->Pixel.MapColorFlag) { + return GL_FALSE; /* can't do this */ + } + else { + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GrLfbInfo_t info; + GLboolean result = GL_FALSE; + + BEGIN_BOARD_LOCK(); + if (grLfbLock(GR_LFB_READ_ONLY, + fxMesa->currentFB, + GR_LFBWRITEMODE_ANY, + GR_ORIGIN_UPPER_LEFT, + FXFALSE, + &info)) { + const GLint winX = fxMesa->x_offset; + const GLint winY = fxMesa->y_offset + fxMesa->height - 1; +#ifdef XF86DRI + const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT) + ? (fxMesa->screen_width) : (info.strideInBytes / 2); +#else + const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */ +#endif + const GLushort *src = (const GLushort *) info.lfbPtr + + (winY - y) * srcStride + (winX + x); + GLubyte *dst = (GLubyte *) _mesa_image_address(packing, dstImage, + width, height, format, type, 0, 0, 0); + GLint dstStride = _mesa_image_row_stride(packing, width, format, type); + + if (format == GL_RGB && type == GL_UNSIGNED_BYTE) { + /* convert 5R6G5B into 8R8G8B */ + GLint row, col; + const GLint halfWidth = width >> 1; + const GLint extraPixel = (width & 1); + for (row = 0; row < height; row++) { + GLubyte *d = dst; + for (col = 0; col < halfWidth; col++) { + const GLuint pixel = ((const GLuint *) src)[col]; + const GLint pixel0 = pixel & 0xffff; + const GLint pixel1 = pixel >> 16; + *d++ = FX_PixelToR[pixel0]; + *d++ = FX_PixelToG[pixel0]; + *d++ = FX_PixelToB[pixel0]; + *d++ = FX_PixelToR[pixel1]; + *d++ = FX_PixelToG[pixel1]; + *d++ = FX_PixelToB[pixel1]; + } + if (extraPixel) { + GLushort pixel = src[width-1]; + *d++ = FX_PixelToR[pixel]; + *d++ = FX_PixelToG[pixel]; + *d++ = FX_PixelToB[pixel]; + } + dst += dstStride; + src -= srcStride; + } + result = GL_TRUE; + } + else if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) { + /* convert 5R6G5B into 8R8G8B8A */ + GLint row, col; + const GLint halfWidth = width >> 1; + const GLint extraPixel = (width & 1); + for (row = 0; row < height; row++) { + GLubyte *d = dst; + for (col = 0; col < halfWidth; col++) { + const GLuint pixel = ((const GLuint *) src)[col]; + const GLint pixel0 = pixel & 0xffff; + const GLint pixel1 = pixel >> 16; + *d++ = FX_PixelToR[pixel0]; + *d++ = FX_PixelToG[pixel0]; + *d++ = FX_PixelToB[pixel0]; + *d++ = 255; + *d++ = FX_PixelToR[pixel1]; + *d++ = FX_PixelToG[pixel1]; + *d++ = FX_PixelToB[pixel1]; + *d++ = 255; + } + if (extraPixel) { + const GLushort pixel = src[width-1]; + *d++ = FX_PixelToR[pixel]; + *d++ = FX_PixelToG[pixel]; + *d++ = FX_PixelToB[pixel]; + *d++ = 255; + } + dst += dstStride; + src -= srcStride; + } + result = GL_TRUE; + } + else if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) { + /* directly memcpy 5R6G5B pixels into client's buffer */ + const GLint widthInBytes = width * 2; + GLint row; + for (row = 0; row < height; row++) { + MEMCPY(dst, src, widthInBytes); + dst += dstStride; + src -= srcStride; + } + result = GL_TRUE; + } + else { + result = GL_FALSE; + } + + grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB); + } + END_BOARD_LOCK(); + return result; + } +} + + + +static void fxDDFinish(GLcontext *ctx) +{ + FX_grFlush(); +} + + +static GLint fxDDGetParameteri(const GLcontext *ctx, GLint param) +{ + switch(param) { + case DD_HAVE_HARDWARE_FOG: + return 1; + default: + fprintf(stderr,"fx Driver: internal error in fxDDGetParameteri(): %x\n", (int) param); + fxCloseHardware(); + exit(-1); + return 0; + } +} + + +void fxDDSetNearFar(GLcontext *ctx, GLfloat n, GLfloat f) +{ + FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG; + ctx->Driver.RenderStart = fxSetupFXUnits; +} + +/* KW: Put the word Mesa in the render string because quakeworld + * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE). + * Why? + */ +static const GLubyte *fxDDGetString(GLcontext *ctx, GLenum name) +{ +#if defined(GLX_DIRECT_RENDERING) + /* Building for DRI driver */ + switch (name) { + case GL_RENDERER: + { + static char buffer[100]; + char hardware[100]; + strcpy(hardware, grGetString(GR_HARDWARE)); + if (strcmp(hardware, "Voodoo3 (tm)") == 0) + strcpy(hardware, "Voodoo3"); + else if (strcmp(hardware, "Voodoo Banshee (tm)") == 0) + strcpy(hardware, "VoodooBanshee"); + else { + /* unexpected result: replace spaces with hyphens */ + int i; + for (i = 0; hardware[i]; i++) { + if (hardware[i] == ' ' || hardware[i] == '\t') + hardware[i] = '-'; + } + } + /* now make the GL_RENDERER string */ + sprintf(buffer, "Mesa DRI %s 20000510", hardware); + return buffer; + } + case GL_VENDOR: + return "Precision Insight, Inc."; + default: + return NULL; + } + +#else + + /* Building for Voodoo1/2 stand-alone Mesa */ + switch (name) { + case GL_RENDERER: + { + static char buf[80]; + + if (glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) { + GrVoodooConfig_t *vc = + &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig; + + sprintf(buf, + "Mesa Glide v0.30 Voodoo_Graphics %d " + "CARD/%d FB/%d TM/%d TMU/%s", + glbCurrentBoard, + (vc->sliDetect ? (vc->fbRam*2) : vc->fbRam), + (vc->tmuConfig[GR_TMU0].tmuRam + + ((vc->nTexelfx>1) ? vc->tmuConfig[GR_TMU1].tmuRam : 0)), + vc->nTexelfx, + (vc->sliDetect ? "SLI" : "NOSLI")); + } + else if (glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96) { + GrSst96Config_t *sc = + &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config; + + sprintf(buf, + "Glide v0.30 Voodoo_Rush %d " + "CARD/%d FB/%d TM/%d TMU/NOSLI", + glbCurrentBoard, + sc->fbRam, + sc->tmuConfig.tmuRam, + sc->nTexelfx); + } + else { + strcpy(buf, "Glide v0.30 UNKNOWN"); + } + return (GLubyte *) buf; + } + default: + return NULL; + } +#endif +} + + +int fxDDInitFxMesaContext( fxMesaContext fxMesa ) +{ + + FX_setupGrVertexLayout(); + + if (getenv("FX_EMULATE_SINGLE_TMU")) + fxMesa->haveTwoTMUs = GL_FALSE; + + fxMesa->emulateTwoTMUs = fxMesa->haveTwoTMUs; + + if (!getenv("FX_DONT_FAKE_MULTITEX")) + fxMesa->emulateTwoTMUs = GL_TRUE; + + if(getenv("FX_GLIDE_SWAPINTERVAL")) + fxMesa->swapInterval=atoi(getenv("FX_GLIDE_SWAPINTERVAL")); + else + fxMesa->swapInterval=1; + + if(getenv("MESA_FX_SWAP_PENDING")) + fxMesa->maxPendingSwapBuffers=atoi(getenv("MESA_FX_SWAP_PENDING")); + else + fxMesa->maxPendingSwapBuffers=2; + + if(getenv("MESA_FX_INFO")) + fxMesa->verbose=GL_TRUE; + else + fxMesa->verbose=GL_FALSE; + + fxMesa->color=0xffffffff; + fxMesa->clearC=0; + fxMesa->clearA=0; + + fxMesa->stats.swapBuffer=0; + fxMesa->stats.reqTexUpload=0; + fxMesa->stats.texUpload=0; + fxMesa->stats.memTexUpload=0; + + fxMesa->tmuSrc=FX_TMU_NONE; + fxMesa->lastUnitsMode=FX_UM_NONE; + fxTMInit(fxMesa); + + /* FX units setup */ + + fxMesa->unitsState.alphaTestEnabled=GL_FALSE; + fxMesa->unitsState.alphaTestFunc=GR_CMP_ALWAYS; + fxMesa->unitsState.alphaTestRefValue=0; + + fxMesa->unitsState.blendEnabled=GL_FALSE; + fxMesa->unitsState.blendSrcFuncRGB=GR_BLEND_ONE; + fxMesa->unitsState.blendDstFuncRGB=GR_BLEND_ZERO; + fxMesa->unitsState.blendSrcFuncAlpha=GR_BLEND_ONE; + fxMesa->unitsState.blendDstFuncAlpha=GR_BLEND_ZERO; + + fxMesa->unitsState.depthTestEnabled =GL_FALSE; + fxMesa->unitsState.depthMask =GL_TRUE; + fxMesa->unitsState.depthTestFunc =GR_CMP_LESS; + + FX_grColorMask(FXTRUE, fxMesa->haveAlphaBuffer ? FXTRUE : FXFALSE); + if(fxMesa->haveDoubleBuffer) { + fxMesa->currentFB=GR_BUFFER_BACKBUFFER; + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + } else { + fxMesa->currentFB=GR_BUFFER_FRONTBUFFER; + FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER); + } + + fxMesa->state = NULL; + fxMesa->fogTable = NULL; + + fxMesa->state = malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE)); + fxMesa->fogTable = malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES)*sizeof(GrFog_t)); + + if (!fxMesa->state || !fxMesa->fogTable) { + if (fxMesa->state) free(fxMesa->state); + if (fxMesa->fogTable) free(fxMesa->fogTable); + return 0; + } + + if(fxMesa->haveZBuffer) + FX_grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER); + +#if (!FXMESA_USE_ARGB) + FX_grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); /* Not every Glide has this */ +#endif + + fxMesa->textureAlign=FX_grGetInteger(FX_TEXTURE_ALIGN); + fxMesa->glCtx->Const.MaxTextureLevels=9; + fxMesa->glCtx->Const.MaxTextureSize=256; + fxMesa->glCtx->Const.MaxTextureUnits=fxMesa->emulateTwoTMUs ? 2 : 1; + fxMesa->glCtx->NewState|=NEW_DRVSTATE1; + fxMesa->new_state = NEW_ALL; + + fxDDSetupInit(); + fxDDCvaInit(); + fxDDClipInit(); + fxDDTrifuncInit(); + fxDDFastPathInit(); + + fxSetupDDPointers(fxMesa->glCtx); + fxDDRenderInit(fxMesa->glCtx); + fxDDInitExtensions(fxMesa->glCtx); + + fxDDSetNearFar(fxMesa->glCtx,1.0,100.0); + + FX_grGlideGetState((GrState*)fxMesa->state); + + /* XXX Fix me: callback not registered when main VB is created. + */ + if (fxMesa->glCtx->VB) + fxDDRegisterVB( fxMesa->glCtx->VB ); + + /* XXX Fix me too: need to have the 'struct dd' prepared prior to + * creating the context... The below is broken if you try to insert + * new stages. + */ + if (fxMesa->glCtx->NrPipelineStages) + fxMesa->glCtx->NrPipelineStages = fxDDRegisterPipelineStages( + fxMesa->glCtx->PipelineStage, + fxMesa->glCtx->PipelineStage, + fxMesa->glCtx->NrPipelineStages); + + /* Run the config file */ + gl_context_initialize( fxMesa->glCtx ); + + return 1; +} + + +#if 0 +/* Example extension function */ +static void fxFooBarEXT(GLint i) +{ + printf("You called glFooBarEXT(%d)\n", i); +} +#endif + + +void fxDDInitExtensions( GLcontext *ctx ) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + + gl_extensions_disable(ctx, "GL_EXT_blend_logic_op"); + gl_extensions_disable(ctx, "GL_EXT_blend_minmax"); + gl_extensions_disable(ctx, "GL_EXT_blend_subtract"); + gl_extensions_disable(ctx, "GL_EXT_blend_color"); + + gl_extensions_add(ctx, DEFAULT_ON, "3DFX_set_global_palette", 0); + + if (!fxMesa->haveTwoTMUs) + gl_extensions_disable(ctx, "GL_EXT_texture_env_add"); + + if (!fxMesa->emulateTwoTMUs) + gl_extensions_disable(ctx, "GL_ARB_multitexture"); + + + /* Example of hooking in an extension function. + * For DRI-based drivers, also see __driRegisterExtensions in the + * tdfx_xmesa.c file. + */ +#if 0 + { + void **dispatchTable = (void **) ctx->Exec; + const int _gloffset_FooBarEXT = 555; /* just an example number! */ + const int tabSize = _glapi_get_dispatch_table_size(); + assert(_gloffset_FooBarEXT < tabSize); + dispatchTable[_gloffset_FooBarEXT] = (void *) fxFooBarEXT; + /* XXX You would also need to hook into the display list dispatch + * table. Really, the implementation of extensions might as well + * be in the core of Mesa since core Mesa and the device driver + * is one big shared lib. + */ + } +#endif +} + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +/* Check if the hardware supports the current context + * + * Performs similar work to fxDDChooseRenderState() - should be merged. + */ +static GLboolean fxIsInHardware(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + + if (!ctx->Hint.AllowDrawMem) + return GL_TRUE; /* you'll take it and like it */ + + if((ctx->RasterMask & (STENCIL_BIT | MULTI_DRAW_BIT)) || + ((ctx->Color.BlendEnabled) && (ctx->Color.BlendEquation!=GL_FUNC_ADD_EXT)) || + ((ctx->Color.ColorLogicOpEnabled) && (ctx->Color.LogicOp!=GL_COPY)) || + (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) || + (!((ctx->Color.ColorMask[RCOMP]==ctx->Color.ColorMask[GCOMP]) && + (ctx->Color.ColorMask[GCOMP]==ctx->Color.ColorMask[BCOMP]) && + (ctx->Color.ColorMask[ACOMP]==ctx->Color.ColorMask[ACOMP]))) + ) + { + return GL_FALSE; + } + /* Unsupported texture/multitexture cases */ + + if(fxMesa->emulateTwoTMUs) { + if((ctx->Enabled & (TEXTURE0_3D | TEXTURE1_3D)) || + /* Not very well written ... */ + ((ctx->Enabled & (TEXTURE0_1D | TEXTURE1_1D)) && + ((ctx->Enabled & (TEXTURE0_2D | TEXTURE1_2D))!=(TEXTURE0_2D | TEXTURE1_2D))) + ) { + return GL_FALSE; + } + + if (ctx->Texture.ReallyEnabled & TEXTURE0_2D) { + if (ctx->Texture.Unit[0].EnvMode == GL_BLEND && + (ctx->Texture.ReallyEnabled & TEXTURE1_2D || + ctx->Texture.Unit[0].EnvColor[0] != 0 || + ctx->Texture.Unit[0].EnvColor[1] != 0 || + ctx->Texture.Unit[0].EnvColor[2] != 0 || + ctx->Texture.Unit[0].EnvColor[3] != 1)) { + return GL_FALSE; + } + if (ctx->Texture.Unit[0].Current->Image[0]->Border > 0) + return GL_FALSE; + } + + if (ctx->Texture.ReallyEnabled & TEXTURE1_2D) { + if (ctx->Texture.Unit[1].EnvMode == GL_BLEND) + return GL_FALSE; + if (ctx->Texture.Unit[0].Current->Image[0]->Border > 0) + return GL_FALSE; + } + + if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE)) + fprintf(stderr, "fxMesa: fxIsInHardware, envmode is %s/%s\n", + gl_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode), + gl_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode)); + + /* KW: This was wrong (I think) and I changed it... which doesn't mean + * it is now correct... + */ + if((ctx->Enabled & (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D)) && + (ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D))) + { + /* Can't use multipass to blend a multitextured triangle - fall + * back to software. + */ + if (!fxMesa->haveTwoTMUs && ctx->Color.BlendEnabled) { + return GL_FALSE; + } + + if ((ctx->Texture.Unit[0].EnvMode!=ctx->Texture.Unit[1].EnvMode) && + (ctx->Texture.Unit[0].EnvMode!=GL_MODULATE) && + (ctx->Texture.Unit[0].EnvMode!=GL_REPLACE)) /* q2, seems ok... */ + { + if (MESA_VERBOSE&VERBOSE_DRIVER) + fprintf(stderr, "fxMesa: unsupported multitex env mode\n"); + return GL_FALSE; + } + } + } else { + if((ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)) || + /* Not very well written ... */ + ((ctx->Enabled & TEXTURE0_1D) && + (!(ctx->Enabled & TEXTURE0_2D))) + ) { + return GL_FALSE; + } + + + if((ctx->Texture.ReallyEnabled & TEXTURE0_2D) && + (ctx->Texture.Unit[0].EnvMode==GL_BLEND)) { + return GL_FALSE; + } + } + + return GL_TRUE; +} + + + +#define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|NEW_PROJECTION|NEW_TEXTURE_MATRIX|NEW_USER_CLIP|NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE)) + +static void fxDDUpdateDDPointers(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint new_state = ctx->NewState; + + if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_STATE)) + fprintf(stderr,"fxmesa: fxDDUpdateDDPointers(...)\n"); + + if (new_state & (NEW_RASTER_OPS|NEW_TEXTURING)) + fxMesa->is_in_hardware = fxIsInHardware(ctx); + + if (fxMesa->is_in_hardware) { + if (fxMesa->new_state) + fxSetupFXUnits(ctx); + + if(new_state & INTERESTED) { + fxDDChooseRenderState( ctx ); + fxMesa->RenderVBTables=fxDDChooseRenderVBTables(ctx); + fxMesa->RenderVBClippedTab=fxMesa->RenderVBTables[0]; + fxMesa->RenderVBCulledTab=fxMesa->RenderVBTables[1]; + fxMesa->RenderVBRawTab=fxMesa->RenderVBTables[2]; + + ctx->Driver.RasterSetup=fxDDChooseSetupFunction(ctx); + } + + ctx->Driver.PointsFunc=fxMesa->PointsFunc; + ctx->Driver.LineFunc=fxMesa->LineFunc; + ctx->Driver.TriangleFunc=fxMesa->TriangleFunc; + ctx->Driver.QuadFunc=fxMesa->QuadFunc; + } else { + fxMesa->render_index = FX_FALLBACK; + } +} + +static void fxDDReducedPrimitiveChange(GLcontext *ctx, GLenum prim) +{ + if (ctx->Polygon.CullFlag) { + if (ctx->PB->primitive != GL_POLYGON) { /* Lines or Points */ + FX_grCullMode(GR_CULL_DISABLE); + FX_CONTEXT(ctx)->cullMode=GR_CULL_DISABLE; + } + } +} + +void fxSetupDDPointers(GLcontext *ctx) +{ + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxSetupDDPointers()\n"); + } + + ctx->Driver.UpdateState=fxDDUpdateDDPointers; + + ctx->Driver.WriteDepthSpan=fxDDWriteDepthSpan; + ctx->Driver.WriteDepthPixels=fxDDWriteDepthPixels; + ctx->Driver.ReadDepthSpan=fxDDReadDepthSpan; + ctx->Driver.ReadDepthPixels=fxDDReadDepthPixels; + + ctx->Driver.GetString=fxDDGetString; + + ctx->Driver.Dither=fxDDDither; + + ctx->Driver.NearFar=fxDDSetNearFar; + + ctx->Driver.GetParameteri=fxDDGetParameteri; + + ctx->Driver.ClearIndex=NULL; + ctx->Driver.ClearColor=fxDDClearColor; + ctx->Driver.Clear=fxDDClear; + + ctx->Driver.Index=NULL; + ctx->Driver.Color=fxDDSetColor; + + ctx->Driver.SetDrawBuffer=fxDDSetDrawBuffer; + ctx->Driver.SetReadBuffer=fxDDSetReadBuffer; + ctx->Driver.GetBufferSize=fxDDBufferSize; + + ctx->Driver.Bitmap=fxDDDrawBitmap; + ctx->Driver.DrawPixels=NULL; + ctx->Driver.ReadPixels=fxDDReadPixels; + + ctx->Driver.Finish=fxDDFinish; + ctx->Driver.Flush=NULL; + + ctx->Driver.RenderStart=NULL; + ctx->Driver.RenderFinish=NULL; + + ctx->Driver.TexImage2D = fxDDTexImage2D; + ctx->Driver.TexSubImage2D = fxDDTexSubImage2D; + ctx->Driver.GetTexImage = fxDDGetTexImage; + ctx->Driver.TexEnv=fxDDTexEnv; + ctx->Driver.TexParameter=fxDDTexParam; + ctx->Driver.BindTexture=fxDDTexBind; + ctx->Driver.DeleteTexture=fxDDTexDel; + ctx->Driver.UpdateTexturePalette=fxDDTexPalette; + + ctx->Driver.RectFunc=NULL; + + ctx->Driver.AlphaFunc=fxDDAlphaFunc; + ctx->Driver.BlendFunc=fxDDBlendFunc; + ctx->Driver.DepthFunc=fxDDDepthFunc; + ctx->Driver.DepthMask=fxDDDepthMask; + ctx->Driver.ColorMask=fxDDColorMask; + ctx->Driver.Fogfv=fxDDFogfv; + ctx->Driver.Scissor=fxDDScissor; + ctx->Driver.FrontFace=fxDDFrontFace; + ctx->Driver.CullFace=fxDDCullFace; + ctx->Driver.ShadeModel=fxDDShadeModel; + ctx->Driver.Enable=fxDDEnable; + ctx->Driver.ReducedPrimitiveChange=fxDDReducedPrimitiveChange; + + ctx->Driver.RegisterVB=fxDDRegisterVB; + ctx->Driver.UnregisterVB=fxDDUnregisterVB; + + ctx->Driver.RegisterPipelineStages = fxDDRegisterPipelineStages; + + ctx->Driver.OptimizeImmediatePipeline = 0; /* nothing done yet */ + ctx->Driver.OptimizePrecalcPipeline = 0; + +/* if (getenv("MESA_USE_FAST") || getenv("FX_USE_FAST")) */ +/* ctx->Driver.OptimizePrecalcPipeline = fxDDOptimizePrecalcPipeline; */ + + if (!getenv("FX_NO_FAST")) + ctx->Driver.BuildPrecalcPipeline = fxDDBuildPrecalcPipeline; + + ctx->Driver.TriangleCaps = DD_TRI_CULL|DD_TRI_OFFSET|DD_TRI_LIGHT_TWOSIDE; + + fxSetupDDSpanPointers(ctx); + + FX_CONTEXT(ctx)->render_index = 1; /* force an update */ + fxDDUpdateDDPointers(ctx); +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_dd(void) +{ + return 0; +} + +#endif /* FX */ + diff --git a/xc/extras/Mesa/src/FX/fxddspan.c b/xc/extras/Mesa/src/FX/fxddspan.c new file mode 100644 index 000000000..c620cc3c6 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxddspan.c @@ -0,0 +1,642 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* fxdd.c - 3Dfx VooDoo Mesa span and pixel functions */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" + +#ifdef _MSC_VER +#ifdef _WIN32 +#pragma warning( disable : 4090 4022 ) +/* 4101 : "different 'const' qualifier" + * 4022 : "pointer mistmatch for actual parameter 'n' + */ +#endif +#endif + + +#if !defined(FXMESA_USE_ARGB) + + +#if defined(FX_GLIDE3) && defined(XF86DRI) + +static FxBool writeRegionClipped(fxMesaContext fxMesa, GrBuffer_t dst_buffer, + FxU32 dst_x, FxU32 dst_y, GrLfbSrcFmt_t src_format, + FxU32 src_width, FxU32 src_height, FxI32 src_stride, + void *src_data) +{ + int i, x, w, srcElt; + void *data; + + if (src_width==1 && src_height==1) { /* Easy case writing a point */ + for (i=0; i<fxMesa->numClipRects; i++) { + if ((dst_x>=fxMesa->pClipRects[i].x1) && + (dst_x<fxMesa->pClipRects[i].x2) && + (dst_y>=fxMesa->pClipRects[i].y1) && + (dst_y<fxMesa->pClipRects[i].y2)) { + FX_grLfbWriteRegion(dst_buffer, dst_x, dst_y, src_format, + 1, 1, src_stride, src_data); + return GL_TRUE; + } + } + } else if (src_height==1) { /* Writing a span */ + if (src_format==GR_LFB_SRC_FMT_8888) srcElt=4; + else if (src_format==GR_LFB_SRC_FMT_ZA16) srcElt=2; + else { + fprintf(stderr, "Unknown src_format passed to writeRegionClipped\n"); + return GL_FALSE; + } + for (i=0; i<fxMesa->numClipRects; i++) { + if (dst_y>=fxMesa->pClipRects[i].y1 && dst_y<fxMesa->pClipRects[i].y2) { + if (dst_x<fxMesa->pClipRects[i].x1) { + x=fxMesa->pClipRects[i].x1; + data=((char*)src_data)+srcElt*(x - dst_x); + w=src_width-(x-dst_x); + } else { + x=dst_x; + data=src_data; + w=src_width; + } + if (x+w>fxMesa->pClipRects[i].x2) { + w=fxMesa->pClipRects[i].x2-x; + } + FX_grLfbWriteRegion(dst_buffer, x, dst_y, src_format, w, 1, + src_stride, data); + } + } + } else { /* Punt on the case of arbitrary rectangles */ + return GL_FALSE; + } + return GL_TRUE; +} + +#else + +#define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \ + FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) + +#endif + + +/* KW: Rearranged the args in the call to grLfbWriteRegion(). + */ +#define LFB_WRITE_SPAN_MESA(dst_buffer, \ + dst_x, \ + dst_y, \ + src_width, \ + src_stride, \ + src_data) \ + writeRegionClipped(fxMesa, dst_buffer, \ + dst_x, \ + dst_y, \ + GR_LFB_SRC_FMT_8888, \ + src_width, \ + 1, \ + src_stride, \ + src_data) \ + + +#else /* !defined(FXMESA_USE_RGBA) */ + +#define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \ + FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) + + +#define MESACOLOR_TO_ARGB(c) ( \ + ( ((unsigned int)(c[ACOMP]))<<24 ) | \ + ( ((unsigned int)(c[RCOMP]))<<16 ) | \ + ( ((unsigned int)(c[GCOMP]))<<8 ) | \ + ( (unsigned int)(c[BCOMP])) ) + +inline void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer, + FxU32 dst_x, + FxU32 dst_y, + FxU32 src_width, + FxI32 src_stride, + void *src_data ) +{ + /* Covert to ARGB */ + GLubyte (*rgba)[4] = src_data; + GLuint argb[MAX_WIDTH]; + int i; + + for (i = 0; i < src_width; i++) + { + argb[i] = MESACOLOR_TO_ARGB(rgba[i]); + } + writeRegionClipped( /*fxMesa,*/ NULL, dst_buffer, + dst_x, + dst_y, + GR_LFB_SRC_FMT_8888, + src_width, + 1, + src_stride, + (void*)argb); +} + +#endif /* !defined(FXMESA_USE_RGBA) */ + + +/************************************************************************/ +/***** Span functions *****/ +/************************************************************************/ + + +static void fxDDWriteRGBASpan(const GLcontext *ctx, + GLuint n, GLint x, GLint y, + const GLubyte rgba[][4], const GLubyte mask[]) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint i; + GLint bottom=fxMesa->height+fxMesa->y_offset-1; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDWriteRGBASpan(...)\n"); + } + + x+=fxMesa->x_offset; + if (mask) { + int span=0; + + for (i=0;i<n;i++) { + if (mask[i]) { + ++span; + } else { + if (span > 0) { + LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+i-span, bottom-y, + /* GR_LFB_SRC_FMT_8888,*/ span, /*1,*/ 0, (void *) rgba[i-span] ); + span = 0; + } + } + } + + if (span > 0) + LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+n-span, bottom-y, + /* GR_LFB_SRC_FMT_8888, */ span, /*1,*/ 0, (void *) rgba[n-span] ); + } else + LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x, bottom-y,/* GR_LFB_SRC_FMT_8888,*/ + n,/* 1,*/ 0, (void *) rgba ); +} + + +static void fxDDWriteRGBSpan(const GLcontext *ctx, + GLuint n, GLint x, GLint y, + const GLubyte rgb[][3], const GLubyte mask[]) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint i; + GLint bottom=fxMesa->height+fxMesa->y_offset-1; + GLubyte rgba[MAX_WIDTH][4]; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDWriteRGBSpan()\n"); + } + + x+=fxMesa->x_offset; + if (mask) { + int span=0; + + for (i=0;i<n;i++) { + if (mask[i]) { + rgba[span][RCOMP] = rgb[i][0]; + rgba[span][GCOMP] = rgb[i][1]; + rgba[span][BCOMP] = rgb[i][2]; + rgba[span][ACOMP] = 255; + ++span; + } else { + if (span > 0) { + LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+i-span, bottom-y, + /*GR_LFB_SRC_FMT_8888,*/ span,/* 1,*/ 0, (void *) rgba ); + span = 0; + } + } + } + + if (span > 0) + LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+n-span, bottom-y, + /*GR_LFB_SRC_FMT_8888,*/ span,/* 1,*/ 0, (void *) rgba ); + } else { + for (i=0;i<n;i++) { + rgba[i][RCOMP]=rgb[i][0]; + rgba[i][GCOMP]=rgb[i][1]; + rgba[i][BCOMP]=rgb[i][2]; + rgba[i][ACOMP]=255; + } + + LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x, bottom-y,/* GR_LFB_SRC_FMT_8888,*/ + n,/* 1,*/ 0, (void *) rgba ); + } +} + + +static void fxDDWriteMonoRGBASpan(const GLcontext *ctx, + GLuint n, GLint x, GLint y, + const GLubyte mask[]) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint i; + GLint bottom=fxMesa->height+fxMesa->y_offset-1; + GLuint data[MAX_WIDTH]; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDWriteMonoRGBASpan(...)\n"); + } + + x+=fxMesa->x_offset; + if (mask) { + int span=0; + + for (i=0;i<n;i++) { + if (mask[i]) { + data[span] = (GLuint) fxMesa->color; + ++span; + } else { + if (span > 0) { + writeRegionClipped(fxMesa, fxMesa->currentFB, x+i-span, bottom-y, + GR_LFB_SRC_FMT_8888, span, 1, 0, + (void *) data ); + span = 0; + } + } + } + + if (span > 0) + writeRegionClipped(fxMesa, fxMesa->currentFB, x+n-span, bottom-y, + GR_LFB_SRC_FMT_8888, span, 1, 0, + (void *) data ); + } else { + for (i=0;i<n;i++) { + data[i]=(GLuint) fxMesa->color; + } + + writeRegionClipped(fxMesa, fxMesa->currentFB, x, bottom-y, GR_LFB_SRC_FMT_8888, + n, 1, 0, (void *) data ); + } +} + + +#if 0 +static void fxDDReadRGBASpan(const GLcontext *ctx, + GLuint n, GLint x, GLint y, GLubyte rgba[][4]) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLushort data[MAX_WIDTH]; + GLuint i; + GLint bottom=fxMesa->height+fxMesa->y_offset-1; + + printf("read span %d, %d, %d\n", x,y,n); + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDReadRGBASpan(...)\n"); + } + + assert(n < MAX_WIDTH); + + x+=fxMesa->x_offset; + FX_grLfbReadRegion( fxMesa->currentFB, x, bottom-y, n, 1, 0, data); + + for (i=0;i<n;i++) { + GLushort pixel = data[i]; + rgba[i][RCOMP] = FX_PixelToR[pixel]; + rgba[i][GCOMP] = FX_PixelToG[pixel]; + rgba[i][BCOMP] = FX_PixelToB[pixel]; + rgba[i][ACOMP] = 255; + } +} +#endif + + +/* + * Read a span of 16-bit RGB pixels. Note, we don't worry about cliprects + * since OpenGL says obscured pixels have undefined values. + */ +static void read_R5G6B5_span(const GLcontext *ctx, + GLuint n, GLint x, GLint y, GLubyte rgba[][4]) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GrLfbInfo_t info; + BEGIN_BOARD_LOCK(); + if (grLfbLock(GR_LFB_READ_ONLY, + fxMesa->currentFB, + GR_LFBWRITEMODE_ANY, + GR_ORIGIN_UPPER_LEFT, + FXFALSE, + &info)) { + const GLint winX = fxMesa->x_offset; + const GLint winY = fxMesa->y_offset + fxMesa->height - 1; +#ifdef XF86DRI + const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT) + ? (fxMesa->screen_width) : (info.strideInBytes / 2); +#else + const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */ +#endif + const GLushort *data16 = (const GLushort *) info.lfbPtr + + (winY - y) * srcStride + + (winX + x); + const GLuint *data32 = (const GLuint *) data16; + GLuint i, j; + GLuint extraPixel = (n & 1); + n -= extraPixel; + for (i = j = 0; i < n; i += 2, j++) { + GLuint pixel = data32[j]; + GLuint pixel0 = pixel & 0xffff; + GLuint pixel1 = pixel >> 16; + rgba[i][RCOMP] = FX_PixelToR[pixel0]; + rgba[i][GCOMP] = FX_PixelToG[pixel0]; + rgba[i][BCOMP] = FX_PixelToB[pixel0]; + rgba[i][ACOMP] = 255; + rgba[i+1][RCOMP] = FX_PixelToR[pixel1]; + rgba[i+1][GCOMP] = FX_PixelToG[pixel1]; + rgba[i+1][BCOMP] = FX_PixelToB[pixel1]; + rgba[i+1][ACOMP] = 255; + } + if (extraPixel) { + GLushort pixel = data16[n]; + rgba[n][RCOMP] = FX_PixelToR[pixel]; + rgba[n][GCOMP] = FX_PixelToG[pixel]; + rgba[n][BCOMP] = FX_PixelToB[pixel]; + rgba[n][ACOMP] = 255; + } + + grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB); + } + END_BOARD_LOCK(); +} + + +/************************************************************************/ +/***** Pixel functions *****/ +/************************************************************************/ + +static void fxDDWriteRGBAPixels(const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + CONST GLubyte rgba[][4], const GLubyte mask[]) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint i; + GLint bottom=fxMesa->height+fxMesa->y_offset-1; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDWriteRGBAPixels(...)\n"); + } + + for(i=0;i<n;i++) + if(mask[i]) + LFB_WRITE_SPAN_MESA(fxMesa->currentFB, x[i]+fxMesa->x_offset, bottom-y[i], + 1, 1, (void *)rgba[i]); +} + +static void fxDDWriteMonoRGBAPixels(const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + const GLubyte mask[]) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint i; + GLint bottom=fxMesa->height+fxMesa->y_offset-1; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDWriteMonoRGBAPixels(...)\n"); + } + + for(i=0;i<n;i++) + if(mask[i]) + writeRegionClipped(fxMesa, fxMesa->currentFB,x[i]+fxMesa->x_offset,bottom-y[i], + GR_LFB_SRC_FMT_8888,1,1,0,(void *) &fxMesa->color); +} + + +static void read_R5G6B5_pixels(const GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + GLubyte rgba[][4], const GLubyte mask[]) +{ + fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx; + GrLfbInfo_t info; + BEGIN_BOARD_LOCK(); + if (grLfbLock(GR_LFB_READ_ONLY, + fxMesa->currentFB, + GR_LFBWRITEMODE_ANY, + GR_ORIGIN_UPPER_LEFT, + FXFALSE, + &info)) { +#ifdef XF86DRI + const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT) + ? (fxMesa->screen_width) : (info.strideInBytes / 2); +#else + const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */ +#endif + const GLint winX = fxMesa->x_offset; + const GLint winY = fxMesa->y_offset + fxMesa->height - 1; + GLuint i; + for(i=0;i<n;i++) { + if(mask[i]) { + const GLushort *data16 = (const GLushort *) info.lfbPtr + + (winY - y[i]) * srcStride + + (winX + x[i]); + const GLushort pixel = *data16; + rgba[i][RCOMP] = FX_PixelToR[pixel]; + rgba[i][GCOMP] = FX_PixelToG[pixel]; + rgba[i][BCOMP] = FX_PixelToB[pixel]; + rgba[i][ACOMP] = 255; + } + } + grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB); + } + END_BOARD_LOCK(); +} + + + +/************************************************************************/ +/***** Depth functions *****/ +/************************************************************************/ + +void fxDDWriteDepthSpan(GLcontext *ctx, + GLuint n, GLint x, GLint y, const GLdepth depth[], + const GLubyte mask[]) +{ + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + GLint bottom = fxMesa->height + fxMesa->y_offset - 1; + + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "fxmesa: fxDDWriteDepthSpan(...)\n"); + } + + x += fxMesa->x_offset; + + if (mask) { + GLint i; + for (i = 0; i < n; i++) { + if (mask[i]) { + GLshort d = depth[i]; + writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, x + i, bottom - y, + GR_LFB_SRC_FMT_ZA16, 1, 1, 0, (void *) &d); + } + } + } + else { + GLushort depth16[MAX_WIDTH]; + GLint i; + for (i = 0; i < n; i++) { + depth16[i] = depth[i]; + } + writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, x, bottom - y, + GR_LFB_SRC_FMT_ZA16, n, 1, 0, (void *) depth16); + } +} + + +void fxDDReadDepthSpan(GLcontext *ctx, + GLuint n, GLint x, GLint y, GLdepth depth[]) +{ + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + GLint bottom = fxMesa->height + fxMesa->y_offset - 1; + GLushort depth16[MAX_WIDTH]; + GLuint i; + + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "fxmesa: fxDDReadDepthSpan(...)\n"); + } + + x += fxMesa->x_offset; + FX_grLfbReadRegion(GR_BUFFER_AUXBUFFER, x, bottom - y, n, 1, 0, depth16); + for (i = 0; i < n; i++) { + depth[i] = depth16[i]; + } +} + + + +void fxDDWriteDepthPixels(GLcontext *ctx, + GLuint n, const GLint x[], const GLint y[], + const GLdepth depth[], const GLubyte mask[]) +{ + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + GLint bottom = fxMesa->height + fxMesa->y_offset - 1; + GLuint i; + + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "fxmesa: fxDDWriteDepthPixels(...)\n"); + } + + for (i = 0; i < n; i++) { + if (mask[i]) { + int xpos = x[i] + fxMesa->x_offset; + int ypos = bottom - y[i]; + GLushort d = depth[i]; + writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, xpos, ypos, + GR_LFB_SRC_FMT_ZA16, 1, 1, 0, (void *) &d); + } + } +} + + +void fxDDReadDepthPixels(GLcontext *ctx, GLuint n, + const GLint x[], const GLint y[], GLdepth depth[]) +{ + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + GLint bottom = fxMesa->height + fxMesa->y_offset - 1; + GLuint i; + + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "fxmesa: fxDDReadDepthPixels(...)\n"); + } + + for (i = 0; i < n; i++) { + int xpos = x[i] + fxMesa->x_offset; + int ypos = bottom - y[i]; + GLushort d; + FX_grLfbReadRegion(GR_BUFFER_AUXBUFFER, xpos, ypos, 1, 1, 0, &d); + depth[i] = d; + } +} + + + + +/************************************************************************/ + + +void fxSetupDDSpanPointers(GLcontext *ctx) +{ + ctx->Driver.WriteRGBASpan =fxDDWriteRGBASpan; + ctx->Driver.WriteRGBSpan =fxDDWriteRGBSpan; + ctx->Driver.WriteMonoRGBASpan =fxDDWriteMonoRGBASpan; + ctx->Driver.WriteRGBAPixels =fxDDWriteRGBAPixels; + ctx->Driver.WriteMonoRGBAPixels =fxDDWriteMonoRGBAPixels; + + ctx->Driver.WriteCI8Span =NULL; + ctx->Driver.WriteCI32Span =NULL; + ctx->Driver.WriteMonoCISpan =NULL; + ctx->Driver.WriteCI32Pixels =NULL; + ctx->Driver.WriteMonoCIPixels =NULL; + + /* ctx->Driver.ReadRGBASpan =fxDDReadRGBASpan;*/ + ctx->Driver.ReadRGBASpan = read_R5G6B5_span; + ctx->Driver.ReadRGBAPixels = read_R5G6B5_pixels; + + ctx->Driver.ReadCI32Span =NULL; + ctx->Driver.ReadCI32Pixels =NULL; +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_span(void) +{ + return 0; +} + +#endif /* FX */ diff --git a/xc/extras/Mesa/src/FX/fxddtex.c b/xc/extras/Mesa/src/FX/fxddtex.c new file mode 100644 index 000000000..dd2bf4456 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxddtex.c @@ -0,0 +1,1197 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" +#include "image.h" +#include "texutil.h" + + +void fxPrintTextureData(tfxTexInfo *ti) +{ + fprintf(stderr, "Texture Data:\n"); + if (ti->tObj) { + fprintf(stderr, "\tName: %d\n", ti->tObj->Name); + fprintf(stderr, "\tBaseLevel: %d\n", ti->tObj->BaseLevel); + fprintf(stderr, "\tSize: %d x %d\n", + ti->tObj->Image[ti->tObj->BaseLevel]->Width, + ti->tObj->Image[ti->tObj->BaseLevel]->Height); + } else + fprintf(stderr, "\tName: UNNAMED\n"); + fprintf(stderr, "\tLast used: %d\n", ti->lastTimeUsed); + fprintf(stderr, "\tTMU: %ld\n", ti->whichTMU); + fprintf(stderr, "\t%s\n", (ti->isInTM)?"In TMU":"Not in TMU"); + if (ti->tm[0]) + fprintf(stderr, "\tMem0: %x-%x\n", (unsigned) ti->tm[0]->startAddr, + (unsigned) ti->tm[0]->endAddr); + if (ti->tm[1]) + fprintf(stderr, "\tMem1: %x-%x\n", (unsigned) ti->tm[1]->startAddr, + (unsigned) ti->tm[1]->endAddr); + fprintf(stderr, "\tMipmaps: %d-%d\n", ti->minLevel, ti->maxLevel); + fprintf(stderr, "\tFilters: min %d min %d\n", + (int) ti->minFilt, (int) ti->maxFilt); + fprintf(stderr, "\tClamps: s %d t %d\n", (int) ti->sClamp, (int) ti->tClamp); + fprintf(stderr, "\tScales: s %f t %f\n", ti->sScale, ti->tScale); + fprintf(stderr, "\tInt Scales: s %d t %d\n", + ti->int_sScale/0x800000, ti->int_tScale/0x800000); + fprintf(stderr, "\t%s\n", (ti->fixedPalette)?"Fixed palette":"Non fixed palette"); + fprintf(stderr, "\t%s\n", (ti->validated)?"Validated":"Not validated"); +} + + +/************************************************************************/ +/*************************** Texture Mapping ****************************/ +/************************************************************************/ + +static void fxTexInvalidate(GLcontext *ctx, struct gl_texture_object *tObj) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxTexInfo *ti; + + ti=fxTMGetTexInfo(tObj); + if (ti->isInTM) fxTMMoveOutTM(fxMesa,tObj); /* TO DO: SLOW but easy to write */ + + ti->validated=GL_FALSE; + fxMesa->new_state|=FX_NEW_TEXTURING; + ctx->Driver.RenderStart = fxSetupFXUnits; +} + +static tfxTexInfo *fxAllocTexObjData(fxMesaContext fxMesa) +{ + tfxTexInfo *ti; + int i; + + if(!(ti=CALLOC(sizeof(tfxTexInfo)))) { + fprintf(stderr,"fx Driver: out of memory !\n"); + fxCloseHardware(); + exit(-1); + } + + ti->validated=GL_FALSE; + ti->isInTM=GL_FALSE; + + ti->whichTMU=FX_TMU_NONE; + + ti->tm[FX_TMU0]=NULL; + ti->tm[FX_TMU1]=NULL; + + ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED; + ti->maxFilt=GR_TEXTUREFILTER_BILINEAR; + + ti->sClamp=GR_TEXTURECLAMP_WRAP; + ti->tClamp=GR_TEXTURECLAMP_WRAP; + + ti->mmMode=GR_MIPMAP_NEAREST; + ti->LODblend=FXFALSE; + + for(i=0;i<MAX_TEXTURE_LEVELS;i++) { + ti->mipmapLevel[i].data=NULL; + } + + return ti; +} + +void fxDDTexBind(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxTexInfo *ti; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDTexBind(%d,%x)\n",tObj->Name,(GLuint)tObj->DriverData); + } + + if(target!=GL_TEXTURE_2D) + return; + + if (!tObj->DriverData) { + tObj->DriverData=fxAllocTexObjData(fxMesa); + } + + ti=fxTMGetTexInfo(tObj); + + fxMesa->texBindNumber++; + ti->lastTimeUsed=fxMesa->texBindNumber; + + fxMesa->new_state|=FX_NEW_TEXTURING; + ctx->Driver.RenderStart = fxSetupFXUnits; +} + +void fxDDTexEnv(GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + if(param) + fprintf(stderr,"fxmesa: texenv(%x,%x)\n",pname,(GLint)(*param)); + else + fprintf(stderr,"fxmesa: texenv(%x)\n",pname); + } + + /* apply any lod biasing right now */ + if (pname==GL_TEXTURE_LOD_BIAS_EXT) { + FX_grTexLodBiasValue(GR_TMU0,*param); + + if(fxMesa->haveTwoTMUs) { + FX_grTexLodBiasValue(GR_TMU1,*param); + } + + } + + fxMesa->new_state|=FX_NEW_TEXTURING; + ctx->Driver.RenderStart = fxSetupFXUnits; +} + +void fxDDTexParam(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, + GLenum pname, const GLfloat *params) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLenum param=(GLenum)(GLint)params[0]; + tfxTexInfo *ti; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDTexParam(%d,%x,%x,%x)\n",tObj->Name,(GLuint)tObj->DriverData,pname,param); + } + + if(target!=GL_TEXTURE_2D) + return; + + if (!tObj->DriverData) + tObj->DriverData=fxAllocTexObjData(fxMesa); + + ti=fxTMGetTexInfo(tObj); + + switch(pname) { + + case GL_TEXTURE_MIN_FILTER: + switch(param) { + case GL_NEAREST: + ti->mmMode=GR_MIPMAP_DISABLE; + ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED; + ti->LODblend=FXFALSE; + break; + case GL_LINEAR: + ti->mmMode=GR_MIPMAP_DISABLE; + ti->minFilt=GR_TEXTUREFILTER_BILINEAR; + ti->LODblend=FXFALSE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + ti->mmMode=GR_MIPMAP_NEAREST; + ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED; + ti->LODblend=FXFALSE; + break; + case GL_LINEAR_MIPMAP_NEAREST: + ti->mmMode=GR_MIPMAP_NEAREST; + ti->minFilt=GR_TEXTUREFILTER_BILINEAR; + ti->LODblend=FXFALSE; + break; + case GL_NEAREST_MIPMAP_LINEAR: + if(fxMesa->haveTwoTMUs) { + ti->mmMode=GR_MIPMAP_NEAREST; + ti->LODblend=FXTRUE; + } else { + ti->mmMode=GR_MIPMAP_NEAREST_DITHER; + ti->LODblend=FXFALSE; + } + ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED; + break; + case GL_LINEAR_MIPMAP_LINEAR: + if(fxMesa->haveTwoTMUs) { + ti->mmMode=GR_MIPMAP_NEAREST; + ti->LODblend=FXTRUE; + } else { + ti->mmMode=GR_MIPMAP_NEAREST_DITHER; + ti->LODblend=FXFALSE; + } + ti->minFilt=GR_TEXTUREFILTER_BILINEAR; + break; + default: + break; + } + fxTexInvalidate(ctx,tObj); + break; + + case GL_TEXTURE_MAG_FILTER: + switch(param) { + case GL_NEAREST: + ti->maxFilt=GR_TEXTUREFILTER_POINT_SAMPLED; + break; + case GL_LINEAR: + ti->maxFilt=GR_TEXTUREFILTER_BILINEAR; + break; + default: + break; + } + fxTexInvalidate(ctx,tObj); + break; + + case GL_TEXTURE_WRAP_S: + switch(param) { + case GL_CLAMP: + ti->sClamp=GR_TEXTURECLAMP_CLAMP; + break; + case GL_REPEAT: + ti->sClamp=GR_TEXTURECLAMP_WRAP; + break; + default: + break; + } + fxMesa->new_state|=FX_NEW_TEXTURING; + ctx->Driver.RenderStart = fxSetupFXUnits; + break; + + case GL_TEXTURE_WRAP_T: + switch(param) { + case GL_CLAMP: + ti->tClamp=GR_TEXTURECLAMP_CLAMP; + break; + case GL_REPEAT: + ti->tClamp=GR_TEXTURECLAMP_WRAP; + break; + default: + break; + } + fxMesa->new_state|=FX_NEW_TEXTURING; + ctx->Driver.RenderStart = fxSetupFXUnits; + break; + + case GL_TEXTURE_BORDER_COLOR: + /* TO DO */ + break; + + case GL_TEXTURE_MIN_LOD: + /* TO DO */ + break; + case GL_TEXTURE_MAX_LOD: + /* TO DO */ + break; + case GL_TEXTURE_BASE_LEVEL: + fxTexInvalidate(ctx,tObj); + break; + case GL_TEXTURE_MAX_LEVEL: + fxTexInvalidate(ctx,tObj); + break; + + default: + break; + } +} + +void fxDDTexDel(GLcontext *ctx, struct gl_texture_object *tObj) +{ + fxMesaContext fxMesa = FX_CONTEXT(ctx); + tfxTexInfo *ti = fxTMGetTexInfo(tObj); + + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "fxmesa: fxDDTexDel(%d,%p)\n", tObj->Name, ti); + } + + if (!ti) + return; + + fxTMFreeTexture(fxMesa, tObj); + + FREE(ti); + tObj->DriverData = NULL; + + ctx->NewState |= NEW_TEXTURING; +} + + + +/* + * Convert a gl_color_table texture palette to Glide's format. + */ +static void +convertPalette(FxU32 data[256], const struct gl_color_table *table) +{ + const GLubyte *tableUB = (const GLubyte *) table->Table; + GLint width = table->Size; + FxU32 r, g, b, a; + GLint i; + + ASSERT(table->TableType == GL_UNSIGNED_BYTE); + + switch (table->Format) { + case GL_INTENSITY: + for (i = 0; i < width; i++) { + r = tableUB[i]; + g = tableUB[i]; + b = tableUB[i]; + a = tableUB[i]; + data[i] = (a << 24) | (r << 16) | (g << 8) | b; + } + break; + case GL_LUMINANCE: + for (i = 0; i < width; i++) { + r = tableUB[i]; + g = tableUB[i]; + b = tableUB[i]; + a = 255; + data[i] = (a << 24) | (r << 16) | (g << 8) | b; + } + break; + case GL_ALPHA: + for (i = 0; i < width; i++) { + r = g = b = 255; + a = tableUB[i]; + data[i] = (a << 24) | (r << 16) | (g << 8) | b; + } + break; + case GL_LUMINANCE_ALPHA: + for (i = 0; i < width; i++) { + r = g = b = tableUB[i*2+0]; + a = tableUB[i*2+1]; + data[i] = (a << 24) | (r << 16) | (g << 8) | b; + } + break; + case GL_RGB: + for (i = 0; i < width; i++) { + r = tableUB[i*3+0]; + g = tableUB[i*3+1]; + b = tableUB[i*3+2]; + a = 255; + data[i] = (a << 24) | (r << 16) | (g << 8) | b; + } + break; + case GL_RGBA: + for (i = 0; i < width; i++) { + r = tableUB[i*4+0]; + g = tableUB[i*4+1]; + b = tableUB[i*4+2]; + a = tableUB[i*4+3]; + data[i] = (a << 24) | (r << 16) | (g << 8) | b; + } + break; + } +} + + +void fxDDTexPalette(GLcontext *ctx, struct gl_texture_object *tObj) +{ + fxMesaContext fxMesa = FX_CONTEXT(ctx); + + if (tObj) { + /* per-texture palette */ + tfxTexInfo *ti; + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "fxmesa: fxDDTexPalette(%d,%x)\n", + tObj->Name, (GLuint) tObj->DriverData); + } + if (!tObj->DriverData) + tObj->DriverData = fxAllocTexObjData(fxMesa); + ti = fxTMGetTexInfo(tObj); + convertPalette(ti->palette.data, &tObj->Palette); + fxTexInvalidate(ctx, tObj); + } + else { + /* global texture palette */ + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "fxmesa: fxDDTexPalette(global)\n"); + } + convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette); + fxMesa->new_state |= FX_NEW_TEXTURING; + ctx->Driver.RenderStart = fxSetupFXUnits; + } +} + + +void fxDDTexUseGlbPalette(GLcontext *ctx, GLboolean state) +{ + fxMesaContext fxMesa = FX_CONTEXT(ctx); + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDTexUseGlbPalette(%d)\n",state); + } + + if (state) { + fxMesa->haveGlobalPaletteTexture = 1; + + FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE, &(fxMesa->glbPalette)); + if (fxMesa->haveTwoTMUs) + FX_grTexDownloadTable(GR_TMU1, GR_TEXTABLE_PALETTE, &(fxMesa->glbPalette)); + } + else { + fxMesa->haveGlobalPaletteTexture = 0; + + if ((ctx->Texture.Unit[0].Current == ctx->Texture.Unit[0].CurrentD[2]) && + (ctx->Texture.Unit[0].Current != NULL)) { + struct gl_texture_object *tObj = ctx->Texture.Unit[0].Current; + + if (!tObj->DriverData) + tObj->DriverData = fxAllocTexObjData(fxMesa); + + fxTexInvalidate(ctx, tObj); + } + } +} + + +static int logbase2(int n) +{ + GLint i = 1; + GLint log2 = 0; + + if (n<0) { + return -1; + } + + while (n > i) { + i *= 2; + log2++; + } + if (i != n) { + return -1; + } + else { + return log2; + } +} + +/* Need different versions for different cpus. + */ +#define INT_TRICK(l2) (0x800000 * l2) + + +int fxTexGetInfo(int w, int h, GrLOD_t *lodlevel, GrAspectRatio_t *ar, + float *sscale, float *tscale, + int *i_sscale, int *i_tscale, + int *wscale, int *hscale) +{ + + static GrLOD_t lod[9]={GR_LOD_256,GR_LOD_128,GR_LOD_64,GR_LOD_32, + GR_LOD_16,GR_LOD_8,GR_LOD_4,GR_LOD_2,GR_LOD_1}; + + int logw,logh,ws,hs; + GrLOD_t l; + GrAspectRatio_t aspectratio; + float s,t; + int is,it; + + logw=logbase2(w); + logh=logbase2(h); + + switch(logw-logh) { + case 0: + aspectratio=GR_ASPECT_1x1; + l=lod[8-logw]; + s=t=256.0f; + is=it=INT_TRICK(8); + ws=hs=1; + break; + case 1: + aspectratio=GR_ASPECT_2x1; + l=lod[8-logw]; + s=256.0f; + t=128.0f; + is=INT_TRICK(8);it=INT_TRICK(7); + ws=1; + hs=1; + break; + case 2: + aspectratio=GR_ASPECT_4x1; + l=lod[8-logw]; + s=256.0f; + t=64.0f; + is=INT_TRICK(8);it=INT_TRICK(6); + ws=1; + hs=1; + break; + case 3: + aspectratio=GR_ASPECT_8x1; + l=lod[8-logw]; + s=256.0f; + t=32.0f; + is=INT_TRICK(8);it=INT_TRICK(5); + ws=1; + hs=1; + break; + case 4: + aspectratio=GR_ASPECT_8x1; + l=lod[8-logw]; + s=256.0f; + t=32.0f; + is=INT_TRICK(8);it=INT_TRICK(5); + ws=1; + hs=2; + break; + case 5: + aspectratio=GR_ASPECT_8x1; + l=lod[8-logw]; + s=256.0f; + t=32.0f; + is=INT_TRICK(8);it=INT_TRICK(5); + ws=1; + hs=4; + break; + case 6: + aspectratio=GR_ASPECT_8x1; + l=lod[8-logw]; + s=256.0f; + t=32.0f; + is=INT_TRICK(8);it=INT_TRICK(5); + ws=1; + hs=8; + break; + case 7: + aspectratio=GR_ASPECT_8x1; + l=lod[8-logw]; + s=256.0f; + t=32.0f; + is=INT_TRICK(8);it=INT_TRICK(5); + ws=1; + hs=16; + break; + case 8: + aspectratio=GR_ASPECT_8x1; + l=lod[8-logw]; + s=256.0f; + t=32.0f; + is=INT_TRICK(8);it=INT_TRICK(5); + ws=1; + hs=32; + break; + case -1: + aspectratio=GR_ASPECT_1x2; + l=lod[8-logh]; + s=128.0f; + t=256.0f; + is=INT_TRICK(7);it=INT_TRICK(8); + ws=1; + hs=1; + break; + case -2: + aspectratio=GR_ASPECT_1x4; + l=lod[8-logh]; + s=64.0f; + t=256.0f; + is=INT_TRICK(6);it=INT_TRICK(8); + ws=1; + hs=1; + break; + case -3: + aspectratio=GR_ASPECT_1x8; + l=lod[8-logh]; + s=32.0f; + t=256.0f; + is=INT_TRICK(5);it=INT_TRICK(8); + ws=1; + hs=1; + break; + case -4: + aspectratio=GR_ASPECT_1x8; + l=lod[8-logh]; + s=32.0f; + t=256.0f; + is=INT_TRICK(5);it=INT_TRICK(8); + ws=2; + hs=1; + break; + case -5: + aspectratio=GR_ASPECT_1x8; + l=lod[8-logh]; + s=32.0f; + t=256.0f; + is=INT_TRICK(5);it=INT_TRICK(8); + ws=4; + hs=1; + break; + case -6: + aspectratio=GR_ASPECT_1x8; + l=lod[8-logh]; + s=32.0f; + t=256.0f; + is=INT_TRICK(5);it=INT_TRICK(8); + ws=8; + hs=1; + break; + case -7: + aspectratio=GR_ASPECT_1x8; + l=lod[8-logh]; + s=32.0f; + t=256.0f; + is=INT_TRICK(5);it=INT_TRICK(8); + ws=16; + hs=1; + break; + case -8: + aspectratio=GR_ASPECT_1x8; + l=lod[8-logh]; + s=32.0f; + t=256.0f; + is=INT_TRICK(5);it=INT_TRICK(8); + ws=32; + hs=1; + break; + default: + return 0; + break; + } + + if(lodlevel) + (*lodlevel)=l; + + if(ar) + (*ar)=aspectratio; + + if(sscale) + (*sscale)=s; + + if(tscale) + (*tscale)=t; + + if(wscale) + (*wscale)=ws; + + if(hscale) + (*hscale)=hs; + + if (i_sscale) + *i_sscale = is; + + if (i_tscale) + *i_tscale = it; + + + return 1; +} + +/* + * Given an OpenGL internal texture format, return the corresponding + * Glide internal texture format and base texture format. + */ +void fxTexGetFormat(GLenum glformat, GrTextureFormat_t *tfmt, GLint *ifmt) +{ + switch(glformat) { + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + if(tfmt) + (*tfmt)=GR_TEXFMT_INTENSITY_8; + if(ifmt) + (*ifmt)=GL_LUMINANCE; + break; + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + if(tfmt) + (*tfmt)=GR_TEXFMT_ALPHA_INTENSITY_88; + if(ifmt) + (*ifmt)=GL_LUMINANCE_ALPHA; + break; + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + if(tfmt) + (*tfmt)=GR_TEXFMT_ALPHA_8; + if(ifmt) + (*ifmt)=GL_INTENSITY; + break; + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + if(tfmt) + (*tfmt)=GR_TEXFMT_ALPHA_8; + if(ifmt) + (*ifmt)=GL_ALPHA; + break; + case 3: + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + if(tfmt) + (*tfmt)=GR_TEXFMT_RGB_565; + if(ifmt) + (*ifmt)=GL_RGB; + break; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + if(tfmt) + (*tfmt)=GR_TEXFMT_ARGB_4444; + if(ifmt) + (*ifmt)=GL_RGBA; + break; + case GL_RGB5_A1: + if(tfmt) + (*tfmt)=GR_TEXFMT_ARGB_1555; + if(ifmt) + (*ifmt)=GL_RGBA; + break; + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + if(tfmt) + (*tfmt)=GR_TEXFMT_P_8; + if(ifmt) + (*ifmt)=GL_RGBA; /* XXX why is this RGBA? */ + break; + default: + fprintf(stderr, + "fx Driver: unsupported internalFormat in fxTexGetFormat()\n"); + fxCloseHardware(); + exit(-1); + break; + } +} + +static GLboolean fxIsTexSupported(GLenum target, GLint internalFormat, + const struct gl_texture_image *image) +{ + if(target != GL_TEXTURE_2D) + return GL_FALSE; + + if(!fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL)) + return GL_FALSE; + + if (image->Border > 0) + return GL_FALSE; + + return GL_TRUE; +} + + +/**********************************************************************/ +/**** NEW TEXTURE IMAGE FUNCTIONS ****/ +/**********************************************************************/ + +GLboolean fxDDTexImage2D(GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + GLboolean *retainInternalCopy) +{ + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + + if (target != GL_TEXTURE_2D) + return GL_FALSE; + + if (!texObj->DriverData) + texObj->DriverData = fxAllocTexObjData(fxMesa); + + if (fxIsTexSupported(target, texImage->IntFormat, texImage)) { + GrTextureFormat_t gldformat; + tfxTexInfo *ti = fxTMGetTexInfo(texObj); + tfxMipMapLevel *mml = &ti->mipmapLevel[level]; + GLint dstWidth, dstHeight, wScale, hScale, texelSize, dstStride; + MesaIntTexFormat intFormat; + + fxTexGetFormat(texImage->IntFormat, &gldformat, NULL); + + fxTexGetInfo(texImage->Width, texImage->Height, NULL,NULL,NULL,NULL, + NULL,NULL, &wScale, &hScale); + + dstWidth = texImage->Width * wScale; + dstHeight = texImage->Height * hScale; + + switch (texImage->IntFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + texelSize = 1; + intFormat = MESA_I8; + break; + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + texelSize = 1; + intFormat = MESA_L8; + break; + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + texelSize = 1; + intFormat = MESA_A8; + break; + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + texelSize = 1; + intFormat = MESA_C8; + break; + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + texelSize = 2; + intFormat = MESA_A8_L8; + break; + case 3: + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + texelSize = 2; + intFormat = MESA_R5_G6_B5; + break; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + texelSize = 2; + intFormat = MESA_A4_R4_G4_B4; + break; + case GL_RGB5_A1: + texelSize = 2; + intFormat = MESA_A1_R5_G5_B5; + break; + default: + gl_problem(NULL, "tdfx driver: texbuildimagemap() bad format"); + return GL_FALSE; + } + + _mesa_set_teximage_component_sizes(intFormat, texImage); + + /*printf("teximage:\n");*/ + /* allocate new storage for texture image, if needed */ + if (!mml->data || mml->glideFormat != gldformat || + mml->width != dstWidth || mml->height != dstHeight) { + if (mml->data) + FREE(mml->data); + mml->data = MALLOC(dstWidth * dstHeight * texelSize); + if (!mml->data) + return GL_FALSE; + mml->glideFormat = gldformat; + mml->width = dstWidth; + mml->height = dstHeight; + fxTexInvalidate(ctx, texObj); + } + + dstStride = dstWidth * texelSize; + + /* store the texture image */ + if (!_mesa_convert_teximage(intFormat, dstWidth, dstHeight, mml->data, + dstStride, + texImage->Width, texImage->Height, + format, type, pixels, packing)) { + return GL_FALSE; + } + + if (ti->validated && ti->isInTM) { + /*printf("reloadmipmaplevels\n");*/ + fxTMReloadMipMapLevel(fxMesa, texObj, level); + } + else { + /*printf("invalidate2\n");*/ + fxTexInvalidate(ctx,texObj); + } + + *retainInternalCopy = GL_FALSE; + return GL_TRUE; + } + else { + gl_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n"); + return GL_FALSE; + } +} + + +GLboolean fxDDTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx; + tfxTexInfo *ti; + GLint wscale, hscale, dstStride; + tfxMipMapLevel *mml; + GLboolean result; + + if (target != GL_TEXTURE_2D) + return GL_FALSE; + + if (!texObj->DriverData) + return GL_FALSE; + + ti = fxTMGetTexInfo(texObj); + mml = &ti->mipmapLevel[level]; + + fxTexGetInfo( texImage->Width, texImage->Height, NULL,NULL,NULL,NULL, + NULL,NULL, &wscale, &hscale); + + assert(mml->data); /* must have an existing texture image! */ + + switch (mml->glideFormat) { + case GR_TEXFMT_INTENSITY_8: + dstStride = mml->width; + result = _mesa_convert_texsubimage(MESA_I8, xoffset, yoffset, + mml->width, mml->height, mml->data, + dstStride, width, height, + texImage->Width, texImage->Height, + format, type, pixels, packing); + break; + case GR_TEXFMT_ALPHA_8: + dstStride = mml->width; + result = _mesa_convert_texsubimage(MESA_A8, xoffset, yoffset, + mml->width, mml->height, mml->data, + dstStride, width, height, + texImage->Width, texImage->Height, + format, type, pixels, packing); + break; + case GR_TEXFMT_P_8: + dstStride = mml->width; + result = _mesa_convert_texsubimage(MESA_C8, xoffset, yoffset, + mml->width, mml->height, mml->data, + dstStride, width, height, + texImage->Width, texImage->Height, + format, type, pixels, packing); + break; + case GR_TEXFMT_ALPHA_INTENSITY_88: + dstStride = mml->width * 2; + result = _mesa_convert_texsubimage(MESA_A8_L8, xoffset, yoffset, + mml->width, mml->height, mml->data, + dstStride, width, height, + texImage->Width, texImage->Height, + format, type, pixels, packing); + break; + case GR_TEXFMT_RGB_565: + dstStride = mml->width * 2; + result = _mesa_convert_texsubimage(MESA_R5_G6_B5, xoffset, yoffset, + mml->width, mml->height, mml->data, + dstStride, width, height, + texImage->Width, texImage->Height, + format, type, pixels, packing); + break; + case GR_TEXFMT_ARGB_4444: + dstStride = mml->width * 2; + result = _mesa_convert_texsubimage(MESA_A4_R4_G4_B4, xoffset, yoffset, + mml->width, mml->height, mml->data, + dstStride, width, height, + texImage->Width, texImage->Height, + format, type, pixels, packing); + break; + case GR_TEXFMT_ARGB_1555: + dstStride = mml->width * 2; + result = _mesa_convert_texsubimage(MESA_A1_R5_G5_B5, xoffset, yoffset, + mml->width, mml->height, mml->data, + dstStride, width, height, + texImage->Width, texImage->Height, + format, type, pixels, packing); + break; + default: + gl_problem(NULL, "tdfx driver: fxTexBuildSubImageMap() bad format"); + result = GL_FALSE; + } + + if (!result) { + return GL_FALSE; + } + + if (ti->validated && ti->isInTM) + fxTMReloadMipMapLevel(fxMesa, texObj, level); + else + fxTexInvalidate(ctx, texObj); + + return GL_TRUE; +} + + +static void PrintTexture(int w, int h, int c, const GLubyte *data) +{ + int i, j; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + if (c==2) + printf("%02x %02x ", data[0], data[1]); + else if (c==3) + printf("%02x %02x %02x ", data[0], data[1], data[2]); + data += c; + } + printf("\n"); + } +} + + +GLvoid *fxDDGetTexImage(GLcontext *ctx, GLenum target, GLint level, + const struct gl_texture_object *texObj, + GLenum *formatOut, GLenum *typeOut, + GLboolean *freeImageOut ) +{ + tfxTexInfo *ti; + tfxMipMapLevel *mml; + + if (target != GL_TEXTURE_2D) + return NULL; + + if (!texObj->DriverData) + return NULL; + + ti = fxTMGetTexInfo(texObj); + mml = &ti->mipmapLevel[level]; + if (mml->data) { + MesaIntTexFormat mesaFormat; + GLenum glFormat; + struct gl_texture_image *texImage = texObj->Image[level]; + GLint srcStride; + + GLubyte *data = (GLubyte *) MALLOC(texImage->Width * texImage->Height * 4); + if (!data) + return NULL; + + switch (mml->glideFormat) { + case GR_TEXFMT_INTENSITY_8: + mesaFormat = MESA_I8; + glFormat = GL_INTENSITY; + srcStride = mml->width; + break; + case GR_TEXFMT_ALPHA_INTENSITY_88: + mesaFormat = MESA_A8_L8; + glFormat = GL_LUMINANCE_ALPHA; + srcStride = mml->width; + break; + case GR_TEXFMT_ALPHA_8: + mesaFormat = MESA_A8; + glFormat = GL_ALPHA; + srcStride = mml->width; + break; + case GR_TEXFMT_RGB_565: + mesaFormat = MESA_R5_G6_B5; + glFormat = GL_RGB; + srcStride = mml->width * 2; + break; + case GR_TEXFMT_ARGB_4444: + mesaFormat = MESA_A4_R4_G4_B4; + glFormat = GL_RGBA; + srcStride = mml->width * 2; + break; + case GR_TEXFMT_ARGB_1555: + mesaFormat = MESA_A1_R5_G5_B5; + glFormat = GL_RGBA; + srcStride = mml->width * 2; + break; + case GR_TEXFMT_P_8: + mesaFormat = MESA_C8; + glFormat = GL_COLOR_INDEX; + srcStride = mml->width; + break; + default: + gl_problem(NULL, "Bad glideFormat in fxDDGetTexImage"); + return NULL; + } + _mesa_unconvert_teximage(mesaFormat, mml->width, mml->height, mml->data, + srcStride, texImage->Width, texImage->Height, + glFormat, data); + *formatOut = glFormat; + *typeOut = GL_UNSIGNED_BYTE; + *freeImageOut = GL_TRUE; + return data; + } + else { + return NULL; + } +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_ddtex(void) +{ + return 0; +} + +#endif /* FX */ diff --git a/xc/extras/Mesa/src/FX/fxdrv.h b/xc/extras/Mesa/src/FX/fxdrv.h new file mode 100644 index 000000000..c85c73d8e --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxdrv.h @@ -0,0 +1,686 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifndef FXDRV_H +#define FXDRV_H + +/* If you comment out this define, a variable takes its place, letting + * you turn debugging on/off from the debugger. + */ + +#ifdef XFree86Server +#include "GL/xf86glx.h" +#else +#include "glheader.h" +#endif + + +#if defined(__linux__) +#include <signal.h> +#endif + +#include "context.h" +#include "macros.h" +#include "matrix.h" +#include "mem.h" +#include "texture.h" +#include "types.h" +#include "vb.h" +#include "xform.h" +#include "clip.h" +#include "vbrender.h" + +#ifdef XF86DRI +typedef struct tfxMesaContext *fxMesaContext; +#else +#include "GL/fxmesa.h" +#endif +#include "fxglidew.h" +/* use gl/gl.h GLAPI/GLAPIENTRY/GLCALLBACK in place of WINGDIAPI/APIENTRY/CALLBACK, */ +/* these are defined in mesa gl/gl.h - tjump@spgs.com */ + + + +extern void fx_sanity_triangle( GrVertex *, GrVertex *, GrVertex * ); +#if defined(MESA_DEBUG) && 0 +#define grDrawTriangle fx_sanity_triangle +#endif + + +/* Define some shorter names for these things. + */ +#define XCOORD GR_VERTEX_X_OFFSET +#define YCOORD GR_VERTEX_Y_OFFSET +#define ZCOORD GR_VERTEX_OOZ_OFFSET +#define OOWCOORD GR_VERTEX_OOW_OFFSET + +#define RCOORD GR_VERTEX_R_OFFSET +#define GCOORD GR_VERTEX_G_OFFSET +#define BCOORD GR_VERTEX_B_OFFSET +#define ACOORD GR_VERTEX_A_OFFSET + +#define S0COORD GR_VERTEX_SOW_TMU0_OFFSET +#define T0COORD GR_VERTEX_TOW_TMU0_OFFSET +#define S1COORD GR_VERTEX_SOW_TMU1_OFFSET +#define T1COORD GR_VERTEX_TOW_TMU1_OFFSET + + +#if FX_USE_PARGB + +#define CLIP_XCOORD 0 /* normal place */ +#define CLIP_YCOROD 1 /* normal place */ +#define CLIP_ZCOORD 2 /* normal place */ +#define CLIP_WCOORD 3 /* normal place */ +#define CLIP_GCOORD 4 /* GR_VERTEX_PARGB_OFFSET */ +#define CLIP_BCOORD 5 /* GR_VERTEX_SOW_TMU0_OFFSET */ +#define CLIP_RCOORD 6 /* GR_VERTEX_TOW_TMU0_OFFSET */ +#define CLIP_ACOORD 7 /* GR_VERTEX_OOW_TMU0_OFFSET */ + +#else + +#define CLIP_XCOORD 0 /* normal place */ +#define CLIP_YCOROD 1 /* normal place */ +#define CLIP_ZCOORD 2 /* GR_VERTEX_Z_OFFSET */ +#define CLIP_WCOORD 3 /* GR_VERTEX_R_OFFSET */ +#define CLIP_GCOORD 4 /* normal place */ +#define CLIP_BCOORD 5 /* normal place */ +#define CLIP_RCOORD 6 /* GR_VERTEX_OOZ_OFFSET */ +#define CLIP_ACOORD 7 /* normal place */ + + +#endif + +/* Should have size == 16 * sizeof(float). + */ +typedef struct { + GLfloat f[15]; /* Same layout as GrVertex */ + GLubyte mask; /* Unsued */ + GLubyte usermask; /* Unused */ +} fxVertex; + + + + +#if defined(FXMESA_USE_ARGB) +#define FXCOLOR4( c ) ( \ + ( ((unsigned int)(c[3]))<<24 ) | \ + ( ((unsigned int)(c[0]))<<16 ) | \ + ( ((unsigned int)(c[1]))<<8 ) | \ + ( (unsigned int)(c[2])) ) + +#else +#ifdef __i386__ +#define FXCOLOR4( c ) (* (int *)c) +#else +#define FXCOLOR4( c ) ( \ + ( ((unsigned int)(c[3]))<<24 ) | \ + ( ((unsigned int)(c[2]))<<16 ) | \ + ( ((unsigned int)(c[1]))<<8 ) | \ + ( (unsigned int)(c[0])) ) +#endif +#endif + +#define FX_VB_COLOR(fxm, color) \ + do { \ + if (sizeof(GLint) == 4*sizeof(GLubyte)) { \ + if (fxm->constColor != *(GLuint*)color) { \ + fxm->constColor = *(GLuint*)color; \ + FX_grConstantColorValue(FXCOLOR4(color)); \ + } \ + } else { \ + FX_grConstantColorValue(FXCOLOR4(color)); \ + } \ + } while (0) + +#define GOURAUD(x) { \ + GLubyte *col = VB->ColorPtr->data[(x)]; \ + gWin[(x)].v.r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \ + gWin[(x)].v.g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \ + gWin[(x)].v.b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \ + gWin[(x)].v.a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \ +} + +#if FX_USE_PARGB +#define GOURAUD2(v, c) { \ + GLubyte *col = c; \ + v->argb=MESACOLOR2PARGB(col); \ +} +#else +#define GOURAUD2(v, c) { \ + GLubyte *col = c; \ + v->r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \ + v->g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \ + v->b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \ + v->a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \ +} +#endif + + +/* Mergable items first + */ +#define SETUP_RGBA 0x1 +#define SETUP_TMU0 0x2 +#define SETUP_TMU1 0x4 +#define SETUP_XY 0x8 +#define SETUP_Z 0x10 +#define SETUP_W 0x20 + +#define MAX_MERGABLE 0x8 + + +#define FX_NUM_TMU 2 + +#define FX_TMU0 GR_TMU0 +#define FX_TMU1 GR_TMU1 +#define FX_TMU_SPLIT 98 +#define FX_TMU_BOTH 99 +#define FX_TMU_NONE 100 + +/* Used for fxMesa->lastUnitsMode */ + +#define FX_UM_NONE 0x00000000 + +#define FX_UM_E0_REPLACE 0x00000001 +#define FX_UM_E0_MODULATE 0x00000002 +#define FX_UM_E0_DECAL 0x00000004 +#define FX_UM_E0_BLEND 0x00000008 +#define FX_UM_E0_ADD 0x00000010 + +#define FX_UM_E1_REPLACE 0x00000020 +#define FX_UM_E1_MODULATE 0x00000040 +#define FX_UM_E1_DECAL 0x00000080 +#define FX_UM_E1_BLEND 0x00000100 +#define FX_UM_E1_ADD 0x00000200 + +#define FX_UM_E_ENVMODE 0x000003ff + +#define FX_UM_E0_ALPHA 0x00001000 +#define FX_UM_E0_LUMINANCE 0x00002000 +#define FX_UM_E0_LUMINANCE_ALPHA 0x00004000 +#define FX_UM_E0_INTENSITY 0x00008000 +#define FX_UM_E0_RGB 0x00010000 +#define FX_UM_E0_RGBA 0x00020000 + +#define FX_UM_E1_ALPHA 0x00040000 +#define FX_UM_E1_LUMINANCE 0x00080000 +#define FX_UM_E1_LUMINANCE_ALPHA 0x00100000 +#define FX_UM_E1_INTENSITY 0x00200000 +#define FX_UM_E1_RGB 0x00400000 +#define FX_UM_E1_RGBA 0x00800000 + +#define FX_UM_E_IFMT 0x00fff000 + +#define FX_UM_COLOR_ITERATED 0x01000000 +#define FX_UM_COLOR_CONSTANT 0x02000000 +#define FX_UM_ALPHA_ITERATED 0x04000000 +#define FX_UM_ALPHA_CONSTANT 0x08000000 + +typedef void (*tfxRenderVBFunc)(GLcontext *); + +/* + Memory range from startAddr to endAddr-1 +*/ +typedef struct MemRange_t { + struct MemRange_t *next; + FxU32 startAddr, endAddr; +} MemRange; + +typedef struct { + GLsizei width, height; /* image size */ + GrTextureFormat_t glideFormat; /* Glide image format */ + unsigned short *data; /* Glide-formated texture image */ +} tfxMipMapLevel; + +typedef struct tfxTexInfo_t { + struct tfxTexInfo *next; + struct gl_texture_object *tObj; + + GLuint lastTimeUsed; + FxU32 whichTMU; + GLboolean isInTM; + + tfxMipMapLevel mipmapLevel[MAX_TEXTURE_LEVELS]; + + MemRange *tm[FX_NUM_TMU]; + + GLint minLevel, maxLevel; + GLint baseLevelInternalFormat; + + GrTexInfo info; + + GrTextureFilterMode_t minFilt; + GrTextureFilterMode_t maxFilt; + FxBool LODblend; + + GrTextureClampMode_t sClamp; + GrTextureClampMode_t tClamp; + + GrMipMapMode_t mmMode; + + GLfloat sScale, tScale; + GLint int_sScale, int_tScale; /* x86 floating point trick for + * multiplication by powers of 2. + * Used in fxfasttmp.h + */ + + GuTexPalette palette; + + GLboolean fixedPalette; + GLboolean validated; +} tfxTexInfo; + +typedef struct { + GLuint swapBuffer; + GLuint reqTexUpload; + GLuint texUpload; + GLuint memTexUpload; +} tfxStats; + + +typedef void (*tfxTriViewClipFunc)( struct vertex_buffer *VB, + GLuint v[], + GLubyte mask ); + +typedef void (*tfxTriClipFunc)( struct vertex_buffer *VB, + GLuint v[], + GLuint mask ); + + +typedef void (*tfxLineClipFunc)( struct vertex_buffer *VB, + GLuint v1, GLuint v2, + GLubyte mask ); + + +extern tfxTriViewClipFunc fxTriViewClipTab[0x8]; +extern tfxTriClipFunc fxTriClipStrideTab[0x8]; +extern tfxLineClipFunc fxLineClipTab[0x8]; + +typedef struct { + /* Alpha test */ + + GLboolean alphaTestEnabled; + GrCmpFnc_t alphaTestFunc; + GrAlpha_t alphaTestRefValue; + + /* Blend function */ + + GLboolean blendEnabled; + GrAlphaBlendFnc_t blendSrcFuncRGB; + GrAlphaBlendFnc_t blendDstFuncRGB; + GrAlphaBlendFnc_t blendSrcFuncAlpha; + GrAlphaBlendFnc_t blendDstFuncAlpha; + + /* Depth test */ + + GLboolean depthTestEnabled; + GLboolean depthMask; + GrCmpFnc_t depthTestFunc; +} tfxUnitsState; + + +/* Flags for render_index. + */ +#define FX_OFFSET 0x1 +#define FX_TWOSIDE 0x2 +#define FX_FRONT_BACK 0x4 +#define FX_FLAT 0x8 +#define FX_ANTIALIAS 0x10 +#define FX_FALLBACK 0x20 + + +/* Flags for fxMesa->new_state + */ +#define FX_NEW_TEXTURING 0x1 +#define FX_NEW_BLEND 0x2 +#define FX_NEW_ALPHA 0x4 +#define FX_NEW_DEPTH 0x8 +#define FX_NEW_FOG 0x10 +#define FX_NEW_SCISSOR 0x20 +#define FX_NEW_COLOR_MASK 0x40 +#define FX_NEW_CULL 0x80 + +/* FX struct stored in VB->driver_data. + */ +struct tfxMesaVertexBuffer { + GLvector1ui clipped_elements; + + fxVertex *verts; + fxVertex *last_vert; + void *vert_store; +#if defined(FX_GLIDE3) + GrVertex **triangle_b; /* Triangle buffer */ + GrVertex **strips_b; /* Strips buffer */ +#endif + + GLuint size; +}; + +#define FX_DRIVER_DATA(vb) ((struct tfxMesaVertexBuffer *)((vb)->driver_data)) +#define FX_CONTEXT(ctx) ((fxMesaContext)((ctx)->DriverCtx)) +#define FX_TEXTURE_DATA(t) fxTMGetTexInfo((t)->Current) + +#if defined(XFree86Server) || defined(GLX_DIRECT_RENDERING) +#include "tdfx_init.h" +#else +#define DRI_FX_CONTEXT +#define BEGIN_BOARD_LOCK() +#define END_BOARD_LOCK() +#define BEGIN_CLIP_LOOP() +#define END_CLIP_LOOP() +#endif + + +/* These lookup table are used to extract RGB values in [0,255] from + * 16-bit pixel values. + */ +extern GLubyte FX_PixelToR[0x10000]; +extern GLubyte FX_PixelToG[0x10000]; +extern GLubyte FX_PixelToB[0x10000]; + + +struct tfxMesaContext { + GuTexPalette glbPalette; + + GLcontext *glCtx; /* the core Mesa context */ +#if !defined(XFree86Server) && !defined(GLX_DIRECT_RENDERING) + GLvisual *glVis; /* describes the color buffer */ + GLframebuffer *glBuffer; /* the ancillary buffers */ +#endif + + GLint board; /* the board used for this context */ + GLint width, height; /* size of color buffer */ + + GrBuffer_t currentFB; + + GLboolean bgrOrder; + GrColor_t color; + GrColor_t clearC; + GrAlpha_t clearA; + GLuint constColor; + GrCullMode_t cullMode; + + tfxUnitsState unitsState; + tfxUnitsState restoreUnitsState; /* saved during multipass */ + + GLuint tmu_source[FX_NUM_TMU]; + GLuint tex_dest[MAX_TEXTURE_UNITS]; + GLuint setupindex; + GLuint partial_setup_index; + GLuint setupdone; + GLuint mergeindex; + GLuint mergeinputs; + GLuint render_index; + GLuint last_tri_caps; + GLuint stw_hint_state; /* for grHints */ + GLuint is_in_hardware; + GLuint new_state; + GLuint using_fast_path, passes, multipass; + + tfxLineClipFunc clip_line; + tfxTriClipFunc clip_tri_stride; + tfxTriViewClipFunc view_clip_tri; + + + /* Texture Memory Manager Data */ + + GLuint texBindNumber; + GLint tmuSrc; + GLuint lastUnitsMode; + GLuint freeTexMem[FX_NUM_TMU]; + MemRange *tmPool; + MemRange *tmFree[FX_NUM_TMU]; + + GLenum fogTableMode; + GLfloat fogDensity; + GLfloat fogStart, fogEnd; + GrFog_t *fogTable; + GLint textureAlign; + + /* Acc. functions */ + + points_func PointsFunc; + line_func LineFunc; + triangle_func TriangleFunc; + quad_func QuadFunc; + + render_func **RenderVBTables; + + render_func *RenderVBClippedTab; + render_func *RenderVBCulledTab; + render_func *RenderVBRawTab; + + + tfxStats stats; + + void *state; + + /* Options */ + + GLboolean verbose; + GLboolean haveTwoTMUs; /* True if we really have 2 tmu's */ + GLboolean emulateTwoTMUs; /* True if we present 2 tmu's to mesa. */ + GLboolean haveAlphaBuffer; + GLboolean haveZBuffer; + GLboolean haveDoubleBuffer; + GLboolean haveGlobalPaletteTexture; + GLint swapInterval; + GLint maxPendingSwapBuffers; + + FX_GrContext_t glideContext; + + int x_offset; + int y_offset; + int y_delta; + int screen_width; + int screen_height; + int initDone; + int clipMinX; + int clipMaxX; + int clipMinY; + int clipMaxY; + int needClip; + + DRI_FX_CONTEXT +}; + +typedef void (*tfxSetupFunc)(struct vertex_buffer *, GLuint, GLuint); + +extern GrHwConfiguration glbHWConfig; +extern int glbCurrentBoard; + +extern void fxPrintSetupFlags( const char *msg, GLuint flags ); +extern void fxSetupFXUnits(GLcontext *); +extern void fxSetupDDPointers(GLcontext *); +extern void fxDDSetNearFar(GLcontext *, GLfloat, GLfloat); + +extern void fxDDSetupInit(void); +extern void fxDDCvaInit(void); +extern void fxDDTrifuncInit(void); +extern void fxDDFastPathInit(void); + +extern void fxDDChooseRenderState( GLcontext *ctx ); + +extern void fxRenderClippedLine( struct vertex_buffer *VB, + GLuint v1, GLuint v2 ); + +extern void fxRenderClippedTriangle( struct vertex_buffer *VB, + GLuint n, GLuint vlist[] ); + + +extern tfxSetupFunc fxDDChooseSetupFunction(GLcontext *); + +extern points_func fxDDChoosePointsFunction(GLcontext *); +extern line_func fxDDChooseLineFunction(GLcontext *); +extern triangle_func fxDDChooseTriangleFunction(GLcontext *); +extern quad_func fxDDChooseQuadFunction(GLcontext *); +extern render_func **fxDDChooseRenderVBTables(GLcontext *); + +extern void fxDDRenderInit(GLcontext *); +extern void fxDDClipInit(void); + +extern void fxUpdateDDSpanPointers(GLcontext *); +extern void fxSetupDDSpanPointers(GLcontext *); + +extern void fxPrintTextureData(tfxTexInfo *ti); +extern GLboolean fxDDTexImage2D(GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + GLboolean *retainInternalCopy); +extern GLboolean fxDDTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); +extern GLvoid *fxDDGetTexImage(GLcontext *ctx, GLenum target, GLint level, + const struct gl_texture_object *texObj, + GLenum *formatOut, GLenum *typeOut, + GLboolean *freeImageOut ); +extern void fxDDTexEnv(GLcontext *, GLenum, GLenum, const GLfloat *); +extern void fxDDTexParam(GLcontext *, GLenum, struct gl_texture_object *, + GLenum, const GLfloat *); +extern void fxDDTexBind(GLcontext *, GLenum, struct gl_texture_object *); +extern void fxDDTexDel(GLcontext *, struct gl_texture_object *); +extern void fxDDTexPalette(GLcontext *, struct gl_texture_object *); +extern void fxDDTexUseGlbPalette(GLcontext *, GLboolean); + +extern void fxDDEnable(GLcontext *, GLenum, GLboolean); +extern void fxDDAlphaFunc(GLcontext *, GLenum, GLclampf); +extern void fxDDBlendFunc(GLcontext *, GLenum, GLenum); +extern void fxDDDepthMask(GLcontext *, GLboolean); +extern void fxDDDepthFunc(GLcontext *, GLenum); + +extern void fxDDRegisterVB( struct vertex_buffer *VB ); +extern void fxDDUnregisterVB( struct vertex_buffer *VB ); +extern void fxDDResizeVB( struct vertex_buffer *VB, GLuint size ); + +extern void fxDDCheckMergeAndRender( GLcontext *ctx, + struct gl_pipeline_stage *d ); + +extern void fxDDMergeAndRender( struct vertex_buffer *VB ); + +extern void fxDDCheckPartialRasterSetup( GLcontext *ctx, + struct gl_pipeline_stage *d ); + +extern void fxDDPartialRasterSetup( struct vertex_buffer *VB ); + +extern void fxDDDoRasterSetup( struct vertex_buffer *VB ); + +extern GLuint fxDDRegisterPipelineStages( struct gl_pipeline_stage *out, + const struct gl_pipeline_stage *in, + GLuint nr ); + +extern GLboolean fxDDBuildPrecalcPipeline( GLcontext *ctx ); + +extern void fxDDOptimizePrecalcPipeline( GLcontext *ctx, + struct gl_pipeline *pipe ); + +extern void fxDDRenderElementsDirect( struct vertex_buffer *VB ); +extern void fxDDRenderVBIndirectDirect( struct vertex_buffer *VB ); + +extern void fxDDInitExtensions( GLcontext *ctx ); + +#define fxTMGetTexInfo(o) ((tfxTexInfo*)((o)->DriverData)) +extern void fxTMInit(fxMesaContext ctx); +extern void fxTMClose(fxMesaContext ctx); +extern void fxTMRestoreTextures_NoLock(fxMesaContext ctx); +extern void fxTMMoveInTM(fxMesaContext, struct gl_texture_object *, GLint); +extern void fxTMMoveOutTM(fxMesaContext, struct gl_texture_object *); +#define fxTMMoveOutTM_NoLock fxTMMoveOutTM +extern void fxTMFreeTexture(fxMesaContext, struct gl_texture_object *); +extern void fxTMReloadMipMapLevel(fxMesaContext, struct gl_texture_object *, GLint); +extern void fxTMReloadSubMipMapLevel(fxMesaContext, struct gl_texture_object *, + GLint, GLint, GLint); + +extern void fxTexGetFormat(GLenum, GrTextureFormat_t *, GLint *); +extern int fxTexGetInfo(int, int, GrLOD_t *, GrAspectRatio_t *, + float *, float *, int *, int *, int *, int *); + +extern void fxDDScissor( GLcontext *ctx, + GLint x, GLint y, GLsizei w, GLsizei h ); +extern void fxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params ); +extern GLboolean fxDDColorMask(GLcontext *ctx, + GLboolean r, GLboolean g, + GLboolean b, GLboolean a ); + +extern void fxDDWriteDepthSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLdepth depth[], const GLubyte mask[]); + +extern void fxDDReadDepthSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, + GLdepth depth[]); + +extern void fxDDWriteDepthPixels(GLcontext *ctx, GLuint n, + const GLint x[], const GLint y[], + const GLdepth depth[], const GLubyte mask[]); + +extern void fxDDReadDepthPixels(GLcontext *ctx, GLuint n, + const GLint x[], const GLint y[], + GLdepth depth[]); + +extern void fxDDFastPath( struct vertex_buffer *VB ); + +extern void fxDDShadeModel(GLcontext *ctx, GLenum mode); + +extern void fxDDCullFace(GLcontext *ctx, GLenum mode); +extern void fxDDFrontFace(GLcontext *ctx, GLenum mode); + +extern void fxPrintRenderState( const char *msg, GLuint state ); +extern void fxPrintHintState( const char *msg, GLuint state ); + +extern void fxDDDoRenderVB( struct vertex_buffer *VB ); + +extern int fxDDInitFxMesaContext( fxMesaContext fxMesa ); + + +extern void fxSetScissorValues(GLcontext *ctx); +extern void fxTMMoveInTM_NoLock(fxMesaContext fxMesa, + struct gl_texture_object *tObj, + GLint where); +extern void fxInitPixelTables(fxMesaContext fxMesa, GLboolean bgrOrder); + +#endif diff --git a/xc/extras/Mesa/src/FX/fxfastpath.c b/xc/extras/Mesa/src/FX/fxfastpath.c new file mode 100644 index 000000000..8a327e72a --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxfastpath.c @@ -0,0 +1,425 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + + +#if defined(FX) + +#include "types.h" +#include "cva.h" +#include "mmath.h" +#include "fxdrv.h" +#include "vertices.h" +#include "X86/common_x86_asm.h" + + +#if 0 && defined(__i386__) +#define NEGATIVE(f) ((*(int *)&f) < 0) +#define DIFFERENT_SIGNS(a,b) (((*(int *)&a)^(*(int *)&b)) < 0) +#else +#define NEGATIVE(f) (f < 0) +#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) +#endif + +#define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) ) + + +#define CLIP(sgn,v,PLANE) \ +if (mask & PLANE) { \ + GLuint *indata = inlist[in]; \ + GLuint *outdata = inlist[in ^= 1]; \ + GLuint nr = n; \ + GLfloat *J = verts[indata[nr-1]].f; \ + GLfloat dpJ = (sgn J[v]) + J[CLIP_WCOORD]; \ + \ + inlist[0] = vlist1; \ + for (i = n = 0 ; i < nr ; i++) { \ + GLuint elt_i = indata[i]; \ + GLfloat *I = verts[elt_i].f; \ + GLfloat dpI = (sgn I[v]) + I[CLIP_WCOORD]; \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLfloat *O = verts[next_vert].f; \ + GLfloat t = dpI / (dpI - dpJ); \ + GLuint j; \ + \ + clipmask[next_vert] = 0; \ + outdata[n++] = next_vert++; \ + \ + for (j = 0 ; j < SIZE ; j += 2) { \ + O[j] = LINTERP(t, I[j], J[j]); \ + O[j+1] = LINTERP(t, I[j+1], J[j+1]); \ + } \ + } \ + \ + clipmask[elt_i] |= PLANE; /* don't set up */ \ + \ + if (!NEGATIVE(dpI)) { \ + outdata[n++] = elt_i; \ + clipmask[elt_i] &= ~PLANE; /* set up after all */ \ + } \ + \ + J = I; \ + dpJ = dpI; \ + } \ + \ + if (n < 3) return; \ +} + +#define LINE_CLIP(x,y,z,w,PLANE) \ +if (mask & PLANE) { \ + GLfloat dpI = DOT4V(I,x,y,z,w); \ + GLfloat dpJ = DOT4V(J,x,y,z,w); \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLfloat *O = verts[next_vert].f; \ + GLfloat t = dpI / (dpI - dpJ); \ + GLuint j; \ + \ + for (j = 0 ; j < SIZE ; j += 2) { \ + O[j] = LINTERP(t, I[j], J[j]); \ + O[j+1] = LINTERP(t, I[j+1], J[j+1]); \ + } \ + \ + clipmask[next_vert] = 0; \ + \ + if (NEGATIVE(dpI)) { \ + clipmask[elts[0]] |= PLANE; \ + I = O; elts[0] = next_vert++; \ + } else { \ + clipmask[elts[1]] |= PLANE; \ + J = O; elts[1] = next_vert++; \ + } \ + } \ + else if (NEGATIVE(dpI)) \ + return; \ +} + + +#define CLIP_POINT( e ) \ + if (mask[e]) \ + *out++ = e + +#define CLIP_LINE( e1, e0 ) \ +do { \ + GLubyte ormask = mask[e0] | mask[e1]; \ + out[0] = e1; \ + out[1] = e0; \ + out+=2; \ + if (ormask) { \ + out-=2; \ + if (!(mask[e0] & mask[e1])) { \ + TAG(fx_line_clip)( &out, verts, mask, &next_vert, ormask); \ + } \ + } \ +} while (0) + +#define CLIP_TRIANGLE( e2, e1, e0 ) \ +do { \ + GLubyte ormask; \ + out[0] = e2; \ + out[1] = e1; \ + out[2] = e0; \ + out += 3; \ + ormask = mask[e2] | mask[e1] | mask[e0]; \ + if (ormask) { \ + out -= 3; \ + if ( !(mask[e2] & mask[e1] & mask[e0])) { \ + TAG(fx_tri_clip)( &out, verts, mask, &next_vert, ormask ); \ + } \ + } \ +} while (0) + +#if defined(FX_V2) || defined(DRIVERTS) + +#define VARS_XYZ \ + GLfloat vsx = mat[MAT_SX]; \ + GLfloat vsy = mat[MAT_SY]; \ + GLfloat vsz = mat[MAT_SZ]; \ + GLfloat vtx = mat[MAT_TX]; \ + GLfloat vty = mat[MAT_TY]; \ + GLfloat vtz = mat[MAT_TZ]; + +#define DO_SETUP_XYZ \ + f[XCOORD] = f[0] * oow * vsx + vtx; \ + f[YCOORD] = f[1] * oow * vsy + vty; \ + f[ZCOORD] = f[2] * oow * vsz + vtz; + +#else +#if defined(HAVE_FAST_MATH) + +#define VARS_XYZ \ + GLfloat vsx = mat[MAT_SX]; \ + GLfloat vsy = mat[MAT_SY]; \ + GLfloat vsz = mat[MAT_SZ]; \ + const GLfloat snapper = (3L << 18); \ + GLfloat vtx = mat[MAT_TX] + snapper; \ + GLfloat vty = mat[MAT_TY] + snapper; \ + GLfloat vtz = mat[MAT_TZ]; + +#define DO_SETUP_XYZ \ + f[XCOORD] = f[0] * oow * vsx + vtx; \ + f[XCOORD] -= snapper; \ + f[YCOORD] = f[1] * oow * vsy + vty; \ + f[YCOORD] -= snapper; \ + f[ZCOORD] = f[2] * oow * vsz + vtz; + +#else + +#define VARS_XYZ \ + GLfloat vsx = mat[MAT_SX] * 16.0f; \ + GLfloat vsy = mat[MAT_SY] * 16.0f; \ + GLfloat vsz = mat[MAT_SZ]; \ + GLfloat vtx = mat[MAT_TX] * 16.0f; \ + GLfloat vty = mat[MAT_TY] * 16.0f; \ + GLfloat vtz = mat[MAT_TZ]; + +#define DO_SETUP_XYZ \ + f[XCOORD] = ((int)(f[0]*oow*vsx+vtx)) * (1.0f/16.0f); \ + f[YCOORD] = ((int)(f[1]*oow*vsy+vty)) * (1.0f/16.0f); \ + f[ZCOORD] = f[2]*oow*vsz + vtz; + + +#endif +#endif + + + +struct fx_fast_tab +{ + void (*build_vertices)( struct vertex_buffer *VB, GLuint do_clip ); + + void (*clip[GL_POLYGON+1])( struct vertex_buffer *VB, + GLuint start, + GLuint count, + GLuint parity ); + + void (*project_clipped_vertices)( GLfloat *first, + GLfloat *last, + const GLfloat *mat, + GLuint stride, + const GLubyte *mask ); + + void (*project_vertices)( GLfloat *first, + GLfloat *last, + const GLfloat *mat, + GLuint stride ); +}; + +/* Pack either rgba or texture into the remaining half of a 32 byte vertex. + */ +#define CLIP_R CLIP_RCOORD +#define CLIP_G CLIP_GCOORD +#define CLIP_B CLIP_BCOORD +#define CLIP_A CLIP_ACOORD +#define CLIP_S0 4 +#define CLIP_T0 5 +#define CLIP_S1 6 +#define CLIP_T1 7 + +#define SIZE 4 +#define TYPE (0) +#define TAG(x) x +#include "fxfasttmp.h" + +#define SIZE 8 +#define TYPE (SETUP_RGBA) +#define TAG(x) x##_RGBA +#include "fxfasttmp.h" + +#define SIZE 6 +#define TYPE (SETUP_TMU0) +#define TAG(x) x##_TMU0 +#include "fxfasttmp.h" + +#define SIZE 8 +#define TYPE (SETUP_TMU0|SETUP_TMU1) +#define TAG(x) x##_TMU0_TMU1 +#include "fxfasttmp.h" + +#undef CLIP_S1 +#undef CLIP_T1 +#define CLIP_S1 4 +#define CLIP_T1 5 + +#define SIZE 6 +#define TYPE (SETUP_TMU1) +#define TAG(x) x##_TMU1 +#include "fxfasttmp.h" + +/* These three need to use a full 64 byte clip-space vertex. + */ +#undef CLIP_S0 +#undef CLIP_T0 +#undef CLIP_S1 +#undef CLIP_T1 + +#define CLIP_S0 8 +#define CLIP_T0 9 +#define CLIP_S1 10 +#define CLIP_T1 11 + +#define SIZE 10 +#define TYPE (SETUP_RGBA|SETUP_TMU0) +#define TAG(x) x##_RGBA_TMU0 +#include "fxfasttmp.h" + +#define SIZE 12 +#define TYPE (SETUP_RGBA|SETUP_TMU0|SETUP_TMU1) +#define TAG(x) x##_RGBA_TMU0_TMU1 +#include "fxfasttmp.h" + +#undef CLIP_S1 +#undef CLIP_T1 +#define CLIP_S1 8 +#define CLIP_T1 9 + +#define SIZE 10 +#define TYPE (SETUP_RGBA|SETUP_TMU1) +#define TAG(x) x##_RGBA_TMU1 +#include "fxfasttmp.h" + +static struct fx_fast_tab fxFastTab[0x8]; + +void fxDDFastPathInit() +{ + fx_init_fastpath( &fxFastTab[0] ); + fx_init_fastpath_RGBA( &fxFastTab[SETUP_RGBA] ); + fx_init_fastpath_TMU0( &fxFastTab[SETUP_TMU0] ); + fx_init_fastpath_TMU1( &fxFastTab[SETUP_TMU1] ); + fx_init_fastpath_RGBA_TMU0( &fxFastTab[SETUP_RGBA|SETUP_TMU0] ); + fx_init_fastpath_RGBA_TMU1( &fxFastTab[SETUP_RGBA|SETUP_TMU1] ); + fx_init_fastpath_TMU0_TMU1( &fxFastTab[SETUP_TMU0|SETUP_TMU1] ); + fx_init_fastpath_RGBA_TMU0_TMU1( &fxFastTab[SETUP_RGBA|SETUP_TMU0| + SETUP_TMU1] ); +} + + + +void fxDDFastPath( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + GLenum prim = ctx->CVA.elt_mode; + struct tfxMesaContext *fxMesa = FX_CONTEXT(ctx); + struct fx_fast_tab *tab = &fxFastTab[fxMesa->setupindex & 0x7]; + GLuint do_clip = 1; + struct tfxMesaVertexBuffer *fxVB = FX_DRIVER_DATA(VB); +#ifdef DRIVERTS + GLfloat tx, ty; +#endif + + fxVertex *first; + GLfloat *mat = ctx->Viewport.WindowMap.m; + + gl_prepare_arrays_cva( VB ); /* still need this */ + + if (VB->EltPtr->count * 12 > fxVB->size) { + fxDDResizeVB( VB, VB->EltPtr->count * 12 ); + do_clip = 1; + } + + tab->build_vertices( VB, do_clip ); /* object->clip space */ + + first = FX_DRIVER_DATA(VB)->verts; + +#ifdef DRIVERTS + tx=mat[MAT_TX]; + ty=mat[MAT_TY]; + mat[MAT_TX]=tx+fxMesa->x_offset; + mat[MAT_TY]=ty+fxMesa->y_delta; +#endif + + if (VB->ClipOrMask) { + if (!VB->ClipAndMask) { + GLubyte tmp = VB->ClipOrMask; + + tab->clip[prim]( VB, 0, VB->EltPtr->count, 0 ); /* clip */ + + tab->project_clipped_vertices( fxVB->verts->f, + fxVB->last_vert->f, + mat, 16 * 4, + VB->ClipMask ); + + ctx->CVA.elt_mode = gl_reduce_prim[prim]; + VB->EltPtr = &(FX_DRIVER_DATA(VB)->clipped_elements); + + VB->ClipOrMask = 0; + fxDDRenderElementsDirect( VB ); /* render using new list */ + VB->ClipOrMask = tmp; + } + } else { + tab->project_vertices( fxVB->verts->f, + fxVB->last_vert->f, + mat, 16 * 4 ); + + fxDDRenderElementsDirect( VB ); /* render using orig list */ + } + +#ifdef DRIVERTS + mat[MAT_TX]=tx; + mat[MAT_TY]=ty; +#endif + + /* This indicates that there is no cached data to reuse. + */ + VB->pipeline->data_valid = 0; + VB->pipeline->pipeline_valid = 0; +} + + +#else + +/* + * Need this to provide at least one external definition. + */ +int gl_fxfastpath_dummy(void) +{ + return 0; +} + +#endif diff --git a/xc/extras/Mesa/src/FX/fxfasttmp.h b/xc/extras/Mesa/src/FX/fxfasttmp.h new file mode 100644 index 000000000..f97b8108f --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxfasttmp.h @@ -0,0 +1,367 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* Build clip space vertices from object space data. + */ +static void TAG(fx_setup_full)( struct vertex_buffer *VB, GLuint do_clip ) +{ + GLcontext *ctx = VB->ctx; + GLfloat *f = (GLfloat *) FX_DRIVER_DATA(VB)->verts; + fxMesaContext fxMesa = FX_CONTEXT(VB->ctx); + GLuint count = VB->Count; + GLuint i; + + const GLfloat * const m = ctx->ModelProjectMatrix.m; + +#if (TYPE & SETUP_RGBA) + GLubyte *color = (GLubyte *)VB->ColorPtr->data; + GLuint color_stride = VB->ColorPtr->stride; +#endif + +#if (TYPE & SETUP_TMU0) + GLuint tmu0_source = fxMesa->tmu_source[0]; + struct gl_texture_unit *t0 = &ctx->Texture.Unit[tmu0_source]; + GLint s0scale = FX_TEXTURE_DATA(t0)->int_sScale; + GLint t0scale = FX_TEXTURE_DATA(t0)->int_tScale; + GLint *tmu0_int_data = (GLint *)VB->TexCoordPtr[tmu0_source]->data; + GLuint tmu0_stride = VB->TexCoordPtr[tmu0_source]->stride; +#endif + +#if (TYPE & SETUP_TMU1) + GLuint tmu1_source = fxMesa->tmu_source[1]; + struct gl_texture_unit *t1 = &ctx->Texture.Unit[tmu1_source]; + GLint s1scale = FX_TEXTURE_DATA(t1)->int_sScale; + GLint t1scale = FX_TEXTURE_DATA(t1)->int_tScale; + GLint *tmu1_int_data = (GLint *)VB->TexCoordPtr[tmu1_source]->data; + GLuint tmu1_stride = VB->TexCoordPtr[tmu1_source]->stride; +#endif + + (void) fxMesa; + (void) ctx; + (void) i; + (void) f; + + /* Use 3 seperate loops because it's easier for assembly. A + * best-case solution might be to do all three in a single assembly + * loop. + */ + gl_xform_points3_v16_general(FX_DRIVER_DATA(VB)->verts[0].f, + m, + VB->ObjPtr->start, + VB->ObjPtr->stride, + count); + + if (do_clip) + { + VB->ClipAndMask = ~0; + VB->ClipOrMask = 0; + gl_cliptest_points4_v16(FX_DRIVER_DATA(VB)->verts[0].f, + FX_DRIVER_DATA(VB)->verts[count].f, + &(VB->ClipOrMask), + &(VB->ClipAndMask), + VB->ClipMask); + } + + +#if (TYPE) + for (i = 0 ; i < count ; i++, f += 16) { +#if (TYPE & SETUP_RGBA) + GLubyte *col = color; color += color_stride; + UBYTE_COLOR_TO_FLOAT_255_COLOR2( f[CLIP_R], col[0] ); + UBYTE_COLOR_TO_FLOAT_255_COLOR2( f[CLIP_G], col[1] ); + UBYTE_COLOR_TO_FLOAT_255_COLOR2( f[CLIP_B], col[2] ); + UBYTE_COLOR_TO_FLOAT_255_COLOR2( f[CLIP_A], col[3] ); +#endif +#if (TYPE & SETUP_TMU0) + * (int *) &f[CLIP_S0] = s0scale + tmu0_int_data[0]; + * (int *) &f[CLIP_T0] = t0scale + tmu0_int_data[1]; + STRIDE_T(tmu0_int_data, GLint, tmu0_stride); +#endif +#if (TYPE & SETUP_TMU1) + * (int *) &f[CLIP_S1] = s1scale + tmu1_int_data[0]; + * (int *) &f[CLIP_T1] = t1scale + tmu1_int_data[1]; + STRIDE_T(tmu1_int_data, GLint, tmu1_stride); +#endif + } +#endif + + FX_DRIVER_DATA(VB)->last_vert = &(FX_DRIVER_DATA(VB)->verts[count]); +} + + +/* Do viewport map, device scale and perspective projection. + * + * Rearrange fxVertices to look like grVertices. + */ +static void TAG(fx_project_vertices)( GLfloat *first, + GLfloat *last, + const GLfloat *mat, + GLuint stride ) +{ + GLfloat *f; + VARS_XYZ; + + for ( f = first ; f != last ; STRIDE_F(f, stride)) + { + GLfloat oow = 1.0f/f[CLIP_WCOORD]; /* urp! */ + +#if FX_USE_PARGB + if (TYPE & SETUP_RGBA) { + PACK_4F_ARGB(GET_PARGB(f),f[CLIP_A],f[CLIP_R],f[CLIP_G],f[CLIP_B]); + } +#else + if (TYPE & SETUP_RGBA) { + f[RCOORD]=f[CLIP_R]; + } +#endif + if (TYPE & SETUP_TMU1) { + f[S1COORD] = f[CLIP_S1] * oow; + f[T1COORD] = f[CLIP_T1] * oow; + } + + if (TYPE & SETUP_TMU0) { + f[T0COORD] = f[CLIP_T0] * oow; + f[S0COORD] = f[CLIP_S0] * oow; + } + + DO_SETUP_XYZ; + + f[OOWCOORD] = oow; + } +} + +static void TAG(fx_project_clipped_vertices)( GLfloat *first, + GLfloat *last, + const GLfloat *mat, + GLuint stride, + const GLubyte *mask ) +{ + GLfloat *f; + VARS_XYZ; + + for ( f = first ; f != last ; STRIDE_F(f, stride), mask++) { + if (!*mask) { + + GLfloat oow = 1.0f / f[CLIP_WCOORD]; +#if FX_USE_PARGB + if (TYPE & SETUP_RGBA) { + const GLuint r = f[CLIP_R]; + const GLuint g = f[CLIP_G]; + const GLuint b = f[CLIP_B]; + const GLuint a = f[CLIP_A]; + /* ToDo Optimize */ + GET_PARGB(f) = a << 24 | r << 16 | g << 8 | b; + } +#else + if (TYPE & SETUP_RGBA) { + f[RCOORD]=f[CLIP_R]; + } +#endif + + if (TYPE & SETUP_TMU1) { + f[S1COORD] = f[CLIP_S1] * oow; + f[T1COORD] = f[CLIP_T1] * oow; + } + + if (TYPE & SETUP_TMU0) { + f[T0COORD] = f[CLIP_T0] * oow; + f[S0COORD] = f[CLIP_S0] * oow; + } + + DO_SETUP_XYZ; + + f[OOWCOORD] = oow; + } + } +} + + +static +#if (SIZE <= 8) +INLINE +#endif +void TAG(fx_tri_clip)( GLuint **p_elts, + fxVertex *verts, + GLubyte *clipmask, + GLuint *p_next_vert, + GLubyte mask ) +{ + GLuint *elts = *p_elts; + GLuint next_vert = *p_next_vert; + GLuint vlist1[VB_MAX_CLIPPED_VERTS]; + GLuint vlist2[VB_MAX_CLIPPED_VERTS]; + GLuint *inlist[2]; + GLuint *out; + GLuint in = 0; + GLuint n = 3; + GLuint i; + + inlist[0] = elts; + inlist[1] = vlist2; + + CLIP(-,0,CLIP_RIGHT_BIT); + CLIP(+,0,CLIP_LEFT_BIT); + CLIP(-,1,CLIP_TOP_BIT); + CLIP(+,1,CLIP_BOTTOM_BIT); + CLIP(-,2,CLIP_FAR_BIT); + CLIP(+,2,CLIP_NEAR_BIT); + + /* Convert the planar polygon to a list of triangles. + */ + out = inlist[in]; + + for (i = 2 ; i < n ; i++) { + elts[0] = out[0]; + elts[1] = out[i-1]; + elts[2] = out[i]; + elts += 3; + } + + *p_next_vert = next_vert; + *p_elts = elts; +} + + +static INLINE void TAG(fx_line_clip)( GLuint **p_elts, + fxVertex *verts, + GLubyte *clipmask, + GLuint *p_next_vert, + GLubyte mask ) +{ + GLuint *elts = *p_elts; + GLfloat *I = verts[elts[0]].f; + GLfloat *J = verts[elts[1]].f; + GLuint next_vert = *p_next_vert; + + LINE_CLIP(1,0,0,-1,CLIP_LEFT_BIT); + LINE_CLIP(-1,0,0,1,CLIP_RIGHT_BIT); + LINE_CLIP(0,1,0,-1,CLIP_TOP_BIT); + LINE_CLIP(0,-1,0,1,CLIP_BOTTOM_BIT); + LINE_CLIP(0,0,1,-1,CLIP_FAR_BIT); + LINE_CLIP(0,0,-1,1,CLIP_NEAR_BIT); + + *p_next_vert = next_vert; + *p_elts += 2; +} + + +/* Build a table of functions to clip each primitive type. + */ +#define LOCAL_VARS \ + GLuint *elt = VB->EltPtr->data; \ + fxVertex *verts = FX_DRIVER_DATA(VB)->verts; \ + GLuint next_vert = VB->Count; \ + GLuint *out = FX_DRIVER_DATA(VB)->clipped_elements.data; \ + GLubyte *mask = VB->ClipMask; \ + + +#define POSTFIX \ + FX_DRIVER_DATA(VB)->clipped_elements.count = \ + out - FX_DRIVER_DATA(VB)->clipped_elements.data; \ + FX_DRIVER_DATA(VB)->last_vert = &verts[next_vert]; + +#define INIT(x) + +#define RENDER_POINTS(start, count) \ +do { \ + GLuint i; \ + for (i = start ; i < count ; i++ ) \ + CLIP_POINT( elt[i] ); \ +} while (0) + +#define RENDER_LINE(i1, i0) \ + CLIP_LINE(elt[i1], elt[i0]) + +#define RENDER_TRI(i2, i1, i0, pv, parroty) \ +do { \ + GLuint e2 = elt[i2], e1 = elt[i1], e0 = elt[i0]; \ + if (parroty) e2 = elt[i1], e1 = elt[i2]; \ + CLIP_TRIANGLE( e2, e1, e0 ); \ +} while (0) + +#define RENDER_QUAD(i3, i2, i1, i0, pv) \ + CLIP_TRIANGLE(elt[i3], elt[i2], elt[i0]); \ + CLIP_TRIANGLE(elt[i2], elt[i1], elt[i0]) + +#define PRESERVE_TAG +#include "render_tmp.h" + + +static void TAG(fx_init_fastpath)( struct fx_fast_tab *tab ) +{ + GLuint i; + + /* Use the render templates to do clipping. + */ + TAG(render_init)(); + for (i = 0 ; i < GL_POLYGON+2 ; i++) + tab->clip[i] = TAG(render_tab)[i]; + + tab->build_vertices = TAG(fx_setup_full); + tab->project_vertices = TAG(fx_project_vertices); + tab->project_clipped_vertices = TAG(fx_project_clipped_vertices); + +#if defined(USE_3DNOW_ASM) + if (gl_x86_cpu_features & GL_CPU_3Dnow) { + extern void TAG(fx_3dnow_project_vertices)( GLfloat *first, + GLfloat *last, + const GLfloat *mat, + GLuint stride ); + + extern void TAG(fx_3dnow_project_clipped_vertices)( GLfloat *first, + GLfloat *last, + const GLfloat *mat, + GLuint stride, + const GLubyte *mask ); + + tab->project_vertices = TAG(fx_3dnow_project_vertices); + tab->project_clipped_vertices = TAG(fx_3dnow_project_clipped_vertices); + } +#endif +} + +#undef TYPE +#undef TAG +#undef SIZE diff --git a/xc/extras/Mesa/src/FX/fxglidew.c b/xc/extras/Mesa/src/FX/fxglidew.c new file mode 100644 index 000000000..5155c825a --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxglidew.c @@ -0,0 +1,451 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) +#include "glide.h" +#include "fxglidew.h" +#include "fxdrv.h" + +#include <stdlib.h> +#include <string.h> + +FxI32 FX_grGetInteger_NoLock(FxU32 pname) +{ +#if !defined(FX_GLIDE3) + switch (pname) + { + case FX_FOG_TABLE_ENTRIES: + return GR_FOG_TABLE_SIZE; + case FX_GLIDE_STATE_SIZE: + return sizeof(GrState); + case FX_LFB_PIXEL_PIPE: + return FXFALSE; + case FX_PENDING_BUFFERSWAPS: + return grBufferNumPending(); + case FX_TEXTURE_ALIGN: + /* This is a guess from reading the glide3 docs */ + return 8; + default: + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"Wrong parameter in FX_grGetInteger!\n"); + } + return -1; + } +#else + FxU32 grname; + FxI32 result; + + switch (pname) + { + case FX_FOG_TABLE_ENTRIES: + case FX_GLIDE_STATE_SIZE: + case FX_LFB_PIXEL_PIPE: + case FX_PENDING_BUFFERSWAPS: + case FX_TEXTURE_ALIGN: + grname = pname; + break; + default: + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"Wrong parameter in FX_grGetInteger!\n"); + } + return -1; + } + + grGet(grname,4,&result); + return result; +#endif +} + +FxI32 FX_grGetInteger(FxU32 pname) +{ + int result; + + BEGIN_BOARD_LOCK(); + result=FX_grGetInteger_NoLock(pname); + END_BOARD_LOCK(); + return result; +} + + +FxBool FX_grLfbLock(GrLock_t type, GrBuffer_t buffer, + GrLfbWriteMode_t writeMode, GrOriginLocation_t origin, + FxBool pixelPipeline, GrLfbInfo_t *info ) { + FxBool result; + + BEGIN_BOARD_LOCK(); + result=grLfbLock(type, buffer, writeMode, origin, pixelPipeline, info); + END_BOARD_LOCK(); + return result; +} + +FxU32 FX_grTexTextureMemRequired(FxU32 evenOdd, GrTexInfo *info) { + FxU32 result; + + BEGIN_BOARD_LOCK(); + result=grTexTextureMemRequired(evenOdd, info); + END_BOARD_LOCK(); + return result; +} + +FxU32 FX_grTexMinAddress(GrChipID_t tmu) { + FxU32 result; + + BEGIN_BOARD_LOCK(); + result=grTexMinAddress(tmu); + END_BOARD_LOCK(); + return result; +} + +extern FxU32 FX_grTexMaxAddress(GrChipID_t tmu) { + FxU32 result; + + BEGIN_BOARD_LOCK(); + result=grTexMaxAddress(tmu); + END_BOARD_LOCK(); + return result; +} + +FxBool FX_grSstControl(FxU32 code) +{ +#if defined(FX_GLIDE3) + /* The glide 3 sources call for grEnable/grDisable to be called in exchange + * for grSstControl. */ + switch(code) { + case GR_CONTROL_ACTIVATE: + grEnable(GR_PASSTHRU); + break; + case GR_CONTROL_DEACTIVATE: + grDisable(GR_PASSTHRU); + break; + } + /* Appearently GR_CONTROL_RESIZE can be ignored. */ + return 1; /* OK? */ +#else + FxU32 result; + BEGIN_BOARD_LOCK(); + result = grSstControl(code); + END_BOARD_LOCK(); + return result; +#endif +} + + +#if defined(FX_GLIDE3) + +void FX_grGammaCorrectionValue(float val) +{ + (void)val; +/* ToDo */ +} + +int FX_getFogTableSize(void) +{ + int result; + BEGIN_BOARD_LOCK(); + grGet(GR_FOG_TABLE_ENTRIES,sizeof(int),(void*)&result); + END_BOARD_LOCK(); + return result; +} + +int FX_getGrStateSize(void) +{ + int result; + BEGIN_BOARD_LOCK(); + grGet(GR_GLIDE_STATE_SIZE,sizeof(int),(void*)&result); + END_BOARD_LOCK(); + + return result; + +} + +int FX_grSstScreenWidth() +{ + FxI32 result[4]; + + BEGIN_BOARD_LOCK(); + grGet(GR_VIEWPORT,sizeof(FxI32)*4,result); + END_BOARD_LOCK(); + + return result[2]; +} + +int FX_grSstScreenHeight() +{ + FxI32 result[4]; + + BEGIN_BOARD_LOCK(); + grGet(GR_VIEWPORT,sizeof(FxI32)*4,result); + END_BOARD_LOCK(); + + return result[3]; +} + +void FX_grGlideGetVersion(char *buf) +{ + BEGIN_BOARD_LOCK(); + strcpy(buf,grGetString(GR_VERSION)); + END_BOARD_LOCK(); +} + +void FX_grSstPerfStats(GrSstPerfStats_t *st) +{ + FxI32 n; + grGet(GR_STATS_PIXELS_IN, 4, &n); st->pixelsIn = n; + grGet(GR_STATS_PIXELS_CHROMA_FAIL, 4, &n); st->chromaFail = n; + grGet(GR_STATS_PIXELS_DEPTHFUNC_FAIL, 4, &n); st->zFuncFail = n; + grGet(GR_STATS_PIXELS_AFUNC_FAIL, 4, &n); st->aFuncFail = n; + grGet(GR_STATS_PIXELS_OUT, 4, &n); st->pixelsOut = n; +} + +void FX_grAADrawLine(GrVertex *a,GrVertex *b) +{ + /* ToDo */ + BEGIN_CLIP_LOOP(); + grDrawLine(a,b); + END_CLIP_LOOP(); +} + +void FX_grAADrawPoint(GrVertex *a) +{ + BEGIN_CLIP_LOOP(); + grDrawPoint(a); + END_CLIP_LOOP(); +} + +void FX_grDrawPolygonVertexList(int n, GrVertex *verts) +{ + BEGIN_CLIP_LOOP(); + grDrawVertexArrayContiguous(GR_POLYGON, n, verts, sizeof(GrVertex)); + END_CLIP_LOOP(); +} + +#if FX_USE_PARGB +void FX_setupGrVertexLayout(void) +{ + BEGIN_BOARD_LOCK(); + grReset(GR_VERTEX_PARAMETER); + + grCoordinateSpace(GR_WINDOW_COORDS); + grVertexLayout(GR_PARAM_XY, GR_VERTEX_X_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_PARGB, GR_VERTEX_PARGB_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_Q, GR_VERTEX_OOW_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_Z, GR_VERTEX_OOZ_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_ST0, GR_VERTEX_SOW_TMU0_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_DISABLE); + grVertexLayout(GR_PARAM_ST1, GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE); + grVertexLayout(GR_PARAM_Q1, GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE); + END_BOARD_LOCK(); +} +#else /* FX_USE_PARGB */ +void FX_setupGrVertexLayout(void) +{ + BEGIN_BOARD_LOCK(); + grReset(GR_VERTEX_PARAMETER); + + grCoordinateSpace(GR_WINDOW_COORDS); + grVertexLayout(GR_PARAM_XY, GR_VERTEX_X_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_RGB, GR_VERTEX_R_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_A, GR_VERTEX_A_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_Q, GR_VERTEX_OOW_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_Z, GR_VERTEX_OOZ_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_ST0, GR_VERTEX_SOW_TMU0_OFFSET << 2, GR_PARAM_ENABLE); + grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_DISABLE); + grVertexLayout(GR_PARAM_ST1, GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE); + grVertexLayout(GR_PARAM_Q1, GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE); + END_BOARD_LOCK(); +} +#endif + +void FX_grHints_NoLock(GrHint_t hintType, FxU32 hintMask) +{ + switch(hintType) { + case GR_HINT_STWHINT: + { + if (hintMask & GR_STWHINT_W_DIFF_TMU0) + grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_ENABLE); + else + grVertexLayout(GR_PARAM_Q0,GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_DISABLE); + + if (hintMask & GR_STWHINT_ST_DIFF_TMU1) + grVertexLayout(GR_PARAM_ST1,GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_ENABLE); + else + grVertexLayout(GR_PARAM_ST1,GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE); + + if (hintMask & GR_STWHINT_W_DIFF_TMU1) + grVertexLayout(GR_PARAM_Q1,GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_ENABLE); + else + grVertexLayout(GR_PARAM_Q1,GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE); + + } + } +} + +void FX_grHints(GrHint_t hintType, FxU32 hintMask) { + BEGIN_BOARD_LOCK(); + FX_grHints_NoLock(hintType, hintMask); + END_BOARD_LOCK(); +} + +int FX_grSstQueryHardware(GrHwConfiguration *config) +{ + int i,j; + int numFB; + + BEGIN_BOARD_LOCK(); + grGet(GR_NUM_BOARDS,4,(void*)&(config->num_sst)); + if (config->num_sst == 0) + return 0; + for (i = 0; i< config->num_sst; i++) + { + config->SSTs[i].type = GR_SSTTYPE_VOODOO; + grSstSelect(i); + grGet(GR_MEMORY_FB,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.fbRam)); + config->SSTs[i].sstBoard.VoodooConfig.fbRam/= 1024*1024; + + grGet(GR_NUM_TMU,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.nTexelfx)); + + + grGet(GR_NUM_FB,4,(void*)&numFB); + if (numFB > 1) + config->SSTs[i].sstBoard.VoodooConfig.sliDetect = FXTRUE; + else + config->SSTs[i].sstBoard.VoodooConfig.sliDetect = FXFALSE; + for (j = 0; j < config->SSTs[i].sstBoard.VoodooConfig.nTexelfx; j++) + { + grGet(GR_MEMORY_TMU,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.tmuConfig[j].tmuRam)); + config->SSTs[i].sstBoard.VoodooConfig.tmuConfig[j].tmuRam /= 1024*1024; + } + } + END_BOARD_LOCK(); + return 1; +} + +#else + +int FX_grSstScreenWidth() +{ + int i; + BEGIN_BOARD_LOCK(); + i = grSstScreenWidth(); + END_BOARD_LOCK(); + return i; +} + +int FX_grSstScreenHeight() +{ + int i; + BEGIN_BOARD_LOCK(); + i = grSstScreenHeight(); + END_BOARD_LOCK(); + return i; +} + +int FX_grSstQueryHardware(GrHwConfiguration *c) +{ + int i; + BEGIN_BOARD_LOCK(); + i = grSstQueryHardware(c); + END_BOARD_LOCK(); + return i; +} + + +#endif /* FX_GLIDE3 */ + +/* It appears to me that this function is needed either way. */ +FX_GrContext_t FX_grSstWinOpen( FxU32 hWnd, + GrScreenResolution_t screen_resolution, + GrScreenRefresh_t refresh_rate, + GrColorFormat_t color_format, + GrOriginLocation_t origin_location, + int nColBuffers, + int nAuxBuffers) +{ + FX_GrContext_t i; + BEGIN_BOARD_LOCK(); + i = grSstWinOpen( hWnd, + screen_resolution, + refresh_rate, + color_format, + origin_location, + nColBuffers, + nAuxBuffers ); + + /* + fprintf(stderr, + "grSstWinOpen( win %d res %d ref %d fmt %d\n" + " org %d ncol %d naux %d )\n" + " ==> %d\n", + hWnd, + screen_resolution, + refresh_rate, + color_format, + origin_location, + nColBuffers, + nAuxBuffers, + i); + */ + END_BOARD_LOCK(); + return i; +} + + + +#else + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_glidew(void) +{ + return 0; +} + +#endif /* FX */ diff --git a/xc/extras/Mesa/src/FX/fxglidew.h b/xc/extras/Mesa/src/FX/fxglidew.h new file mode 100644 index 000000000..6da1ea5f3 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxglidew.h @@ -0,0 +1,845 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifndef __FX_GLIDE_WARPER__ +#define __FX_GLIDE_WARPER__ + +#include <glide.h> + +/* + * General context: + */ +#if !defined(FX_GLIDE3) + typedef FxU32 FX_GrContext_t; /* Not used in Glide2 */ +#else + typedef GrContext_t FX_GrContext_t; +#endif + +/* + * Glide3 emulation on Glide2: + */ +#if !defined(FX_GLIDE3) + /* Constanst for FX_grGetInteger( ) */ + #define FX_FOG_TABLE_ENTRIES 0x0004 /* The number of entries in the hardware fog table. */ + #define FX_GLIDE_STATE_SIZE 0x0006 /* Size of buffer, in bytes, needed to save Glide state. */ + #define FX_LFB_PIXEL_PIPE 0x0009 /* 1 if LFB writes can go through the 3D pixel pipe. */ + #define FX_PENDING_BUFFERSWAPS 0x0014 /* The number of buffer swaps pending. */ + #define FX_TEXTURE_ALIGN 0x0024 /* The required alignment for textures */ +#else + #define FX_FOG_TABLE_ENTRIES GR_FOG_TABLE_ENTRIES + #define FX_GLIDE_STATE_SIZE GR_GLIDE_STATE_SIZE + #define FX_LFB_PIXEL_PIPE GR_LFB_PIXEL_PIPE + #define FX_PENDING_BUFFERSWAPS GR_PENDING_BUFFERSWAPS + #define FX_TEXTURE_ALIGN GR_TEXTURE_ALIGN +#endif + +/* + * Genral warper functions for Glide2/Glide3: + */ +extern FxI32 FX_grGetInteger(FxU32 pname); +extern FxI32 FX_grGetInteger_NoLock(FxU32 pname); + +/* + * Glide2 emulation on Glide3: + */ +#if defined(FX_GLIDE3) + +#define GR_ASPECT_1x1 GR_ASPECT_LOG2_1x1 +#define GR_ASPECT_2x1 GR_ASPECT_LOG2_2x1 +#define GR_ASPECT_4x1 GR_ASPECT_LOG2_4x1 +#define GR_ASPECT_8x1 GR_ASPECT_LOG2_8x1 +#define GR_ASPECT_1x2 GR_ASPECT_LOG2_1x2 +#define GR_ASPECT_1x4 GR_ASPECT_LOG2_1x4 +#define GR_ASPECT_1x8 GR_ASPECT_LOG2_1x8 + +#define GR_LOD_256 GR_LOD_LOG2_256 +#define GR_LOD_128 GR_LOD_LOG2_128 +#define GR_LOD_64 GR_LOD_LOG2_64 +#define GR_LOD_32 GR_LOD_LOG2_32 +#define GR_LOD_16 GR_LOD_LOG2_16 +#define GR_LOD_8 GR_LOD_LOG2_8 +#define GR_LOD_4 GR_LOD_LOG2_4 +#define GR_LOD_2 GR_LOD_LOG2_2 +#define GR_LOD_1 GR_LOD_LOG2_1 + +#define GR_FOG_WITH_TABLE GR_FOG_WITH_TABLE_ON_Q + +typedef int GrSstType; + +#define MAX_NUM_SST 4 + +#define GR_SSTTYPE_VOODOO 0 +#define GR_SSTTYPE_SST96 1 +#define GR_SSTTYPE_AT3D 2 +#define GR_SSTTYPE_Voodoo2 3 + +typedef struct GrTMUConfig_St { + int tmuRev; /* Rev of Texelfx chip */ + int tmuRam; /* 1, 2, or 4 MB */ +} GrTMUConfig_t; + +typedef struct GrVoodooConfig_St { + int fbRam; /* 1, 2, or 4 MB */ + int fbiRev; /* Rev of Pixelfx chip */ + int nTexelfx; /* How many texelFX chips are there? */ + FxBool sliDetect; /* Is it a scan-line interleaved board? */ + GrTMUConfig_t tmuConfig[GLIDE_NUM_TMU]; /* Configuration of the Texelfx chips */ +} GrVoodooConfig_t; + +typedef struct GrSst96Config_St { + int fbRam; /* How much? */ + int nTexelfx; + GrTMUConfig_t tmuConfig; +} GrSst96Config_t; + +typedef GrVoodooConfig_t GrVoodoo2Config_t; + +typedef struct GrAT3DConfig_St { + int rev; +} GrAT3DConfig_t; + +typedef struct { + int num_sst; /* # of HW units in the system */ + struct { + GrSstType type; /* Which hardware is it? */ + union SstBoard_u { + GrVoodooConfig_t VoodooConfig; + GrSst96Config_t SST96Config; + GrAT3DConfig_t AT3DConfig; + GrVoodoo2Config_t Voodoo2Config; + } sstBoard; + } SSTs[MAX_NUM_SST]; /* configuration for each board */ +} GrHwConfiguration; + +typedef FxU32 GrHint_t; +#define GR_HINTTYPE_MIN 0 +#define GR_HINT_STWHINT 0 + +typedef FxU32 GrSTWHint_t; +#define GR_STWHINT_W_DIFF_FBI FXBIT(0) +#define GR_STWHINT_W_DIFF_TMU0 FXBIT(1) +#define GR_STWHINT_ST_DIFF_TMU0 FXBIT(2) +#define GR_STWHINT_W_DIFF_TMU1 FXBIT(3) +#define GR_STWHINT_ST_DIFF_TMU1 FXBIT(4) +#define GR_STWHINT_W_DIFF_TMU2 FXBIT(5) +#define GR_STWHINT_ST_DIFF_TMU2 FXBIT(6) + +#define GR_CONTROL_ACTIVATE 1 +#define GR_CONTROL_DEACTIVATE 0 + +#define GrState void + +/* +** move the vertex layout defintion to application +*/ +typedef struct { + float sow; /* s texture ordinate (s over w) */ + float tow; /* t texture ordinate (t over w) */ + float oow; /* 1/w (used mipmapping - really 0xfff/w) */ +} GrTmuVertex; + + +#if FX_USE_PARGB + +typedef struct +{ + float x, y; /* X and Y in screen space */ + float ooz; /* 65535/Z (used for Z-buffering) */ + float oow; /* 1/W (used for W-buffering, texturing) */ + FxU32 argb; /* R, G, B, A [0..255.0] */ + GrTmuVertex tmuvtx[GLIDE_NUM_TMU]; + float z; /* Z is ignored */ +} GrVertex; + +#define GR_VERTEX_X_OFFSET 0 +#define GR_VERTEX_Y_OFFSET 1 +#define GR_VERTEX_OOZ_OFFSET 2 +#define GR_VERTEX_OOW_OFFSET 3 +#define GR_VERTEX_PARGB_OFFSET 4 +#define GR_VERTEX_SOW_TMU0_OFFSET 5 +#define GR_VERTEX_TOW_TMU0_OFFSET 6 +#define GR_VERTEX_OOW_TMU0_OFFSET 7 +#define GR_VERTEX_SOW_TMU1_OFFSET 8 +#define GR_VERTEX_TOW_TMU1_OFFSET 9 +#define GR_VERTEX_OOW_TMU1_OFFSET 10 +#define GR_VERTEX_Z_OFFSET 11 + +#define GET_PARGB(v) ((FxU32*)(v))[GR_VERTEX_PARGB_OFFSET] +/* GET_PA: returns the alpha component */ +#if GLIDE_ENDIAN == GLIDE_ENDIAN_BIG + #define GET_PA(v) ((FxU8*)(v))[GR_VERTEX_PARGB_OFFSET*4] +#else + #define GET_PA(v) ((FxU8*)(v))[GR_VERTEX_PARGB_OFFSET*4+3] +#endif +#define MESACOLOR2PARGB(c) (c[ACOMP] << 24 | c[GCOMP] << 16 | c[GCOMP] << 8 | c[BCOMP]) +#define PACK_4F_ARGB(dest,a,r,g,b) { \ + const GLuint cr = (int)r; \ + const GLuint cg = (int)g; \ + const GLuint ca = (int)a; \ + const GLuint cb = (int)b; \ + dest = ca << 24 | cr << 16 | cg << 8 | cb; \ + } + +#else /* FX_USE_PARGB */ + +typedef struct +{ + float x, y, z; /* X, Y, and Z of scrn space -- Z is ignored */ + float r, g, b; /* R, G, B, ([0..255.0]) */ + float ooz; /* 65535/Z (used for Z-buffering) */ + float a; /* Alpha [0..255.0] */ + float oow; /* 1/W (used for W-buffering, texturing) */ + GrTmuVertex tmuvtx[GLIDE_NUM_TMU]; +} GrVertex; + +#define GR_VERTEX_X_OFFSET 0 +#define GR_VERTEX_Y_OFFSET 1 +#define GR_VERTEX_Z_OFFSET 2 +#define GR_VERTEX_R_OFFSET 3 +#define GR_VERTEX_G_OFFSET 4 +#define GR_VERTEX_B_OFFSET 5 +#define GR_VERTEX_OOZ_OFFSET 6 +#define GR_VERTEX_A_OFFSET 7 +#define GR_VERTEX_OOW_OFFSET 8 +#define GR_VERTEX_SOW_TMU0_OFFSET 9 +#define GR_VERTEX_TOW_TMU0_OFFSET 10 +#define GR_VERTEX_OOW_TMU0_OFFSET 11 +#define GR_VERTEX_SOW_TMU1_OFFSET 12 +#define GR_VERTEX_TOW_TMU1_OFFSET 13 +#define GR_VERTEX_OOW_TMU1_OFFSET 14 +#endif /* FX_USE_PARGB */ + +#endif + + +/* + * Glide2 functions for Glide3 + */ +#if defined(FX_GLIDE3) +#define FX_grTexDownloadTable(TMU,type,data) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grTexDownloadTable(type,data); \ + END_BOARD_LOCK(); \ + } while (0); +#define FX_grTexDownloadTable_NoLock(TMU,type,data) \ + grTexDownloadTable(type, data) +#else +#define FX_grTexDownloadTable(TMU,type,data) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grTexDownloadTable(TMU,type,data); \ + END_BOARD_LOCK(); \ + } while (0); +#define FX_grTexDownloadTable_NoLock grTexDownloadTable +#endif + +/* + * Flush + */ +#if defined(FX_GLIDE3) +#define FX_grFlush() \ + do { \ + BEGIN_BOARD_LOCK(); \ + grFlush(); \ + END_BOARD_LOCK(); \ + } while (0) +#else +#define FX_grFlush() \ + do { \ + BEGIN_BOARD_LOCK(); \ + grSstIdle(); \ + END_BOARD_LOCK(); \ + } while (0) +#endif + +#define FX_grFinish() \ + do { \ + BEGIN_BOARD_LOCK(); \ + grFinish(); \ + END_BOARD_LOCK(); \ + } while (0) + +/* + * Write region: ToDo possible exploit the PixelPipe parameter. + */ +#if defined(FX_GLIDE3) +#define FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,FXFALSE,src_stride,src_data); \ + END_BOARD_LOCK(); \ + } while(0) +#else +#define FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data); \ + END_BOARD_LOCK(); \ + } while (0) +#endif + +/* + * Read region + */ +#define FX_grLfbReadRegion(src_buffer,src_x,src_y,src_width,src_height,dst_stride,dst_data) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grLfbReadRegion(src_buffer,src_x,src_y,src_width,src_height,dst_stride,dst_data); \ + END_BOARD_LOCK(); \ + } while (0); + +/* + * Draw triangle + */ +#define FX_grDrawTriangle(a,b,c) \ + do { \ + BEGIN_CLIP_LOOP(); \ + grDrawTriangle(a,b,c); \ + END_CLIP_LOOP(); \ + } while (0) + +/* + * For Lod/LodLog2 conversion. + */ +#if defined(FX_GLIDE3) + #define FX_largeLodLog2(info) (info).largeLodLog2 +#else + #define FX_largeLodLog2(info) (info).largeLod +#endif + +#if defined(FX_GLIDE3) + #define FX_aspectRatioLog2(info) (info).aspectRatioLog2 +#else + #define FX_aspectRatioLog2(info) (info).aspectRatio +#endif + +#if defined(FX_GLIDE3) + #define FX_smallLodLog2(info) (info).smallLodLog2 +#else + #define FX_smallLodLog2(info) (info).smallLod +#endif + +#if defined(FX_GLIDE3) + #define FX_lodToValue(val) ((int)(GR_LOD_256-val)) +#else + #define FX_lodToValue(val) ((int)(val)) +#endif + +#if defined(FX_GLIDE3) + #define FX_largeLodValue(info) ((int)(GR_LOD_256-(info).largeLodLog2)) +#else + #define FX_largeLodValue(info) ((int)(info).largeLod) +#endif +#define FX_largeLodValue_NoLock FX_largeLodValue + +#if defined(FX_GLIDE3) + #define FX_smallLodValue(info) ((int)(GR_LOD_256-(info).smallLodLog2)) +#else + #define FX_smallLodValue(info) ((int)(info).smallLod) +#endif +#define FX_smallLodValue_NoLock FX_smallLodValue + +#if defined(FX_GLIDE3) + #define FX_valueToLod(val) ((GrLOD_t)(GR_LOD_256-val)) +#else + #define FX_valueToLod(val) ((GrLOD_t)(val)) +#endif + +/* + * ScreenWidth/Height stuff. + */ + extern int FX_grSstScreenWidth(void); + extern int FX_grSstScreenHeight(void); + + + +/* + * Version string. + */ +#if defined(FX_GLIDE3) + extern void FX_grGlideGetVersion(char *buf); +#else + #define FX_grGlideGetVersion(b) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grGlideGetVersion(b); \ + END_BOARD_LOCK(); \ + } while (0) +#endif +/* + * Performance statistics + */ +#if defined(FX_GLIDE3) + extern void FX_grSstPerfStats(GrSstPerfStats_t *st); +#else + #define FX_grSstPerfStats(s) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grSstPerfStats(s); \ + END_BOARD_LOCK(); \ + } while (0) +#endif + +/* + * Hardware Query + */ + extern int FX_grSstQueryHardware(GrHwConfiguration *config); + +/* + * GrHints + */ +#if defined(FX_GLIDE3) + extern void FX_grHints_NoLock(GrHint_t hintType, FxU32 hintMask); + extern void FX_grHints(GrHint_t hintType, FxU32 hintMask); +#else + #define FX_grHints(t,m) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grHints(t, m); \ + END_BOARD_LOCK(); \ + } while(0) + #define FX_grHints_NoLock grHints +#endif +/* + * Antialiashed line+point drawing. + */ +#if defined(FX_GLIDE3) + extern void FX_grAADrawLine(GrVertex *a,GrVertex *b); +#else + #define FX_grAADrawLine(a,b) \ + do { \ + BEGIN_CLIP_LOOP(); \ + grAADrawLine(a,b); \ + END_CLIP_LOOP(); \ + } while (0) +#endif + +#if defined(FX_GLIDE3) + extern void FX_grAADrawPoint(GrVertex *a); +#else + #define FX_grAADrawPoint(a) \ + do { \ + BEGIN_CLIP_LOOP(); \ + grAADrawPoint(a); \ + END_CLIP_LOOP(); \ + } while (0) +#endif + +/* + * Needed for Glide3 only, to set up Glide2 compatible vertex layout. + */ +#if defined(FX_GLIDE3) + extern void FX_setupGrVertexLayout(void); +#else + #define FX_setupGrVertexLayout() do {} while (0) +#endif +/* + * grSstControl stuff + */ +extern FxBool FX_grSstControl(FxU32 code); + +/* + * grGammaCorrectionValue + */ +#if defined(FX_GLIDE3) + extern void FX_grGammaCorrectionValue(float val); +#else + #define FX_grGammaCorrectionValue(v) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grGammaCorrectionValue(v) \ + END_BOARD_LOCK(); \ + } while (0) +#endif + +#if defined(FX_GLIDE3) +#define FX_grSstWinClose(w) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grSstWinClose(w); \ + END_BOARD_LOCK(); \ + } while (0) +#else +#define FX_grSstWinClose(w) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grSstWinClose(); \ + END_BOARD_LOCK(); \ + } while (0) +#endif + + +extern FX_GrContext_t FX_grSstWinOpen( FxU32 hWnd, + GrScreenResolution_t screen_resolution, + GrScreenRefresh_t refresh_rate, + GrColorFormat_t color_format, + GrOriginLocation_t origin_location, + int nColBuffers, + int nAuxBuffers); + + +#define FX_grDrawLine(v1, v2) \ + do { \ + BEGIN_CLIP_LOOP(); \ + grDrawLine(v1, v2); \ + END_CLIP_LOOP(); \ + } while (0) + +#define FX_grDrawPoint(p) \ + do { \ + BEGIN_CLIP_LOOP(); \ + grDrawPoint(p); \ + END_CLIP_LOOP(); \ + } while (0) + +#if defined(FX_GLIDE3) +extern void FX_grDrawPolygonVertexList(int n, GrVertex *v); +#else +#define FX_grDrawPolygonVertexList(n, v) \ + do { \ + BEGIN_CLIP_LOOP(); \ + grDrawPolygonVertexList(n, v); \ + END_CLIP_LOOP(); \ + } while (0) +#endif + +#define FX_grDitherMode(m) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grDitherMode(m); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grRenderBuffer(b) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grRenderBuffer(b); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grBufferClear(c, a, d) \ + do { \ + BEGIN_CLIP_LOOP(); \ + grBufferClear(c, a, d); \ + END_CLIP_LOOP(); \ + } while (0) + +#define FX_grDepthMask(m) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grDepthMask(m); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grColorMask(c, a) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grColorMask(c, a); \ + END_BOARD_LOCK(); \ + } while (0) + +extern FxBool FX_grLfbLock(GrLock_t type, GrBuffer_t buffer, + GrLfbWriteMode_t writeMode, + GrOriginLocation_t origin, FxBool pixelPipeline, + GrLfbInfo_t *info ); + +#define FX_grLfbUnlock(t, b) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grLfbUnlock(t, b); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grConstantColorValue(v) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grConstantColorValue(v); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grConstantColorValue_NoLock grConstantColorValue + +#define FX_grAADrawTriangle(a, b, c, ab, bc, ca) \ + do { \ + BEGIN_CLIP_LOOP(); \ + grAADrawTriangle(a, b, c, ab, bc, ca); \ + END_CLIP_LOOP(); \ + } while (0) + +#define FX_grAlphaBlendFunction(rs, rd, as, ad) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grAlphaBlendFunction(rs, rd, as, ad); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grAlphaCombine(func, fact, loc, oth, inv) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grAlphaCombine(func, fact, loc, oth, inv); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grAlphaCombine_NoLock grAlphaCombine + +#define FX_grAlphaTestFunction(f) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grAlphaTestFunction(f); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grAlphaTestReferenceValue(v) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grAlphaTestReferenceValue(v); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grClipWindow(minx, miny, maxx, maxy) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grClipWindow(minx, miny, maxx, maxy); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grClipWindow_NoLock grClipWindow + +#define FX_grColorCombine(func, fact, loc, oth, inv) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grColorCombine(func, fact, loc, oth, inv); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grColorCombine_NoLock grColorCombine + +#define FX_grCullMode(m) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grCullMode(m); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grDepthBiasLevel(lev) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grDepthBiasLevel(lev); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grDepthBufferFunction(func) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grDepthBufferFunction(func); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grFogColorValue(c) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grFogColorValue(c); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grFogMode(m) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grFogMode(m); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grFogTable(t) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grFogTable(t); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grTexClampMode(t, sc, tc) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grTexClampMode(t, sc, tc); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grTexClampMode_NoLock grTexClampMode + +#define FX_grTexCombine(t, rfunc, rfact, afunc, afact, rinv, ainv) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grTexCombine(t, rfunc, rfact, afunc, afact, rinv, ainv); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grTexCombine_NoLock grTexCombine + +#define FX_grTexDownloadMipMapLevel(t, sa, tlod, llod, ar, f, eo, d) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grTexDownloadMipMapLevel(t, sa, tlod, llod, ar, f, eo, d); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grTexDownloadMipMapLevel_NoLock grTexDownloadMipMapLevel + +#define FX_grTexDownloadMipMapLevelPartial(t, sa, tlod, llod, ar, f, eo, d, s, e); \ + do { \ + BEGIN_BOARD_LOCK(); \ + grTexDownloadMipMapLevelPartial(t, sa, tlod, llod, ar, f, eo, d, s, e); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grTexFilterMode(t, minf, magf) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grTexFilterMode(t, minf, magf); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grTexFilterMode_NoLock grTexFilterMode + +extern FxU32 FX_grTexMinAddress(GrChipID_t tmu); +extern FxU32 FX_grTexMaxAddress(GrChipID_t tmu); + +#define FX_grTexMipMapMode(t, m, lod) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grTexMipMapMode(t, m, lod); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grTexMipMapMode_NoLock grTexMipMapMode + +#define FX_grTexSource(t, sa, eo, i) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grTexSource(t, sa, eo, i); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grTexSource_NoLock grTexSource + +extern FxU32 FX_grTexTextureMemRequired(FxU32 evenOdd, GrTexInfo *info); +#define FX_grTexTextureMemRequired_NoLock grTexTextureMemRequired + +#define FX_grGlideGetState(s) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grGlideGetState(s); \ + END_BOARD_LOCK(); \ + } while (0) +#define FX_grGlideGetState_NoLock(s) grGlideGetState(s); + +#define FX_grDRIBufferSwap(i) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grDRIBufferSwap(i); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grSstSelect(b) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grSstSelect(b); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grSstSelect_NoLock grSstSelect + +#define FX_grGlideSetState(s) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grGlideSetState(s); \ + END_BOARD_LOCK(); \ + } while (0) +#define FX_grGlideSetState_NoLock(s) grGlideSetState(s); + +#define FX_grDepthBufferMode(m) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grDepthBufferMode(m); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grLfbWriteColorFormat(f) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grLfbWriteColorFormat(f); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grDrawVertexArray(m, c, p) \ + do { \ + BEGIN_CLIP_LOOP(); \ + grDrawVertexArray(m, c, p); \ + END_CLIP_LOOP(); \ + } while (0) + +#define FX_grGlideShutdown() \ + do { \ + BEGIN_BOARD_LOCK(); \ + grGlideShutdown(); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grTexLodBiasValue_NoLock(t, v) grTexLodBiasValue(t, v) + +#define FX_grTexLodBiasValue(t, v) \ + do { \ + BEGIN_BOARD_LOCK(); \ + grTexLodBiasValue(t, v); \ + END_BOARD_LOCK(); \ + } while (0) + +#define FX_grGlideInit_NoLock grGlideInit +#define FX_grSstWinOpen_NoLock grSstWinOpen + +extern int FX_getFogTableSize(void); +extern int FX_getGrStateSize(void); + +#endif /* __FX_GLIDE_WARPER__ */ + diff --git a/xc/extras/Mesa/src/FX/fxpipeline.c b/xc/extras/Mesa/src/FX/fxpipeline.c new file mode 100644 index 000000000..cf4c9ebbc --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxpipeline.c @@ -0,0 +1,302 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + + +#if defined(FX) + +#include "fxdrv.h" +#include "vbindirect.h" + + +/* We don't handle texcoord-4 in the safe clip routines - maybe we should. + */ +static void fxDDRenderElements( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + + if (fxMesa->render_index != 0 || + ((ctx->Texture.ReallyEnabled & 0xf) && VB->TexCoordPtr[0]->size>2) || + ((ctx->Texture.ReallyEnabled & 0xf0) && VB->TexCoordPtr[1]->size>2) || + (VB->ClipPtr->size != 4)) /* Brokes clipping otherwise */ + gl_render_elts( VB ); + else + fxDDRenderElementsDirect( VB ); +} + +static void fxDDCheckRenderVBIndirect( GLcontext *ctx, + struct gl_pipeline_stage *d ) +{ + d->type = 0; + + if ((ctx->IndirectTriangles & DD_SW_SETUP) == 0 && + ctx->Driver.MultipassFunc == 0) + { + d->type = PIPE_IMMEDIATE; + d->inputs = VERT_SETUP_FULL | VERT_ELT | VERT_PRECALC_DATA; + } +} + +static void fxDDRenderVBIndirect( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + struct vertex_buffer *cvaVB = ctx->CVA.VB; + + if (fxMesa->render_index != 0 || + ((ctx->Texture.ReallyEnabled & 0xf) && cvaVB->TexCoordPtr[0]->size>2) || + ((ctx->Texture.ReallyEnabled & 0xf0) && cvaVB->TexCoordPtr[1]->size>2) || + (VB->ClipPtr->size != 4)) /* Brokes clipping otherwise */ + gl_render_vb_indirect( VB ); + else + fxDDRenderVBIndirectDirect( VB ); +} + + +static void fxDDRenderVB( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + + if ((fxMesa->render_index != 0) || + ((ctx->Texture.ReallyEnabled & 0xf) && VB->TexCoordPtr[0]->size>2) || + ((ctx->Texture.ReallyEnabled & 0xf0) && VB->TexCoordPtr[1]->size>2)) + gl_render_vb( VB ); + else + fxDDDoRenderVB( VB ); +} + + + + +/* This sort of driver-based reconfiguration of the pipeline could be + * used to support accelerated transformation and lighting on capable + * hardware. + * + */ +GLuint fxDDRegisterPipelineStages( struct gl_pipeline_stage *out, + const struct gl_pipeline_stage *in, + GLuint nr ) +{ + GLuint i, o; + + for (i = o = 0 ; i < nr ; i++) { + switch (in[i].ops) { + case PIPE_OP_RAST_SETUP_1|PIPE_OP_RENDER: + out[o] = in[i]; + out[o].state_change = NEW_CLIENT_STATE; + out[o].check = fxDDCheckMergeAndRender; + out[o].run = fxDDMergeAndRender; + o++; + break; + case PIPE_OP_RAST_SETUP_0: + out[o] = in[i]; + out[o].cva_state_change = NEW_LIGHTING|NEW_TEXTURING|NEW_RASTER_OPS; + out[o].state_change = ~0; + out[o].check = fxDDCheckPartialRasterSetup; + out[o].run = fxDDPartialRasterSetup; + o++; + break; + case PIPE_OP_RAST_SETUP_0|PIPE_OP_RAST_SETUP_1: + out[o] = in[i]; + out[o].run = fxDDDoRasterSetup; + o++; + break; + case PIPE_OP_RENDER: + out[o] = in[i]; + if (in[i].run == gl_render_elts) { + out[o].run = fxDDRenderElements; + } else if (in[i].run == gl_render_vb_indirect) { + out[o].check = fxDDCheckRenderVBIndirect; + out[o].run = fxDDRenderVBIndirect; + } else if (in[i].run == gl_render_vb) { + out[o].run = fxDDRenderVB; + } + + o++; + break; + default: + out[o++] = in[i]; + break; + } + } + + return o; +} + +#define ILLEGAL_ENABLES (TEXTURE0_3D| \ + TEXTURE1_3D| \ + ENABLE_TEXMAT0 | \ + ENABLE_TEXMAT1 | \ + ENABLE_TEXGEN0 | \ + ENABLE_TEXGEN1 | \ + ENABLE_USERCLIP | \ + ENABLE_LIGHT | \ + ENABLE_FOG) + + + +/* Because this is slotted in by the OptimizePipeline function, most + * of the information here is just for gl_print_pipeline(). Only the + * run member is required. + */ +static struct gl_pipeline_stage fx_fast_stage = { + "FX combined vertex transform, setup and rasterization stage", + PIPE_OP_VERT_XFORM|PIPE_OP_RAST_SETUP_0|PIPE_OP_RAST_SETUP_1|PIPE_OP_RENDER, + PIPE_PRECALC, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* never called */ + fxDDFastPath +}; + + + + +/* Better than optimizing the pipeline, we can do the whole build very + * quickly with the aid of a new flags member. + */ +GLboolean fxDDBuildPrecalcPipeline( GLcontext *ctx ) +{ + struct gl_pipeline *pipe = &ctx->CVA.pre; + fxMesaContext fxMesa = FX_CONTEXT(ctx); + + + if (fxMesa->is_in_hardware && + fxMesa->render_index == 0 && + (ctx->Enabled & ILLEGAL_ENABLES) == 0 && + (ctx->Array.Flags & (VERT_OBJ_234| + VERT_TEX0_4| + VERT_TEX1_4| + VERT_ELT)) == (VERT_OBJ_23|VERT_ELT)) + { + if (MESA_VERBOSE & (VERBOSE_STATE|VERBOSE_DRIVER)) + if (!fxMesa->using_fast_path) + fprintf(stderr, "fxMesa: using fast path\n"); + + pipe->stages[0] = &fx_fast_stage; + pipe->stages[1] = 0; + pipe->new_inputs = ctx->RenderFlags & VERT_DATA; + pipe->ops = pipe->stages[0]->ops; + fxMesa->using_fast_path = 1; + return 1; + } + + if (fxMesa->using_fast_path) + { + if (MESA_VERBOSE & (VERBOSE_STATE|VERBOSE_DRIVER)) + fprintf(stderr, "fxMesa: fall back to full pipeline %x %x %x %x %x\n", + fxMesa->is_in_hardware, + fxMesa->render_index, + (ctx->Enabled & ILLEGAL_ENABLES), + (ctx->Array.Summary & (VERT_OBJ_23)), + (ctx->Array.Summary & (VERT_OBJ_4|VERT_TEX0_4|VERT_TEX1_4))); + + fxMesa->using_fast_path = 0; + ctx->CVA.VB->ClipOrMask = 0; + ctx->CVA.VB->ClipAndMask = CLIP_ALL_BITS; + ctx->Array.NewArrayState |= ctx->Array.Summary; + return 0; + } + + return 0; +} + + + + + + +/* Perform global optimizations to the pipeline. The fx driver + * implements a single such fast path, which corresponds to the standard + * quake3 cva pipeline. + * + * This is now handled by the 'build' function above. + */ +void fxDDOptimizePrecalcPipeline( GLcontext *ctx, struct gl_pipeline *pipe ) +{ + fxMesaContext fxMesa = FX_CONTEXT(ctx); + + if (fxMesa->is_in_hardware && + fxMesa->render_index == 0 && + (ctx->Enabled & ILLEGAL_ENABLES) == 0 && + (ctx->Array.Summary & VERT_ELT)) + { + pipe->stages[0] = &fx_fast_stage; + pipe->stages[1] = 0; + } +} + + + +/* unused? +void fxDDOptimizeEltPipeline( GLcontext *ctx, struct gl_pipeline *pipe ) +{ + (void) ctx; + (void) pipe; +} +*/ + +#else + +/* + * Need this to provide at least one external definition. + */ +int gl_fxpipeline_dummy(void) +{ + return 0; +} + +#endif diff --git a/xc/extras/Mesa/src/FX/fxrender.c b/xc/extras/Mesa/src/FX/fxrender.c new file mode 100644 index 000000000..5935998f8 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxrender.c @@ -0,0 +1,785 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* fxrender.c - 3Dfx VooDoo RenderVB driver function support */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" +#include "vbcull.h" + +/* + * Render a line segment from VB[v1] to VB[v2] when either one or both + * endpoints must be clipped. + */ +#if !defined(__MWERKS__) +INLINE +#endif +void fxRenderClippedLine( struct vertex_buffer *VB, + GLuint v1, GLuint v2 ) +{ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + GLubyte mask = VB->ClipMask[v1] | VB->ClipMask[v2]; + + if (!mask || (VB->ctx->line_clip_tab[VB->ClipPtr->size])(VB, &v1, &v2, mask)) + FX_grDrawLine((GrVertex *)gWin[v1].f,(GrVertex *)gWin[v2].f); +} + + + + +/* This is legal for Quads as well as triangles, hence the 'n' parameter. + */ +INLINE void fxRenderClippedTriangle( struct vertex_buffer *VB, + GLuint n, GLuint vlist[] ) +{ + GLubyte mask = 0; + GLuint i; + + for (i = 0 ; i < n ; i++) + mask |= VB->ClipMask[vlist[i]]; + + if (mask & CLIP_USER_BIT) { + GLubyte *userclipmask = VB->UserClipMask; + if (userclipmask[vlist[0]] & userclipmask[vlist[1]] & userclipmask[vlist[2]]) + return; + } + + n = (VB->ctx->poly_clip_tab[VB->ClipPtr->size])( VB, n, vlist, mask ); + if (n >= 3) { + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + GrVertex *i0 = (GrVertex *)gWin[vlist[0]].f; + GrVertex *i1 = (GrVertex *)gWin[vlist[1]].f; + GrVertex *i2 = (GrVertex *)gWin[vlist[2]].f; + GLuint i; + + for (i=2;i<n;i++, i1 = i2, i2 = (GrVertex *)gWin[vlist[i]].f) { + FX_grDrawTriangle(i0,i1,i2); + } + } +} + + + + + +static INLINE void fxSafeClippedLine( struct vertex_buffer *VB, + GLuint v1, GLuint v2 ) +{ + GLubyte mask = VB->ClipMask[v1] | VB->ClipMask[v2]; + + if (!mask) { + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + FX_grDrawLine((GrVertex *)gWin[v1].f,(GrVertex *)gWin[v2].f); + } else { + fxMesaContext fxMesa = (fxMesaContext)VB->ctx->DriverCtx; + fxLineClipTab[fxMesa->setupindex & 0x7]( VB, v1, v2, mask ); + } +} + + +static INLINE void fxSafeClippedTriangle( struct vertex_buffer *VB, + fxVertex *gWin, + tfxTriClipFunc cliptri, + GLuint v2, GLuint v1, GLuint v ) +{ + GLubyte *clipmask = VB->ClipMask; + GLubyte mask = clipmask[v2] | clipmask[v1] | clipmask[v]; + + if (!mask) { + FX_grDrawTriangle((GrVertex *)gWin[v2].f, + (GrVertex *)gWin[v1].f, + (GrVertex *)gWin[v].f); + return; + } + + if (!(clipmask[v2] & clipmask[v1] & clipmask[v] & CLIP_ALL_BITS)) + { + GLuint vl[3]; + GLuint imask = mask; + + if (imask & CLIP_USER_BIT) { + GLubyte *userclipmask = VB->UserClipMask; + if (userclipmask[v2] & userclipmask[v1] & userclipmask[v]) + return; + imask |= (userclipmask[v2] | userclipmask[v1] | userclipmask[v]) << 8; + } + + ASSIGN_3V(vl, v2, v1, v ); + cliptri( VB, vl, imask ); + } +} + + +static INLINE void fxSafeClippedTriangle2( struct vertex_buffer *VB, + fxVertex *gWin, + tfxTriViewClipFunc cliptri, + GLuint v2, GLuint v1, GLuint v ) +{ + GLubyte *clipmask = VB->ClipMask; + GLubyte mask = clipmask[v2] | clipmask[v1] | clipmask[v]; + + if (!mask) { + FX_grDrawTriangle((GrVertex *)gWin[v2].f,(GrVertex *)gWin[v1].f, + (GrVertex *)gWin[v].f); + } else if (!(clipmask[v2] & clipmask[v1] & clipmask[v])) { + GLuint vl[3]; + ASSIGN_3V(vl, v2, v1, v ); + cliptri( VB, vl, mask ); + } +} + + +static INLINE void fxSafeClippedTriangle3( struct vertex_buffer *VB, + fxVertex *gWin, + tfxTriClipFunc cliptri, + GLuint v2, GLuint v1, GLuint v ) +{ + GLubyte *clipmask = VB->ClipMask; + GLubyte mask = clipmask[v2] | clipmask[v1] | clipmask[v]; + GLuint imask = mask; + + if (imask & CLIP_USER_BIT) { + GLubyte *userclipmask = VB->UserClipMask; + if (userclipmask[v2] & userclipmask[v1] & userclipmask[v]) + return; + imask |= (userclipmask[v2] | userclipmask[v1] | userclipmask[v]) << 8; + } + + { + GLuint vl[3]; + ASSIGN_3V(vl, v2, v1, v ); + cliptri( VB, vl, imask ); + } +} + + + + + +/************************************************************************/ +/************************ RenderVB functions ****************************/ +/************************************************************************/ + + +/* Render front-facing, non-clipped primitives. + */ + +#define RENDER_POINTS( start, count ) \ + (void) gWin; \ + (void) VB; \ + (VB->ctx->Driver.PointsFunc)( VB->ctx, start, count-1 ) + +#define RENDER_LINE( i1, i ) \ + do { \ + RVB_COLOR(i); \ + FX_grDrawLine((GrVertex *)gWin[i1].f, \ + (GrVertex *)gWin[i].f); \ + } while (0) + +#define RENDER_TRI( i2, i1, i, pv, parity ) \ + do { \ + RVB_COLOR(pv); \ + if (parity) { \ + FX_grDrawTriangle((GrVertex *)gWin[i1].f, \ + (GrVertex *)gWin[i2].f, \ + (GrVertex *)gWin[i].f); \ + } else { \ + FX_grDrawTriangle((GrVertex *)gWin[i2].f, \ + (GrVertex *)gWin[i1].f, \ + (GrVertex *)gWin[i].f); \ + } \ + } while (0) + +#define RENDER_QUAD( i3, i2, i1, i, pv ) \ + do { \ + RVB_COLOR(pv); \ + FX_grDrawTriangle((GrVertex *)gWin[i3].f, \ + (GrVertex *)gWin[i2].f, \ + (GrVertex *)gWin[i].f); \ + FX_grDrawTriangle((GrVertex *)gWin[i2].f, \ + (GrVertex *)gWin[i1].f, \ + (GrVertex *)gWin[i].f); \ + } while (0) + + + +#define LOCAL_VARS \ + fxMesaContext fxMesa=(fxMesaContext)VB->ctx->DriverCtx; \ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; \ + (void) fxMesa; + +#define INIT(x) + +#define TAG(x) x##_fx_flat_raw +#undef RVB_COLOR +#define RVB_COLOR(pv) FX_VB_COLOR(fxMesa, VB->ColorPtr->data[pv]) +#define PRESERVE_VB_DEFS + +#include "render_tmp.h" + +#define TAG(x) x##_fx_smooth_raw +#undef RVB_COLOR +#define RVB_COLOR(x) + +#include "render_tmp.h" + + + +/* Render with clipped and/or culled primitives with cullmask information. + */ +#define RENDER_POINTS( start, count ) \ + (void) gWin; \ + (void) cullmask; \ + (VB->ctx->Driver.PointsFunc)( VB->ctx, start, count-1 ) + + +#define RENDER_LINE( i1, i ) \ + do { \ + const GLubyte flags = cullmask[i]; \ + \ + if (!(flags & PRIM_NOT_CULLED)) \ + continue; \ + \ + RVB_COLOR(i); \ + if (flags & PRIM_ANY_CLIP) \ + fxRenderClippedLine( VB, i1, i ); \ + else \ + FX_grDrawLine( (GrVertex *)gWin[i1].f, (GrVertex *)gWin[i].f ); \ + } while (0) + + +#define RENDER_TRI( i2, i1, i, pv, parity) \ + do { \ + const GLubyte flags = cullmask[i]; \ + GLuint e2,e1; \ + \ + if (!(flags & PRIM_NOT_CULLED)) \ + continue; \ + \ + e2=i2, e1=i1; \ + if (parity) { e2=i1; e1=i2; } \ + \ + RVB_COLOR(pv); \ + if (flags & PRIM_ANY_CLIP) { \ + fxSafeClippedTriangle3(VB,gWin,cliptri,e2,e1,i); \ + } else { \ + FX_grDrawTriangle((GrVertex *)gWin[e2].f, \ + (GrVertex *)gWin[e1].f, \ + (GrVertex *)gWin[i].f); \ + } \ + } while (0) + + +#define RENDER_QUAD(i3, i2, i1, i, pv) \ + do { \ + const GLubyte flags = cullmask[i]; \ + \ + if (!(flags & PRIM_NOT_CULLED)) \ + continue; \ + \ + RVB_COLOR(pv); \ + if (flags&PRIM_ANY_CLIP) { \ + fxSafeClippedTriangle3(VB,gWin,cliptri,i3,i2,i); \ + fxSafeClippedTriangle3(VB,gWin,cliptri,i2,i1,i); \ + } else { \ + FX_grDrawTriangle((GrVertex *)gWin[i3].f, \ + (GrVertex *)gWin[i2].f, \ + (GrVertex *)gWin[i].f); \ + FX_grDrawTriangle((GrVertex *)gWin[i2].f, \ + (GrVertex *)gWin[i1].f, \ + (GrVertex *)gWin[i].f); \ + } \ + } while (0) + + + + + +#define LOCAL_VARS \ + fxMesaContext fxMesa=(fxMesaContext)VB->ctx->DriverCtx; \ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; \ + const GLubyte *cullmask = VB->CullMask; \ + tfxTriClipFunc cliptri = fxMesa->clip_tri_stride; + + + + +#define INIT(x) (void) cliptri; (void) fxMesa; + +#define TAG(x) x##_fx_smooth_culled +#undef RVB_COLOR +#define RVB_COLOR(x) +#define PRESERVE_VB_DEFS +#include "render_tmp.h" + +#define TAG(x) x##_fx_flat_culled +#undef RVB_COLOR +#define RVB_COLOR(pv) FX_VB_COLOR(fxMesa, VB->ColorPtr->data[pv]) + +#include "render_tmp.h" + + + + +/* Direct, with the possibility of clipping. + */ +#define RENDER_POINTS( start, count ) \ + do { \ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; \ + GLubyte *clipmask = VB->ClipMask; \ + GLuint i; \ + for (i = start ; i <= count ; i++) \ + if (clipmask[i] == 0) { \ + RVB_COLOR(i); \ + FX_grDrawPoint( (GrVertex *)gWin[i].f );\ + } \ + } while (0) + +#define RENDER_LINE( i1, i ) \ + do { \ + RVB_COLOR(i); \ + fxSafeClippedLine( VB, i1, i ); \ + } while (0) + +#define RENDER_TRI( i2, i1, i, pv, parity) \ + do { \ + GLuint e2=i2, e1=i1; \ + if (parity) { GLuint t=e2; e2=e1; e1=t; } \ + RVB_COLOR(pv); \ + fxSafeClippedTriangle(VB,gWin,cliptri,e2,e1,i); \ + } while (0) + +#define RENDER_QUAD( i3, i2, i1, i, pv) \ + do { \ + RVB_COLOR(pv); \ + fxSafeClippedTriangle(VB,gWin,cliptri,i3,i2,i); \ + fxSafeClippedTriangle(VB,gWin,cliptri,i2,i1,i); \ + } while (0) + +#define LOCAL_VARS \ + fxMesaContext fxMesa=(fxMesaContext)VB->ctx->DriverCtx; \ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; \ + tfxTriClipFunc cliptri = fxMesa->clip_tri_stride; + +#define INIT(x) (void) cliptri; (void) gWin; + +#define TAG(x) x##_fx_smooth_clipped +#undef RVB_COLOR +#define RVB_COLOR(x) +#define PRESERVE_VB_DEFS +#include "render_tmp.h" + + +#define TAG(x) x##_fx_flat_clipped +#undef RVB_COLOR +#define RVB_COLOR(pv) FX_VB_COLOR(fxMesa, VB->ColorPtr->data[pv]) +#include "render_tmp.h" + + + + + + +/* Indirect, with the possibility of clipping. + */ +#define RENDER_POINTS( start, count ) \ + do { \ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; \ + GLuint e; \ + GLubyte *clipmask = VB->ClipMask; \ + for(e=start;e<=count;e++) \ + if(clipmask[elt[e]]==0) { \ + FX_grDrawPoint((GrVertex *)gWin[elt[e]].f); \ + } \ + } while (0) + +#define RENDER_LINE( i1, i ) \ + do { \ + GLuint e1 = elt[i1], e = elt[i]; \ + RVB_COLOR(e); \ + fxSafeClippedLine( VB, e1, e ); \ + } while (0) + +#define RENDER_TRI( i2, i1, i, pv, parity) \ + do { \ + GLuint e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ + if (parity) { GLuint t=e2; e2=e1; e1=t; } \ + fxSafeClippedTriangle(VB,gWin,cliptri,e2,e1,e); \ + } while (0) + +#define RENDER_QUAD( i3, i2, i1, i, pv) \ + do { \ + GLuint e3 = elt[i3], e2 = elt[i2], e1 = elt[i1], e = elt[i];\ + fxSafeClippedTriangle(VB,gWin,cliptri,e3,e2,e); \ + fxSafeClippedTriangle(VB,gWin,cliptri,e2,e1,e); \ + } while (0) + +#define LOCAL_VARS const GLuint *elt = VB->EltPtr->data; \ + fxMesaContext fxMesa = (fxMesaContext)VB->ctx->DriverCtx; \ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; \ + tfxTriClipFunc cliptri = fxMesa->clip_tri_stride; + +#define INIT(x) (void) cliptri; (void) gWin; + +#define TAG(x) x##_fx_smooth_indirect_clipped +#undef RVB_COLOR +#define RVB_COLOR(x) +#include "render_tmp.h" + + +/* Indirect, clipped, but no user clip. + */ +#define RENDER_POINTS( start, count ) \ + do { \ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; \ + GLuint e; \ + GLubyte *clipmask = VB->ClipMask; \ + for(e=start;e<=count;e++) \ + if(clipmask[elt[e]]==0) { \ + FX_grDrawPoint((GrVertex *)gWin[elt[e]].f); \ + } \ + } while (0) + +#define RENDER_LINE( i1, i ) \ + do { \ + GLuint e1 = elt[i1], e = elt[i]; \ + RVB_COLOR(e); \ + fxSafeClippedLine( VB, e1, e ); \ + } while (0) + +#define RENDER_TRI( i2, i1, i, pv, parity) \ + do { \ + GLuint e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ + if (parity) { GLuint t=e2; e2=e1; e1=t; } \ + fxSafeClippedTriangle2(VB,gWin,cliptri,e2,e1,e); \ + } while (0) + +#define RENDER_QUAD( i3, i2, i1, i, pv) \ + do { \ + GLuint e3 = elt[i3], e2 = elt[i2], e1 = elt[i1], e = elt[i];\ + fxSafeClippedTriangle2(VB,gWin,cliptri,e3,e2,e); \ + fxSafeClippedTriangle2(VB,gWin,cliptri,e2,e1,e); \ + } while (0) + +#define LOCAL_VARS const GLuint *elt = VB->EltPtr->data; \ + fxMesaContext fxMesa = (fxMesaContext)VB->ctx->DriverCtx; \ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; \ + tfxTriViewClipFunc cliptri = fxMesa->view_clip_tri; + +#define INIT(x) (void) cliptri; (void) gWin; + +#define TAG(x) x##_fx_smooth_indirect_view_clipped +#undef RVB_COLOR +#define RVB_COLOR(x) +#include "render_tmp.h" + + + + + + + +/* Indirect, and no clipping required. + */ +#define RENDER_POINTS( start, count ) \ + do { \ + GLuint e; \ + for(e=start;e<=count;e++) { \ + FX_grDrawPoint((GrVertex *)gWin[elt[e]].f); \ + } \ + } while (0) + +#define RENDER_LINE( i1, i ) \ + do { \ + GLuint e1 = elt[i1], e = elt[i]; \ + FX_grDrawLine((GrVertex *)gWin[e1].f, (GrVertex *)gWin[e].f); \ + } while (0) + + +#define RENDER_TRI( i2, i1, i, pv, parity) \ + do { \ + GLuint e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ + if (parity) {GLuint tmp = e2; e2 = e1; e1 = tmp;} \ + FX_grDrawTriangle((GrVertex *)gWin[e2].f, \ + (GrVertex *)gWin[e1].f, \ + (GrVertex *)gWin[e].f); \ + } while (0) + + +#define RENDER_QUAD( i3, i2, i1, i, pv) \ + do { \ + GLuint e3 = elt[i3], e2 = elt[i2], e1 = elt[i1], e = elt[i];\ + FX_grDrawTriangle((GrVertex *)gWin[e3].f, \ + (GrVertex *)gWin[e2].f, \ + (GrVertex *)gWin[e].f); \ + FX_grDrawTriangle((GrVertex *)gWin[e2].f, \ + (GrVertex *)gWin[e1].f, \ + (GrVertex *)gWin[e].f); \ + } while (0) + +#define LOCAL_VARS \ + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; \ + const GLuint *elt = VB->EltPtr->data; + +#define INIT(x) + +#define TAG(x) x##_fx_smooth_indirect +#undef RVB_COLOR +#define RVB_COLOR(x) +#include "render_tmp.h" + + + + + +/* Direct in this context means that triangles, lines, points can be + * rendered simply by calling grDrawTriangle, etc., without any + * additional setup (such as calling grConstantColor). We also use a + * 'safe' set of clipping routines which don't require write-access to + * the arrays in the vertex buffer, and don't care about array + * stride. + * + * Thus there is no call to gl_import_arrays() in this function. + * + * This safe clipping should be generalized to call driver->trianglefunc + * under the appropriate conditions. + * + * We don't handle texcoord-4 in the safe clip routines - maybe we should. + * + */ +void fxDDRenderElementsDirect( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + struct vertex_buffer *saved_vb = ctx->VB; + GLenum prim = ctx->CVA.elt_mode; + GLuint nr = VB->EltPtr->count; + render_func func = render_tab_fx_smooth_indirect[prim]; + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint p = 0; + + if (!nr) + return; + + if (fxMesa->new_state) + fxSetupFXUnits(ctx); + + if (!nr) return; + + if (VB->ClipOrMask) { + func = render_tab_fx_smooth_indirect_view_clipped[prim]; + if (VB->ClipOrMask & CLIP_USER_BIT) + func = render_tab_fx_smooth_indirect_clipped[prim]; + } + + ctx->VB = VB; /* kludge */ + + do { + func( VB, 0, nr, 0 ); + } while (ctx->Driver.MultipassFunc && + ctx->Driver.MultipassFunc( VB, ++p )); + + + ctx->VB = saved_vb; +} + + +void fxDDRenderVBIndirectDirect( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + struct vertex_buffer *cvaVB = ctx->CVA.VB; + struct vertex_buffer *saved_vb = ctx->VB; + GLuint i, next, count = VB->Count; + render_func *tab = render_tab_fx_smooth_indirect; + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint p = 0; + + if (cvaVB->ClipOrMask) + tab = render_tab_fx_smooth_indirect_clipped; + + if (!VB->CullDone) + gl_fast_copy_vb( VB ); + + if (fxMesa->new_state) + fxSetupFXUnits( ctx ); + + ctx->VB = cvaVB; + cvaVB->EltPtr = VB->EltPtr; + + do { + GLuint parity = VB->Parity; + + for (i = VB->CopyStart ; i < count ; parity = 0, i = next) + { + GLuint prim = VB->Primitive[i]; + next = VB->NextPrimitive[i]; + tab[prim]( cvaVB, i, next, parity ); + } + /* loop never taken */ + } while (ctx->Driver.MultipassFunc && + ctx->Driver.MultipassFunc( cvaVB, ++p )); + + cvaVB->EltPtr = 0; + ctx->VB = saved_vb; +} + + +static render_func *fxDDRenderVBSmooth_tables[3] = { + render_tab_fx_smooth_clipped, + render_tab_fx_smooth_culled, + render_tab_fx_smooth_raw +}; + +static render_func *fxDDRenderVBFlat_tables[3] = { + render_tab_fx_flat_clipped, + render_tab_fx_flat_culled, + render_tab_fx_flat_raw +}; + + +static render_func *null_tables[3] = { + 0, + 0, + 0 +}; + +#if defined(FX_GLIDE3) +#include "fxstripdet.c" +#endif + +void fxDDRenderInit( GLcontext *ctx ) +{ + render_init_fx_smooth_indirect_view_clipped(); + render_init_fx_smooth_indirect_clipped(); + render_init_fx_smooth_indirect(); + render_init_fx_smooth_raw(); + render_init_fx_smooth_culled(); + render_init_fx_smooth_clipped(); + render_init_fx_flat_raw(); + render_init_fx_flat_culled(); + render_init_fx_flat_clipped(); +#if defined(FX_GLIDE3) + fxDDRenderInitGlide3(ctx); +#endif +} + + +/* Now used to set an internal var in fxMesa - we hook out at the + * level of gl_render_vb() instead. + */ +render_func **fxDDChooseRenderVBTables(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + + if (ctx->IndirectTriangles & DD_SW_SETUP) + return null_tables; + + switch (fxMesa->render_index) { +/* case FX_FLAT: */ +/* return fxDDRenderVBFlat_tables; */ + case 0: + return fxDDRenderVBSmooth_tables; + default: + return null_tables; + } +} + + +void fxDDDoRenderVB( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint i, next, prim; + GLuint parity = VB->Parity; + render_func *tab; + GLuint count = VB->Count; + GLint p = 0; + + if (fxMesa->new_state) + fxSetupFXUnits(ctx); + + if (VB->Indirect) { + return; + } else if (VB->CullMode & CLIP_MASK_ACTIVE) { + tab = fxMesa->RenderVBClippedTab; + } else { + tab = fxMesa->RenderVBRawTab; + } + + if (!VB->CullDone) + gl_fast_copy_vb( VB ); + + do + { + for ( i= VB->CopyStart ; i < count ; parity = 0, i = next ) + { + prim = VB->Primitive[i]; + next = VB->NextPrimitive[i]; + tab[prim]( VB, i, next, parity ); + } + + } while (ctx->Driver.MultipassFunc && + ctx->Driver.MultipassFunc( VB, ++p )); +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_render(void) +{ + return 0; +} + +#endif /* FX */ diff --git a/xc/extras/Mesa/src/FX/fxsanity.c b/xc/extras/Mesa/src/FX/fxsanity.c new file mode 100644 index 000000000..9f815012e --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxsanity.c @@ -0,0 +1,124 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + + + +#if defined(FX) +#include "fxdrv.h" + +/* I have found this quite useful in tracking down transformation & + * clipping bugs. If you get a random graphics card freeze, running + * your triangles through this will probably catch the problem. + */ + +#define WID 640 +#define HI 480 + +#undef grDrawTriangle + +void fx_sanity_triangle( GrVertex *v1, GrVertex *v2, GrVertex *v3 ) +{ + GLuint rv = 1, print = 0; + + GLfloat area = ((v1->x - v3->x) * (v2->y - v3->y) - + (v1->y - v3->y) * (v2->x - v3->x)); + + if (v1->x < 0 || v1->y < 0 || v1->x > WID || v1->y > HI || + v2->x < 0 || v2->y < 0 || v2->x > WID || v2->y > HI || + v3->x < 0 || v3->y < 0 || v3->x > WID || v3->y > HI) + { + fprintf(stderr,"not clipped/set up!!!!!\n"); + rv = 0; + print = 1; + } + + if (area > (WID*HI)) { + fprintf(stderr,"too big\n"); + rv = 0; + } + if (v1->oow == 0 || v2->oow == 0 || v3->oow == 0) { + fprintf(stderr,"zero oow\n"); + rv = 0; + } + if (0 && area == 0) { + fprintf(stderr,"zero area %p %p %p\n", v1,v2,v3); + rv =0; + } + + if (print) { + fprintf(stderr,"v1: %f %f %f %f col %.0f %.0f %.0f %.0f t0 %f %f %f t1 %f %f %f\n", + v1->x, v1->y, v1->ooz, v1->oow, + v1->r, v1->g, v1->b, v1->a, + v1->tmuvtx[0].sow, v1->tmuvtx[0].tow, v1->tmuvtx[0].oow, + v1->tmuvtx[1].sow, v1->tmuvtx[1].tow, v1->tmuvtx[1].oow); + fprintf(stderr,"v2: %f %f %f %f col %.0f %.0f %.0f %.0f t0 %f %f %f t1 %f %f %f\n", + v2->x, v2->y, v2->ooz, v2->oow, + v2->r, v2->g, v2->b, v2->a, + v2->tmuvtx[0].sow, v2->tmuvtx[0].tow, v2->tmuvtx[0].oow, + v2->tmuvtx[1].sow, v2->tmuvtx[1].tow, v2->tmuvtx[1].oow); + fprintf(stderr,"v3: %f %f %f %f col %.0f %.0f %.0f %.0f t0 %f %f %f t1 %f %f %f\n", + v3->x, v3->y, v3->ooz, v3->oow, + v3->r, v3->g, v3->b, v3->a, + v3->tmuvtx[0].sow, v3->tmuvtx[0].tow, v3->tmuvtx[0].oow, + v3->tmuvtx[1].sow, v3->tmuvtx[1].tow, v3->tmuvtx[1].oow); + } + + if (1) + FX_grDrawTriangle(v1,v2,v3); + else + fprintf(stderr, "\n\n\n"); +} + +#else + +void gl_fxsanity_dummy() +{ +} + +#endif diff --git a/xc/extras/Mesa/src/FX/fxsdettmp.h b/xc/extras/Mesa/src/FX/fxsdettmp.h new file mode 100644 index 000000000..7b77b36c2 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxsdettmp.h @@ -0,0 +1,161 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* + * Notes: the folowing code works only if count is > start. + * Corrently we are looking for the pattern: + * v0,v1,v2 v2,v1,v3, v2,v3,v4.... + * + * For this: + * #define STRIP0 ((u1 == v1) && (u2 == v0)) + * #define STRIP1 ((u0 == v0) && (u2 == v1)) + * + */ + + +static void TAG(render_vb_triangles_smooth_indirect_sd) + ( struct vertex_buffer *VB, + GLuint start, + GLuint count, + GLuint parity) +{ + GLint u0,u1,u2; + GLint v0,v1,v2; + GLuint *elt = VB->EltPtr->data; + + int i; + LOCAL_VARS + + INIT(GL_TRIANGLES); + + elt = &elt[start-1]; + u0 = *(++elt); + u1 = *(++elt); + u2 = *(++elt); + i = start+3; + while (i < count) + { + v0 = *(++elt); + v1 = *(++elt); + v2 = *(++elt); + + if (CLIPPED(u0,u1,u2)) + { + if (!CULLED(u0,u1,u2)) SENDCLIPTRI(u0,u1,u2); + } + else + { + if (STRIP0(u,v)) + { + int is_strips = 1; + int parity = 0; + STRIPSLOCAL_VAR + + FLUSHTRI(); + STARTSTRIPS(u0,u1,u2); + while (is_strips && i < count) + { + SENDSTRIPS(v2); + + u0 = v0; u1 = v1; u2 = v2; i+= 3; + v0 = *(++elt); + v1 = *(++elt); + v2 = *(++elt); + + if (parity) { + is_strips = STRIP0(u,v); + parity = 0; + } else { + is_strips = STRIP1(u,v); + parity = 1; + } + } + FLUSHSTRIPS(); + + if (i >= count) + return; + } + else + { + SENDTRI(u0,u1,u2); + } + } + u0 = v0; u1 = v1; u2 = v2; i+= 3; + } + if (CLIPPED(u0,u1,u2)) + { + if (!CULLED(u0,u1,u2)) SENDCLIPTRI(u0,u1,u2); + } + else + { + SENDTRI(u0,u1,u2); + } + FLUSHTRI(); + +} + +#ifndef PRESERVE_VB_DEFS +#undef SENDTRI +#undef STRIP0 +#undef STRIP1 +#undef LOCAL_VARS +#undef STRIPSLOCAL_VAR +#undef INIT +#undef SENDTRI +#undef FLUSHTRI +#undef STARTSTRIPS +#undef SENDSTRIPS +#undef FLUSHSTRIPS +#undef CLIPPED +#undef CULLED +#undef SENDCLIPTRI +#endif + +#ifndef PRESERVE_TAG +#undef TAG +#endif + +#undef PRESERVE_VB_DEFS +#undef PRESERVE_TAG diff --git a/xc/extras/Mesa/src/FX/fxsetup.c b/xc/extras/Mesa/src/FX/fxsetup.c new file mode 100644 index 000000000..f1a56650b --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxsetup.c @@ -0,0 +1,1858 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* fxsetup.c - 3Dfx VooDoo rendering mode setup functions */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" +#include "enums.h" + +static GLuint fxGetTexSetConfiguration(GLcontext *ctx, + struct gl_texture_object *tObj0, + struct gl_texture_object *tObj1); +static void fxSetupTextureSingleTMU_NoLock(GLcontext *ctx, GLuint textureset); +static void fxSetupDoubleTMU_NoLock(fxMesaContext fxMesa, + struct gl_texture_object *tObj0, + struct gl_texture_object *tObj1); +static void fxSetupTexture_NoLock(GLcontext *ctx); +static void fxSetupTexture(GLcontext *ctx); +static void fxSetupBlend(GLcontext *ctx); +static void fxSetupDepthTest(GLcontext *ctx); +static void fxSetupScissor(GLcontext *ctx); +static void fxSetupCull(GLcontext *ctx); +static void gl_print_fx_state_flags( const char *msg, GLuint flags); +/*static GLboolean fxMultipassBlend(struct vertex_buffer *, GLuint);*/ +static GLboolean fxMultipassTexture( struct vertex_buffer *, GLuint ); + +static void fxTexValidate(GLcontext *ctx, struct gl_texture_object *tObj) +{ + tfxTexInfo *ti=fxTMGetTexInfo(tObj); + GLint minl, maxl; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxTexValidate(...) Start\n"); + } + + if(ti->validated) { + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxTexValidate(...) End (validated=GL_TRUE)\n"); + } + return; + } + + ti->tObj=tObj; + minl=ti->minLevel=tObj->BaseLevel; + maxl=ti->maxLevel=MIN2(tObj->MaxLevel,tObj->Image[0]->MaxLog2); + + fxTexGetInfo(tObj->Image[minl]->Width, tObj->Image[minl]->Height, + &(FX_largeLodLog2(ti->info)), &(FX_aspectRatioLog2(ti->info)), + &(ti->sScale), &(ti->tScale), + &(ti->int_sScale), &(ti->int_tScale), + NULL, NULL); + + if((tObj->MinFilter!=GL_NEAREST) && (tObj->MinFilter!=GL_LINEAR)) + fxTexGetInfo(tObj->Image[maxl]->Width,tObj->Image[maxl]->Height, + &(FX_smallLodLog2(ti->info)),NULL, + NULL,NULL, + NULL,NULL, + NULL,NULL); + else + FX_smallLodLog2(ti->info)=FX_largeLodLog2(ti->info); + + fxTexGetFormat(tObj->Image[minl]->IntFormat,&(ti->info.format),&(ti->baseLevelInternalFormat)); + + switch (tObj->WrapS) { + case GL_CLAMP_TO_EDGE: + /* What's this really mean compared to GL_CLAMP? */ + case GL_CLAMP: + ti->sClamp=1; + break; + case GL_REPEAT: + ti->sClamp=0; + break; + default: + ; /* silence compiler warning */ + } + switch (tObj->WrapT) { + case GL_CLAMP_TO_EDGE: + /* What's this really mean compared to GL_CLAMP? */ + case GL_CLAMP: + ti->tClamp=1; + break; + case GL_REPEAT: + ti->tClamp=0; + break; + default: + ; /* silence compiler warning */ + } + + ti->validated=GL_TRUE; + + ti->info.data=NULL; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxTexValidate(...) End\n"); + } +} + +static void fxPrintUnitsMode( const char *msg, GLuint mode ) +{ + fprintf(stderr, + "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + msg, + mode, + (mode & FX_UM_E0_REPLACE) ? "E0_REPLACE, " : "", + (mode & FX_UM_E0_MODULATE) ? "E0_MODULATE, " : "", + (mode & FX_UM_E0_DECAL) ? "E0_DECAL, " : "", + (mode & FX_UM_E0_BLEND) ? "E0_BLEND, " : "", + (mode & FX_UM_E1_REPLACE) ? "E1_REPLACE, " : "", + (mode & FX_UM_E1_MODULATE) ? "E1_MODULATE, " : "", + (mode & FX_UM_E1_DECAL) ? "E1_DECAL, " : "", + (mode & FX_UM_E1_BLEND) ? "E1_BLEND, " : "", + (mode & FX_UM_E0_ALPHA) ? "E0_ALPHA, " : "", + (mode & FX_UM_E0_LUMINANCE) ? "E0_LUMINANCE, " : "", + (mode & FX_UM_E0_LUMINANCE_ALPHA) ? "E0_LUMINANCE_ALPHA, " : "", + (mode & FX_UM_E0_INTENSITY) ? "E0_INTENSITY, " : "", + (mode & FX_UM_E0_RGB) ? "E0_RGB, " : "", + (mode & FX_UM_E0_RGBA) ? "E0_RGBA, " : "", + (mode & FX_UM_E1_ALPHA) ? "E1_ALPHA, " : "", + (mode & FX_UM_E1_LUMINANCE) ? "E1_LUMINANCE, " : "", + (mode & FX_UM_E1_LUMINANCE_ALPHA) ? "E1_LUMINANCE_ALPHA, " : "", + (mode & FX_UM_E1_INTENSITY) ? "E1_INTENSITY, " : "", + (mode & FX_UM_E1_RGB) ? "E1_RGB, " : "", + (mode & FX_UM_E1_RGBA) ? "E1_RGBA, " : "", + (mode & FX_UM_COLOR_ITERATED) ? "COLOR_ITERATED, " : "", + (mode & FX_UM_COLOR_CONSTANT) ? "COLOR_CONSTANT, " : "", + (mode & FX_UM_ALPHA_ITERATED) ? "ALPHA_ITERATED, " : "", + (mode & FX_UM_ALPHA_CONSTANT) ? "ALPHA_CONSTANT, " : ""); +} + +static GLuint fxGetTexSetConfiguration(GLcontext *ctx, + struct gl_texture_object *tObj0, + struct gl_texture_object *tObj1) +{ + GLuint unitsmode=0; + GLuint envmode=0; + GLuint ifmt=0; + + if((ctx->Light.ShadeModel==GL_SMOOTH) || 1 || + (ctx->Point.SmoothFlag) || + (ctx->Line.SmoothFlag) || + (ctx->Polygon.SmoothFlag)) + unitsmode|=FX_UM_ALPHA_ITERATED; + else + unitsmode|=FX_UM_ALPHA_CONSTANT; + + if(ctx->Light.ShadeModel==GL_SMOOTH || 1) + unitsmode|=FX_UM_COLOR_ITERATED; + else + unitsmode|=FX_UM_COLOR_CONSTANT; + + + + /* + OpenGL Feeds Texture 0 into Texture 1 + Glide Feeds Texture 1 into Texture 0 + */ + if(tObj0) { + tfxTexInfo *ti0=fxTMGetTexInfo(tObj0); + + switch(ti0->baseLevelInternalFormat) { + case GL_ALPHA: + ifmt|=FX_UM_E0_ALPHA; + break; + case GL_LUMINANCE: + ifmt|=FX_UM_E0_LUMINANCE; + break; + case GL_LUMINANCE_ALPHA: + ifmt|=FX_UM_E0_LUMINANCE_ALPHA; + break; + case GL_INTENSITY: + ifmt|=FX_UM_E0_INTENSITY; + break; + case GL_RGB: + ifmt|=FX_UM_E0_RGB; + break; + case GL_RGBA: + ifmt|=FX_UM_E0_RGBA; + break; + } + + switch(ctx->Texture.Unit[0].EnvMode) { + case GL_DECAL: + envmode|=FX_UM_E0_DECAL; + break; + case GL_MODULATE: + envmode|=FX_UM_E0_MODULATE; + break; + case GL_REPLACE: + envmode|=FX_UM_E0_REPLACE; + break; + case GL_BLEND: + envmode|=FX_UM_E0_BLEND; + break; + case GL_ADD: + envmode|=FX_UM_E0_ADD; + break; + default: + /* do nothing */ + break; + } + } + + if(tObj1) { + tfxTexInfo *ti1=fxTMGetTexInfo(tObj1); + + switch(ti1->baseLevelInternalFormat) { + case GL_ALPHA: + ifmt|=FX_UM_E1_ALPHA; + break; + case GL_LUMINANCE: + ifmt|=FX_UM_E1_LUMINANCE; + break; + case GL_LUMINANCE_ALPHA: + ifmt|=FX_UM_E1_LUMINANCE_ALPHA; + break; + case GL_INTENSITY: + ifmt|=FX_UM_E1_INTENSITY; + break; + case GL_RGB: + ifmt|=FX_UM_E1_RGB; + break; + case GL_RGBA: + ifmt|=FX_UM_E1_RGBA; + break; + default: + /* do nothing */ + break; + } + + switch(ctx->Texture.Unit[1].EnvMode) { + case GL_DECAL: + envmode|=FX_UM_E1_DECAL; + break; + case GL_MODULATE: + envmode|=FX_UM_E1_MODULATE; + break; + case GL_REPLACE: + envmode|=FX_UM_E1_REPLACE; + break; + case GL_BLEND: + envmode|=FX_UM_E1_BLEND; + break; + case GL_ADD: + envmode|=FX_UM_E1_ADD; + break; + default: + /* do nothing */ + break; + } + } + + unitsmode|=(ifmt | envmode); + + if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE)) + fxPrintUnitsMode("unitsmode", unitsmode); + + return unitsmode; +} + +/************************************************************************/ +/************************* Rendering Mode SetUp *************************/ +/************************************************************************/ + +/************************* Single Texture Set ***************************/ + +static void fxSetupSingleTMU_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj) +{ + tfxTexInfo *ti=fxTMGetTexInfo(tObj); + int tmu; + + /* Make sure we're not loaded incorrectly */ + if (ti->isInTM) { + if (ti->LODblend) { + if (ti->whichTMU!=FX_TMU_SPLIT) + fxTMMoveOutTM(fxMesa, tObj); + } else { + if (ti->whichTMU==FX_TMU_SPLIT) + fxTMMoveOutTM(fxMesa, tObj); + } + } + + /* Make sure we're loaded correctly */ + if (!ti->isInTM) { + if (ti->LODblend) + fxTMMoveInTM_NoLock(fxMesa,tObj,FX_TMU_SPLIT); + else { + if (fxMesa->haveTwoTMUs) { + if (fxMesa->freeTexMem[FX_TMU0] > + FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH, + &(ti->info))) { + fxTMMoveInTM_NoLock(fxMesa,tObj, FX_TMU0); + } else { + fxTMMoveInTM_NoLock(fxMesa,tObj, FX_TMU1); + } + } else + fxTMMoveInTM_NoLock(fxMesa,tObj,FX_TMU0); + } + } + + if (ti->LODblend && ti->whichTMU == FX_TMU_SPLIT) { + if ((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) { + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: uploading texture palette\n"); + } + FX_grTexDownloadTable_NoLock(GR_TMU0,GR_TEXTABLE_PALETTE,&(ti->palette)); + FX_grTexDownloadTable_NoLock(GR_TMU1,GR_TEXTABLE_PALETTE,&(ti->palette)); + } + + FX_grTexClampMode_NoLock(GR_TMU0,ti->sClamp,ti->tClamp); + FX_grTexClampMode_NoLock(GR_TMU1,ti->sClamp,ti->tClamp); + FX_grTexFilterMode_NoLock(GR_TMU0,ti->minFilt,ti->maxFilt); + FX_grTexFilterMode_NoLock(GR_TMU1,ti->minFilt,ti->maxFilt); + FX_grTexMipMapMode_NoLock(GR_TMU0,ti->mmMode,ti->LODblend); + FX_grTexMipMapMode_NoLock(GR_TMU1,ti->mmMode,ti->LODblend); + + FX_grTexSource_NoLock(GR_TMU0,ti->tm[FX_TMU0]->startAddr, + GR_MIPMAPLEVELMASK_ODD,&(ti->info)); + FX_grTexSource_NoLock(GR_TMU1,ti->tm[FX_TMU1]->startAddr, + GR_MIPMAPLEVELMASK_EVEN,&(ti->info)); + } else { + if (ti->whichTMU==FX_TMU_BOTH) tmu=FX_TMU0; + else tmu=ti->whichTMU; + + if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) { + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: uploading texture palette\n"); + } + FX_grTexDownloadTable_NoLock(tmu, GR_TEXTABLE_PALETTE, &(ti->palette)); + } + + /* KW: The alternative is to do the download to the other tmu. If + * we get to this point, I think it means we are thrashing the + * texture memory, so perhaps it's not a good idea. + */ + if (ti->LODblend && (MESA_VERBOSE&VERBOSE_DRIVER)) + fprintf(stderr, "fxmesa: not blending texture - only on one tmu\n"); + + FX_grTexClampMode_NoLock(tmu, ti->sClamp, ti->tClamp); + FX_grTexFilterMode_NoLock(tmu, ti->minFilt, ti->maxFilt); + FX_grTexMipMapMode_NoLock(tmu, ti->mmMode, FXFALSE); + + FX_grTexSource_NoLock(tmu, ti->tm[tmu]->startAddr, + GR_MIPMAPLEVELMASK_BOTH, &(ti->info)); + } +} + +static void fxSelectSingleTMUSrc_NoLock(fxMesaContext fxMesa, GLint tmu, + FxBool LODblend) +{ + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxSelectSingleTMUSrc(%d,%d)\n",tmu,LODblend); + } + + if (LODblend) { + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_BLEND, + GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION, + GR_COMBINE_FUNCTION_BLEND, + GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION, + FXFALSE,FXFALSE); + + if (fxMesa->haveTwoTMUs) + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, + FXFALSE,FXFALSE); + fxMesa->tmuSrc=FX_TMU_SPLIT; + } + else { + if (tmu!=FX_TMU1) { + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, + FXFALSE,FXFALSE); + if (fxMesa->haveTwoTMUs) { + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, + FXFALSE,FXFALSE); + } + fxMesa->tmuSrc=FX_TMU0; + } + else { + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, + FXFALSE,FXFALSE); + + /* GR_COMBINE_FUNCTION_SCALE_OTHER doesn't work ?!? */ + + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_BLEND, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_FUNCTION_BLEND, + GR_COMBINE_FACTOR_ONE, + FXFALSE,FXFALSE); + + fxMesa->tmuSrc=FX_TMU1; + } + } +} + +static void fxSetupTextureSingleTMU_NoLock(GLcontext *ctx, GLuint textureset) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GrCombineLocal_t localc,locala; + GLuint unitsmode; + GLint ifmt; + tfxTexInfo *ti; + struct gl_texture_object *tObj=ctx->Texture.Unit[textureset].CurrentD[2]; + int tmu; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) Start\n"); + } + + ti=fxTMGetTexInfo(tObj); + + fxTexValidate(ctx,tObj); + + fxSetupSingleTMU_NoLock(fxMesa,tObj); + + if (ti->whichTMU==FX_TMU_BOTH) tmu=FX_TMU0; + else tmu=ti->whichTMU; + if (fxMesa->tmuSrc!=tmu) + fxSelectSingleTMUSrc_NoLock(fxMesa, tmu, ti->LODblend); + + if(textureset==0 || !fxMesa->haveTwoTMUs) + unitsmode=fxGetTexSetConfiguration(ctx,tObj,NULL); + else + unitsmode=fxGetTexSetConfiguration(ctx,NULL,tObj); + +/* if(fxMesa->lastUnitsMode==unitsmode) */ +/* return; */ + + fxMesa->lastUnitsMode=unitsmode; + + fxMesa->stw_hint_state = 0; + FX_grHints_NoLock(GR_HINT_STWHINT,0); + + ifmt=ti->baseLevelInternalFormat; + + if(unitsmode & FX_UM_ALPHA_ITERATED) + locala=GR_COMBINE_LOCAL_ITERATED; + else + locala=GR_COMBINE_LOCAL_CONSTANT; + + if(unitsmode & FX_UM_COLOR_ITERATED) + localc=GR_COMBINE_LOCAL_ITERATED; + else + localc=GR_COMBINE_LOCAL_CONSTANT; + + if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE)) + fprintf(stderr, "fxMesa: fxSetupTextureSingleTMU, envmode is %s\n", + gl_lookup_enum_by_nr(ctx->Texture.Unit[textureset].EnvMode)); + + switch(ctx->Texture.Unit[textureset].EnvMode) { + case GL_DECAL: + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + locala, + GR_COMBINE_OTHER_NONE, + FXFALSE); + + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_BLEND, + GR_COMBINE_FACTOR_TEXTURE_ALPHA, + localc, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + break; + case GL_MODULATE: + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + locala, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + + if(ifmt==GL_ALPHA) + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + localc, + GR_COMBINE_OTHER_NONE, + FXFALSE); + else + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + localc, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + break; + case GL_BLEND: +#if 0 + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + locala, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + if (ifmt==GL_ALPHA) + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + localc, + GR_COMBINE_OTHER_NONE, + FXFALSE); + else + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, + GR_COMBINE_FACTOR_LOCAL, + localc, + GR_COMBINE_OTHER_TEXTURE, + FXTRUE); + ctx->Driver.MultipassFunc = fxMultipassBlend; +#else + if (MESA_VERBOSE&VERBOSE_DRIVER) + fprintf(stderr,"fx Driver: GL_BLEND not yet supported\n"); +#endif + break; + case GL_REPLACE: + if((ifmt==GL_RGB) || (ifmt==GL_LUMINANCE)) + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + locala, + GR_COMBINE_OTHER_NONE, + FXFALSE); + else + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + locala, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + + if(ifmt==GL_ALPHA) + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + localc, + GR_COMBINE_OTHER_NONE, + FXFALSE); + else + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + localc, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + break; + default: + if (MESA_VERBOSE&VERBOSE_DRIVER) + fprintf(stderr, "fx Driver: %x Texture.EnvMode not yet supported\n", + ctx->Texture.Unit[textureset].EnvMode); + break; + } + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) End\n"); + } +} + +static void fxSetupTextureSingleTMU(GLcontext *ctx, GLuint textureset) { + BEGIN_BOARD_LOCK(); + fxSetupTextureSingleTMU_NoLock(ctx, textureset); + END_BOARD_LOCK(); +} + +/************************* Double Texture Set ***************************/ + +static void fxSetupDoubleTMU_NoLock(fxMesaContext fxMesa, + struct gl_texture_object *tObj0, + struct gl_texture_object *tObj1) +{ +#define T0_NOT_IN_TMU 0x01 +#define T1_NOT_IN_TMU 0x02 +#define T0_IN_TMU0 0x04 +#define T1_IN_TMU0 0x08 +#define T0_IN_TMU1 0x10 +#define T1_IN_TMU1 0x20 + + tfxTexInfo *ti0=fxTMGetTexInfo(tObj0); + tfxTexInfo *ti1=fxTMGetTexInfo(tObj1); + GLuint tstate=0; + int tmu0=0, tmu1=1; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxSetupDoubleTMU(...)\n"); + } + + /* We shouldn't need to do this. There is something wrong with + mutlitexturing when the TMUs are swapped. So, we're forcing + them to always be loaded correctly. !!! */ + if (ti0->whichTMU==FX_TMU1) + fxTMMoveOutTM_NoLock(fxMesa, tObj0); + if (ti1->whichTMU==FX_TMU0) + fxTMMoveOutTM_NoLock(fxMesa, tObj1); + + if (ti0->isInTM) { + switch (ti0->whichTMU) { + case FX_TMU0: + tstate|=T0_IN_TMU0; + break; + case FX_TMU1: + tstate|=T0_IN_TMU1; + break; + case FX_TMU_BOTH: + tstate|=T0_IN_TMU0|T0_IN_TMU1; + break; + case FX_TMU_SPLIT: + tstate|=T0_NOT_IN_TMU; + break; + } + } else tstate|=T0_NOT_IN_TMU; + + if (ti1->isInTM) { + switch (ti1->whichTMU) { + case FX_TMU0: + tstate|=T1_IN_TMU0; + break; + case FX_TMU1: + tstate|=T1_IN_TMU1; + break; + case FX_TMU_BOTH: + tstate|=T1_IN_TMU0|T1_IN_TMU1; + break; + case FX_TMU_SPLIT: + tstate|=T1_NOT_IN_TMU; + break; + } + } else tstate|=T1_NOT_IN_TMU; + + ti0->lastTimeUsed=fxMesa->texBindNumber; + ti1->lastTimeUsed=fxMesa->texBindNumber; + + /* Move texture maps into TMUs */ + + if (!(((tstate&T0_IN_TMU0) && (tstate&T1_IN_TMU1)) || + ((tstate&T0_IN_TMU1) && (tstate&T1_IN_TMU0)))) { + if (tObj0==tObj1) fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU_BOTH); + else { + /* Find the minimal way to correct the situation */ + if ((tstate&T0_IN_TMU0) || (tstate&T1_IN_TMU1)) { + /* We have one in the standard order, setup the other */ + if (tstate&T0_IN_TMU0) { /* T0 is in TMU0, put T1 in TMU1 */ + fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU1); + } else { + fxTMMoveInTM_NoLock(fxMesa, tObj0, FX_TMU0); + } + /* tmu0 and tmu1 are setup */ + } else if ((tstate&T0_IN_TMU1) || (tstate&T1_IN_TMU0)) { + /* we have one in the reverse order, setup the other */ + if (tstate&T1_IN_TMU0) { /* T1 is in TMU0, put T0 in TMU1 */ + fxTMMoveInTM_NoLock(fxMesa, tObj0, FX_TMU1); + } else { + fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU0); + } + tmu0=1; + tmu1=0; + } else { /* Nothing is loaded */ + fxTMMoveInTM_NoLock(fxMesa, tObj0, FX_TMU0); + fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU1); + /* tmu0 and tmu1 are setup */ + } + } + } + + if (!fxMesa->haveGlobalPaletteTexture) { + if (ti0->info.format==GR_TEXFMT_P_8) { + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: uploading texture palette TMU0\n"); + } + FX_grTexDownloadTable_NoLock(tmu0, GR_TEXTABLE_PALETTE, &(ti0->palette)); + } + + if (ti1->info.format==GR_TEXFMT_P_8) { + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: uploading texture palette TMU1\n"); + } + FX_grTexDownloadTable_NoLock(tmu1, GR_TEXTABLE_PALETTE, &(ti1->palette)); + } + } + + FX_grTexSource_NoLock(tmu0, ti0->tm[tmu0]->startAddr, + GR_MIPMAPLEVELMASK_BOTH, &(ti0->info)); + FX_grTexClampMode_NoLock(tmu0, ti0->sClamp, ti0->tClamp); + FX_grTexFilterMode_NoLock(tmu0, ti0->minFilt, ti0->maxFilt); + FX_grTexMipMapMode_NoLock(tmu0, ti0->mmMode, FXFALSE); + + FX_grTexSource_NoLock(tmu1, ti1->tm[tmu1]->startAddr, + GR_MIPMAPLEVELMASK_BOTH, &(ti1->info)); + FX_grTexClampMode_NoLock(tmu1, ti1->sClamp, ti1->tClamp); + FX_grTexFilterMode_NoLock(tmu1, ti1->minFilt, ti1->maxFilt); + FX_grTexMipMapMode_NoLock(tmu1, ti1->mmMode, FXFALSE); + +#undef T0_NOT_IN_TMU +#undef T1_NOT_IN_TMU +#undef T0_IN_TMU0 +#undef T1_IN_TMU0 +#undef T0_IN_TMU1 +#undef T1_IN_TMU1 +} + +static void fxSetupTextureDoubleTMU_NoLock(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GrCombineLocal_t localc,locala; + tfxTexInfo *ti0,*ti1; + struct gl_texture_object *tObj0=ctx->Texture.Unit[0].CurrentD[2]; + struct gl_texture_object *tObj1=ctx->Texture.Unit[1].CurrentD[2]; + GLuint envmode,ifmt,unitsmode; + int tmu0=0, tmu1=1; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) Start\n"); + } + + ti0=fxTMGetTexInfo(tObj0); + fxTexValidate(ctx,tObj0); + + ti1=fxTMGetTexInfo(tObj1); + fxTexValidate(ctx,tObj1); + + fxSetupDoubleTMU_NoLock(fxMesa,tObj0,tObj1); + + unitsmode=fxGetTexSetConfiguration(ctx,tObj0,tObj1); + +/* if(fxMesa->lastUnitsMode==unitsmode) */ +/* return; */ + + fxMesa->lastUnitsMode=unitsmode; + + fxMesa->stw_hint_state |= GR_STWHINT_ST_DIFF_TMU1; + FX_grHints_NoLock(GR_HINT_STWHINT, fxMesa->stw_hint_state); + + envmode=unitsmode & FX_UM_E_ENVMODE; + ifmt=unitsmode & FX_UM_E_IFMT; + + if(unitsmode & FX_UM_ALPHA_ITERATED) + locala=GR_COMBINE_LOCAL_ITERATED; + else + locala=GR_COMBINE_LOCAL_CONSTANT; + + if(unitsmode & FX_UM_COLOR_ITERATED) + localc=GR_COMBINE_LOCAL_ITERATED; + else + localc=GR_COMBINE_LOCAL_CONSTANT; + + + if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE)) + fprintf(stderr, "fxMesa: fxSetupTextureDoubleTMU, envmode is %s/%s\n", + gl_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode), + gl_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode)); + + + if ((ti0->whichTMU==FX_TMU1) || (ti1->whichTMU==FX_TMU0)) { + tmu0=1; + tmu1=0; + } + fxMesa->tmuSrc=FX_TMU_BOTH; + switch(envmode) { + case (FX_UM_E0_MODULATE | FX_UM_E1_MODULATE): + { + GLboolean isalpha[FX_NUM_TMU]; + + if(ti0->baseLevelInternalFormat==GL_ALPHA) + isalpha[tmu0]=GL_TRUE; + else + isalpha[tmu0]=GL_FALSE; + + if(ti1->baseLevelInternalFormat==GL_ALPHA) + isalpha[tmu1]=GL_TRUE; + else + isalpha[tmu1]=GL_FALSE; + + if(isalpha[FX_TMU1]) + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + FXTRUE,FXFALSE); + else + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + FXFALSE,FXFALSE); + + if(isalpha[FX_TMU0]) + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_LOCAL, + FXFALSE,FXFALSE); + else + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_LOCAL, + FXFALSE,FXFALSE); + + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + localc, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + locala, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + break; + } + case (FX_UM_E0_REPLACE | FX_UM_E1_BLEND): /* Only for GLQuake */ + if (tmu1==FX_TMU1) { + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + FXTRUE,FXFALSE); + + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_LOCAL, + FXFALSE,FXFALSE); + } else { + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + FXFALSE,FXFALSE); + + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, + FXFALSE,FXFALSE); + } + + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + locala, + GR_COMBINE_OTHER_NONE, + FXFALSE); + + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + localc, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + break; + case (FX_UM_E0_REPLACE | FX_UM_E1_MODULATE): /* Quake 2 and 3 */ + if (tmu1==FX_TMU1) { + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + FXFALSE,FXTRUE); + + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_LOCAL, + FXFALSE,FXFALSE); + + } else { + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + FXFALSE,FXFALSE); + + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_FUNCTION_BLEND_OTHER, + GR_COMBINE_FACTOR_ONE, + FXFALSE,FXFALSE); + } + + if(ti0->baseLevelInternalFormat==GL_RGB) + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + locala, + GR_COMBINE_OTHER_NONE, + FXFALSE); + else + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + locala, + GR_COMBINE_OTHER_NONE, + FXFALSE); + + + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + localc, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + break; + + + case (FX_UM_E0_MODULATE | FX_UM_E1_ADD): /* Quake 3 Sky */ + { + GLboolean isalpha[FX_NUM_TMU]; + + if(ti0->baseLevelInternalFormat==GL_ALPHA) + isalpha[tmu0]=GL_TRUE; + else + isalpha[tmu0]=GL_FALSE; + + if(ti1->baseLevelInternalFormat==GL_ALPHA) + isalpha[tmu1]=GL_TRUE; + else + isalpha[tmu1]=GL_FALSE; + + if(isalpha[FX_TMU1]) + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_ZERO, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + FXTRUE,FXFALSE); + else + FX_grTexCombine_NoLock(GR_TMU1, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + FXFALSE,FXFALSE); + + if(isalpha[FX_TMU0]) + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, + GR_COMBINE_FACTOR_ONE, + FXFALSE,FXFALSE); + else + FX_grTexCombine_NoLock(GR_TMU0, + GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, + GR_COMBINE_FACTOR_ONE, + FXFALSE,FXFALSE); + + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + localc, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + locala, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + break; + } + default: + fprintf(stderr, "Unexpected dual texture mode encountered\n"); + break; + } + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) End\n"); + } +} + +/************************* No Texture ***************************/ + +static void fxSetupTextureNone_NoLock(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GrCombineLocal_t localc,locala; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxSetupTextureNone(...)\n"); + } + + if((ctx->Light.ShadeModel==GL_SMOOTH) || 1 || + (ctx->Point.SmoothFlag) || + (ctx->Line.SmoothFlag) || + (ctx->Polygon.SmoothFlag)) + locala=GR_COMBINE_LOCAL_ITERATED; + else + locala=GR_COMBINE_LOCAL_CONSTANT; + + if(ctx->Light.ShadeModel==GL_SMOOTH || 1) + localc=GR_COMBINE_LOCAL_ITERATED; + else + localc=GR_COMBINE_LOCAL_CONSTANT; + + FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + locala, + GR_COMBINE_OTHER_NONE, + FXFALSE); + + FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + localc, + GR_COMBINE_OTHER_NONE, + FXFALSE); + + fxMesa->lastUnitsMode=FX_UM_NONE; +} + +/************************************************************************/ +/************************** Texture Mode SetUp **************************/ +/************************************************************************/ + +static void fxSetupTexture_NoLock(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint tex2Denabled; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxSetupTexture(...)\n"); + } + + /* Disable multipass texturing. + */ + ctx->Driver.MultipassFunc = 0; + + /* Texture Combine, Color Combine and Alpha Combine. + */ + tex2Denabled = (ctx->Texture.ReallyEnabled & TEXTURE0_2D); + + if (fxMesa->emulateTwoTMUs) + tex2Denabled |= (ctx->Texture.ReallyEnabled & TEXTURE1_2D); + + switch(tex2Denabled) { + case TEXTURE0_2D: + fxSetupTextureSingleTMU_NoLock(ctx,0); + break; + case TEXTURE1_2D: + fxSetupTextureSingleTMU_NoLock(ctx,1); + break; + case (TEXTURE0_2D|TEXTURE1_2D): + if (fxMesa->haveTwoTMUs) + fxSetupTextureDoubleTMU_NoLock(ctx); + else { + if (MESA_VERBOSE&VERBOSE_DRIVER) + fprintf(stderr, "fxmesa: enabling fake multitexture\n"); + + fxSetupTextureSingleTMU_NoLock(ctx,0); + ctx->Driver.MultipassFunc = fxMultipassTexture; + } + break; + default: + fxSetupTextureNone_NoLock(ctx); + break; + } +} + +static void fxSetupTexture(GLcontext *ctx) { + BEGIN_BOARD_LOCK(); + fxSetupTexture_NoLock(ctx); + END_BOARD_LOCK(); +} + +/************************************************************************/ +/**************************** Blend SetUp *******************************/ +/************************************************************************/ + +/* XXX consider supporting GL_INGR_blend_func_separate */ +void fxDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxUnitsState *us=&fxMesa->unitsState; + GrAlphaBlendFnc_t sfact,dfact,asfact,adfact; + + /* From the Glide documentation: + For alpha source and destination blend function factor + parameters, Voodoo Graphics supports only + GR_BLEND_ZERO and GR_BLEND_ONE. + */ + + switch(sfactor) { + case GL_ZERO: + asfact=sfact=GR_BLEND_ZERO; + break; + case GL_ONE: + asfact=sfact=GR_BLEND_ONE; + break; + case GL_DST_COLOR: + sfact=GR_BLEND_DST_COLOR; + asfact=GR_BLEND_ONE; + break; + case GL_ONE_MINUS_DST_COLOR: + sfact=GR_BLEND_ONE_MINUS_DST_COLOR; + asfact=GR_BLEND_ONE; + break; + case GL_SRC_ALPHA: + sfact=GR_BLEND_SRC_ALPHA; + asfact=GR_BLEND_ONE; + break; + case GL_ONE_MINUS_SRC_ALPHA: + sfact=GR_BLEND_ONE_MINUS_SRC_ALPHA; + asfact=GR_BLEND_ONE; + break; + case GL_DST_ALPHA: + sfact=GR_BLEND_DST_ALPHA; + asfact=GR_BLEND_ONE; + break; + case GL_ONE_MINUS_DST_ALPHA: + sfact=GR_BLEND_ONE_MINUS_DST_ALPHA; + asfact=GR_BLEND_ONE; + break; + case GL_SRC_ALPHA_SATURATE: + sfact=GR_BLEND_ALPHA_SATURATE; + asfact=GR_BLEND_ONE; + break; + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + /* USELESS */ + asfact=sfact=GR_BLEND_ONE; + break; + default: + asfact=sfact=GR_BLEND_ONE; + break; + } + + if((sfact!=us->blendSrcFuncRGB) || + (asfact!=us->blendSrcFuncAlpha)) { + us->blendSrcFuncRGB=sfact; + us->blendSrcFuncAlpha=asfact; + fxMesa->new_state |= FX_NEW_BLEND; + ctx->Driver.RenderStart = fxSetupFXUnits; + } + + switch(dfactor) { + case GL_ZERO: + adfact=dfact=GR_BLEND_ZERO; + break; + case GL_ONE: + adfact=dfact=GR_BLEND_ONE; + break; + case GL_SRC_COLOR: + dfact=GR_BLEND_SRC_COLOR; + adfact=GR_BLEND_ZERO; + break; + case GL_ONE_MINUS_SRC_COLOR: + dfact=GR_BLEND_ONE_MINUS_SRC_COLOR; + adfact=GR_BLEND_ZERO; + break; + case GL_SRC_ALPHA: + dfact=GR_BLEND_SRC_ALPHA; + adfact=GR_BLEND_ZERO; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dfact=GR_BLEND_ONE_MINUS_SRC_ALPHA; + adfact=GR_BLEND_ZERO; + break; + case GL_DST_ALPHA: + /* dfact=GR_BLEND_DST_ALPHA; */ + /* We can't do DST_ALPHA */ + dfact=GR_BLEND_ONE; + adfact=GR_BLEND_ZERO; + break; + case GL_ONE_MINUS_DST_ALPHA: + /* dfact=GR_BLEND_ONE_MINUS_DST_ALPHA; */ + /* We can't do DST_ALPHA */ + dfact=GR_BLEND_ZERO; + adfact=GR_BLEND_ZERO; + break; + case GL_SRC_ALPHA_SATURATE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + /* USELESS */ + adfact=dfact=GR_BLEND_ZERO; + break; + default: + adfact=dfact=GR_BLEND_ZERO; + break; + } + + if((dfact!=us->blendDstFuncRGB) || + (adfact!=us->blendDstFuncAlpha)) { + us->blendDstFuncRGB=dfact; + us->blendDstFuncAlpha=adfact; + fxMesa->new_state |= FX_NEW_BLEND; + ctx->Driver.RenderStart = fxSetupFXUnits; + } +} + +static void fxSetupBlend(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxUnitsState *us=&fxMesa->unitsState; + + if(us->blendEnabled) + FX_grAlphaBlendFunction(us->blendSrcFuncRGB,us->blendDstFuncRGB, + us->blendSrcFuncAlpha,us->blendDstFuncAlpha); + else + FX_grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ONE,GR_BLEND_ZERO); +} + +/************************************************************************/ +/************************** Alpha Test SetUp ****************************/ +/************************************************************************/ + +void fxDDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxUnitsState *us=&fxMesa->unitsState; + GrCmpFnc_t newfunc; + + switch(func) { + case GL_NEVER: + newfunc=GR_CMP_NEVER; + break; + case GL_LESS: + newfunc=GR_CMP_LESS; + break; + case GL_EQUAL: + newfunc=GR_CMP_EQUAL; + break; + case GL_LEQUAL: + newfunc=GR_CMP_LEQUAL; + break; + case GL_GREATER: + newfunc=GR_CMP_GREATER; + break; + case GL_NOTEQUAL: + newfunc=GR_CMP_NOTEQUAL; + break; + case GL_GEQUAL: + newfunc=GR_CMP_GEQUAL; + break; + case GL_ALWAYS: + newfunc=GR_CMP_ALWAYS; + break; + default: + fprintf(stderr,"fx Driver: internal error in fxDDAlphaFunc()\n"); + fxCloseHardware(); + exit(-1); + break; + } + + if(newfunc!=us->alphaTestFunc) { + us->alphaTestFunc=newfunc; + fxMesa->new_state |= FX_NEW_ALPHA; + ctx->Driver.RenderStart = fxSetupFXUnits; + } + + if(ctx->Color.AlphaRef!=us->alphaTestRefValue) { + us->alphaTestRefValue=ctx->Color.AlphaRef; + fxMesa->new_state |= FX_NEW_ALPHA; + ctx->Driver.RenderStart = fxSetupFXUnits; + } +} + +static void fxSetupAlphaTest(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxUnitsState *us=&fxMesa->unitsState; + + if(us->alphaTestEnabled) { + FX_grAlphaTestFunction(us->alphaTestFunc); + FX_grAlphaTestReferenceValue(us->alphaTestRefValue); + } else + FX_grAlphaTestFunction(GR_CMP_ALWAYS); +} + +/************************************************************************/ +/************************** Depth Test SetUp ****************************/ +/************************************************************************/ + +void fxDDDepthFunc(GLcontext *ctx, GLenum func) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxUnitsState *us=&fxMesa->unitsState; + GrCmpFnc_t dfunc; + + switch(func) { + case GL_NEVER: + dfunc=GR_CMP_NEVER; + break; + case GL_LESS: + dfunc=GR_CMP_LESS; + break; + case GL_GEQUAL: + dfunc=GR_CMP_GEQUAL; + break; + case GL_LEQUAL: + dfunc=GR_CMP_LEQUAL; + break; + case GL_GREATER: + dfunc=GR_CMP_GREATER; + break; + case GL_NOTEQUAL: + dfunc=GR_CMP_NOTEQUAL; + break; + case GL_EQUAL: + dfunc=GR_CMP_EQUAL; + break; + case GL_ALWAYS: + dfunc=GR_CMP_ALWAYS; + break; + default: + fprintf(stderr,"fx Driver: internal error in fxDDDepthFunc()\n"); + fxCloseHardware(); + exit(-1); + break; + } + + if(dfunc!=us->depthTestFunc) { + us->depthTestFunc=dfunc; + fxMesa->new_state |= FX_NEW_DEPTH; + ctx->Driver.RenderStart = fxSetupFXUnits; + } + +} + +void fxDDDepthMask(GLcontext *ctx, GLboolean flag) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxUnitsState *us=&fxMesa->unitsState; + + if(flag!=us->depthMask) { + us->depthMask=flag; + fxMesa->new_state |= FX_NEW_DEPTH; + ctx->Driver.RenderStart = fxSetupFXUnits; + } +} + +static void fxSetupDepthTest(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxUnitsState *us=&fxMesa->unitsState; + + if (us->depthTestEnabled) { + FX_grDepthBufferFunction(us->depthTestFunc); + FX_grDepthMask(us->depthMask); + } + else { + FX_grDepthBufferFunction(GR_CMP_ALWAYS); + FX_grDepthMask(FXFALSE); + } +} + +/************************************************************************/ +/**************************** Color Mask SetUp **************************/ +/************************************************************************/ + +GLboolean fxDDColorMask(GLcontext *ctx, + GLboolean r, GLboolean g, + GLboolean b, GLboolean a ) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + fxMesa->new_state |= FX_NEW_COLOR_MASK; + ctx->Driver.RenderStart = fxSetupFXUnits; + (void) r; (void) g; (void) b; (void) a; + return GL_FALSE; +} + +static void fxSetupColorMask(GLcontext *ctx) +{ + fxMesaContext fxMesa = FX_CONTEXT(ctx); + + if (ctx->Color.DrawBuffer == GL_NONE) { + FX_grColorMask(FXFALSE, FXFALSE); + } + else { + FX_grColorMask(ctx->Color.ColorMask[RCOMP] || + ctx->Color.ColorMask[GCOMP] || + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer); + } +} + + + + +/************************************************************************/ +/**************************** Fog Mode SetUp ****************************/ +/************************************************************************/ + +/* + * This is called during state update in order to update the Glide fog state. + */ +static void fxSetupFog(GLcontext *ctx) +{ + if (ctx->Fog.Enabled && ctx->FogMode==FOG_FRAGMENT) { + fxMesaContext fxMesa = FX_CONTEXT(ctx); + + /* update fog color */ + GLubyte col[4]; + col[0]=(unsigned int)(255*ctx->Fog.Color[0]); + col[1]=(unsigned int)(255*ctx->Fog.Color[1]); + col[2]=(unsigned int)(255*ctx->Fog.Color[2]); + col[3]=(unsigned int)(255*ctx->Fog.Color[3]); + FX_grFogColorValue(FXCOLOR4(col)); + + if(fxMesa->fogTableMode != ctx->Fog.Mode || + fxMesa->fogDensity != ctx->Fog.Density || + fxMesa->fogStart != ctx->Fog.Start || + fxMesa->fogEnd != ctx->Fog.End) { + /* reload the fog table */ + switch (ctx->Fog.Mode) { + case GL_LINEAR: + guFogGenerateLinear(fxMesa->fogTable, ctx->Fog.Start, ctx->Fog.End); + break; + case GL_EXP: + guFogGenerateExp(fxMesa->fogTable, ctx->Fog.Density); + break; + case GL_EXP2: + guFogGenerateExp2(fxMesa->fogTable, ctx->Fog.Density); + break; + default: + ; + } + fxMesa->fogTableMode = ctx->Fog.Mode; + fxMesa->fogDensity = ctx->Fog.Density; + fxMesa->fogStart = ctx->Fog.Start; + fxMesa->fogEnd = ctx->Fog.End; + } + + FX_grFogTable(fxMesa->fogTable); + FX_grFogMode(GR_FOG_WITH_TABLE); + } + else { + FX_grFogMode(GR_FOG_DISABLE); + } +} + +void fxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params ) +{ + FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG; + ctx->Driver.RenderStart = fxSetupFXUnits; /* XXX why is this here? */ +} + +/************************************************************************/ +/************************** Scissor Test SetUp **************************/ +/************************************************************************/ + +/* This routine is used in managing the lock state, and therefore can't lock */ +void fxSetScissorValues(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + int xmin, xmax; + int ymin, ymax, check; + + if (ctx->Scissor.Enabled) { + xmin=ctx->Scissor.X; + xmax=ctx->Scissor.X+ctx->Scissor.Width; + ymin=ctx->Scissor.Y; + ymax=ctx->Scissor.Y+ctx->Scissor.Height; + check=1; + } else { + xmin=0; + ymin=0; + xmax=fxMesa->width; + ymax=fxMesa->height; + check=0; + } + xmin+=fxMesa->x_offset; + xmax+=fxMesa->x_offset; + ymin+=fxMesa->y_delta; + ymax+=fxMesa->y_delta; + if (xmin<fxMesa->clipMinX) xmin=fxMesa->clipMinX; + if (xmax>fxMesa->clipMaxX) xmax=fxMesa->clipMaxX; + if (ymin<fxMesa->screen_height-fxMesa->clipMaxY) + ymin=fxMesa->screen_height-fxMesa->clipMaxY; + if (ymax>fxMesa->screen_height-fxMesa->clipMinY) + ymax=fxMesa->screen_height-fxMesa->clipMinY; + FX_grClipWindow_NoLock(xmin, ymin, xmax, ymax); +} + +static void fxSetupScissor(GLcontext *ctx) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + if (!fxMesa->needClip) { + BEGIN_BOARD_LOCK(); + fxSetScissorValues(ctx); + END_BOARD_LOCK(); + } +} + +void fxDDScissor( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h ) +{ + FX_CONTEXT(ctx)->new_state |= FX_NEW_SCISSOR; + ctx->Driver.RenderStart = fxSetupFXUnits; +} + +/************************************************************************/ +/*************************** Cull mode setup ****************************/ +/************************************************************************/ + + +void fxDDCullFace(GLcontext *ctx, GLenum mode) +{ + (void) mode; + FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL; + ctx->Driver.RenderStart = fxSetupFXUnits; +} + +void fxDDFrontFace(GLcontext *ctx, GLenum mode) +{ + (void) mode; + FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL; + ctx->Driver.RenderStart = fxSetupFXUnits; +} + + +static void fxSetupCull(GLcontext *ctx) +{ + if (ctx->Polygon.CullFlag) { + switch (ctx->Polygon.CullFaceMode) { + case GL_BACK: + if (ctx->Polygon.FrontFace==GL_CCW) + FX_CONTEXT(ctx)->cullMode=GR_CULL_NEGATIVE; + else + FX_CONTEXT(ctx)->cullMode=GR_CULL_POSITIVE; + break; + case GL_FRONT: + if(ctx->Polygon.FrontFace==GL_CCW) + FX_CONTEXT(ctx)->cullMode=GR_CULL_POSITIVE; + else + FX_CONTEXT(ctx)->cullMode=GR_CULL_NEGATIVE; + break; + case GL_FRONT_AND_BACK: + FX_CONTEXT(ctx)->cullMode=GR_CULL_DISABLE; + break; + default: + break; + } + } else FX_CONTEXT(ctx)->cullMode=GR_CULL_DISABLE; + FX_grCullMode(FX_CONTEXT(ctx)->cullMode); +} + + +/************************************************************************/ +/****************************** DD Enable ******************************/ +/************************************************************************/ + +void fxDDEnable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxUnitsState *us=&fxMesa->unitsState; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDEnable(...)\n"); + } + + switch(cap) { + case GL_ALPHA_TEST: + if(state!=us->alphaTestEnabled) { + us->alphaTestEnabled=state; + fxMesa->new_state |= FX_NEW_ALPHA; + ctx->Driver.RenderStart = fxSetupFXUnits; + } + break; + case GL_BLEND: + if(state!=us->blendEnabled) { + us->blendEnabled=state; + fxMesa->new_state |= FX_NEW_BLEND; + ctx->Driver.RenderStart = fxSetupFXUnits; + } + break; + case GL_DEPTH_TEST: + if(state!=us->depthTestEnabled) { + us->depthTestEnabled=state; + fxMesa->new_state |= FX_NEW_DEPTH; + ctx->Driver.RenderStart = fxSetupFXUnits; + } + break; + case GL_SCISSOR_TEST: + fxMesa->new_state |= FX_NEW_SCISSOR; + ctx->Driver.RenderStart = fxSetupFXUnits; + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + fxDDTexUseGlbPalette(ctx, state); + break; + case GL_FOG: + fxMesa->new_state |= FX_NEW_FOG; + ctx->Driver.RenderStart = fxSetupFXUnits; + break; + case GL_CULL_FACE: + fxMesa->new_state |= FX_NEW_CULL; + ctx->Driver.RenderStart = fxSetupFXUnits; + break; + case GL_LINE_SMOOTH: + case GL_LINE_STIPPLE: + case GL_POINT_SMOOTH: + case GL_POLYGON_SMOOTH: + case GL_TEXTURE_2D: + fxMesa->new_state |= FX_NEW_TEXTURING; + ctx->Driver.RenderStart = fxSetupFXUnits; + break; + default: + ; /* XXX no-op? */ + } +} + +#if 0 +/* + Multipass to do GL_BLEND texture functions + Cf*(1-Ct) has already been written to the buffer during the first pass + Cc*Ct gets written during the second pass (in this function) + Everything gets reset in the third call (in this function) +*/ +static GLboolean fxMultipassBlend(struct vertex_buffer *VB, GLuint pass) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = FX_CONTEXT(ctx); + + switch (pass) { + case 1: + /* Add Cc*Ct */ + fxMesa->restoreUnitsState=fxMesa->unitsState; + if (ctx->Depth.Mask) { + /* We don't want to check or change the depth buffers */ + switch (ctx->Depth.Func) { + case GL_NEVER: + case GL_ALWAYS: + break; + default: + fxDDDepthFunc(ctx, GL_EQUAL); + break; + } + fxDDDepthMask(ctx, FALSE); + } + /* Enable Cc*Ct mode */ + /* XXX Set the Constant Color ? */ + fxDDEnable(ctx, GL_BLEND, GL_TRUE); + fxDDBlendFunc(ctx, XXX, XXX); + fxSetupTextureSingleTMU(ctx, XXX); + fxSetupBlend(ctx); + fxSetupDepthTest(ctx); + break; + + case 2: + /* Reset everything back to normal */ + fxMesa->unitsState = fxMesa->restoreUnitsState; + fxMesa->setupdone &= XXX; + fxSetupTextureSingleTMU(ctx, XXX); + fxSetupBlend(ctx); + fxSetupDepthTest(ctx); + break; + } + + return pass==1; +} +#endif + +/************************************************************************/ +/******************** Fake Multitexture Support *************************/ +/************************************************************************/ + +/* Its considered cheeky to try to fake ARB multitexture by doing + * multipass rendering, because it is not possible to emulate the full + * spec in this way. The fact is that the voodoo 2 supports only a + * subset of the possible multitexturing modes, and it is possible to + * support almost the same subset using multipass blending on the + * voodoo 1. In all other cases for both voodoo 1 and 2, we fall back + * to software rendering, satisfying the spec if not the user. + */ +static GLboolean fxMultipassTexture( struct vertex_buffer *VB, GLuint pass ) +{ + GLcontext *ctx = VB->ctx; + fxVertex *v = FX_DRIVER_DATA(VB)->verts; + fxVertex *last = FX_DRIVER_DATA(VB)->last_vert; + fxMesaContext fxMesa = FX_CONTEXT(ctx); + + switch (pass) { + case 1: + if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_PIPELINE|VERBOSE_TEXTURE)) + fprintf(stderr, "fxmesa: Second texture pass\n"); + + for ( ; v != last ; v++) { + v->f[S0COORD] = v->f[S1COORD]; + v->f[T0COORD] = v->f[T1COORD]; + } + + fxMesa->restoreUnitsState = fxMesa->unitsState; + fxMesa->tmu_source[0] = 1; + + if (ctx->Depth.Mask) { + switch (ctx->Depth.Func) { + case GL_NEVER: + case GL_ALWAYS: + break; + default: + fxDDDepthFunc( ctx, GL_EQUAL ); + break; + } + + fxDDDepthMask( ctx, GL_FALSE ); + } + + if (ctx->Texture.Unit[1].EnvMode == GL_MODULATE) { + fxDDEnable( ctx, GL_BLEND, GL_TRUE ); + fxDDBlendFunc( ctx, GL_DST_COLOR, GL_ZERO ); + } + + fxSetupTextureSingleTMU( ctx, 1 ); + fxSetupBlend( ctx ); + fxSetupDepthTest( ctx ); + break; + + case 2: + /* Restore original state. + */ + fxMesa->tmu_source[0] = 0; + fxMesa->unitsState = fxMesa->restoreUnitsState; + fxMesa->setupdone &= ~SETUP_TMU0; + fxSetupTextureSingleTMU( ctx, 0 ); + fxSetupBlend( ctx ); + fxSetupDepthTest( ctx ); + break; + } + + return pass == 1; +} + + +/************************************************************************/ +/************************** Changes to units state **********************/ +/************************************************************************/ + + +/* All units setup is handled under texture setup. + */ +void fxDDShadeModel(GLcontext *ctx, GLenum mode) +{ + FX_CONTEXT(ctx)->new_state |= FX_NEW_TEXTURING; + ctx->Driver.RenderStart = fxSetupFXUnits; +} + + + +/************************************************************************/ +/****************************** Units SetUp *****************************/ +/************************************************************************/ +static void gl_print_fx_state_flags( const char *msg, GLuint flags ) +{ + fprintf(stderr, + "%s: (0x%x) %s%s%s%s%s%s%s\n", + msg, + flags, + (flags & FX_NEW_TEXTURING) ? "texture, " : "", + (flags & FX_NEW_BLEND) ? "blend, " : "", + (flags & FX_NEW_ALPHA) ? "alpha, " : "", + (flags & FX_NEW_FOG) ? "fog, " : "", + (flags & FX_NEW_SCISSOR) ? "scissor, " : "", + (flags & FX_NEW_COLOR_MASK) ? "colormask, " : "", + (flags & FX_NEW_CULL) ? "cull, " : ""); +} + +void fxSetupFXUnits( GLcontext *ctx ) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint newstate = fxMesa->new_state; + + if (MESA_VERBOSE&VERBOSE_DRIVER) + gl_print_fx_state_flags("fxmesa: fxSetupFXUnits", newstate); + + if (newstate) { + if (newstate & FX_NEW_TEXTURING) + fxSetupTexture(ctx); + + if (newstate & FX_NEW_BLEND) + fxSetupBlend(ctx); + + if (newstate & FX_NEW_ALPHA) + fxSetupAlphaTest(ctx); + + if (newstate & FX_NEW_DEPTH) + fxSetupDepthTest(ctx); + + if (newstate & FX_NEW_FOG) + fxSetupFog(ctx); + + if (newstate & FX_NEW_SCISSOR) + fxSetupScissor(ctx); + + if (newstate & FX_NEW_COLOR_MASK) + fxSetupColorMask(ctx); + + if (newstate & FX_NEW_CULL) + fxSetupCull(ctx); + + fxMesa->new_state = 0; +/* ctx->Driver.RenderStart = 0; */ + } +} + + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_setup(void) +{ + return 0; +} + +#endif /* FX */ diff --git a/xc/extras/Mesa/src/FX/fxstripdet.c b/xc/extras/Mesa/src/FX/fxstripdet.c new file mode 100644 index 000000000..bc21234b6 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxstripdet.c @@ -0,0 +1,164 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif +#if defined(FX) && defined(FX_GLIDE3) + +#include "fxdrv.h" +#include "vbcull.h" + + +#define STRIP0(u,v) ((u1 == v1) && (u2 == v0)) +#define STRIP1(u,v) ((u0 == v0) && (u2 == v1)) + +#define LOCAL_VARS fxVertex* gWin = FX_DRIVER_DATA(VB)->verts; \ + GrVertex** sb = FX_DRIVER_DATA(VB)->strips_b; + +#define STRIPSLOCAL_VAR int sc = 0; + +#define INIT(a) + +#define SENDTRI(u0,u1,u2) FX_grDrawTriangle((GrVertex*)&(gWin[u0].f),(GrVertex*)&(gWin[u1].f),(GrVertex*)&(gWin[u2].f)) +#define FLUSHTRI() /* No-Op */ +#define STARTSTRIPS(u0,u1,u2) { sb[sc++] = (GrVertex*)&(gWin[u0].f); sb[sc++] = (GrVertex*)&(gWin[u1].f); sb[sc++] = (GrVertex*)&(gWin[u2].f); } +#define SENDSTRIPS(v2) { sb[sc++] = (GrVertex*)&(gWin[v2].f); } +#define FLUSHSTRIPS() FX_grDrawVertexArray(GR_TRIANGLE_STRIP,sc,sb) + +#define CLIPPED(a,b,c) 0 +#define CULLED(a,b,c) 0 +#define SENDCLIPTRI(a,b,c) /* NoOp */ + +#define TAG(x) x##_fx + +#include "fxsdettmp.h" + + +/* Clipped but no userclip */ +#define STRIP0(u,v) ((u1 == v1) && (u2 == v0)) && !clipmask[v2] +#define STRIP1(u,v) ((u0 == v0) && (u2 == v1)) && !clipmask[v2] + +#define LOCAL_VARS fxVertex* gWin = FX_DRIVER_DATA(VB)->verts; \ + GrVertex** sb = FX_DRIVER_DATA(VB)->strips_b; \ + const GLubyte *const clipmask = VB->ClipMask; \ + const fxMesaContext fxMesa=(fxMesaContext)VB->ctx->DriverCtx; \ + const tfxTriClipFunc cliptri = fxMesa->clip_tri_stride; + +#define STRIPSLOCAL_VAR int sc = 0; + +#define INIT(a) + +#define SENDTRI(u0,u1,u2) FX_grDrawTriangle((GrVertex*)&(gWin[u0].f),(GrVertex*)&(gWin[u1].f),(GrVertex*)&(gWin[u2].f)) +#define FLUSHTRI() /* No-Op */ +#define STARTSTRIPS(u0,u1,u2) { sb[sc++] = (GrVertex*)&(gWin[u0].f); sb[sc++] = (GrVertex*)&(gWin[u1].f); sb[sc++] = (GrVertex*)&(gWin[u2].f); } +#define SENDSTRIPS(v2) { sb[sc++] = (GrVertex*)&(gWin[v2].f); } +#define FLUSHSTRIPS() FX_grDrawVertexArray(GR_TRIANGLE_STRIP,sc,sb) + +#define CLIPPED(u0,u1,u2) (clipmask[u0] | clipmask[u1] | clipmask[u2]) +#define CULLED(u0,u1,u2) (clipmask[u0] & clipmask[u1] & clipmask[u2]) +#define SENDCLIPTRI(u0,u1,u2) { \ + GLuint vl[3]; \ + ASSIGN_3V(vl, u0, u1, u2 ); \ + cliptri(VB,vl,clipmask[u0] | clipmask[u1] | clipmask[u2]); \ + } + +#define TAG(x) x##_fx_view_clipped + +#include "fxsdettmp.h" + +/* Clipped and might be userclip */ +#define STRIP0(u,v) ((u1 == v1) && (u2 == v0)) && !clipmask[v2] +#define STRIP1(u,v) ((u0 == v0) && (u2 == v1)) && !clipmask[v2] + +#define LOCAL_VARS fxVertex* gWin = FX_DRIVER_DATA(VB)->verts; \ + GrVertex** sb = FX_DRIVER_DATA(VB)->strips_b; \ + const GLubyte *const clipmask = VB->ClipMask; \ + const GLubyte *userclipmask = VB->UserClipMask; \ + const fxMesaContext fxMesa=(fxMesaContext)VB->ctx->DriverCtx; \ + const tfxTriClipFunc cliptri = fxMesa->clip_tri_stride; + +#define STRIPSLOCAL_VAR int sc = 0; + +#define INIT(a) + +#define SENDTRI(u0,u1,u2) FX_grDrawTriangle((GrVertex*)&(gWin[u0].f),(GrVertex*)&(gWin[u1].f),(GrVertex*)&(gWin[u2].f)) +#define FLUSHTRI() /* No-Op */ +#define STARTSTRIPS(u0,u1,u2) { sb[sc++] = (GrVertex*)&(gWin[u0].f); sb[sc++] = (GrVertex*)&(gWin[u1].f); sb[sc++] = (GrVertex*)&(gWin[u2].f); } +#define SENDSTRIPS(v2) { sb[sc++] = (GrVertex*)&(gWin[v2].f); } +#define FLUSHSTRIPS() FX_grDrawVertexArray(GR_TRIANGLE_STRIP,sc,sb) + +#define CLIPPED(u0,u1,u2) (clipmask[u0] | clipmask[u1] | clipmask[u2]) +#define CULLED(u0,u1,u2) (clipmask[u0] & clipmask[u1] & clipmask[u2] & CLIP_ALL_BITS) +#define SENDCLIPTRI(u0,u1,u2) { \ + GLuint vl[3]; \ + GLuint imask = (clipmask[u0] | clipmask[u1] | clipmask[u2]); \ + \ + if (imask & CLIP_USER_BIT) { \ + if (!(userclipmask[u2] & userclipmask[u1] & userclipmask[u0])) \ + { ASSIGN_3V(vl, u2, u1, u0 ); \ + imask |= (userclipmask[u2] | userclipmask[u1] | userclipmask[u0]) << 8; \ + cliptri( VB, vl, imask );} \ + } \ + else { ASSIGN_3V(vl, u2, u1, u0 ); \ + cliptri( VB, vl, imask ); } \ + } + +#define TAG(x) x##_fx_clipped + +#include "fxsdettmp.h" + + +void fxDDRenderInitGlide3(GLcontext *ctx) +{ +#if 0 + render_tab_fx_smooth_indirect[GL_TRIANGLES] = render_vb_triangles_smooth_indirect_sd_fx; + render_tab_fx_smooth_indirect_view_clipped[GL_TRIANGLES] = render_vb_triangles_smooth_indirect_sd_fx_view_clipped; + render_tab_fx_smooth_indirect_clipped[GL_TRIANGLES] = render_vb_triangles_smooth_indirect_sd_fx_clipped; +#endif +} + + +#endif /* defined(FX) && FX_GLIDE3 */ diff --git a/xc/extras/Mesa/src/FX/fxtexman.c b/xc/extras/Mesa/src/FX/fxtexman.c new file mode 100644 index 000000000..2ffaeadd7 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxtexman.c @@ -0,0 +1,747 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* fxtexman.c - 3Dfx VooDoo texture memory functions */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" + +int texSwaps=0; + +#define FX_2MB_SPLIT 0x200000 + +static struct gl_texture_object *fxTMFindOldestObject(fxMesaContext fxMesa, + int tmu); + + +#ifdef TEXSANITY +static void fubar() +{ +} + + /* Sanity Check */ +static void sanity(fxMesaContext fxMesa) +{ + MemRange *tmp, *prev, *pos; + + prev=0; + tmp = fxMesa->tmFree[0]; + while (tmp) { + if (!tmp->startAddr && !tmp->endAddr) { + fprintf(stderr, "Textures fubar\n"); + fubar(); + } + if (tmp->startAddr>=tmp->endAddr) { + fprintf(stderr, "Node fubar\n"); + fubar(); + } + if (prev && (prev->startAddr>=tmp->startAddr || + prev->endAddr>tmp->startAddr)) { + fprintf(stderr, "Sorting fubar\n"); + fubar(); + } + prev=tmp; + tmp=tmp->next; + } + prev=0; + tmp = fxMesa->tmFree[1]; + while (tmp) { + if (!tmp->startAddr && !tmp->endAddr) { + fprintf(stderr, "Textures fubar\n"); + fubar(); + } + if (tmp->startAddr>=tmp->endAddr) { + fprintf(stderr, "Node fubar\n"); + fubar(); + } + if (prev && (prev->startAddr>=tmp->startAddr || + prev->endAddr>tmp->startAddr)) { + fprintf(stderr, "Sorting fubar\n"); + fubar(); + } + prev=tmp; + tmp=tmp->next; + } +} +#endif + +static MemRange *fxTMNewRangeNode(fxMesaContext fxMesa, FxU32 start, FxU32 end) { + MemRange *result=0; + + if (fxMesa->tmPool) { + result=fxMesa->tmPool; + fxMesa->tmPool=fxMesa->tmPool->next; + } else { + if (!(result=MALLOC(sizeof(MemRange)))) { + fprintf(stderr, "fxDriver: out of memory!\n"); + fxCloseHardware(); + exit(-1); + } + } + result->startAddr=start; + result->endAddr=end; + return result; +} + +static void fxTMDeleteRangeNode(fxMesaContext fxMesa, MemRange *range) +{ + range->next=fxMesa->tmPool; + fxMesa->tmPool=range; +} + +static void fxTMUInit(fxMesaContext fxMesa, int tmu) +{ + MemRange *tmn, *last; + FxU32 start,end,blockstart,blockend; + + start=FX_grTexMinAddress(tmu); + end=FX_grTexMaxAddress(tmu); + + if(fxMesa->verbose) { + fprintf(stderr,"Voodoo %s configuration:",(tmu==FX_TMU0) ? "TMU0" : "TMU1"); + fprintf(stderr,"Voodoo Lower texture memory address (%u)\n",(unsigned int)start); + fprintf(stderr,"Voodoo Higher texture memory address (%u)\n",(unsigned int)end); + fprintf(stderr,"Voodoo Splitting Texture memory in 2b blocks:\n"); + } + + fxMesa->freeTexMem[tmu]=end-start; + fxMesa->tmFree[tmu]=NULL; + + last=0; + blockstart=start; + while (blockstart<end) { + if (blockstart+FX_2MB_SPLIT>end) blockend=end; + else blockend=blockstart+FX_2MB_SPLIT; + + if(fxMesa->verbose) + fprintf(stderr,"Voodoo %07u-%07u\n", + (unsigned int)blockstart,(unsigned int)blockend); + + tmn=fxTMNewRangeNode(fxMesa, blockstart, blockend); + tmn->next=0; + + if (last) last->next=tmn; + else fxMesa->tmFree[tmu]=tmn; + last=tmn; + + blockstart+=FX_2MB_SPLIT; + } +} + +static int fxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size) +{ + MemRange *prev, *tmp; + int result; + struct gl_texture_object *obj; + + while (1) { + prev=0; + tmp=fxMesa->tmFree[tmu]; + while (tmp) { + if (tmp->endAddr-tmp->startAddr>=size) { /* Fits here */ + result=tmp->startAddr; + tmp->startAddr+=size; + if (tmp->startAddr==tmp->endAddr) { /* Empty */ + if (prev) { + prev->next=tmp->next; + } else { + fxMesa->tmFree[tmu]=tmp->next; + } + fxTMDeleteRangeNode(fxMesa, tmp); + } + fxMesa->freeTexMem[tmu]-=size; + return result; + } + prev=tmp; + tmp=tmp->next; + } + /* No free space. Discard oldest */ + obj=fxTMFindOldestObject(fxMesa, tmu); + if (!obj) { + fprintf(stderr, "fx Driver: No space for texture\n"); + return -1; + } + fxTMMoveOutTM(fxMesa, obj); + texSwaps++; + } +} + +static void fxTMRemoveRange(fxMesaContext fxMesa, GLint tmu, MemRange *range) +{ + MemRange *tmp, *prev; + + if (range->startAddr==range->endAddr) { + fxTMDeleteRangeNode(fxMesa, range); + return; + } + fxMesa->freeTexMem[tmu]+=range->endAddr-range->startAddr; + prev=0; + tmp=fxMesa->tmFree[tmu]; + while (tmp) { + if (range->startAddr>tmp->startAddr) { + prev=tmp; + tmp=tmp->next; + } else break; + } + /* When we create the regions, we make a split at the 2MB boundary. + Now we have to make sure we don't join those 2MB boundary regions + back together again. */ + range->next=tmp; + if (tmp) { + if (range->endAddr==tmp->startAddr && tmp->startAddr&(FX_2MB_SPLIT-1)) { + /* Combine */ + tmp->startAddr=range->startAddr; + fxTMDeleteRangeNode(fxMesa, range); + range=tmp; + } + } + if (prev) { + if (prev->endAddr==range->startAddr && range->startAddr&(FX_2MB_SPLIT-1)) { + /* Combine */ + prev->endAddr=range->endAddr; + prev->next=range->next; + fxTMDeleteRangeNode(fxMesa, range); + } else prev->next=range; + } else { + fxMesa->tmFree[tmu]=range; + } +} + +static struct gl_texture_object *fxTMFindOldestObject(fxMesaContext fxMesa, + int tmu) +{ + GLuint age, old, lasttime, bindnumber; + tfxTexInfo *info; + struct gl_texture_object *obj, *tmp; + + tmp=fxMesa->glCtx->Shared->TexObjectList; + if (!tmp) return 0; + obj=0; + old=0; + + bindnumber=fxMesa->texBindNumber; + while (tmp) { + info=fxTMGetTexInfo(tmp); + + if (info && info->isInTM && + ((info->whichTMU==tmu) || (info->whichTMU==FX_TMU_BOTH) || + (info->whichTMU==FX_TMU_SPLIT))) { + lasttime=info->lastTimeUsed; + + if (lasttime>bindnumber) + age=bindnumber+(UINT_MAX-lasttime+1); /* TO DO: check wrap around */ + else + age=bindnumber-lasttime; + + if (age>=old) { + old=age; + obj=tmp; + } + } + tmp=tmp->Next; + } + return obj; +} + +static MemRange *fxTMAddObj(fxMesaContext fxMesa, + struct gl_texture_object *tObj, + GLint tmu, int texmemsize) +{ + FxU32 startAddr; + MemRange *range; + + startAddr=fxTMFindStartAddr(fxMesa, tmu, texmemsize); + if (startAddr<0) return 0; + range=fxTMNewRangeNode(fxMesa, startAddr, startAddr+texmemsize); + return range; +} + +/* External Functions */ + +void fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint where) +{ + tfxTexInfo *ti=fxTMGetTexInfo(tObj); + int i,l; + int texmemsize; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxTMMoveInTM(%d)\n",tObj->Name); + } + + fxMesa->stats.reqTexUpload++; + + if (!ti->validated) { + fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> not validated\n"); + fxCloseHardware(); + exit(-1); + } + + if (ti->isInTM) { + if (ti->whichTMU==where) return; + if (where==FX_TMU_SPLIT || ti->whichTMU==FX_TMU_SPLIT) + fxTMMoveOutTM_NoLock(fxMesa, tObj); + else { + if (ti->whichTMU==FX_TMU_BOTH) return; + where=FX_TMU_BOTH; + } + } + + if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_TEXTURE)) { + fprintf(stderr,"fxmesa: downloading %x (%d) in texture memory in %d\n",(GLuint)tObj,tObj->Name,where); + } + + ti->whichTMU=(FxU32)where; + + switch (where) { + case FX_TMU0: + case FX_TMU1: + texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH, + &(ti->info)); + ti->tm[where]=fxTMAddObj(fxMesa, tObj, where, texmemsize); + fxMesa->stats.memTexUpload+=texmemsize; + + for (i=FX_largeLodValue(ti->info), l=ti->minLevel; + i<=FX_smallLodValue(ti->info); + i++,l++) + FX_grTexDownloadMipMapLevel_NoLock(where, + ti->tm[where]->startAddr, + FX_valueToLod(i), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_BOTH, + ti->mipmapLevel[l].data); + break; + case FX_TMU_SPLIT: + texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_ODD, + &(ti->info)); + ti->tm[FX_TMU0]=fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize); + fxMesa->stats.memTexUpload+=texmemsize; + + texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_EVEN, + &(ti->info)); + ti->tm[FX_TMU1]=fxTMAddObj(fxMesa, tObj, FX_TMU1, texmemsize); + fxMesa->stats.memTexUpload+=texmemsize; + + for (i=FX_largeLodValue(ti->info),l=ti->minLevel; + i<=FX_smallLodValue(ti->info); + i++,l++) { + FX_grTexDownloadMipMapLevel_NoLock(GR_TMU0, + ti->tm[FX_TMU0]->startAddr, + FX_valueToLod(i), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_ODD, + ti->mipmapLevel[l].data); + + FX_grTexDownloadMipMapLevel_NoLock(GR_TMU1, + ti->tm[FX_TMU1]->startAddr, + FX_valueToLod(i), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_EVEN, + ti->mipmapLevel[l].data); + } + break; + case FX_TMU_BOTH: + texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH, + &(ti->info)); + ti->tm[FX_TMU0]=fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize); + fxMesa->stats.memTexUpload+=texmemsize; + + texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH, + &(ti->info)); + ti->tm[FX_TMU1]=fxTMAddObj(fxMesa, tObj, FX_TMU1, texmemsize); + fxMesa->stats.memTexUpload+=texmemsize; + + for (i=FX_largeLodValue(ti->info),l=ti->minLevel; + i<=FX_smallLodValue(ti->info); + i++,l++) { + FX_grTexDownloadMipMapLevel_NoLock(GR_TMU0, + ti->tm[FX_TMU0]->startAddr, + FX_valueToLod(i), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_BOTH, + ti->mipmapLevel[l].data); + + FX_grTexDownloadMipMapLevel_NoLock(GR_TMU1, + ti->tm[FX_TMU1]->startAddr, + FX_valueToLod(i), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_BOTH, + ti->mipmapLevel[l].data); + } + break; + default: + fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> wrong tmu (%d)\n",where); + fxCloseHardware(); + exit(-1); + } + + fxMesa->stats.texUpload++; + + ti->isInTM=GL_TRUE; +} + +void fxTMMoveInTM(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint where) { + BEGIN_BOARD_LOCK(); + fxTMMoveInTM_NoLock(fxMesa, tObj, where); + END_BOARD_LOCK(); +} + +void fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint level) +{ + tfxTexInfo *ti=fxTMGetTexInfo(tObj); + GrLOD_t lodlevel; + GLint tmu; + + if (!ti->validated) { + fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> not validated\n"); + fxCloseHardware(); + exit(-1); + } + + tmu=(int)ti->whichTMU; + fxTMMoveInTM(fxMesa, tObj, tmu); + + fxTexGetInfo(ti->mipmapLevel[0].width,ti->mipmapLevel[0].height, + &lodlevel, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + +#ifdef FX_GLIDE3 + lodlevel-=level; +#else + lodlevel+=level; +#endif + switch(tmu) { + case FX_TMU0: + case FX_TMU1: + FX_grTexDownloadMipMapLevel(tmu, + ti->tm[tmu]->startAddr, + FX_valueToLod(FX_lodToValue(lodlevel)), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_BOTH, + ti->mipmapLevel[level].data); + break; + case FX_TMU_SPLIT: + FX_grTexDownloadMipMapLevel(GR_TMU0, + ti->tm[GR_TMU0]->startAddr, + FX_valueToLod(FX_lodToValue(lodlevel)), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_ODD, + ti->mipmapLevel[level].data); + + FX_grTexDownloadMipMapLevel(GR_TMU1, + ti->tm[GR_TMU1]->startAddr, + FX_valueToLod(FX_lodToValue(lodlevel)), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_EVEN, + ti->mipmapLevel[level].data); + break; + case FX_TMU_BOTH: + FX_grTexDownloadMipMapLevel(GR_TMU0, + ti->tm[GR_TMU0]->startAddr, + FX_valueToLod(FX_lodToValue(lodlevel)), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_BOTH, + ti->mipmapLevel[level].data); + + FX_grTexDownloadMipMapLevel(GR_TMU1, + ti->tm[GR_TMU1]->startAddr, + FX_valueToLod(FX_lodToValue(lodlevel)), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_BOTH, + ti->mipmapLevel[level].data); + break; + + default: + fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> wrong tmu (%d)\n",tmu); + fxCloseHardware(); + exit(-1); + } +} + +void fxTMReloadSubMipMapLevel(fxMesaContext fxMesa, + struct gl_texture_object *tObj, + GLint level, GLint yoffset, GLint height) +{ + tfxTexInfo *ti=fxTMGetTexInfo(tObj); + GrLOD_t lodlevel; + unsigned short *data; + GLint tmu; + + if(!ti->validated) { + fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> not validated\n"); + fxCloseHardware(); + exit(-1); + } + + tmu=(int)ti->whichTMU; + fxTMMoveInTM(fxMesa, tObj, tmu); + + fxTexGetInfo(ti->mipmapLevel[0].width, ti->mipmapLevel[0].height, + &lodlevel, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + if((ti->info.format==GR_TEXFMT_INTENSITY_8) || + (ti->info.format==GR_TEXFMT_P_8) || + (ti->info.format==GR_TEXFMT_ALPHA_8)) + data=ti->mipmapLevel[level].data+((yoffset*ti->mipmapLevel[level].width)>>1); + else + data=ti->mipmapLevel[level].data+yoffset*ti->mipmapLevel[level].width; + + switch(tmu) { + case FX_TMU0: + case FX_TMU1: + FX_grTexDownloadMipMapLevelPartial(tmu, + ti->tm[tmu]->startAddr, + FX_valueToLod(FX_lodToValue(lodlevel)+level), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_BOTH, + data, + yoffset,yoffset+height-1); + break; + case FX_TMU_SPLIT: + FX_grTexDownloadMipMapLevelPartial(GR_TMU0, + ti->tm[FX_TMU0]->startAddr, + FX_valueToLod(FX_lodToValue(lodlevel)+level), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_ODD, + data, + yoffset,yoffset+height-1); + + FX_grTexDownloadMipMapLevelPartial(GR_TMU1, + ti->tm[FX_TMU1]->startAddr, + FX_valueToLod(FX_lodToValue(lodlevel)+level), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_EVEN, + data, + yoffset,yoffset+height-1); + break; + case FX_TMU_BOTH: + FX_grTexDownloadMipMapLevelPartial(GR_TMU0, + ti->tm[FX_TMU0]->startAddr, + FX_valueToLod(FX_lodToValue(lodlevel)+level), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_BOTH, + data, + yoffset,yoffset+height-1); + + FX_grTexDownloadMipMapLevelPartial(GR_TMU1, + ti->tm[FX_TMU1]->startAddr, + FX_valueToLod(FX_lodToValue(lodlevel)+level), + FX_largeLodLog2(ti->info), + FX_aspectRatioLog2(ti->info), + ti->info.format, + GR_MIPMAPLEVELMASK_BOTH, + data, + yoffset,yoffset+height-1); + break; + default: + fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> wrong tmu (%d)\n",tmu); + fxCloseHardware(); + exit(-1); + } +} + +void fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj) +{ + tfxTexInfo *ti=fxTMGetTexInfo(tObj); + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxTMMoveOutTM(%x (%d))\n",(GLuint)tObj,tObj->Name); + } + + if (!ti->isInTM) return; + + switch(ti->whichTMU) { + case FX_TMU0: + case FX_TMU1: + fxTMRemoveRange(fxMesa, (int)ti->whichTMU, ti->tm[ti->whichTMU]); + break; + case FX_TMU_SPLIT: + case FX_TMU_BOTH: + fxTMRemoveRange(fxMesa, FX_TMU0, ti->tm[FX_TMU0]); + fxTMRemoveRange(fxMesa, FX_TMU1, ti->tm[FX_TMU1]); + break; + default: + fprintf(stderr,"fx Driver: internal error in fxTMMoveOutTM()\n"); + fxCloseHardware(); + exit(-1); + } + + ti->isInTM=GL_FALSE; + ti->whichTMU=FX_TMU_NONE; +} + +void fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj) +{ + tfxTexInfo *ti=fxTMGetTexInfo(tObj); + int i; + + fxTMMoveOutTM(fxMesa, tObj); + + for (i=0; i<MAX_TEXTURE_LEVELS; i++) { + if (ti->mipmapLevel[i].data) { + FREE(ti->mipmapLevel[i].data); + ti->mipmapLevel[i].data = NULL; + } + } + switch (ti->whichTMU) { + case FX_TMU0: + case FX_TMU1: + fxTMDeleteRangeNode(fxMesa, ti->tm[ti->whichTMU]); + break; + case FX_TMU_SPLIT: + case FX_TMU_BOTH: + fxTMDeleteRangeNode(fxMesa, ti->tm[FX_TMU0]); + fxTMDeleteRangeNode(fxMesa, ti->tm[FX_TMU1]); + break; + } +} + +void fxTMInit(fxMesaContext fxMesa) +{ + fxMesa->texBindNumber=0; + fxMesa->tmPool=0; + + fxTMUInit(fxMesa,FX_TMU0); + + if(fxMesa->haveTwoTMUs) + fxTMUInit(fxMesa,FX_TMU1); +} + +void fxTMClose(fxMesaContext fxMesa) +{ + MemRange *tmp, *next; + + tmp=fxMesa->tmPool; + while (tmp) { + next=tmp->next; + FREE(tmp); + tmp=next; + } + tmp=fxMesa->tmFree[FX_TMU0]; + while (tmp) { + next=tmp->next; + FREE(tmp); + tmp=next; + } + if (fxMesa->haveTwoTMUs) { + tmp=fxMesa->tmFree[FX_TMU1]; + while (tmp) { + next=tmp->next; + FREE(tmp); + tmp=next; + } + } +} + +void +fxTMRestoreTextures_NoLock(fxMesaContext ctx) { + tfxTexInfo *ti; + struct gl_texture_object *tObj; + int i, where; + + tObj=ctx->glCtx->Shared->TexObjectList; + while (tObj) { + ti=fxTMGetTexInfo(tObj); + if (ti && ti->isInTM) { + for (i=0; i<MAX_TEXTURE_UNITS; i++) + if (ctx->glCtx->Texture.Unit[i].Current==tObj) { + /* Force the texture onto the board, as it could be in use */ + where=ti->whichTMU; + fxTMMoveOutTM_NoLock(ctx, tObj); + fxTMMoveInTM_NoLock(ctx, tObj, where); + break; + } + if (i==MAX_TEXTURE_UNITS) /* Mark the texture as off the board */ + fxTMMoveOutTM_NoLock(ctx, tObj); + } + tObj=tObj->Next; + } +} + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_texman(void) +{ + return 0; +} + +#endif /* FX */ diff --git a/xc/extras/Mesa/src/FX/fxtrifuncs.c b/xc/extras/Mesa/src/FX/fxtrifuncs.c new file mode 100644 index 000000000..4b349b31b --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxtrifuncs.c @@ -0,0 +1,372 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* fxtris.c - 3Dfx VooDoo triangle functions */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" +#include "../mmath.h" + + + +/* Is this enough? Do we need more triangle funcs? + */ +static triangle_func tri_tab[0x40]; /* only 0x20 actually used */ +static quad_func quad_tab[0x40]; /* only 0x20 actually used */ +static line_func line_tab[0x40]; /* less than 0x20 used */ +static points_func points_tab[0x40]; /* less than 0x20 used */ + +#define IND (0) +#define TAG(x) x +#include "fxtritmp.h" + +#define IND (FX_OFFSET) +#define TAG(x) x##_offset +#include "fxtritmp.h" + +#define IND (FX_TWOSIDE) +#define TAG(x) x##_twoside +#include "fxtritmp.h" + +#define IND (FX_TWOSIDE|FX_OFFSET) +#define TAG(x) x##_twoside_offset +#include "fxtritmp.h" + +#define IND (FX_FRONT_BACK) +#define TAG(x) x##_front_back +#include "fxtritmp.h" + +#define IND (FX_FRONT_BACK|FX_OFFSET) +#define TAG(x) x##_front_back_offset +#include "fxtritmp.h" + +#define IND (FX_FRONT_BACK|FX_TWOSIDE) +#define TAG(x) x##_front_back_twoside +#include "fxtritmp.h" + +#define IND (FX_FRONT_BACK|FX_TWOSIDE|FX_OFFSET) +#define TAG(x) x##_front_back_twoside_offset +#include "fxtritmp.h" + +#define IND (FX_FLAT) +#define TAG(x) x##_flat +#include "fxtritmp.h" + +#define IND (FX_FLAT|FX_OFFSET) +#define TAG(x) x##_flat_offset +#include "fxtritmp.h" + +#define IND (FX_FLAT|FX_TWOSIDE) +#define TAG(x) x##_flat_twoside +#include "fxtritmp.h" + +#define IND (FX_FLAT|FX_TWOSIDE|FX_OFFSET) +#define TAG(x) x##_flat_twoside_offset +#include "fxtritmp.h" + +#define IND (FX_FLAT|FX_FRONT_BACK) +#define TAG(x) x##_flat_front_back +#include "fxtritmp.h" + +#define IND (FX_FLAT|FX_FRONT_BACK|FX_OFFSET) +#define TAG(x) x##_flat_front_back_offset +#include "fxtritmp.h" + +#define IND (FX_FLAT|FX_FRONT_BACK|FX_TWOSIDE) +#define TAG(x) x##_flat_front_back_twoside +#include "fxtritmp.h" + +#define IND (FX_FLAT|FX_FRONT_BACK|FX_TWOSIDE|FX_OFFSET) +#define TAG(x) x##_flat_front_back_twoside_offset +#include "fxtritmp.h" + +/* We don't actually do antialiasing correctly. Geometry has to be + sorted for glide's antialiasing to operate */ +#if 0 +#define IND (FX_ANTIALIAS) +#define TAG(x) x##_aa +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_OFFSET) +#define TAG(x) x##_aa_offset +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_TWOSIDE) +#define TAG(x) x##_aa_twoside +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_TWOSIDE|FX_OFFSET) +#define TAG(x) x##_aa_twoside_offset +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FRONT_BACK) +#define TAG(x) x##_aa_front_back +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FRONT_BACK|FX_OFFSET) +#define TAG(x) x##_aa_front_back_offset +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FRONT_BACK|FX_TWOSIDE) +#define TAG(x) x##_aa_front_back_twoside +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FRONT_BACK|FX_TWOSIDE|FX_OFFSET) +#define TAG(x) x##_aa_front_back_twoside_offset +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FLAT) +#define TAG(x) x##_aa_flat +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FLAT|FX_OFFSET) +#define TAG(x) x##_aa_flat_offset +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FLAT|FX_TWOSIDE) +#define TAG(x) x##_aa_flat_twoside +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FLAT|FX_TWOSIDE|FX_OFFSET) +#define TAG(x) x##_aa_flat_twoside_offset +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FLAT|FX_FRONT_BACK) +#define TAG(x) x##_aa_flat_front_back +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FLAT|FX_FRONT_BACK|FX_OFFSET) +#define TAG(x) x##_aa_flat_front_back_offset +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FLAT|FX_FRONT_BACK|FX_TWOSIDE) +#define TAG(x) x##_aa_flat_front_back_twoside +#include "fxtritmp.h" + +#define IND (FX_ANTIALIAS|FX_FLAT|FX_FRONT_BACK|FX_TWOSIDE|FX_OFFSET) +#define TAG(x) x##_aa_flat_front_back_twoside_offset +#include "fxtritmp.h" +#endif + +void fxDDTrifuncInit() +{ + init(); + init_offset(); + init_twoside(); + init_twoside_offset(); + init_front_back(); + init_front_back_offset(); + init_front_back_twoside(); + init_front_back_twoside_offset(); + init_flat(); + init_flat_offset(); + init_flat_twoside(); + init_flat_twoside_offset(); + init_flat_front_back(); + init_flat_front_back_offset(); + init_flat_front_back_twoside(); + init_flat_front_back_twoside_offset(); +#if 0 + init_aa(); + init_aa_offset(); + init_aa_twoside(); + init_aa_twoside_offset(); + init_aa_front_back(); + init_aa_front_back_offset(); + init_aa_front_back_twoside(); + init_aa_front_back_twoside_offset(); + init_aa_flat(); + init_aa_flat_offset(); + init_aa_flat_twoside(); + init_aa_flat_twoside_offset(); + init_aa_flat_front_back(); + init_aa_flat_front_back_offset(); + init_aa_flat_front_back_twoside(); + init_aa_flat_front_back_twoside_offset(); +#endif +} + +void fxPrintRenderState( const char *msg, GLuint state ) +{ + fprintf(stderr, "%s: (%x) %s%s%s%s%s%s\n", + msg, state, + (state & FX_ANTIALIAS) ? "antialias, " : "", + (state & FX_FLAT) ? "flat, " : "", + (state & FX_TWOSIDE) ? "twoside, " : "", + (state & FX_OFFSET) ? "offset, " : "", + (state & FX_FRONT_BACK) ? "front-back, " : "", + (state & FX_FALLBACK) ? "fallback" : ""); +} + + +void fxPrintHintState( const char *msg, GLuint state ) +{ + fprintf(stderr, "%s: (%x) %s %s%s %s%s\n", + msg, state, + (state & GR_STWHINT_W_DIFF_FBI) ? "w-fbi, " : "", + (state & GR_STWHINT_W_DIFF_TMU0) ? "w-tmu0, " : "", + (state & GR_STWHINT_ST_DIFF_TMU0) ? "st-tmu0, " : "", + (state & GR_STWHINT_W_DIFF_TMU1) ? "w-tmu1, " : "", + (state & GR_STWHINT_ST_DIFF_TMU1) ? "st-tmu1, " : ""); + +} + + +void fxDDChooseRenderState( GLcontext *ctx ) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + GLuint ind = 0; + GLuint flags = ctx->TriangleCaps; + + ctx->IndirectTriangles &= ~DD_SW_RASTERIZE; + + if (flags) { + if (fxMesa->render_index & FX_OFFSET) + FX_grDepthBiasLevel(0); + + if (flags & (DD_SELECT|DD_FEEDBACK)) { + fxMesa->PointsFunc = 0; + fxMesa->LineFunc = 0; + fxMesa->TriangleFunc = 0; + fxMesa->QuadFunc = 0; + fxMesa->render_index = FX_FALLBACK; + ctx->IndirectTriangles |= DD_SW_RASTERIZE; +#if 0 + fprintf(stderr, "Fallback select|feeback\n"); +#endif + return; + } + + if (flags & DD_FLATSHADE) ind |= FX_FLAT; + if (flags & DD_TRI_LIGHT_TWOSIDE) ind |= FX_TWOSIDE; + if (flags & DD_MULTIDRAW) ind |= FX_FRONT_BACK; + if (flags & (DD_POINT_ATTEN|DD_POINT_SMOOTH)) { + ind |= FX_FALLBACK; +#if 0 + if (flags&DD_POINT_ATTEN) + fprintf(stderr, "Fallback point atten\n"); + if (flags&DD_POINT_SMOOTH) + fprintf(stderr, "Fallback point smooth\n"); +#endif + } + + fxMesa->render_index = ind; + fxMesa->PointsFunc = points_tab[ind]; + if (ind&FX_FALLBACK) + ctx->IndirectTriangles |= DD_POINT_SW_RASTERIZE; + ind &= ~(FX_ANTIALIAS|FX_FALLBACK); + + if (flags & (DD_LINE_STIPPLE|DD_LINE_SMOOTH)) { + ind |= FX_FALLBACK; +#if 0 + if (flags&DD_LINE_STIPPLE) + fprintf(stderr, "Fallback line stipple\n"); + if (flags&DD_LINE_SMOOTH) + fprintf(stderr, "Fallback line smooth\n"); +#endif + } + + fxMesa->render_index |= ind; + fxMesa->LineFunc = line_tab[ind]; + if (ind&FX_FALLBACK) + ctx->IndirectTriangles |= DD_LINE_SW_RASTERIZE; + ind &= ~(FX_ANTIALIAS|FX_FALLBACK); + + if (flags & DD_TRI_OFFSET) ind |= FX_OFFSET; + if (flags & (DD_TRI_UNFILLED|DD_TRI_STIPPLE|DD_TRI_SMOOTH)) { + ind |= FX_FALLBACK; +#if 0 + if (flags&DD_TRI_UNFILLED) + fprintf(stderr, "Fallback tri unfilled\n"); + if (flags&DD_TRI_STIPPLE) + fprintf(stderr, "Fallback tri stippled\n"); + if (flags&DD_TRI_SMOOTH) + fprintf(stderr, "Fallback tri smooth\n"); +#endif + } + + fxMesa->render_index |= ind; + fxMesa->TriangleFunc = tri_tab[ind]; + fxMesa->QuadFunc = quad_tab[ind]; + + if (ind&FX_FALLBACK) + ctx->IndirectTriangles |= DD_TRI_SW_RASTERIZE | DD_QUAD_SW_RASTERIZE; + } + else if (fxMesa->render_index) + { + if (fxMesa->render_index & FX_OFFSET) + FX_grDepthBiasLevel(0); + + fxMesa->render_index = 0; + fxMesa->PointsFunc = points_tab[0]; + fxMesa->LineFunc = line_tab[0]; + fxMesa->TriangleFunc = tri_tab[0]; + fxMesa->QuadFunc = quad_tab[0]; + } + + if (MESA_VERBOSE&(VERBOSE_STATE|VERBOSE_DRIVER)) + fxPrintRenderState("fxmesa: Render state", fxMesa->render_index); +} + +#else + + +/* + * Need this to provide at least one external definition. + */ + +extern int gl_fx_dummy_function_tris(void); +int gl_fx_dummy_function_tris(void) +{ + return 0; +} + +#endif /* FX */ diff --git a/xc/extras/Mesa/src/FX/fxtritmp.h b/xc/extras/Mesa/src/FX/fxtritmp.h new file mode 100644 index 000000000..9e59b4fc7 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxtritmp.h @@ -0,0 +1,475 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +static void TAG(fx_tri)(GLcontext *ctx, GLuint e1, GLuint e2, GLuint e3, GLuint pv) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + struct vertex_buffer *VB=ctx->VB; + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + GrVertex *v1 = (GrVertex *)gWin[e1].f; + GrVertex *v2 = (GrVertex *)gWin[e2].f; + GrVertex *v3 = (GrVertex *)gWin[e3].f; + + (void) fxMesa; + + if (IND & (FX_TWOSIDE|FX_OFFSET)) + { + GLfloat ex = v1->x - v3->x; + GLfloat ey = v1->y - v3->y; + GLfloat fx = v2->x - v3->x; + GLfloat fy = v2->y - v3->y; + GLfloat c = ex*fy-ey*fx; + + if (IND & FX_TWOSIDE) { + GLuint facing = (c<0.0) ^ ctx->Polygon.FrontBit; + GLubyte (*color)[4] = VB->Color[facing]->data; + if (IND & FX_FLAT) { + GOURAUD2(v1,color[pv]); + GOURAUD2(v2,color[pv]); + GOURAUD2(v3,color[pv]); + } else { + GOURAUD2(v1,color[e1]); + GOURAUD2(v2,color[e2]); + GOURAUD2(v3,color[e3]); + } + } + + /* Should apply a factor to ac to compensate for different x/y + * scaling introduced in the Viewport matrix. + * + * The driver should supply scaling factors for 'factor' and 'units'. + */ + if (IND & FX_OFFSET) { + GLfloat offset = ctx->Polygon.OffsetUnits; + + if (c * c > 1e-16) { + GLfloat factor = ctx->Polygon.OffsetFactor; + GLfloat ez = v1->ooz - v3->ooz; + GLfloat fz = v2->ooz - v3->ooz; + GLfloat a = ey*fz-ez*fy; + GLfloat b = ez*fx-ex*fz; + GLfloat ic = 1.0 / c; + GLfloat ac = a * ic; + GLfloat bc = b * ic; + if (ac<0.0F) ac = -ac; + if (bc<0.0F) bc = -bc; + offset += MAX2( ac, bc ) * factor; + } + /* Probably a lot quicker just to nudge the z values and put + * them back afterwards. + */ + FX_grDepthBiasLevel((int)offset); + } + } + else if (IND & FX_FLAT) { + GLubyte (*color)[4] = VB->Color[0]->data; + GOURAUD2(v1,color[pv]); + GOURAUD2(v2,color[pv]); + GOURAUD2(v3,color[pv]); + } + + if (IND & FX_FRONT_BACK) { + FX_grColorMask(ctx->Color.ColorMask[RCOMP] || + ctx->Color.ColorMask[GCOMP] || + ctx->Color.ColorMask[BCOMP], + FXFALSE); + + FX_grDepthMask(FXFALSE); + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + } + + if (IND & FX_ANTIALIAS) + FX_grAADrawTriangle(v1, v2, v3, FXTRUE, FXTRUE, FXTRUE); + else + FX_grDrawTriangle(v1, v2, v3); + + /* Might be quicker to do two passes, one for each buffer? + */ + if (IND & FX_FRONT_BACK) { + FX_grColorMask(ctx->Color.ColorMask[RCOMP] || + ctx->Color.ColorMask[GCOMP] || + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer); + + if(ctx->Depth.Mask) FX_grDepthMask(FXTRUE); + + FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER); + + if (IND & FX_ANTIALIAS) + FX_grAADrawTriangle(v1,v2,v3, FXTRUE,FXTRUE,FXTRUE); + else + FX_grDrawTriangle(v1, v2, v3); + } +} + + +/* Not worth the space? + */ +static void TAG(fx_quad)(GLcontext *ctx, GLuint e1, GLuint e2, GLuint e3, + GLuint e4, GLuint pv) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + struct vertex_buffer *VB=ctx->VB; + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + GrVertex *v1 = (GrVertex *)gWin[e1].f; + GrVertex *v2 = (GrVertex *)gWin[e2].f; + GrVertex *v3 = (GrVertex *)gWin[e3].f; + GrVertex *v4 = (GrVertex *)gWin[e4].f; + + (void) fxMesa; + + if (IND & (FX_TWOSIDE|FX_OFFSET)) + { + GLfloat ex = v3->x - v1->x; + GLfloat ey = v3->y - v1->y; + GLfloat fx = v4->x - v2->x; + GLfloat fy = v4->y - v2->y; + GLfloat c = ex*fy-ey*fx; + + if (IND & FX_TWOSIDE) { + GLuint facing = (c<0.0) ^ ctx->Polygon.FrontBit; + GLubyte (*color)[4] = VB->Color[facing]->data; + if (IND & FX_FLAT) { + GOURAUD2(v1,color[pv]); + GOURAUD2(v2,color[pv]); + GOURAUD2(v3,color[pv]); + GOURAUD2(v4,color[pv]); + } else { + GOURAUD2(v1,color[e1]); + GOURAUD2(v2,color[e2]); + GOURAUD2(v3,color[e3]); + GOURAUD2(v4,color[e4]); + } + } + + /* Should apply a factor to ac to compensate for different x/y + * scaling introduced in the Viewport matrix. + * + * The driver should supply scaling factors for 'factor' and 'units'. + */ + if (IND & FX_OFFSET) { + GLfloat offset = ctx->Polygon.OffsetUnits; + + if (c * c > 1e-16) { + GLfloat factor = ctx->Polygon.OffsetFactor; + GLfloat ez = v3->ooz - v1->ooz; + GLfloat fz = v4->ooz - v2->ooz; + GLfloat a = ey*fz-ez*fy; + GLfloat b = ez*fx-ex*fz; + GLfloat ic = 1.0 / c; + GLfloat ac = a * ic; + GLfloat bc = b * ic; + if (ac<0.0F) ac = -ac; + if (bc<0.0F) bc = -bc; + offset += MAX2( ac, bc ) * factor; + } + /* Probably a lot quicker just to nudge the z values and put + * them back afterwards. + */ + FX_grDepthBiasLevel((int)offset); + } + } + else if (IND & FX_FLAT) { + GLubyte (*color)[4] = VB->Color[0]->data; + GOURAUD2(v1,color[pv]); + GOURAUD2(v2,color[pv]); + GOURAUD2(v3,color[pv]); + GOURAUD2(v4,color[pv]); + } + + if (IND & FX_FRONT_BACK) { + FX_grColorMask(ctx->Color.ColorMask[RCOMP] || + ctx->Color.ColorMask[GCOMP] || + ctx->Color.ColorMask[BCOMP], + FXFALSE); + + FX_grDepthMask(FXFALSE); + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + } + + if (IND & FX_ANTIALIAS) { + FX_grAADrawTriangle(v1, v2, v4, FXTRUE, FXTRUE, FXTRUE); + FX_grAADrawTriangle(v2, v3, v4, FXTRUE, FXTRUE, FXTRUE); + } else { + FX_grDrawTriangle(v1, v2, v4); + FX_grDrawTriangle(v2, v3, v4); + } + + /* Might be quicker to do two passes, one for each buffer? + */ + if (IND & FX_FRONT_BACK) { + FX_grColorMask(ctx->Color.ColorMask[RCOMP] || + ctx->Color.ColorMask[GCOMP] || + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer); + + if(ctx->Depth.Mask) FX_grDepthMask(FXTRUE); + + FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER); + + if (IND & FX_ANTIALIAS) { + FX_grAADrawTriangle(v1, v2, v4, FXTRUE, FXTRUE, FXTRUE); + FX_grAADrawTriangle(v2, v3, v4, FXTRUE, FXTRUE, FXTRUE); + } else { + FX_grDrawTriangle(v1, v2, v4); + FX_grDrawTriangle(v2, v3, v4); + } + } +} + +#define DRAW_LINE(tmp0, tmp1, width) \ + do { \ + const float xoff = 0.125, yoff = 0.125; \ + GrVertex verts[4]; \ + float dx, dy, wx, wy; \ + \ + dx = tmp0->x - tmp1->x; \ + dy = tmp0->y - tmp1->y; \ + \ + if (dx * dx > dy * dy) { \ + wx = 0; \ + wy = width; \ + } else { \ + wx = width; \ + wy = 0; \ + } \ + \ + verts[0] = *tmp0; \ + verts[1] = *tmp0; \ + verts[2] = *tmp1; \ + verts[3] = *tmp1; \ + \ + verts[0].x = tmp0->x - wx + xoff; \ + verts[0].y = tmp0->y - wy + yoff; \ + \ + verts[1].x = tmp0->x + wx + xoff; \ + verts[1].y = tmp0->y + wy + yoff; \ + \ + verts[2].x = tmp1->x + wx + xoff; \ + verts[2].y = tmp1->y + wy + yoff; \ + \ + verts[3].x = tmp1->x - wx + xoff; \ + verts[3].y = tmp1->y - wy + yoff; \ + \ + FX_grDrawPolygonVertexList(4, verts); \ + } while (0) + +#if (IND & FX_OFFSET) == 0 +static void TAG(fx_line)(GLcontext *ctx, GLuint e1, GLuint e2, GLuint pv) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + struct vertex_buffer *VB=ctx->VB; + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + GLubyte (* const color)[4] = VB->ColorPtr->data; + GrVertex *v1 = (GrVertex *)gWin[e1].f; + GrVertex *v2 = (GrVertex *)gWin[e2].f; + GLfloat w = ctx->Line.Width*.5; + + if (IND & FX_FLAT) + { + /* Flat shading seems broke. Explicitly set vertex colors to same color */ + GOURAUD2(v1,color[pv]); + GOURAUD2(v2,color[pv]); + } + else if (IND & FX_TWOSIDE) + { + /* XXX use signed area of the polygon to determine front/back color choice */ + GOURAUD2(v1,color[e1]); + GOURAUD2(v2,color[e2]); + } + + if (IND & FX_FRONT_BACK) { + FX_grColorMask(ctx->Color.ColorMask[RCOMP] || + ctx->Color.ColorMask[GCOMP] || + ctx->Color.ColorMask[BCOMP], + FXFALSE); + FX_grDepthMask(FXFALSE); + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + } + + if (IND & FX_ANTIALIAS) + FX_grAADrawLine(v1,v2); + else + DRAW_LINE(v1,v2,w); + + if (IND & FX_FRONT_BACK) + { + FX_grColorMask(ctx->Color.ColorMask[RCOMP] || + ctx->Color.ColorMask[GCOMP] || + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer); + + if(ctx->Depth.Mask) + FX_grDepthMask(FXTRUE); + + FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER); + + if (IND & FX_ANTIALIAS) + FX_grAADrawLine(v1,v2); + else + DRAW_LINE(v1,v2,w); + } +} +#endif + + +#if (IND & FX_OFFSET) == 0 + +#if IND & FX_FLAT +# if IND & FX_ANTIALIAS +#if FX_USE_PARGB +# define FLAT_COLOR(x,y) GET_PA(gWin[i].f) = y[3]; +#else +# define FLAT_COLOR(x,y) gWin[i].f[ACOORD] = y[3]; \ + FX_VB_COLOR(x, y) +#endif +# else +# define FLAT_COLOR(x,y) FX_VB_COLOR(x, y) +# endif +#else +#define FLAT_COLOR(x,y) +#endif + + +#define DRAW_POINT(i, sz) \ + do { \ + GrVertex verts[4], *tmp; \ + \ + tmp = (GrVertex*)gWin[i].f; \ + verts[0] = *tmp; \ + verts[1] = *tmp; \ + verts[2] = *tmp; \ + verts[3] = *tmp; \ + verts[0].x = verts[3].x = tmp->x + sz; \ + verts[0].y = verts[1].y = tmp->y + sz; \ + verts[2].x = verts[1].x = tmp->x - sz; \ + verts[2].y = verts[3].y = tmp->y - sz; \ + \ + FX_grDrawPolygonVertexList(4, verts); \ + } while (0) + +static void TAG(fx_points)(GLcontext *ctx, GLuint first, GLuint last) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + struct vertex_buffer *VB = ctx->VB; + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + GLubyte (*color)[4] = VB->ColorPtr->data; + GLuint i; + GLfloat sz = ctx->Point.Size * .5; + + (void) color; (void) fxMesa; + + if (IND & FX_FRONT_BACK) { + FX_grColorMask(ctx->Color.ColorMask[RCOMP] || + ctx->Color.ColorMask[GCOMP] || + ctx->Color.ColorMask[BCOMP], + FXFALSE); + + FX_grDepthMask(FXFALSE); + FX_grRenderBuffer(GR_BUFFER_BACKBUFFER); + } + + if(!VB->ClipOrMask) { + for(i=first;i<=last;i++) { + FLAT_COLOR(fxMesa, color[i]); + DRAW_POINT(i, sz); + } + } else { + for(i=first;i<=last;i++) { + if(VB->ClipMask[i]==0) { + FLAT_COLOR(fxMesa, color[i]); + DRAW_POINT(i, sz); + } + } + } + + if (IND & FX_FRONT_BACK) { + FX_grColorMask(ctx->Color.ColorMask[RCOMP] || + ctx->Color.ColorMask[GCOMP] || + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer); + if(ctx->Depth.Mask) + FX_grDepthMask(FXTRUE); + FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER); + + + if(!VB->ClipOrMask) { + for(i=first;i<=last;i++) { + FLAT_COLOR(fxMesa, color[i]); + DRAW_POINT(i, sz); + } + } else { + for(i=first;i<=last;i++) { + if(VB->ClipMask[i]==0) { + FLAT_COLOR(fxMesa, color[i]); + DRAW_POINT(i, sz); + } + } + } + } +} + +#endif + + + +static void TAG(init)( void ) +{ + tri_tab[IND] = TAG(fx_tri); + quad_tab[IND] = TAG(fx_quad); + +#if ((IND & FX_OFFSET) == 0) + line_tab[IND] = TAG(fx_line); + points_tab[IND] = TAG(fx_points); +#else + line_tab[IND] = line_tab[IND & ~FX_OFFSET]; + points_tab[IND] = points_tab[IND & ~FX_OFFSET]; +#endif +} + +#undef IND +#undef TAG +#undef FLAT_COLOR +#undef DRAW_POINT diff --git a/xc/extras/Mesa/src/FX/fxvs_tmp.h b/xc/extras/Mesa/src/FX/fxvs_tmp.h new file mode 100644 index 000000000..d9001db5e --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxvs_tmp.h @@ -0,0 +1,215 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#if (IND & (SETUP_XY|SETUP_W|SETUP_Z)) +#define V1 VARS_XY +#define I1 , INCR_XY +#else +#define V1 +#define I1 +#endif + +#if (IND & SETUP_XY) +#define S1 DO_SETUP_XY +#else +#define S1 +#endif + +#if (IND & SETUP_W) +#define S2 S1 DO_SETUP_W +#define V2 V1 VARS_W +#else +#define S2 S1 +#define V2 V1 +#endif + +#if (IND & SETUP_Z) +#define S3 S2 DO_SETUP_Z +#else +#define S3 S2 +#endif + +#if (IND & SETUP_RGBA) +#define V4 V2 VARS_RGBA +#define S4 S3 DO_SETUP_RGBA +#define I4 I1 , INCR_RGBA +#else +#define V4 V2 +#define S4 S3 +#define I4 I1 +#endif + +#if (IND & SETUP_TMU0) +#define V5 V4 VARS_TMU0 +#define S5 S4 DO_SETUP_TMU0 +#define I5 I4 , INCR_TMU0 +#define F5 FIXUP_TMU0 +#else +#define V5 V4 +#define S5 S4 +#define I5 I4 +#define F5 +#endif + +#if (IND & SETUP_TMU1) +#define V6 V5 VARS_TMU1 +#define S6 S5 DO_SETUP_TMU1 +#define I6 I5 , INCR_TMU1 +#define F6 F5 FIXUP_TMU1 +#else +#define V6 V5 +#define S6 S5 +#define I6 I5 +#define F6 F5 +#endif + +#if (IND & SETUP_TMU0) && (IND & SETUP_TMU1) +#define F7 FIXUP_TMU01 +#else +#define F7 F6 +#endif + +#define VARS V6 +#define DO_SETUP S6 +#define INCR I6 +#define FIXUP F7 + +static void NAME(struct vertex_buffer *VB, GLuint start, GLuint end) +{ + GLcontext *ctx = VB->ctx; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + + if (fxMesa->new_state) + fxSetupFXUnits( ctx ); + + { + const float snapper = (3L<<18); + fxVertex *gWin = FX_DRIVER_DATA(VB)->verts; + GLfloat *v = gWin[start].f; + GLfloat *vend = gWin[end].f; + VARS; + + (void) gWin; + (void) fxMesa; + (void) snapper; + + if (VB->ClipOrMask) { + GLubyte *clipmask = &VB->ClipMask[start]; + for (;v!=vend;v+=16,clipmask++ INCR) { + if (*clipmask == 0) { + DO_SETUP; + } + } + } + else { + for (;v!=vend;v+=16 INCR) { + DO_SETUP; + } + } + + if (ctx->FogMode == FOG_FRAGMENT && ctx->ProjectionMatrix.m[15] != 0.0F) { + /* need to compute W values for fogging purposes */ + const GLfloat m10 = ctx->ProjectionMatrix.m[10]; + const GLfloat m14 = ctx->ProjectionMatrix.m[14]; + const GLfloat v10 = ctx->Viewport.WindowMap.m[10]; + const GLfloat v14 = ctx->Viewport.WindowMap.m[14]; + GLfloat *v = gWin[start].f; + GLfloat *win = VB->Win.data[start]; + if (VB->ClipOrMask) { + GLubyte *clipmask = &VB->ClipMask[start]; + for (;v!=vend;v+=16,clipmask++, win+=4) { + if (*clipmask == 0) { + GLfloat zNDC = (win[2] - v14) / v10; + GLfloat zEye = (zNDC - m14) / m10; + v[OOWCOORD] = -1.0F / zEye; + } + } + } + else { + for (;v!=vend;v+=16, win+=4) { + GLfloat zNDC = (win[2] - v14) / v10; + GLfloat zEye = (zNDC - m14) / m10; + v[OOWCOORD] = -1.0F / zEye; + } + } + } + + /* rare - I hope */ + FIXUP; + } +} + + +#undef V1 +#undef V2 +#undef V3 +#undef V4 +#undef V5 +#undef V6 +#undef VARS + +#undef S1 +#undef S2 +#undef S3 +#undef S4 +#undef S5 +#undef S6 +#undef DO_SETUP + +#undef I1 +#undef I4 +#undef I5 +#undef I6 +#undef INCR + +#undef F5 +#undef F6 +#undef F7 +#undef FIXUP + + +#undef IND +#undef NAME + diff --git a/xc/extras/Mesa/src/FX/fxvsetup.c b/xc/extras/Mesa/src/FX/fxvsetup.c new file mode 100644 index 000000000..5b075f404 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxvsetup.c @@ -0,0 +1,576 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +/* fxvsetup.c - 3Dfx VooDoo vertices setup functions */ + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" +#include "mmath.h" +#include "pipeline.h" +#include "fxvsetup.h" + +void fxPrintSetupFlags( const char *msg, GLuint flags ) +{ + fprintf(stderr, "%s: %d %s%s%s%s%s%s\n", + msg, + flags, + (flags & SETUP_XY) ? " xy," : "", + (flags & SETUP_Z) ? " z," : "", + (flags & SETUP_W) ? " w," : "", + (flags & SETUP_RGBA) ? " rgba," : "", + (flags & SETUP_TMU0) ? " tmu0," : "", + (flags & SETUP_TMU1) ? " tmu1," : ""); +} + +static void project_texcoords( struct vertex_buffer *VB, + GLuint tmu_nr, GLuint tc_nr, + GLuint start, GLuint count ) +{ + fxVertex *v = FX_DRIVER_DATA(VB)->verts + start; + GrTmuVertex *tmu = &(((GrVertex *)v->f)->tmuvtx[tmu_nr]); + GLvector4f *vec = VB->TexCoordPtr[tc_nr]; + + GLuint i; + GLuint stride = vec->stride; + GLfloat *data = VEC_ELT(vec, GLfloat, start); + + for (i = start ; i < count ; i++, STRIDE_F(data, stride), v++) { + tmu->oow = v->f[OOWCOORD] * data[3]; + tmu = (GrTmuVertex *)((char *)tmu + sizeof(fxVertex)); + } +} + + +static void copy_w( struct vertex_buffer *VB, + GLuint tmu_nr, + GLuint start, GLuint count ) +{ + fxVertex *v = FX_DRIVER_DATA(VB)->verts + start; + GrTmuVertex *tmu = &(((GrVertex *)v->f)->tmuvtx[tmu_nr]); + GLuint i; + + for (i = start ; i < count ; i++, v++) { + tmu->oow = v->f[OOWCOORD]; + tmu = (GrTmuVertex *)((char *)tmu + sizeof(fxVertex)); + } +} + + +static tfxSetupFunc setupfuncs[0x40]; + + + + +#define IND SETUP_XY +#define NAME fxsetupXY +#include "fxvs_tmp.h" + +#define IND (SETUP_XY|SETUP_Z) +#define NAME fxsetupXYZ +#include "fxvs_tmp.h" + +#define IND (SETUP_XY|SETUP_W) +#define NAME fxsetupXYW +#include "fxvs_tmp.h" + +#define IND (SETUP_XY|SETUP_Z|SETUP_W) +#define NAME fxsetupXYZW +#include "fxvs_tmp.h" + +#define IND (SETUP_RGBA|SETUP_XY) +#define NAME fxsetupXYRGBA +#include "fxvs_tmp.h" + +#define IND (SETUP_RGBA|SETUP_XY|SETUP_Z) +#define NAME fxsetupXYZRGBA +#include "fxvs_tmp.h" + +#define IND (SETUP_RGBA|SETUP_XY|SETUP_W) +#define NAME fxsetupXYWRGBA +#include "fxvs_tmp.h" + +#define IND (SETUP_RGBA|SETUP_XY|SETUP_Z|SETUP_W) +#define NAME fxsetupXYZWRGBA +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU0|SETUP_XY|SETUP_W) +#define NAME fxsetupXYWT0 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU0|SETUP_XY|SETUP_Z|SETUP_W) +#define NAME fxsetupXYZWT0 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU1|SETUP_TMU0|SETUP_XY|SETUP_W) +#define NAME fxsetupXYWT0T1 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU1|SETUP_TMU0|SETUP_XY|SETUP_Z|SETUP_W) +#define NAME fxsetupXYZWT0T1 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU0|SETUP_RGBA|SETUP_XY|SETUP_W) +#define NAME fxsetupXYWRGBAT0 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU0|SETUP_RGBA|SETUP_XY|SETUP_Z|SETUP_W) +#define NAME fxsetupXYZWRGBAT0 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU1|SETUP_TMU0|SETUP_RGBA|SETUP_XY|SETUP_W) +#define NAME fxsetupXYWRGBAT0T1 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU1|SETUP_TMU0|SETUP_RGBA|SETUP_XY|SETUP_Z|SETUP_W) +#define NAME fxsetupXYZWRGBAT0T1 +#include "fxvs_tmp.h" + +#define IND (SETUP_RGBA) +#define NAME fxsetupRGBA +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU0) +#define NAME fxsetupT0 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU1) +#define NAME fxsetupT1 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU1|SETUP_TMU0) +#define NAME fxsetupT0T1 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU0|SETUP_RGBA) +#define NAME fxsetupRGBAT0 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU1|SETUP_RGBA) +#define NAME fxsetupRGBAT1 +#include "fxvs_tmp.h" + +#define IND (SETUP_TMU1|SETUP_TMU0|SETUP_RGBA) +#define NAME fxsetupRGBAT0T1 +#include "fxvs_tmp.h" + +#define IND (SETUP_W|SETUP_RGBA) +#define NAME fxsetupWRGBA +#include "fxvs_tmp.h" + +#define IND (SETUP_W|SETUP_TMU0) +#define NAME fxsetupWT0 +#include "fxvs_tmp.h" + +#define IND (SETUP_W|SETUP_TMU1) +#define NAME fxsetupWT1 +#include "fxvs_tmp.h" + +#define IND (SETUP_W|SETUP_TMU1|SETUP_TMU0) +#define NAME fxsetupWT0T1 +#include "fxvs_tmp.h" + +#define IND (SETUP_W|SETUP_TMU0|SETUP_RGBA) +#define NAME fxsetupWRGBAT0 +#include "fxvs_tmp.h" + +#define IND (SETUP_W|SETUP_TMU1|SETUP_RGBA) +#define NAME fxsetupWRGBAT1 +#include "fxvs_tmp.h" + +#define IND (SETUP_W|SETUP_TMU1|SETUP_TMU0|SETUP_RGBA) +#define NAME fxsetupWRGBAT0T1 +#include "fxvs_tmp.h" + + + +void fxDDSetupInit( void ) +{ + setupfuncs[SETUP_XY] = fxsetupXY; + setupfuncs[SETUP_XY|SETUP_Z] = fxsetupXYZ; + setupfuncs[SETUP_XY|SETUP_W] = fxsetupXYW; + setupfuncs[SETUP_XY|SETUP_Z|SETUP_W] = fxsetupXYZW; + + setupfuncs[SETUP_RGBA|SETUP_XY] = fxsetupXYRGBA; + setupfuncs[SETUP_RGBA|SETUP_XY|SETUP_Z] = fxsetupXYZRGBA; + setupfuncs[SETUP_RGBA|SETUP_XY|SETUP_W] = fxsetupXYWRGBA; + setupfuncs[SETUP_RGBA|SETUP_XY|SETUP_Z|SETUP_W] = fxsetupXYZWRGBA; + + /* If we have texture and xy then we must have w. + * If we have texture1 and w then we must have texture 0. + */ + setupfuncs[SETUP_TMU0|SETUP_XY|SETUP_W] = fxsetupXYWT0; + setupfuncs[SETUP_TMU0|SETUP_XY|SETUP_Z|SETUP_W] = fxsetupXYZWT0; + + setupfuncs[SETUP_TMU1|SETUP_TMU0|SETUP_XY|SETUP_W] = fxsetupXYWT0T1; + setupfuncs[SETUP_TMU1|SETUP_TMU0|SETUP_XY|SETUP_Z|SETUP_W] = fxsetupXYZWT0T1; + + setupfuncs[SETUP_TMU0|SETUP_RGBA|SETUP_XY|SETUP_W] = fxsetupXYWRGBAT0; + setupfuncs[SETUP_TMU0|SETUP_RGBA|SETUP_XY|SETUP_Z|SETUP_W] = fxsetupXYZWRGBAT0; + + setupfuncs[SETUP_TMU1|SETUP_TMU0|SETUP_RGBA|SETUP_XY|SETUP_W] = fxsetupXYWRGBAT0T1; + setupfuncs[SETUP_TMU1|SETUP_TMU0|SETUP_RGBA|SETUP_XY|SETUP_Z|SETUP_W] = fxsetupXYZWRGBAT0T1; + + /* If we don't have xy then we can't have z... w is still a possibility. + */ + setupfuncs[SETUP_RGBA] = fxsetupRGBA; + setupfuncs[SETUP_TMU0] = fxsetupT0; + setupfuncs[SETUP_TMU1] = fxsetupT1; + setupfuncs[SETUP_TMU1|SETUP_TMU0] = fxsetupT0T1; + setupfuncs[SETUP_TMU0|SETUP_RGBA] = fxsetupRGBAT0; + setupfuncs[SETUP_TMU1|SETUP_RGBA] = fxsetupRGBAT1; + setupfuncs[SETUP_TMU1|SETUP_TMU0|SETUP_RGBA] = fxsetupRGBAT0T1; + + setupfuncs[SETUP_W|SETUP_RGBA] = fxsetupWRGBA; + setupfuncs[SETUP_W|SETUP_TMU0] = fxsetupWT0; + setupfuncs[SETUP_W|SETUP_TMU1] = fxsetupWT1; + setupfuncs[SETUP_W|SETUP_TMU1|SETUP_TMU0] = fxsetupWT0T1; + setupfuncs[SETUP_W|SETUP_TMU0|SETUP_RGBA] = fxsetupWRGBAT0; + setupfuncs[SETUP_W|SETUP_TMU1|SETUP_RGBA] = fxsetupWRGBAT1; + setupfuncs[SETUP_W|SETUP_TMU1|SETUP_TMU0|SETUP_RGBA] = fxsetupWRGBAT0T1; + +} + + + +tfxSetupFunc fxDDChooseSetupFunction(GLcontext *ctx) +{ + GLuint setupindex = SETUP_XY|SETUP_Z; + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + + fxMesa->setupindex = 0; + + if (ctx->RenderMode != GL_RENDER) + return 0; + + fxMesa->tmu_source[0] = 0; + fxMesa->tmu_source[1] = 1; + + fxMesa->tex_dest[0] = SETUP_TMU0; + fxMesa->tex_dest[1] = SETUP_TMU1; + + if (ctx->Light.ShadeModel == GL_SMOOTH && !ctx->Light.Model.TwoSide) + setupindex |= SETUP_RGBA; + + if (ctx->Fog.Enabled && ctx->FogMode==FOG_FRAGMENT) + setupindex |= SETUP_RGBA|SETUP_W; + + if ((ctx->Texture.ReallyEnabled & (TEXTURE0_2D|TEXTURE0_3D)) == TEXTURE0_2D) + { + /* This only works for GL_RGBA texture format. + if (ctx->Texture.Unit[0].EnvMode == GL_REPLACE) + setupindex &= ~SETUP_RGBA; + */ + setupindex |= SETUP_TMU0|SETUP_W; + } + + if ((ctx->Texture.ReallyEnabled & (TEXTURE1_2D|TEXTURE1_3D)) == TEXTURE1_2D) + { + setupindex |= SETUP_TMU1|SETUP_W; + if (setupindex & SETUP_TMU0) { /* both TMUs in use */ + struct gl_texture_object *tObj=ctx->Texture.Unit[0].CurrentD[2]; + tfxTexInfo *ti=fxTMGetTexInfo(tObj); + + if (ti->whichTMU!=FX_TMU0) { /* TMU0 and TMU1 are swapped */ + fxMesa->tmu_source[0] = 1; fxMesa->tex_dest[1] = SETUP_TMU0; + fxMesa->tmu_source[1] = 0; fxMesa->tex_dest[0] = SETUP_TMU1; + } + } + } + + if (ctx->Color.BlendEnabled) + setupindex |= SETUP_RGBA; + + if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_PIPELINE|VERBOSE_STATE)) + fxPrintSetupFlags("fxmesa: vertex setup function", setupindex); + + fxMesa->setupindex = setupindex; + fxMesa->view_clip_tri = fxTriViewClipTab[setupindex&0x7]; + fxMesa->clip_tri_stride = fxTriClipStrideTab[setupindex&0x7]; + return setupfuncs[setupindex]; +} + +void fxDDDoRasterSetup( struct vertex_buffer *VB ) +{ + GLcontext *ctx = VB->ctx; + FX_DRIVER_DATA(VB)->last_vert = FX_DRIVER_DATA(VB)->verts + VB->Count; + +#if 0 /* leaving this out fixes the Heretic2 stray polygon bug */ + if ((ctx->IndirectTriangles & DD_SW_RASTERIZE) == DD_SW_RASTERIZE) { + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + fxMesa->setupdone = 0; + return; + } +#endif + + if (VB->Type == VB_CVA_PRECALC) + fxDDPartialRasterSetup( VB ); + else { + if ((ctx != NULL) && (ctx->Driver.RasterSetup != NULL)) + ctx->Driver.RasterSetup( VB, VB->CopyStart, VB->Count ); + } +} + + +/* + * Need to check that merge&render will work before allowing this to + * happen here. Therefore - need to know that this will be fired when + * we get a forbidden input in the elt pipeline - and therefore need to check + * whether we have one *now*. Similarly need to know if state changes cause + * size4 texcoords to be introduced. + */ +void fxDDCheckPartialRasterSetup( GLcontext *ctx, struct gl_pipeline_stage *d ) +{ + fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx; + GLuint tmp = fxMesa->setupdone; + + d->type = 0; + d->pre_forbidden_inputs = 0; + fxMesa->setupdone = 0; /* cleared if we return */ + + /* Indirect triangles must be rendered via the immediate pipeline. + * If all rasterization is software, no need to set up. + */ + if ((ctx->Array.Summary & VERT_OBJ_ANY) == 0) + return; + + if ((ctx->IndirectTriangles & DD_SW_SETUP) || + (ctx->IndirectTriangles & DD_SW_RASTERIZE) == DD_SW_RASTERIZE) + return; + + if ((ctx->Texture.ReallyEnabled & 0xf) && + !(ctx->Array.Flags & VERT_TEX0_ANY)) + { + if (ctx->TextureMatrix[0].type == MATRIX_GENERAL || + ctx->TextureMatrix[0].type == MATRIX_PERSPECTIVE || + (ctx->Texture.Unit[1].TexGenEnabled & Q_BIT)) + return; + + d->pre_forbidden_inputs |= VERT_TEX0_4; + } + + if ((ctx->Texture.ReallyEnabled & 0xf0) && + !(ctx->Array.Flags & VERT_TEX1_ANY)) + { + if (ctx->TextureMatrix[1].type == MATRIX_GENERAL || + ctx->TextureMatrix[1].type == MATRIX_PERSPECTIVE || + (ctx->Texture.Unit[1].TexGenEnabled & Q_BIT)) + return; + + d->pre_forbidden_inputs |= VERT_TEX1_4; + } + + + fxMesa->setupdone = tmp; + d->inputs = 0; + d->outputs = VERT_SETUP_PART; + d->type = PIPE_PRECALC; +} + + +/* Will be different every time - no point in trying to precalc the + * function to call. + */ +void fxDDPartialRasterSetup( struct vertex_buffer *VB ) +{ + GLuint new = VB->pipeline->new_outputs; + fxMesaContext fxMesa = (fxMesaContext)VB->ctx->DriverCtx; + GLuint ind = 0; + + FX_DRIVER_DATA(VB)->last_vert = FX_DRIVER_DATA(VB)->verts + VB->Count; + + if (new & VERT_WIN) { + new = VB->pipeline->outputs; + ind |= SETUP_XY|SETUP_W|SETUP_Z; + } + + if (new & VERT_TEX0_ANY) + ind |= SETUP_W | fxMesa->tex_dest[0]; + + if (new & VERT_TEX1_ANY) + ind |= SETUP_W | fxMesa->tex_dest[1]; + + if (new & VERT_RGBA) + ind |= SETUP_W|SETUP_RGBA; + + if ((new & VERT_WIN) == 0) + ind &= ~(fxMesa->setupdone & SETUP_W); + + fxMesa->setupdone &= ~ind; + ind &= fxMesa->setupindex; + fxMesa->setupdone |= ind; + + if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_PIPELINE)) { + gl_print_vert_flags("new outputs", VB->pipeline->new_outputs); + fxPrintSetupFlags("fxmesa: partial setup function", ind); + } + + if (ind) + setupfuncs[ind]( VB, VB->Start, VB->Count ); +} + +/* Almost certainly never called. + */ +void fxDDResizeVB( struct vertex_buffer *VB, GLuint size ) +{ + struct tfxMesaVertexBuffer *fvb = FX_DRIVER_DATA(VB); + + while (fvb->size < size) + fvb->size *= 2; + + ALIGN_FREE( VB->ClipMask ); + VB->ClipMask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte) * fvb->size, 4); + + FREE( fvb->vert_store ); + fvb->vert_store = MALLOC( sizeof(fxVertex) * fvb->size + 31); + if (!fvb->vert_store || !VB->ClipMask) + { + fprintf(stderr,"fx Driver: out of memory !\n"); + fxCloseHardware(); + exit(-1); + } + fvb->verts = (fxVertex *)(((unsigned long)fvb->vert_store + 31) & ~31); + + gl_vector1ui_free( &fvb->clipped_elements ); + gl_vector1ui_alloc( &fvb->clipped_elements, VEC_WRITABLE, fvb->size, 32 ); + + if (!fvb->clipped_elements.start) goto memerror; + + return; +memerror: + fprintf(stderr,"fx Driver: out of memory !\n"); + fxCloseHardware(); + exit(-1); +} + + +void fxDDRegisterVB( struct vertex_buffer *VB ) +{ + struct tfxMesaVertexBuffer *fvb; + + fvb = (struct tfxMesaVertexBuffer *)calloc( 1, sizeof(*fvb) ); + + /* This looks like it allocates a lot of memory, but it basically + * just sets an upper limit on how much can be used - nothing like + * this amount will ever be turned into 'real' memory. + */ + if (VB->Type == VB_CVA_PRECALC) { + fvb->size = VB->Size * 5; + fvb->vert_store = MALLOC( sizeof(fxVertex) * fvb->size + 31); + if (!fvb->vert_store) goto memerror; +#if defined(FX_GLIDE3) + fvb->triangle_b = MALLOC( sizeof(GrVertex*) *4* fvb->size+ 31); + if (!fvb->triangle_b) goto memerror; + fvb->strips_b = MALLOC( sizeof(GrVertex*) *4* fvb->size+ 31); + if (!fvb->strips_b ) goto memerror; +#endif + fvb->verts = (fxVertex *)(((unsigned long)fvb->vert_store + 31) & ~31); + gl_vector1ui_alloc( &fvb->clipped_elements, VEC_WRITABLE, fvb->size, 32 ); + if (!fvb->clipped_elements.start) goto memerror; + + ALIGN_FREE( VB->ClipMask ); + VB->ClipMask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte) * fvb->size, 4); + if (!VB->ClipMask) goto memerror; + + } else { + fvb->vert_store = MALLOC( sizeof(fxVertex) * (VB->Size + 12) + 31); + if (!fvb->vert_store) goto memerror; +#if defined(FX_GLIDE3) + fvb->triangle_b = MALLOC( sizeof(GrVertex*) *4* fvb->size+ 31); + if (!fvb->triangle_b) goto memerror; + fvb->strips_b = MALLOC( sizeof(GrVertex*) *4* fvb->size+ 31); + if (!fvb->strips_b ) goto memerror; +#endif + fvb->verts = (fxVertex *)(((unsigned long)fvb->vert_store + 31) & ~31); + fvb->size = VB->Size + 12; + } + + + VB->driver_data = fvb; + return; +memerror: + fprintf(stderr,"fx Driver: out of memory !\n"); + fxCloseHardware(); + exit(-1); +} + +void fxDDUnregisterVB( struct vertex_buffer *VB ) +{ + struct tfxMesaVertexBuffer *fvb = FX_DRIVER_DATA(VB); + + if (fvb) { + if (fvb->vert_store) FREE(fvb->vert_store); + gl_vector1ui_free( &fvb->clipped_elements ); + FREE(fvb); +#if defined(FX_GLIDE3) + if (fvb->strips_b) + FREE(fvb->strips_b); + if (fvb->triangle_b) + FREE(fvb->triangle_b); +#endif + VB->driver_data = 0; + } +} + + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_vsetup(void) +{ + return 0; +} + +#endif /* FX */ diff --git a/xc/extras/Mesa/src/FX/fxvsetup.h b/xc/extras/Mesa/src/FX/fxvsetup.h new file mode 100644 index 000000000..48123c46b --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxvsetup.h @@ -0,0 +1,199 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + +#ifndef _FXVSETUP_H_ +#define _FXVSETUP_H_ + + +#define VARS_W + +#define VARS_Z + +#define VARS_TMU0 \ + GLuint tmu0_source = fxMesa->tmu_source[0]; \ + GLfloat *tmu0_data = VEC_ELT(VB->TexCoordPtr[tmu0_source], \ + GLfloat, start); \ + GLuint tmu0_stride = VB->TexCoordPtr[tmu0_source]->stride; \ + GLuint tmu0_sz = VB->TexCoordPtr[tmu0_source]->size; \ + struct gl_texture_unit *t0 = &ctx->Texture.Unit[tmu0_source]; \ + GLfloat sscale0 = FX_TEXTURE_DATA(t0)->sScale; \ + GLfloat tscale0 = FX_TEXTURE_DATA(t0)->tScale; + +#define VARS_TMU1 \ + GLuint tmu1_source = fxMesa->tmu_source[1]; \ + GLfloat *tmu1_data = VEC_ELT(VB->TexCoordPtr[tmu1_source], \ + GLfloat, start); \ + GLuint tmu1_stride = VB->TexCoordPtr[tmu1_source]->stride; \ + GLuint tmu1_sz = VB->TexCoordPtr[tmu1_source]->size; \ + struct gl_texture_unit *t1 = &ctx->Texture.Unit[tmu1_source]; \ + GLfloat sscale1 = FX_TEXTURE_DATA(t1)->sScale; \ + GLfloat tscale1 = FX_TEXTURE_DATA(t1)->tScale; + +#define VARS_RGBA \ + GLubyte *color = VEC_ELT(VB->ColorPtr, GLubyte, start); \ + GLuint col_stride = VB->ColorPtr->stride; + +#define VARS_XY GLfloat *win = VB->Win.data[start]; + +#define INCR_XY win += 4 + + +#ifdef FX_V2 +# define DO_SETUP_XY \ + v[XCOORD]=win[0]; \ + v[YCOORD]=win[1]; +#else +#ifdef DRIVERTS +# define DO_SETUP_XY \ + v[XCOORD]=win[0]+fxMesa->x_offset; \ + v[YCOORD]=win[1]+fxMesa->y_delta; +#else +# if (defined(__linux__) && defined(__i386__)) || defined(macintosh) +# define DO_SETUP_XY { \ + GLfloat t1 = win[0] + snapper; \ + GLfloat t2 = win[1] + snapper; \ + v[XCOORD] = t1 - snapper; \ + v[YCOORD] = t2 - snapper; \ + } +# else +# define DO_SETUP_XY { \ + /* trunc (x,y) to multiple of 1/16 */ \ + v[XCOORD]=((int)(win[0]*16.0f))*(1.0f/16.0f); \ + v[YCOORD]=((int)(win[1]*16.0f))*(1.0f/16.0f); \ + } +# endif +#endif +#endif + + +#define DO_SETUP_W { \ + v[OOWCOORD]=win[3]; \ +} + +#define DO_SETUP_Z v[ZCOORD]=win[2]; + +#define DO_SETUP_TMU0 \ +{ \ + v[S0COORD]=sscale0*tmu0_data[0]*v[OOWCOORD]; \ + v[T0COORD]=tscale0*tmu0_data[1]*v[OOWCOORD]; \ +} + +#define INCR_TMU0 STRIDE_F(tmu0_data, tmu0_stride) + +#define DO_SETUP_TMU1 \ +{ \ + v[S1COORD]=sscale1*tmu1_data[0]*v[OOWCOORD]; \ + v[T1COORD]=tscale1*tmu1_data[1]*v[OOWCOORD]; \ +} + +#define INCR_TMU1 STRIDE_F(tmu1_data, tmu1_stride) + +#if FX_USE_PARGB +#define DO_SETUP_RGBA \ + { GET_PARGB(v) = color[ACOMP] << 24 | color[RCOMP] << 16 | color[GCOMP] << 8 | color[BCOMP];} + +#else +#define DO_SETUP_RGBA \ +{ \ + UBYTE_COLOR_TO_FLOAT_255_COLOR2(v[RCOORD], color[0]); \ + UBYTE_COLOR_TO_FLOAT_255_COLOR2(v[GCOORD], color[1]); \ + UBYTE_COLOR_TO_FLOAT_255_COLOR2(v[BCOORD], color[2]); \ + UBYTE_COLOR_TO_FLOAT_255_COLOR2(v[ACOORD], color[3]); \ +} +#endif + +#define INCR_RGBA color += col_stride + + +#define _FIXUP_PRE \ + GLuint hs = fxMesa->stw_hint_state & ~(GR_STWHINT_W_DIFF_TMU0 | \ + GR_STWHINT_W_DIFF_TMU1); + +#define _FIXUP_TMU0 \ + if (tmu0_sz == 4) { \ + project_texcoords( VB, 0, tmu0_source, start, end ); \ + hs |= GR_STWHINT_W_DIFF_TMU0; \ + } + + +#define _FIXUP_TMU1 \ + if (tmu1_sz == 4) { \ + project_texcoords( VB, 1, tmu1_source, start, end ); \ + hs |= GR_STWHINT_W_DIFF_TMU1; \ + } + + +#define _FIXUP_TMU01 \ + if (tmu0_sz == 4) { \ + project_texcoords( VB, 0, tmu0_source, start, end ); \ + if (tmu1_sz == 4) \ + project_texcoords( VB, 1, tmu1_source, start, end ); \ + else \ + copy_w( VB, 1, start, end ); \ + hs |= (GR_STWHINT_W_DIFF_TMU0|GR_STWHINT_W_DIFF_TMU1); \ + } else if (tmu1_sz == 4) { \ + project_texcoords( VB, 1, tmu1_source, start, end ); \ + hs |= GR_STWHINT_W_DIFF_TMU1; \ + } + +#define _FIXUP_POST \ + if (hs != fxMesa->stw_hint_state) { \ + fxMesa->stw_hint_state = hs; \ + FX_grHints(GR_HINT_STWHINT, hs); \ + } + + +#define FIXUP_TMU0 { _FIXUP_PRE _FIXUP_TMU0 _FIXUP_POST } +#define FIXUP_TMU1 { _FIXUP_PRE _FIXUP_TMU1 _FIXUP_POST } +#define FIXUP_TMU01 { _FIXUP_PRE _FIXUP_TMU01 _FIXUP_POST } + + +/* v - pointer to destination GrVertex + * VB - source of data + * i - index into vb for data + */ + + +#endif diff --git a/xc/extras/Mesa/src/FX/fxwgl.c b/xc/extras/Mesa/src/FX/fxwgl.c new file mode 100644 index 000000000..1f0e16a95 --- /dev/null +++ b/xc/extras/Mesa/src/FX/fxwgl.c @@ -0,0 +1,870 @@ +/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ + +/* + * Mesa 3-D graphics library + * Version: 3.3 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the + * terms stated above. + * + * Thank you for your contribution, David! + * + * Please make note of the above copyright/license statement. If you + * contributed code or bug fixes to this code under the previous (GNU + * Library) license and object to the new license, your code will be + * removed at your request. Please see the Mesa docs/COPYRIGHT file + * for more information. + * + * Additional Mesa/3Dfx driver developers: + * Daryll Strauss <daryll@precisioninsight.com> + * Keith Whitwell <keith@precisioninsight.com> + * + * See fxapi.h for more revision/author details. + */ + + + +/* fxwgl.c - Microsoft wgl functions emulation for + * 3Dfx VooDoo/Mesa interface + */ + + +#ifdef __WIN32__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <windows.h> +#include "GL/gl.h" + +#ifdef __cplusplus + } +#endif + +#include <stdio.h> +#include "GL/fxmesa.h" +#include "fxdrv.h" + +#define MAX_MESA_ATTRS 20 + +struct __extensions__ +{ + PROC proc; + char *name; +}; + +struct __pixelformat__ +{ + PIXELFORMATDESCRIPTOR pfd; + GLint mesaAttr[MAX_MESA_ATTRS]; +}; + +WINGDIAPI void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *); + +static struct __extensions__ ext[] = { + +#ifdef GL_EXT_polygon_offset + { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" }, +#endif + { (PROC)glBlendEquationEXT, "glBlendEquationEXT" }, + { (PROC)glBlendColorEXT, "glBlendColorExt" }, + { (PROC)glVertexPointerEXT, "glVertexPointerEXT" }, + { (PROC)glNormalPointerEXT, "glNormalPointerEXT" }, + { (PROC)glColorPointerEXT, "glColorPointerEXT" }, + { (PROC)glIndexPointerEXT, "glIndexPointerEXT" }, + { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" }, + { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" }, + { (PROC)glGetPointervEXT, "glGetPointervEXT" }, + { (PROC)glArrayElementEXT, "glArrayElementEXT" }, + { (PROC)glDrawArraysEXT, "glDrawArrayEXT" }, + { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" }, + { (PROC)glBindTextureEXT, "glBindTextureEXT" }, + { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" }, + { (PROC)glGenTexturesEXT, "glGenTexturesEXT" }, + { (PROC)glIsTextureEXT, "glIsTextureEXT" }, + { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" }, + { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" }, + { (PROC)glTexImage3DEXT, "glTexImage3DEXT" }, + { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" }, + { (PROC)gl3DfxSetPaletteEXT, "3DFX_set_global_palette" }, + { (PROC)glColorTableEXT, "glColorTableEXT" }, + { (PROC)glColorSubTableEXT, "glColorSubTableEXT" }, + { (PROC)glGetColorTableEXT, "glGetColorTableEXT" }, + { (PROC)glGetColorTableParameterfvEXT, "glGetColorTableParameterfvEXT" }, + { (PROC)glGetColorTableParameterivEXT, "glGetColorTableParameterivEXT" }, + { (PROC)glPointParameterfEXT, "glPointParameterfEXT" }, + { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" }, + { (PROC)glBlendFuncSeparateINGR, "glBlendFuncSeparateINGR" }, + { (PROC)glActiveTextureARB, "glActiveTextureARB" }, + { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" }, + { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" }, + { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" }, + { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" }, + { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" }, + { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" }, + { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" }, + { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" }, + { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" }, + { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" }, + { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" }, + { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" }, + { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" }, + { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" }, + { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" }, + { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" }, + { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" }, + { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" }, + { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" }, + { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" }, + { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" }, + { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" }, + { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" }, + { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" }, + { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" }, + { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" }, + { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" }, + { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" }, + { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" }, + { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" }, + { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" }, + { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" }, + { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" }, + { (PROC)glLockArraysEXT, "glLockArraysEXT" }, + { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" } +}; + +static int qt_ext = sizeof(ext) / sizeof(ext[0]); + +struct __pixelformat__ pix[] = +{ + /* None */ + { + { + sizeof(PIXELFORMATDESCRIPTOR), 1, + PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| + PFD_DOUBLEBUFFER|PFD_SWAP_COPY, + PFD_TYPE_RGBA, + 32, + 8,0,8,8,8,16,0,24, + 0,0,0,0,0, + 0, + 0, + 0, + PFD_MAIN_PLANE, + 0,0,0,0 + }, + { + FXMESA_DOUBLEBUFFER, + FXMESA_ALPHA_SIZE, 0, + FXMESA_DEPTH_SIZE, 0, + FXMESA_STENCIL_SIZE, 0, + FXMESA_ACCUM_SIZE, 0, + FXMESA_NONE + } + }, + + /* Alpha */ + { + { + sizeof(PIXELFORMATDESCRIPTOR), 1, + PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| + PFD_DOUBLEBUFFER|PFD_SWAP_COPY, + PFD_TYPE_RGBA, + 32, + 8,0,8,8,8,16,8,24, + 0,0,0,0,0, + 0, + 0, + 0, + PFD_MAIN_PLANE, + 0,0,0,0 + }, + { + FXMESA_DOUBLEBUFFER, + FXMESA_ALPHA_SIZE, 8, + FXMESA_DEPTH_SIZE, 0, + FXMESA_STENCIL_SIZE, 0, + FXMESA_ACCUM_SIZE, 0, + FXMESA_NONE + } + }, + + /* Depth */ + { + { + sizeof(PIXELFORMATDESCRIPTOR), 1, + PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| + PFD_DOUBLEBUFFER|PFD_SWAP_COPY, + PFD_TYPE_RGBA, + 32, + 8,0,8,8,8,16,0,24, + 0,0,0,0,0, + 16, + 0, + 0, + PFD_MAIN_PLANE, + 0,0,0,0 + }, + { + FXMESA_DOUBLEBUFFER, + FXMESA_ALPHA_SIZE, 0, + FXMESA_DEPTH_SIZE, 16, + FXMESA_STENCIL_SIZE, 0, + FXMESA_ACCUM_SIZE, 0, + FXMESA_NONE + } + } +}; +static int qt_pix = sizeof(pix) / sizeof(pix[0]); + +static fxMesaContext ctx = NULL; +static WNDPROC hWNDOldProc; +static int curPFD = 0; +static HDC hDC; +static HWND hWND; + +static GLboolean haveDualHead; + +/* For the in-window-rendering hack */ + +static GLboolean gdiWindowHack; +static GLboolean gdiWindowHackEna; +static void *dibSurfacePtr; +static BITMAPINFO *dibBMI; +static HBITMAP dibHBM; +static HWND dibWnd; + +LONG GLAPIENTRY __wglMonitor(HWND hwnd,UINT message,UINT wParam,LONG lParam) + +{ + long ret; /* Now gives the resized window at the end to hWNDOldProc */ + + if(ctx && hwnd == hWND) { + switch(message) { + case WM_PAINT: + case WM_MOVE: + break; + case WM_DISPLAYCHANGE: + case WM_SIZE: + if (wParam != SIZE_MINIMIZED) { + static int moving = 0; + if (!moving) { + if(fxQueryHardware()!=GR_SSTTYPE_VOODOO) { + if(!FX_grSstControl(GR_CONTROL_RESIZE)) { + moving = 1; + SetWindowPos(hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOZORDER); + moving = 0; + if(!FX_grSstControl(GR_CONTROL_RESIZE)) { + /*MessageBox(0,_T("Error changing windowsize"),_T("fxMESA"),MB_OK);*/ + PostMessage(hWND,WM_CLOSE,0,0); + } + } + } + + /* Do the clipping in the glide library */ + FX_grClipWindow(0,0,FX_grSstScreenWidth(),FX_grSstScreenHeight()); + /* And let the new size set in the context */ + fxMesaUpdateScreenSize(ctx); + } + } + break; + case WM_ACTIVATE: + if((fxQueryHardware()==GR_SSTTYPE_VOODOO) && + (!gdiWindowHack) && + (!haveDualHead)) { + WORD fActive = LOWORD(wParam); + BOOL fMinimized = (BOOL) HIWORD(wParam); + + if((fActive == WA_INACTIVE) || fMinimized) + FX_grSstControl(GR_CONTROL_DEACTIVATE); + else + FX_grSstControl(GR_CONTROL_ACTIVATE); + } + break; + case WM_SHOWWINDOW: + break; + case WM_SYSKEYDOWN: + case WM_SYSCHAR: + if(gdiWindowHackEna && (VK_RETURN == wParam)) { + if(gdiWindowHack) { + gdiWindowHack = GL_FALSE; + FX_grSstControl(GR_CONTROL_ACTIVATE); + } else { + gdiWindowHack = GL_TRUE; + FX_grSstControl(GR_CONTROL_DEACTIVATE); + } + } + break; + } + } + + /* Finaly call the hWNDOldProc, which handles the resize witch the + now changed window sizes */ + ret = CallWindowProc( hWNDOldProc, hwnd, message, wParam, lParam ); + + return(ret); +} + +BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask) +{ + return(FALSE); +} + +HGLRC GLAPIENTRY wglCreateContext(HDC hdc) +{ + HWND hWnd; + WNDPROC oldProc; + int error; + + if(ctx) { + SetLastError(0); + return(NULL); + } + + if(!(hWnd = WindowFromDC(hdc))) { + SetLastError(0); + return(NULL); + } + + if(curPFD == 0) { + SetLastError(0); + return(NULL); + } + + if((oldProc = (WNDPROC)GetWindowLong(hWnd,GWL_WNDPROC)) != __wglMonitor) { + hWNDOldProc = oldProc; + SetWindowLong(hWnd,GWL_WNDPROC,(LONG)__wglMonitor); + } + +#ifndef FX_SILENT + freopen("MESA.LOG","w",stderr); +#endif + + ShowWindow(hWnd, SW_SHOWNORMAL); + SetForegroundWindow(hWnd); + Sleep(100); /* an hack for win95 */ + + if(fxQueryHardware() == GR_SSTTYPE_VOODOO) { + RECT cliRect; + + GetClientRect(hWnd,&cliRect); + error = !(ctx = fxMesaCreateBestContext((GLuint)hWnd,cliRect.right,cliRect.bottom, + pix[curPFD - 1].mesaAttr)); + + if(!error) { + /* create the DIB section for windowed rendering */ + DWORD *p; + + dibWnd = hWnd; + + hDC = GetDC(dibWnd); + + dibBMI = (BITMAPINFO*) MALLOC( sizeof(BITMAPINFO) + (256*sizeof(RGBQUAD))); + + memset(dibBMI,0,sizeof(BITMAPINFO) + (256*sizeof(RGBQUAD))); + + dibBMI->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + dibBMI->bmiHeader.biWidth = ctx->width; + dibBMI->bmiHeader.biHeight = -ctx->height; + dibBMI->bmiHeader.biPlanes = (short)1; + dibBMI->bmiHeader.biBitCount = (short)16; + dibBMI->bmiHeader.biCompression = BI_BITFIELDS; + dibBMI->bmiHeader.biSizeImage = 0; + dibBMI->bmiHeader.biXPelsPerMeter = 0; + dibBMI->bmiHeader.biYPelsPerMeter = 0; + dibBMI->bmiHeader.biClrUsed = 3; + dibBMI->bmiHeader.biClrImportant = 3; + + p = (DWORD*)dibBMI->bmiColors; + p[0] = 0xF800; + p[1] = 0x07E0; + p[2] = 0x001F; + + dibHBM = CreateDIBSection(hDC, dibBMI, DIB_RGB_COLORS, &dibSurfacePtr, NULL, 0); + + ReleaseDC(dibWnd, hDC); + + gdiWindowHackEna = (dibHBM != NULL ? GL_TRUE : GL_FALSE); + + if (!getenv("MESA_WGL_FX") || !strcmp(getenv("MESA_WGL_FX"),"fullscreen")) + gdiWindowHack = GL_FALSE; + else { + gdiWindowHack = GL_TRUE; + FX_grSstControl(GR_CONTROL_DEACTIVATE); + } + } + } else { + /* For the Voodoo Rush */ + + if(getenv("MESA_WGL_FX") && !strcmp(getenv("MESA_WGL_FX"),"fullscreen")) { + RECT cliRect; + + GetClientRect(hWnd,&cliRect); + error = !(ctx = fxMesaCreateBestContext((GLuint)hWnd,cliRect.right,cliRect.bottom, + pix[curPFD - 1].mesaAttr)); + } else + error = !(ctx = fxMesaCreateContext((GLuint)hWnd,GR_RESOLUTION_NONE,GR_REFRESH_75Hz, + pix[curPFD - 1].mesaAttr)); + } + + if(getenv("SST_DUALHEAD")) + haveDualHead=((atoi(getenv("SST_DUALHEAD"))==1) ? GL_TRUE:GL_FALSE); + else + haveDualHead=GL_FALSE; + + if(error) { + SetLastError(0); + return(NULL); + } + + hDC = hdc; + hWND = hWnd; + + /* Required by the OpenGL Optimizer 1.1 (is it a Optimizer bug ?) */ + wglMakeCurrent(hdc,(HGLRC)1); + + return((HGLRC)1); +} + +HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc,int iLayerPlane) +{ + SetLastError(0); + return(NULL); +} + +BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc) +{ + if(ctx && hglrc == (HGLRC)1) { + if (gdiWindowHackEna) { + DeleteObject(dibHBM); + FREE(dibBMI); + + dibSurfacePtr = NULL; + dibBMI = NULL; + dibHBM = NULL; + dibWnd = NULL; + } + + fxMesaDestroyContext(ctx); + + SetWindowLong(WindowFromDC(hDC),GWL_WNDPROC,(LONG)hWNDOldProc); + + ctx = NULL; + hDC = 0; + return(TRUE); + } + + SetLastError(0); + + return(FALSE); +} + +HGLRC GLAPIENTRY wglGetCurrentContext(VOID) +{ + if(ctx) + return((HGLRC)1); + + SetLastError(0); + return(NULL); +} + +HDC GLAPIENTRY wglGetCurrentDC(VOID) +{ + if(ctx) + return(hDC); + + SetLastError(0); + return(NULL); +} + +PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc) +{ + int i; + + /*fprintf(stderr,"fxMesa: looking for extension %s\n",lpszProc); + fflush(stderr);*/ + + for(i = 0;i < qt_ext;i++) + if(!strcmp(lpszProc,ext[i].name)) { + /*fprintf(stderr,"fxMesa: found extension %s\n",lpszProc); + fflush(stderr);*/ + + return(ext[i].proc); + } + SetLastError(0); + return(NULL); +} + +BOOL GLAPIENTRY wglMakeCurrent(HDC hdc,HGLRC hglrc) +{ + if((hdc==NULL) && (hglrc==NULL)) + return(TRUE); + + if(!ctx || hglrc != (HGLRC)1 || WindowFromDC(hdc) != hWND) { + SetLastError(0); + return(FALSE); + } + + hDC = hdc; + + fxMesaMakeCurrent(ctx); + + return(TRUE); +} + +BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1,HGLRC hglrc2) +{ + if(!ctx || hglrc1 != (HGLRC)1 || hglrc1 != hglrc2) { + SetLastError(0); + return(FALSE); + } + + return(TRUE); +} + +BOOL GLAPIENTRY wglUseFontBitmaps(HDC fontDevice, DWORD firstChar, DWORD numChars, DWORD listBase) +{ +#define VERIFY(a) a + + TEXTMETRIC metric; + BITMAPINFO *dibInfo; + HDC bitDevice; + COLORREF tempColor; + int i; + + VERIFY(GetTextMetrics(fontDevice, &metric)); + + dibInfo = (BITMAPINFO *) calloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD), 1); + dibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + dibInfo->bmiHeader.biPlanes = 1; + dibInfo->bmiHeader.biBitCount = 1; + dibInfo->bmiHeader.biCompression = BI_RGB; + + bitDevice = CreateCompatibleDC(fontDevice); + // HDC bitDevice = CreateDC("DISPLAY", NULL, NULL, NULL); + // VERIFY(bitDevice); + + // Swap fore and back colors so the bitmap has the right polarity + tempColor = GetBkColor(bitDevice); + SetBkColor(bitDevice, GetTextColor(bitDevice)); + SetTextColor(bitDevice, tempColor); + + // Place chars based on base line + VERIFY(SetTextAlign(bitDevice, TA_BASELINE) >= 0 ? 1 : 0); + + for(i = 0; i < numChars; i++) { + SIZE size; + char curChar; + int charWidth,charHeight,bmapWidth,bmapHeight,numBytes,res; + HBITMAP bitObject; + HGDIOBJ origBmap; + unsigned char *bmap; + + curChar = i + firstChar; + + // Find how high/wide this character is + VERIFY(GetTextExtentPoint32(bitDevice, &curChar, 1, &size)); + + // Create the output bitmap + charWidth = size.cx; + charHeight = size.cy; + bmapWidth = ((charWidth + 31) / 32) * 32; // Round up to the next multiple of 32 bits + bmapHeight = charHeight; + bitObject = CreateCompatibleBitmap(bitDevice, + bmapWidth, + bmapHeight); + //VERIFY(bitObject); + + // Assign the output bitmap to the device + origBmap = SelectObject(bitDevice, bitObject); + VERIFY(origBmap); + + VERIFY( PatBlt( bitDevice, 0, 0, bmapWidth, bmapHeight,BLACKNESS ) ); + + // Use our source font on the device + VERIFY(SelectObject(bitDevice, GetCurrentObject(fontDevice,OBJ_FONT))); + + // Draw the character + VERIFY(TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1)); + + // Unselect our bmap object + VERIFY(SelectObject(bitDevice, origBmap)); + + // Convert the display dependant representation to a 1 bit deep DIB + numBytes = (bmapWidth * bmapHeight) / 8; + bmap = MALLOC(numBytes); + dibInfo->bmiHeader.biWidth = bmapWidth; + dibInfo->bmiHeader.biHeight = bmapHeight; + res = GetDIBits(bitDevice, bitObject, 0, bmapHeight, bmap, + dibInfo, + DIB_RGB_COLORS); + //VERIFY(res); + + // Create the GL object + glNewList(i + listBase, GL_COMPILE); + glBitmap(bmapWidth, bmapHeight, 0.0, metric.tmDescent, + charWidth, 0.0, + bmap); + glEndList(); + // CheckGL(); + + // Destroy the bmap object + DeleteObject(bitObject); + + // Deallocate the bitmap data + FREE(bmap); + } + + // Destroy the DC + VERIFY(DeleteDC(bitDevice)); + + FREE(dibInfo); + + return TRUE; +#undef VERIFY +} + +BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc,DWORD first,DWORD count,DWORD listBase) +{ + return(FALSE); +} + +BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc,DWORD first,DWORD count, + DWORD listBase,FLOAT deviation, + FLOAT extrusion,int format, + LPGLYPHMETRICSFLOAT lpgmf) +{ + SetLastError(0); + return(FALSE); +} + +BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc,DWORD first,DWORD count, + DWORD listBase,FLOAT deviation, + FLOAT extrusion,int format, + LPGLYPHMETRICSFLOAT lpgmf) +{ + SetLastError(0); + return(FALSE); +} + + +BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc,UINT fuPlanes) +{ + if(ctx && WindowFromDC(hdc) == hWND) { + fxMesaSwapBuffers(); + + return(TRUE); + } + + SetLastError(0); + return(FALSE); +} + +int GLAPIENTRY wglChoosePixelFormat(HDC hdc, + CONST PIXELFORMATDESCRIPTOR *ppfd) +{ + int i,best=-1,qt_valid_pix; + + qt_valid_pix = qt_pix; + + if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1) { + SetLastError(0); + return(0); + } + + for(i = 0;i < qt_valid_pix;i++) { + if((ppfd->dwFlags & PFD_DRAW_TO_WINDOW) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW)) + continue; + if((ppfd->dwFlags & PFD_DRAW_TO_BITMAP) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP)) + continue; + if((ppfd->dwFlags & PFD_SUPPORT_GDI) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI)) + continue; + if((ppfd->dwFlags & PFD_SUPPORT_OPENGL) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL)) + continue; + if(!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && + ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER))) + continue; + if(!(ppfd->dwFlags & PFD_STEREO_DONTCARE) && + ((ppfd->dwFlags & PFD_STEREO) != (pix[i].pfd.dwFlags & PFD_STEREO))) + continue; + + if (ppfd->cDepthBits > 0 && pix[i].pfd.cDepthBits == 0) + continue; /* need depth buffer */ + + if (ppfd->cAlphaBits > 0 && pix[i].pfd.cAlphaBits == 0) + continue; /* need alpha buffer */ + + if(ppfd->iPixelType == pix[i].pfd.iPixelType) { + best = i + 1; + break; + } + } + + if(best == -1) { + SetLastError(0); + return(0); + } + + return(best); +} + +int GLAPIENTRY ChoosePixelFormat(HDC hdc, + CONST PIXELFORMATDESCRIPTOR *ppfd) +{ + return wglChoosePixelFormat(hdc,ppfd); +} + +int GLAPIENTRY wglDescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes, + LPPIXELFORMATDESCRIPTOR ppfd) +{ + int qt_valid_pix; + + qt_valid_pix = qt_pix; + + if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || + ((nBytes != sizeof(PIXELFORMATDESCRIPTOR)) && (nBytes != 0))) { + SetLastError(0); + return(0); + } + + if(nBytes != 0) + *ppfd = pix[iPixelFormat - 1].pfd; + + return(qt_valid_pix); +} + +int GLAPIENTRY DescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes, + LPPIXELFORMATDESCRIPTOR ppfd) +{ + return wglDescribePixelFormat(hdc,iPixelFormat,nBytes,ppfd); +} + +int GLAPIENTRY wglGetPixelFormat(HDC hdc) +{ + if(curPFD == 0) { + SetLastError(0); + return(0); + } + + return(curPFD); +} + +int GLAPIENTRY GetPixelFormat(HDC hdc) +{ + return wglGetPixelFormat(hdc); +} + +BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat, + CONST PIXELFORMATDESCRIPTOR *ppfd) +{ + int qt_valid_pix; + + qt_valid_pix = qt_pix; + + if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR)) { + SetLastError(0); + return(FALSE); + } + curPFD = iPixelFormat; + + return(TRUE); +} + +BOOL GLAPIENTRY wglSwapBuffers(HDC hdc) +{ + if(!ctx) { + SetLastError(0); + return(FALSE); + } + + fxMesaSwapBuffers(); + + if(gdiWindowHack) { + GLuint width=ctx->width; + GLuint height=ctx->height; + + HDC hdcScreen = GetDC(dibWnd); + HDC hdcDIBSection = CreateCompatibleDC(hdcScreen); + HBITMAP holdBitmap = (HBITMAP) SelectObject(hdcDIBSection, dibHBM); + + FX_grLfbReadRegion(GR_BUFFER_FRONTBUFFER, 0, 0, + width, height, + width * 2, + dibSurfacePtr); + + /* Since the hardware is configured for GR_COLORFORMAT_ABGR the pixel data is + * going to come out as BGR 565, which is reverse of what we need for blitting + * to screen, so we need to convert it here pixel-by-pixel (ick). This loop would NOT + * be required if the color format was changed to GR_COLORFORMAT_ARGB, but I do + * not know the ramifications of that, so this will work until that is resolved. + * + * This routine CRIES out for MMX implementation, however since that's not + * guaranteed to be running on MMX enabled hardware so I'm not going to do + * that. I'm just going to try to make a reasonably efficient C + * version. -TAJ + * + * This routine drops frame rate by <1 fps on a 200Mhz MMX processor with a 640x480 + * display. Obviously, it's performance hit will be higher on larger displays and + * less on smaller displays. To support the window-hack display this is probably fine. + */ +#if FXMESA_USE_ARGB + { + unsigned long *pixel = dibSurfacePtr; + unsigned long count = (width * height) / 2; + + while (count--) + { + *pixel++ = (*pixel & 0x07e007e0) /* greens */ + | ((*pixel & 0xf800f800) >> 11) /* swap blues */ + | ((*pixel & 0x001f001f) << 11) /* swap reds */ + ; + } + } +#endif + + BitBlt(hdcScreen, 0, 0, + width, height, + hdcDIBSection, + 0, 0, SRCCOPY); + + ReleaseDC(dibWnd, hdcScreen); + SelectObject(hdcDIBSection, holdBitmap); + DeleteDC(hdcDIBSection); + } + + return(TRUE); +} + +BOOL GLAPIENTRY SetPixelFormat(HDC hdc, int iPixelFormat, + CONST PIXELFORMATDESCRIPTOR *ppfd) +{ + return wglSetPixelFormat(hdc,iPixelFormat,ppfd); +} + +BOOL GLAPIENTRY SwapBuffers(HDC hdc) +{ + return wglSwapBuffers(hdc); +} + +#endif /* FX */ |