3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
29 * Thank you for your contribution, David!
31 * Please make note of the above copyright/license statement. If you
32 * contributed code or bug fixes to this code under the previous (GNU
33 * Library) license and object to the new license, your code will be
34 * removed at your request. Please see the Mesa docs/COPYRIGHT file
35 * for more information.
37 * Additional Mesa/3Dfx driver developers:
38 * Daryll Strauss <daryll@precisioninsight.com>
39 * Keith Whitwell <keith@precisioninsight.com>
41 * See fxapi.h for more revision/author details.
45 /* fxdd.c - 3Dfx VooDoo Mesa device driver functions */
58 #include "extensions.h"
60 #include "swrast/swrast.h"
61 #include "swrast_setup/swrast_setup.h"
63 #include "tnl/t_pipeline.h"
64 #include "array_cache/acache.h"
68 float gl_ubyte_to_float_255_color_tab
[256];
70 /* These lookup table are used to extract RGB values in [0,255] from
71 * 16-bit pixel values.
73 GLubyte FX_PixelToR
[0x10000];
74 GLubyte FX_PixelToG
[0x10000];
75 GLubyte FX_PixelToB
[0x10000];
79 * Initialize the FX_PixelTo{RGB} arrays.
80 * Input: bgrOrder - if TRUE, pixels are in BGR order, else RGB order.
82 void fxInitPixelTables(fxMesaContext fxMesa
, GLboolean bgrOrder
)
86 fxMesa
->bgrOrder
=bgrOrder
;
87 for (pixel
= 0; pixel
<= 0xffff; pixel
++) {
90 r
= (pixel
& 0x001F) << 3;
91 g
= (pixel
& 0x07E0) >> 3;
92 b
= (pixel
& 0xF800) >> 8;
95 r
= (pixel
& 0xF800) >> 8;
96 g
= (pixel
& 0x07E0) >> 3;
97 b
= (pixel
& 0x001F) << 3;
99 r
= r
* 255 / 0xF8; /* fill in low-order bits */
102 FX_PixelToR
[pixel
] = r
;
103 FX_PixelToG
[pixel
] = g
;
104 FX_PixelToB
[pixel
] = b
;
109 /**********************************************************************/
110 /***** Miscellaneous functions *****/
111 /**********************************************************************/
113 /* Return buffer size information */
114 static void fxDDBufferSize(GLcontext
*ctx
, GLuint
*width
, GLuint
*height
)
116 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
118 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
119 fprintf(stderr
,"fxmesa: fxDDBufferSize(...) Start\n");
122 *width
=fxMesa
->width
;
123 *height
=fxMesa
->height
;
125 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
126 fprintf(stderr
,"fxmesa: fxDDBufferSize(...) End\n");
131 /* Implements glClearColor() */
132 static void fxDDClearColor(GLcontext
*ctx
, const GLchan color
[4])
134 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
137 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
138 fprintf(stderr
,"fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",
139 color
[0], color
[1], color
[2], color
[3]);
142 ASSIGN_4V( col
, color
[0], color
[1], color
[2], 255 );
143 fxMesa
->clearC
= FXCOLOR4( col
);
144 fxMesa
->clearA
= color
[3];
148 /* Clear the color and/or depth buffers */
149 static void fxDDClear(GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
150 GLint x
, GLint y
, GLint width
, GLint height
)
152 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
153 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
154 const FxU16 clearD
= (FxU16
) (ctx
->Depth
.Clear
* 0xffff);
155 GLbitfield softwareMask
= mask
& (DD_STENCIL_BIT
| DD_ACCUM_BIT
);
157 /* we can't clear stencil or accum buffers */
158 mask
&= ~(DD_STENCIL_BIT
| DD_ACCUM_BIT
);
160 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
161 fprintf(stderr
,"fxmesa: fxDDClear(%d,%d,%d,%d)\n", (int) x
, (int) y
,
162 (int) width
, (int) height
);
165 if (colorMask
!= 0xffffffff) {
166 /* do masked color buffer clears in software */
167 softwareMask
|= (mask
& (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
));
168 mask
&= ~(DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
);
172 * This could probably be done fancier but doing each possible case
173 * explicitly is less error prone.
176 case DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
:
177 /* back buffer & depth */
178 FX_grDepthMask(FXTRUE
);
179 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
180 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
181 if (!ctx
->Depth
.Mask
) {
182 FX_grDepthMask(FXFALSE
);
185 case DD_FRONT_LEFT_BIT
| DD_DEPTH_BIT
:
186 /* XXX it appears that the depth buffer isn't cleared when
187 * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set.
188 * This is a work-around/
191 FX_grDepthMask(FXTRUE
);
192 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
193 FX_grColorMask(FXFALSE
,FXFALSE
);
194 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
196 FX_grColorMask(FXTRUE
, ctx
->Color
.ColorMask
[ACOMP
] && fxMesa
->haveAlphaBuffer
);
197 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
198 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
200 case DD_BACK_LEFT_BIT
:
201 /* back buffer only */
202 FX_grDepthMask(FXFALSE
);
203 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
204 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
205 if (ctx
->Depth
.Mask
) {
206 FX_grDepthMask(FXTRUE
);
209 case DD_FRONT_LEFT_BIT
:
210 /* front buffer only */
211 FX_grDepthMask(FXFALSE
);
212 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
213 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
214 if (ctx
->Depth
.Mask
) {
215 FX_grDepthMask(FXTRUE
);
218 case DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
:
220 FX_grDepthMask(FXFALSE
);
221 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
222 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
223 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
224 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
225 if (ctx
->Depth
.Mask
) {
226 FX_grDepthMask(FXTRUE
);
229 case DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
:
231 FX_grDepthMask(FXFALSE
);
232 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
233 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
234 /* clear back and depth */
235 FX_grDepthMask(FXTRUE
);
236 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
237 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
238 if (!ctx
->Depth
.Mask
) {
239 FX_grDepthMask(FXFALSE
);
243 /* just the depth buffer */
244 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
245 FX_grColorMask(FXFALSE
,FXFALSE
);
246 FX_grDepthMask(FXTRUE
);
247 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
248 FX_grColorMask(FXTRUE
, ctx
->Color
.ColorMask
[ACOMP
] && fxMesa
->haveAlphaBuffer
);
249 if (ctx
->Color
.DrawDestMask
& FRONT_LEFT_BIT
)
250 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
251 if (!ctx
->Depth
.Test
|| !ctx
->Depth
.Mask
)
252 FX_grDepthMask(FXFALSE
);
259 /* Clear any remaining buffers:
262 _swrast_Clear( ctx
, softwareMask
, all
, x
, y
, width
, height
);
266 /* Set the buffer used for drawing */
267 /* XXX support for separate read/draw buffers hasn't been tested */
268 static GLboolean
fxDDSetDrawBuffer(GLcontext
*ctx
, GLenum mode
)
270 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
272 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
273 fprintf(stderr
,"fxmesa: fxDDSetBuffer(%x)\n", (int) mode
);
276 if (mode
== GL_FRONT_LEFT
) {
277 fxMesa
->currentFB
= GR_BUFFER_FRONTBUFFER
;
278 FX_grRenderBuffer(fxMesa
->currentFB
);
281 else if (mode
== GL_BACK_LEFT
) {
282 fxMesa
->currentFB
= GR_BUFFER_BACKBUFFER
;
283 FX_grRenderBuffer(fxMesa
->currentFB
);
286 else if (mode
== GL_NONE
) {
287 FX_grColorMask(FXFALSE
,FXFALSE
);
296 /* Set the buffer used for reading */
297 /* XXX support for separate read/draw buffers hasn't been tested */
298 static void fxDDSetReadBuffer(GLcontext
*ctx
, GLframebuffer
*buffer
,
301 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
304 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
305 fprintf(stderr
,"fxmesa: fxDDSetBuffer(%x)\n", (int) mode
);
308 if (mode
== GL_FRONT_LEFT
) {
309 fxMesa
->currentFB
= GR_BUFFER_FRONTBUFFER
;
310 FX_grRenderBuffer(fxMesa
->currentFB
);
312 else if (mode
== GL_BACK_LEFT
) {
313 fxMesa
->currentFB
= GR_BUFFER_BACKBUFFER
;
314 FX_grRenderBuffer(fxMesa
->currentFB
);
320 static void fxDDDrawBitmap(GLcontext
*ctx
, GLint px
, GLint py
,
321 GLsizei width
, GLsizei height
,
322 const struct gl_pixelstore_attrib
*unpack
,
323 const GLubyte
*bitmap
)
325 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
328 const struct gl_pixelstore_attrib
*finalUnpack
;
329 struct gl_pixelstore_attrib scissoredUnpack
;
331 /* check if there's any raster operations enabled which we can't handle */
332 if (ctx
->Color
.AlphaEnabled
||
333 ctx
->Color
.BlendEnabled
||
336 ctx
->Color
.ColorLogicOpEnabled
||
337 ctx
->Stencil
.Enabled
||
338 ctx
->Scissor
.Enabled
||
339 ( ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
&&
340 ctx
->Color
.ColorMask
[ACOMP
]) ||
341 ctx
->Color
.MultiDrawBuffer
)
343 _swrast_Bitmap( ctx
, px
, py
, width
, height
, unpack
, bitmap
);
348 if (ctx
->Scissor
.Enabled
) {
349 /* This is a bit tricky, but by carefully adjusting the px, py,
350 * width, height, skipPixels and skipRows values we can do
351 * scissoring without special code in the rendering loop.
353 * KW: This code is never reached, see the test above.
356 /* we'll construct a new pixelstore struct */
357 finalUnpack
= &scissoredUnpack
;
358 scissoredUnpack
= *unpack
;
359 if (scissoredUnpack
.RowLength
== 0)
360 scissoredUnpack
.RowLength
= width
;
363 if (px
< ctx
->Scissor
.X
) {
364 scissoredUnpack
.SkipPixels
+= (ctx
->Scissor
.X
- px
);
365 width
-= (ctx
->Scissor
.X
- px
);
369 if (px
+ width
>= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
) {
370 width
-= (px
+ width
- (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
));
373 if (py
< ctx
->Scissor
.Y
) {
374 scissoredUnpack
.SkipRows
+= (ctx
->Scissor
.Y
- py
);
375 height
-= (ctx
->Scissor
.Y
- py
);
379 if (py
+ height
>= ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
) {
380 height
-= (py
+ height
- (ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
));
383 if (width
<= 0 || height
<= 0)
387 finalUnpack
= unpack
;
390 /* compute pixel value */
392 GLint r
= (GLint
) (ctx
->Current
.RasterColor
[0] * 255.0f
);
393 GLint g
= (GLint
) (ctx
->Current
.RasterColor
[1] * 255.0f
);
394 GLint b
= (GLint
) (ctx
->Current
.RasterColor
[2] * 255.0f
);
395 /*GLint a = (GLint)(ctx->Current.RasterColor[3]*255.0f);*/
396 if (fxMesa
->bgrOrder
)
398 ( ((FxU16
)0xf8 & b
) << (11-3)) |
399 ( ((FxU16
)0xfc & g
) << (5-3+1)) |
400 ( ((FxU16
)0xf8 & r
) >> 3);
403 ( ((FxU16
)0xf8 & r
) << (11-3)) |
404 ( ((FxU16
)0xfc & g
) << (5-3+1)) |
405 ( ((FxU16
)0xf8 & b
) >> 3);
408 info
.size
= sizeof(info
);
409 if (!FX_grLfbLock(GR_LFB_WRITE_ONLY
,
412 GR_ORIGIN_UPPER_LEFT
,
416 fprintf(stderr
,"fx Driver: error locking the linear frame buffer\n");
422 const GLint winX
= 0;
423 const GLint winY
= fxMesa
->height
- 1;
424 /* The dest stride depends on the hardware and whether we're drawing
425 * to the front or back buffer. This compile-time test seems to do
428 const GLint dstStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
431 /* compute dest address of bottom-left pixel in bitmap */
432 GLushort
*dst
= (GLushort
*) info
.lfbPtr
433 + (winY
- py
) * dstStride
436 for (row
= 0; row
< height
; row
++) {
437 const GLubyte
*src
= (const GLubyte
*) _mesa_image_address( finalUnpack
,
438 bitmap
, width
, height
, GL_COLOR_INDEX
, GL_BITMAP
, 0, row
, 0 );
439 if (finalUnpack
->LsbFirst
) {
440 /* least significan bit first */
441 GLubyte mask
= 1U << (finalUnpack
->SkipPixels
& 0x7);
443 for (col
=0; col
<width
; col
++) {
459 /* most significan bit first */
460 GLubyte mask
= 128U >> (finalUnpack
->SkipPixels
& 0x7);
462 for (col
=0; col
<width
; col
++) {
481 FX_grLfbUnlock(GR_LFB_WRITE_ONLY
,fxMesa
->currentFB
);
485 static void fxDDReadPixels( GLcontext
*ctx
, GLint x
, GLint y
,
486 GLsizei width
, GLsizei height
,
487 GLenum format
, GLenum type
,
488 const struct gl_pixelstore_attrib
*packing
,
491 if (ctx
->_ImageTransferState
) {
492 _swrast_ReadPixels( ctx
, x
, y
, width
, height
, format
, type
,
497 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
501 if (grLfbLock(GR_LFB_READ_ONLY
,
504 GR_ORIGIN_UPPER_LEFT
,
507 const GLint winX
= 0;
508 const GLint winY
= fxMesa
->height
- 1;
509 const GLint srcStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
510 const GLushort
*src
= (const GLushort
*) info
.lfbPtr
511 + (winY
- y
) * srcStride
+ (winX
+ x
);
512 GLubyte
*dst
= (GLubyte
*) _mesa_image_address(packing
, dstImage
,
513 width
, height
, format
, type
, 0, 0, 0);
514 GLint dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
516 if (format
== GL_RGB
&& type
== GL_UNSIGNED_BYTE
) {
517 /* convert 5R6G5B into 8R8G8B */
519 const GLint halfWidth
= width
>> 1;
520 const GLint extraPixel
= (width
& 1);
521 for (row
= 0; row
< height
; row
++) {
523 for (col
= 0; col
< halfWidth
; col
++) {
524 const GLuint pixel
= ((const GLuint
*) src
)[col
];
525 const GLint pixel0
= pixel
& 0xffff;
526 const GLint pixel1
= pixel
>> 16;
527 *d
++ = FX_PixelToR
[pixel0
];
528 *d
++ = FX_PixelToG
[pixel0
];
529 *d
++ = FX_PixelToB
[pixel0
];
530 *d
++ = FX_PixelToR
[pixel1
];
531 *d
++ = FX_PixelToG
[pixel1
];
532 *d
++ = FX_PixelToB
[pixel1
];
535 GLushort pixel
= src
[width
-1];
536 *d
++ = FX_PixelToR
[pixel
];
537 *d
++ = FX_PixelToG
[pixel
];
538 *d
++ = FX_PixelToB
[pixel
];
544 else if (format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) {
545 /* convert 5R6G5B into 8R8G8B8A */
547 const GLint halfWidth
= width
>> 1;
548 const GLint extraPixel
= (width
& 1);
549 for (row
= 0; row
< height
; row
++) {
551 for (col
= 0; col
< halfWidth
; col
++) {
552 const GLuint pixel
= ((const GLuint
*) src
)[col
];
553 const GLint pixel0
= pixel
& 0xffff;
554 const GLint pixel1
= pixel
>> 16;
555 *d
++ = FX_PixelToR
[pixel0
];
556 *d
++ = FX_PixelToG
[pixel0
];
557 *d
++ = FX_PixelToB
[pixel0
];
559 *d
++ = FX_PixelToR
[pixel1
];
560 *d
++ = FX_PixelToG
[pixel1
];
561 *d
++ = FX_PixelToB
[pixel1
];
565 const GLushort pixel
= src
[width
-1];
566 *d
++ = FX_PixelToR
[pixel
];
567 *d
++ = FX_PixelToG
[pixel
];
568 *d
++ = FX_PixelToB
[pixel
];
575 else if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
576 /* directly memcpy 5R6G5B pixels into client's buffer */
577 const GLint widthInBytes
= width
* 2;
579 for (row
= 0; row
< height
; row
++) {
580 MEMCPY(dst
, src
, widthInBytes
);
586 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
588 _swrast_ReadPixels( ctx
, x
, y
, width
, height
, format
, type
,
593 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
601 static void fxDDFinish(GLcontext
*ctx
)
610 /* KW: Put the word Mesa in the render string because quakeworld
611 * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
614 static const GLubyte
*fxDDGetString(GLcontext
*ctx
, GLenum name
)
621 if (glbHWConfig
.SSTs
[glbCurrentBoard
].type
==GR_SSTTYPE_VOODOO
) {
622 GrVoodooConfig_t
*vc
=
623 &glbHWConfig
.SSTs
[glbCurrentBoard
].sstBoard
.VoodooConfig
;
626 "Mesa Glide v0.30 Voodoo_Graphics %d "
627 "CARD/%d FB/%d TM/%d TMU/%s",
629 (vc
->sliDetect
? (vc
->fbRam
*2) : vc
->fbRam
),
630 (vc
->tmuConfig
[GR_TMU0
].tmuRam
+
631 ((vc
->nTexelfx
>1) ? vc
->tmuConfig
[GR_TMU1
].tmuRam
: 0)),
633 (vc
->sliDetect
? "SLI" : "NOSLI"));
635 else if (glbHWConfig
.SSTs
[glbCurrentBoard
].type
==GR_SSTTYPE_SST96
) {
636 GrSst96Config_t
*sc
=
637 &glbHWConfig
.SSTs
[glbCurrentBoard
].sstBoard
.SST96Config
;
640 "Glide v0.30 Voodoo_Rush %d "
641 "CARD/%d FB/%d TM/%d TMU/NOSLI",
644 sc
->tmuConfig
.tmuRam
,
648 strcpy(buf
, "Glide v0.30 UNKNOWN");
650 return (GLubyte
*) buf
;
657 static const struct gl_pipeline_stage
*fx_pipeline
[] = {
658 &_tnl_vertex_transform_stage
, /* TODO: Add the fastpath here */
659 &_tnl_normal_transform_stage
,
660 &_tnl_lighting_stage
,
661 &_tnl_fog_coordinate_stage
, /* TODO: Omit fog stage */
663 &_tnl_texture_transform_stage
,
664 &_tnl_point_attenuation_stage
,
672 int fxDDInitFxMesaContext( fxMesaContext fxMesa
)
675 static int firsttime
= 1;
677 for (i
= 0 ; i
< 256 ; i
++) {
678 gl_ubyte_to_float_255_color_tab
[i
] = (float) i
;
687 FX_setupGrVertexLayout();
689 if (getenv("FX_EMULATE_SINGLE_TMU"))
690 fxMesa
->haveTwoTMUs
= GL_FALSE
;
692 fxMesa
->emulateTwoTMUs
= fxMesa
->haveTwoTMUs
;
694 if (!getenv("FX_DONT_FAKE_MULTITEX"))
695 fxMesa
->emulateTwoTMUs
= GL_TRUE
;
697 if(getenv("FX_GLIDE_SWAPINTERVAL"))
698 fxMesa
->swapInterval
=atoi(getenv("FX_GLIDE_SWAPINTERVAL"));
700 fxMesa
->swapInterval
=1;
702 if(getenv("MESA_FX_SWAP_PENDING"))
703 fxMesa
->maxPendingSwapBuffers
=atoi(getenv("MESA_FX_SWAP_PENDING"));
705 fxMesa
->maxPendingSwapBuffers
=2;
707 if(getenv("MESA_FX_INFO"))
708 fxMesa
->verbose
=GL_TRUE
;
710 fxMesa
->verbose
=GL_FALSE
;
712 fxMesa
->color
=0xffffffff;
716 fxMesa
->stats
.swapBuffer
=0;
717 fxMesa
->stats
.reqTexUpload
=0;
718 fxMesa
->stats
.texUpload
=0;
719 fxMesa
->stats
.memTexUpload
=0;
721 fxMesa
->tmuSrc
=FX_TMU_NONE
;
722 fxMesa
->lastUnitsMode
=FX_UM_NONE
;
727 fxMesa
->unitsState
.alphaTestEnabled
=GL_FALSE
;
728 fxMesa
->unitsState
.alphaTestFunc
=GR_CMP_ALWAYS
;
729 fxMesa
->unitsState
.alphaTestRefValue
=0;
731 fxMesa
->unitsState
.blendEnabled
=GL_FALSE
;
732 fxMesa
->unitsState
.blendSrcFuncRGB
=GR_BLEND_ONE
;
733 fxMesa
->unitsState
.blendDstFuncRGB
=GR_BLEND_ZERO
;
734 fxMesa
->unitsState
.blendSrcFuncAlpha
=GR_BLEND_ONE
;
735 fxMesa
->unitsState
.blendDstFuncAlpha
=GR_BLEND_ZERO
;
737 fxMesa
->unitsState
.depthTestEnabled
=GL_FALSE
;
738 fxMesa
->unitsState
.depthMask
=GL_TRUE
;
739 fxMesa
->unitsState
.depthTestFunc
=GR_CMP_LESS
;
741 FX_grColorMask(FXTRUE
, fxMesa
->haveAlphaBuffer
? FXTRUE
: FXFALSE
);
742 if(fxMesa
->haveDoubleBuffer
) {
743 fxMesa
->currentFB
=GR_BUFFER_BACKBUFFER
;
744 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
746 fxMesa
->currentFB
=GR_BUFFER_FRONTBUFFER
;
747 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
750 fxMesa
->state
= malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE
));
751 fxMesa
->fogTable
= malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES
) *
754 if (!fxMesa
->state
|| !fxMesa
->fogTable
) {
755 if (fxMesa
->state
) free(fxMesa
->state
);
756 if (fxMesa
->fogTable
) free(fxMesa
->fogTable
);
760 if(fxMesa
->haveZBuffer
)
761 FX_grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER
);
763 #if (!FXMESA_USE_ARGB)
764 FX_grLfbWriteColorFormat(GR_COLORFORMAT_ABGR
); /* Not every Glide has this */
767 fxMesa
->textureAlign
=FX_grGetInteger(FX_TEXTURE_ALIGN
);
768 fxMesa
->glCtx
->Const
.MaxTextureLevels
=9;
769 fxMesa
->glCtx
->Const
.MaxTextureSize
=256;
770 fxMesa
->glCtx
->Const
.MaxTextureUnits
=fxMesa
->emulateTwoTMUs
? 2 : 1;
771 fxMesa
->new_state
= _NEW_ALL
;
773 /* Initialize the software rasterizer and helper modules.
775 _swrast_CreateContext( fxMesa
->glCtx
);
776 _ac_CreateContext( fxMesa
->glCtx
);
777 _tnl_CreateContext( fxMesa
->glCtx
);
778 _swsetup_CreateContext( fxMesa
->glCtx
);
780 _tnl_destroy_pipeline( fxMesa
->glCtx
);
781 _tnl_install_pipeline( fxMesa
->glCtx
, fx_pipeline
);
783 fxAllocVB( fxMesa
->glCtx
);
785 fxSetupDDPointers(fxMesa
->glCtx
);
787 /* Tell the software rasterizer to use pixel fog always.
789 _swrast_allow_vertex_fog( fxMesa
->glCtx
, GL_FALSE
);
790 _swrast_allow_pixel_fog( fxMesa
->glCtx
, GL_TRUE
);
792 /* Tell tnl not to calculate or use vertex fog factors. (Needed to
793 * tell render stage not to clip fog coords).
795 /* _tnl_calculate_vertex_fog( fxMesa->glCtx, GL_FALSE ); */
797 fxDDInitExtensions(fxMesa
->glCtx
);
800 fxDDInitVtxfmt(fxMesa
->glCtx
);
803 FX_grGlideGetState((GrState
*)fxMesa
->state
);
805 /* Run the config file */
806 _mesa_context_initialize( fxMesa
->glCtx
);
813 void fxDDDestroyFxMesaContext( fxMesaContext fxMesa
)
815 _swsetup_DestroyContext( fxMesa
->glCtx
);
816 _tnl_DestroyContext( fxMesa
->glCtx
);
817 _ac_DestroyContext( fxMesa
->glCtx
);
818 _swrast_DestroyContext( fxMesa
->glCtx
);
822 if (fxMesa
->fogTable
)
823 free(fxMesa
->fogTable
);
825 fxFreeVB(fxMesa
->glCtx
);
831 void fxDDInitExtensions( GLcontext
*ctx
)
833 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
835 _mesa_add_extension(ctx
, GL_TRUE
, "3DFX_set_global_palette", 0);
836 _mesa_enable_extension(ctx
, "GL_EXT_point_parameters");
838 if (fxMesa
->haveTwoTMUs
)
839 _mesa_enable_extension(ctx
, "GL_EXT_texture_env_add");
841 if (fxMesa
->emulateTwoTMUs
)
842 _mesa_enable_extension(ctx
, "GL_ARB_multitexture");
846 /************************************************************************/
847 /************************************************************************/
848 /************************************************************************/
850 /* Check if the hardware supports the current context
852 * Performs similar work to fxDDChooseRenderState() - should be merged.
854 static GLboolean
fxIsInHardware(GLcontext
*ctx
)
856 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
858 if (ctx
->RenderMode
!= GL_RENDER
)
861 if (ctx
->Stencil
.Enabled
||
862 ctx
->Color
.MultiDrawBuffer
||
863 ((ctx
->Color
.BlendEnabled
) && (ctx
->Color
.BlendEquation
!=GL_FUNC_ADD_EXT
)) ||
864 ((ctx
->Color
.ColorLogicOpEnabled
) && (ctx
->Color
.LogicOp
!=GL_COPY
)) ||
865 (ctx
->Light
.Model
.ColorControl
==GL_SEPARATE_SPECULAR_COLOR
) ||
866 (!((ctx
->Color
.ColorMask
[RCOMP
]==ctx
->Color
.ColorMask
[GCOMP
]) &&
867 (ctx
->Color
.ColorMask
[GCOMP
]==ctx
->Color
.ColorMask
[BCOMP
]) &&
868 (ctx
->Color
.ColorMask
[ACOMP
]==ctx
->Color
.ColorMask
[ACOMP
])))
873 /* Unsupported texture/multitexture cases */
875 if (fxMesa
->emulateTwoTMUs
) {
876 if (ctx
->Texture
._ReallyEnabled
& (TEXTURE0_3D
| TEXTURE1_3D
))
877 return GL_FALSE
; /* can't do 3D textures */
878 if (ctx
->Texture
._ReallyEnabled
& (TEXTURE0_1D
| TEXTURE1_1D
))
879 return GL_FALSE
; /* can't do 1D textures */
881 if (ctx
->Texture
._ReallyEnabled
& TEXTURE0_2D
) {
882 if (ctx
->Texture
.Unit
[0].EnvMode
== GL_BLEND
&&
883 (ctx
->Texture
._ReallyEnabled
& TEXTURE1_2D
||
884 ctx
->Texture
.Unit
[0].EnvColor
[0] != 0 ||
885 ctx
->Texture
.Unit
[0].EnvColor
[1] != 0 ||
886 ctx
->Texture
.Unit
[0].EnvColor
[2] != 0 ||
887 ctx
->Texture
.Unit
[0].EnvColor
[3] != 1)) {
890 if (ctx
->Texture
.Unit
[0]._Current
->Image
[0]->Border
> 0)
894 if (ctx
->Texture
._ReallyEnabled
& TEXTURE1_2D
) {
895 if (ctx
->Texture
.Unit
[1].EnvMode
== GL_BLEND
)
897 if (ctx
->Texture
.Unit
[0]._Current
->Image
[0]->Border
> 0)
901 if (MESA_VERBOSE
& (VERBOSE_DRIVER
|VERBOSE_TEXTURE
))
902 fprintf(stderr
, "fxMesa: fxIsInHardware, envmode is %s/%s\n",
903 gl_lookup_enum_by_nr(ctx
->Texture
.Unit
[0].EnvMode
),
904 gl_lookup_enum_by_nr(ctx
->Texture
.Unit
[1].EnvMode
));
906 /* KW: This was wrong (I think) and I changed it... which doesn't mean
907 * it is now correct...
909 if((ctx
->_Enabled
& (TEXTURE0_1D
| TEXTURE0_2D
| TEXTURE0_3D
)) &&
910 (ctx
->_Enabled
& (TEXTURE1_1D
| TEXTURE1_2D
| TEXTURE1_3D
)))
912 /* Can't use multipass to blend a multitextured triangle - fall
915 if (!fxMesa
->haveTwoTMUs
&& ctx
->Color
.BlendEnabled
) {
919 if ((ctx
->Texture
.Unit
[0].EnvMode
!=ctx
->Texture
.Unit
[1].EnvMode
) &&
920 (ctx
->Texture
.Unit
[0].EnvMode
!=GL_MODULATE
) &&
921 (ctx
->Texture
.Unit
[0].EnvMode
!=GL_REPLACE
)) /* q2, seems ok... */
923 if (MESA_VERBOSE
&VERBOSE_DRIVER
)
924 fprintf(stderr
, "fxMesa: unsupported multitex env mode\n");
929 if((ctx
->_Enabled
& (TEXTURE1_1D
| TEXTURE1_2D
| TEXTURE1_3D
)) ||
930 /* Not very well written ... */
931 ((ctx
->_Enabled
& TEXTURE0_1D
) &&
932 (!(ctx
->_Enabled
& TEXTURE0_2D
)))
938 if((ctx
->Texture
._ReallyEnabled
& TEXTURE0_2D
) &&
939 (ctx
->Texture
.Unit
[0].EnvMode
==GL_BLEND
)) {
947 static void update_texture_scales( GLcontext
*ctx
)
949 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
950 struct gl_texture_unit
*t0
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[0]];
951 struct gl_texture_unit
*t1
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[1]];
953 if (t0
&& t0
->_Current
&& FX_TEXTURE_DATA(t0
)) {
954 fxMesa
->s0scale
= FX_TEXTURE_DATA(t0
)->sScale
;
955 fxMesa
->t0scale
= FX_TEXTURE_DATA(t0
)->tScale
;
956 fxMesa
->inv_s0scale
= 1.0 / fxMesa
->s0scale
;
957 fxMesa
->inv_t0scale
= 1.0 / fxMesa
->t0scale
;
960 if (t1
&& t1
->_Current
&& FX_TEXTURE_DATA(t1
)) {
961 fxMesa
->s1scale
= FX_TEXTURE_DATA(t1
)->sScale
;
962 fxMesa
->t1scale
= FX_TEXTURE_DATA(t1
)->tScale
;
963 fxMesa
->inv_s1scale
= 1.0 / fxMesa
->s1scale
;
964 fxMesa
->inv_t1scale
= 1.0 / fxMesa
->t1scale
;
968 static void fxDDUpdateDDPointers(GLcontext
*ctx
, GLuint new_state
)
970 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
972 _swrast_InvalidateState( ctx
, new_state
);
973 _ac_InvalidateState( ctx
, new_state
);
974 _tnl_InvalidateState( ctx
, new_state
);
975 _swsetup_InvalidateState( ctx
, new_state
);
977 /* Recalculate fog table on projection matrix changes. This used to
978 * be triggered by the NearFar callback.
980 if (new_state
& _NEW_PROJECTION
)
981 fxMesa
->new_state
|= FX_NEW_FOG
;
983 if (new_state
& (_FX_NEW_IS_IN_HARDWARE
|
984 _FX_NEW_RENDERSTATE
|
985 _FX_NEW_SETUP_FUNCTION
|
988 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
990 if (new_state
& _FX_NEW_IS_IN_HARDWARE
)
991 fxMesa
->is_in_hardware
= fxIsInHardware(ctx
);
993 if (fxMesa
->new_state
)
996 if (new_state
& _FX_NEW_RENDERSTATE
)
997 fxDDChooseRenderState( ctx
);
999 if (new_state
& _FX_NEW_SETUP_FUNCTION
)
1000 ctx
->Driver
.BuildProjectedVertices
= fx_validate_BuildProjVerts
;
1002 if (new_state
& _NEW_TEXTURE
)
1003 update_texture_scales( ctx
);
1008 if (fxMesa
->allow_vfmt
) {
1009 if (new_state
& _NEW_LIGHT
)
1010 fx_update_lighting( ctx
);
1012 if (new_state
& _FX_NEW_VTXFMT
)
1013 fxDDCheckVtxfmt( ctx
);
1018 static void fxDDRenderPrimitive( GLcontext
*ctx
, GLenum mode
)
1020 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
1022 if (!fxMesa
->is_in_hardware
) {
1023 _swsetup_RenderPrimitive( ctx
, mode
);
1026 fxMesa
->render_prim
= mode
;
1031 static void fxDDRenderStart( GLcontext
*ctx
)
1033 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
1035 _swsetup_RenderStart( ctx
);
1037 if (fxMesa
->new_state
) {
1038 fxSetupFXUnits( ctx
);
1042 static void fxDDRenderFinish( GLcontext
*ctx
)
1044 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
1046 if (!fxMesa
->is_in_hardware
) {
1047 _swsetup_RenderFinish( ctx
);
1053 void fxSetupDDPointers(GLcontext
*ctx
)
1055 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
1056 fprintf(stderr
,"fxmesa: fxSetupDDPointers()\n");
1059 ctx
->Driver
.UpdateState
=fxDDUpdateDDPointers
;
1061 ctx
->Driver
.WriteDepthSpan
=fxDDWriteDepthSpan
;
1062 ctx
->Driver
.WriteDepthPixels
=fxDDWriteDepthPixels
;
1063 ctx
->Driver
.ReadDepthSpan
=fxDDReadDepthSpan
;
1064 ctx
->Driver
.ReadDepthPixels
=fxDDReadDepthPixels
;
1066 ctx
->Driver
.GetString
=fxDDGetString
;
1068 ctx
->Driver
.ClearIndex
=NULL
;
1069 ctx
->Driver
.ClearColor
=fxDDClearColor
;
1070 ctx
->Driver
.Clear
=fxDDClear
;
1072 ctx
->Driver
.SetDrawBuffer
=fxDDSetDrawBuffer
;
1073 ctx
->Driver
.SetReadBuffer
=fxDDSetReadBuffer
;
1074 ctx
->Driver
.GetBufferSize
=fxDDBufferSize
;
1076 ctx
->Driver
.Accum
= _swrast_Accum
;
1077 ctx
->Driver
.Bitmap
= fxDDDrawBitmap
;
1078 ctx
->Driver
.CopyPixels
= _swrast_CopyPixels
;
1079 ctx
->Driver
.DrawPixels
= _swrast_DrawPixels
;
1080 ctx
->Driver
.ReadPixels
= fxDDReadPixels
;
1081 ctx
->Driver
.ResizeBuffersMESA
= _swrast_alloc_buffers
;
1083 ctx
->Driver
.Finish
=fxDDFinish
;
1084 ctx
->Driver
.Flush
=NULL
;
1086 ctx
->Driver
.RenderStart
=fxDDRenderStart
;
1087 ctx
->Driver
.RenderFinish
=fxDDRenderFinish
;
1088 ctx
->Driver
.ResetLineStipple
=_swrast_ResetLineStipple
;
1089 ctx
->Driver
.RenderPrimitive
=fxDDRenderPrimitive
;
1091 /* Install the oldstyle interp functions:
1093 ctx
->Driver
.RenderInterp
= _swsetup_RenderInterp
;
1094 ctx
->Driver
.RenderCopyPV
= _swsetup_RenderCopyPV
;
1095 ctx
->Driver
.RenderClippedLine
= _swsetup_RenderClippedLine
;
1096 ctx
->Driver
.RenderClippedPolygon
= _swsetup_RenderClippedPolygon
;
1098 ctx
->Driver
.TexImage1D
= _mesa_store_teximage1d
;
1099 ctx
->Driver
.TexImage2D
= fxDDTexImage2D
;
1100 ctx
->Driver
.TexImage3D
= _mesa_store_teximage3d
;
1101 ctx
->Driver
.TexSubImage1D
= _mesa_store_texsubimage1d
;
1102 ctx
->Driver
.TexSubImage2D
= fxDDTexSubImage2D
;
1103 ctx
->Driver
.TexSubImage3D
= _mesa_store_texsubimage3d
;
1104 ctx
->Driver
.CopyTexImage1D
= _mesa_copy_teximage1d
;
1105 ctx
->Driver
.CopyTexImage2D
= _mesa_copy_teximage2d
;
1106 ctx
->Driver
.CopyTexSubImage1D
= _mesa_copy_texsubimage1d
;
1107 ctx
->Driver
.CopyTexSubImage2D
= _mesa_copy_texsubimage2d
;
1108 ctx
->Driver
.CopyTexSubImage3D
= _mesa_copy_texsubimage3d
;
1109 ctx
->Driver
.TestProxyTexImage
= _mesa_test_proxy_teximage
;
1111 ctx
->Driver
.TexEnv
= fxDDTexEnv
;
1112 ctx
->Driver
.TexParameter
= fxDDTexParam
;
1113 ctx
->Driver
.BindTexture
= fxDDTexBind
;
1114 ctx
->Driver
.DeleteTexture
= fxDDTexDel
;
1115 ctx
->Driver
.UpdateTexturePalette
= fxDDTexPalette
;
1117 ctx
->Driver
.AlphaFunc
=fxDDAlphaFunc
;
1118 ctx
->Driver
.BlendFunc
=fxDDBlendFunc
;
1119 ctx
->Driver
.DepthFunc
=fxDDDepthFunc
;
1120 ctx
->Driver
.DepthMask
=fxDDDepthMask
;
1121 ctx
->Driver
.ColorMask
=fxDDColorMask
;
1122 ctx
->Driver
.Fogfv
=fxDDFogfv
;
1123 ctx
->Driver
.Scissor
=fxDDScissor
;
1124 ctx
->Driver
.FrontFace
=fxDDFrontFace
;
1125 ctx
->Driver
.CullFace
=fxDDCullFace
;
1126 ctx
->Driver
.ShadeModel
=fxDDShadeModel
;
1127 ctx
->Driver
.Enable
=fxDDEnable
;
1131 fxSetupDDSpanPointers(ctx
);
1132 fxDDUpdateDDPointers(ctx
,~0);
1140 * Need this to provide at least one external definition.
1143 extern int gl_fx_dummy_function_dd(void);
1144 int gl_fx_dummy_function_dd(void)