1 /* $Id: fxdd.c,v 1.91 2002/09/27 02:45:38 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 /* fxdd.c - 3Dfx VooDoo Mesa device driver functions */
47 #include "extensions.h"
49 #include "swrast/swrast.h"
50 #include "swrast_setup/swrast_setup.h"
52 #include "tnl/t_context.h"
53 #include "tnl/t_pipeline.h"
54 #include "array_cache/acache.h"
58 float gl_ubyte_to_float_255_color_tab
[256];
60 /* These lookup table are used to extract RGB values in [0,255] from
61 * 16-bit pixel values.
63 GLubyte FX_PixelToR
[0x10000];
64 GLubyte FX_PixelToG
[0x10000];
65 GLubyte FX_PixelToB
[0x10000];
69 * Initialize the FX_PixelTo{RGB} arrays.
70 * Input: bgrOrder - if TRUE, pixels are in BGR order, else RGB order.
73 fxInitPixelTables(fxMesaContext fxMesa
, GLboolean bgrOrder
)
77 fxMesa
->bgrOrder
= bgrOrder
;
78 for (pixel
= 0; pixel
<= 0xffff; pixel
++) {
81 r
= (pixel
& 0x001F) << 3;
82 g
= (pixel
& 0x07E0) >> 3;
83 b
= (pixel
& 0xF800) >> 8;
86 r
= (pixel
& 0xF800) >> 8;
87 g
= (pixel
& 0x07E0) >> 3;
88 b
= (pixel
& 0x001F) << 3;
90 r
= r
* 255 / 0xF8; /* fill in low-order bits */
93 FX_PixelToR
[pixel
] = r
;
94 FX_PixelToG
[pixel
] = g
;
95 FX_PixelToB
[pixel
] = b
;
100 /**********************************************************************/
101 /***** Miscellaneous functions *****/
102 /**********************************************************************/
104 /* Return buffer size information */
106 fxDDBufferSize(GLframebuffer
*buffer
, GLuint
* width
, GLuint
* height
)
108 GET_CURRENT_CONTEXT(ctx
);
109 if (ctx
&& ctx
->DriverCtx
) {
110 fxMesaContext fxMesa
= (fxMesaContext
) ctx
->DriverCtx
;
112 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
113 fprintf(stderr
, "fxmesa: fxDDBufferSize(...) Start\n");
116 *width
= fxMesa
->width
;
117 *height
= fxMesa
->height
;
119 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
120 fprintf(stderr
, "fxmesa: fxDDBufferSize(...) End\n");
126 /* Implements glClearColor() */
128 fxDDClearColor(GLcontext
* ctx
, const GLchan color
[4])
130 fxMesaContext fxMesa
= (fxMesaContext
) ctx
->DriverCtx
;
133 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
134 fprintf(stderr
, "fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",
135 color
[0], color
[1], color
[2], color
[3]);
138 ASSIGN_4V(col
, color
[0], color
[1], color
[2], 255);
139 fxMesa
->clearC
= FXCOLOR4(col
);
140 fxMesa
->clearA
= color
[3];
144 /* Clear the color and/or depth buffers */
146 fxDDClear(GLcontext
* ctx
, GLbitfield mask
, GLboolean all
,
147 GLint x
, GLint y
, GLint width
, GLint height
)
149 fxMesaContext fxMesa
= (fxMesaContext
) ctx
->DriverCtx
;
150 const GLuint colorMask
= *((GLuint
*) & ctx
->Color
.ColorMask
);
151 const FxU16 clearD
= (FxU16
) (ctx
->Depth
.Clear
* 0xffff);
152 GLbitfield softwareMask
= mask
& (DD_STENCIL_BIT
| DD_ACCUM_BIT
);
154 /* we can't clear stencil or accum buffers */
155 mask
&= ~(DD_STENCIL_BIT
| DD_ACCUM_BIT
);
157 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
158 fprintf(stderr
, "fxmesa: fxDDClear(%d,%d,%d,%d)\n", (int) x
, (int) y
,
159 (int) width
, (int) height
);
162 if (colorMask
!= 0xffffffff) {
163 /* do masked color buffer clears in software */
164 softwareMask
|= (mask
& (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
));
165 mask
&= ~(DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
);
169 * This could probably be done fancier but doing each possible case
170 * explicitly is less error prone.
173 case DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
:
174 /* back buffer & depth */
175 FX_grDepthMask(FXTRUE
);
176 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
177 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
178 if (!ctx
->Depth
.Mask
) {
179 FX_grDepthMask(FXFALSE
);
182 case DD_FRONT_LEFT_BIT
| DD_DEPTH_BIT
:
183 /* XXX it appears that the depth buffer isn't cleared when
184 * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set.
185 * This is a work-around/
188 FX_grDepthMask(FXTRUE
);
189 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
190 FX_grColorMask(FXFALSE
, FXFALSE
);
191 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
193 FX_grColorMask(FXTRUE
, ctx
->Color
.ColorMask
[ACOMP
]
194 && fxMesa
->haveAlphaBuffer
);
195 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
196 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
198 case DD_BACK_LEFT_BIT
:
199 /* back buffer only */
200 FX_grDepthMask(FXFALSE
);
201 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
202 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
203 if (ctx
->Depth
.Mask
) {
204 FX_grDepthMask(FXTRUE
);
207 case DD_FRONT_LEFT_BIT
:
208 /* front buffer only */
209 FX_grDepthMask(FXFALSE
);
210 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
211 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
212 if (ctx
->Depth
.Mask
) {
213 FX_grDepthMask(FXTRUE
);
216 case DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
:
218 FX_grDepthMask(FXFALSE
);
219 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
220 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
221 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
222 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
223 if (ctx
->Depth
.Mask
) {
224 FX_grDepthMask(FXTRUE
);
227 case DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
:
229 FX_grDepthMask(FXFALSE
);
230 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
231 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
232 /* clear back and depth */
233 FX_grDepthMask(FXTRUE
);
234 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
235 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
236 if (!ctx
->Depth
.Mask
) {
237 FX_grDepthMask(FXFALSE
);
241 /* just the depth buffer */
242 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
243 FX_grColorMask(FXFALSE
, FXFALSE
);
244 FX_grDepthMask(FXTRUE
);
245 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
246 FX_grColorMask(FXTRUE
, ctx
->Color
.ColorMask
[ACOMP
]
247 && fxMesa
->haveAlphaBuffer
);
248 if (ctx
->Color
._DrawDestMask
& FRONT_LEFT_BIT
)
249 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
250 if (!ctx
->Depth
.Test
|| !ctx
->Depth
.Mask
)
251 FX_grDepthMask(FXFALSE
);
258 /* Clear any remaining buffers:
261 _swrast_Clear(ctx
, softwareMask
, all
, x
, y
, width
, height
);
265 /* Set the buffer used for drawing */
266 /* XXX support for separate read/draw buffers hasn't been tested */
268 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
);
280 else if (mode
== GL_BACK_LEFT
) {
281 fxMesa
->currentFB
= GR_BUFFER_BACKBUFFER
;
282 FX_grRenderBuffer(fxMesa
->currentFB
);
284 else if (mode
== GL_NONE
) {
285 FX_grColorMask(FXFALSE
, FXFALSE
);
288 /* we'll need a software fallback */
289 /* XXX not implemented */
292 /* update s/w fallback state */
293 _swrast_DrawBuffer(ctx
, mode
);
301 fxDDDrawBitmap(GLcontext
* ctx
, GLint px
, GLint py
,
302 GLsizei width
, GLsizei height
,
303 const struct gl_pixelstore_attrib
*unpack
,
304 const GLubyte
* bitmap
)
306 fxMesaContext fxMesa
= (fxMesaContext
) ctx
->DriverCtx
;
309 const struct gl_pixelstore_attrib
*finalUnpack
;
310 struct gl_pixelstore_attrib scissoredUnpack
;
312 /* check if there's any raster operations enabled which we can't handle */
313 if (ctx
->Color
.AlphaEnabled
||
314 ctx
->Color
.BlendEnabled
||
317 ctx
->Color
.ColorLogicOpEnabled
||
318 ctx
->Stencil
.Enabled
||
319 ctx
->Scissor
.Enabled
||
320 (ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
&&
321 ctx
->Color
.ColorMask
[ACOMP
]) ||
322 (ctx
->Color
._DrawDestMask
!= FRONT_LEFT_BIT
&&
323 ctx
->Color
._DrawDestMask
!= BACK_LEFT_BIT
)) {
324 _swrast_Bitmap(ctx
, px
, py
, width
, height
, unpack
, bitmap
);
329 if (ctx
->Scissor
.Enabled
) {
330 /* This is a bit tricky, but by carefully adjusting the px, py,
331 * width, height, skipPixels and skipRows values we can do
332 * scissoring without special code in the rendering loop.
334 * KW: This code is never reached, see the test above.
337 /* we'll construct a new pixelstore struct */
338 finalUnpack
= &scissoredUnpack
;
339 scissoredUnpack
= *unpack
;
340 if (scissoredUnpack
.RowLength
== 0)
341 scissoredUnpack
.RowLength
= width
;
344 if (px
< ctx
->Scissor
.X
) {
345 scissoredUnpack
.SkipPixels
+= (ctx
->Scissor
.X
- px
);
346 width
-= (ctx
->Scissor
.X
- px
);
350 if (px
+ width
>= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
) {
351 width
-= (px
+ width
- (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
));
354 if (py
< ctx
->Scissor
.Y
) {
355 scissoredUnpack
.SkipRows
+= (ctx
->Scissor
.Y
- py
);
356 height
-= (ctx
->Scissor
.Y
- py
);
360 if (py
+ height
>= ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
) {
361 height
-= (py
+ height
- (ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
));
364 if (width
<= 0 || height
<= 0)
368 finalUnpack
= unpack
;
371 /* compute pixel value */
373 GLint r
= (GLint
) (ctx
->Current
.RasterColor
[0] * 255.0f
);
374 GLint g
= (GLint
) (ctx
->Current
.RasterColor
[1] * 255.0f
);
375 GLint b
= (GLint
) (ctx
->Current
.RasterColor
[2] * 255.0f
);
376 /*GLint a = (GLint)(ctx->Current.RasterColor[3]*255.0f); */
377 if (fxMesa
->bgrOrder
)
379 (((FxU16
) 0xf8 & b
) << (11 - 3)) |
380 (((FxU16
) 0xfc & g
) << (5 - 3 + 1)) | (((FxU16
) 0xf8 & r
) >> 3);
383 (((FxU16
) 0xf8 & r
) << (11 - 3)) |
384 (((FxU16
) 0xfc & g
) << (5 - 3 + 1)) | (((FxU16
) 0xf8 & b
) >> 3);
387 info
.size
= sizeof(info
);
388 if (!FX_grLfbLock(GR_LFB_WRITE_ONLY
,
391 GR_ORIGIN_UPPER_LEFT
, FXFALSE
, &info
)) {
393 fprintf(stderr
, "fx Driver: error locking the linear frame buffer\n");
399 const GLint winX
= 0;
400 const GLint winY
= fxMesa
->height
- 1;
401 /* The dest stride depends on the hardware and whether we're drawing
402 * to the front or back buffer. This compile-time test seems to do
405 const GLint dstStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
408 /* compute dest address of bottom-left pixel in bitmap */
409 GLushort
*dst
= (GLushort
*) info
.lfbPtr
410 + (winY
- py
) * dstStride
+ (winX
+ px
);
412 for (row
= 0; row
< height
; row
++) {
414 (const GLubyte
*) _mesa_image_address(finalUnpack
,
415 bitmap
, width
, height
,
416 GL_COLOR_INDEX
, GL_BITMAP
,
418 if (finalUnpack
->LsbFirst
) {
419 /* least significan bit first */
420 GLubyte mask
= 1U << (finalUnpack
->SkipPixels
& 0x7);
422 for (col
= 0; col
< width
; col
++) {
438 /* most significan bit first */
439 GLubyte mask
= 128U >> (finalUnpack
->SkipPixels
& 0x7);
441 for (col
= 0; col
< width
; col
++) {
460 FX_grLfbUnlock(GR_LFB_WRITE_ONLY
, fxMesa
->currentFB
);
465 fxDDReadPixels(GLcontext
* ctx
, GLint x
, GLint y
,
466 GLsizei width
, GLsizei height
,
467 GLenum format
, GLenum type
,
468 const struct gl_pixelstore_attrib
*packing
, GLvoid
* dstImage
)
470 if (ctx
->_ImageTransferState
) {
471 _swrast_ReadPixels(ctx
, x
, y
, width
, height
, format
, type
,
476 fxMesaContext fxMesa
= (fxMesaContext
) ctx
->DriverCtx
;
480 if (grLfbLock(GR_LFB_READ_ONLY
,
483 GR_ORIGIN_UPPER_LEFT
, FXFALSE
, &info
)) {
484 const GLint winX
= 0;
485 const GLint winY
= fxMesa
->height
- 1;
486 const GLint srcStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
487 const GLushort
*src
= (const GLushort
*) info
.lfbPtr
488 + (winY
- y
) * srcStride
+ (winX
+ x
);
489 GLubyte
*dst
= (GLubyte
*) _mesa_image_address(packing
, dstImage
,
490 width
, height
, format
,
493 _mesa_image_row_stride(packing
, width
, format
, type
);
495 if (format
== GL_RGB
&& type
== GL_UNSIGNED_BYTE
) {
496 /* convert 5R6G5B into 8R8G8B */
498 const GLint halfWidth
= width
>> 1;
499 const GLint extraPixel
= (width
& 1);
500 for (row
= 0; row
< height
; row
++) {
502 for (col
= 0; col
< halfWidth
; col
++) {
503 const GLuint pixel
= ((const GLuint
*) src
)[col
];
504 const GLint pixel0
= pixel
& 0xffff;
505 const GLint pixel1
= pixel
>> 16;
506 *d
++ = FX_PixelToR
[pixel0
];
507 *d
++ = FX_PixelToG
[pixel0
];
508 *d
++ = FX_PixelToB
[pixel0
];
509 *d
++ = FX_PixelToR
[pixel1
];
510 *d
++ = FX_PixelToG
[pixel1
];
511 *d
++ = FX_PixelToB
[pixel1
];
514 GLushort pixel
= src
[width
- 1];
515 *d
++ = FX_PixelToR
[pixel
];
516 *d
++ = FX_PixelToG
[pixel
];
517 *d
++ = FX_PixelToB
[pixel
];
523 else if (format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) {
524 /* convert 5R6G5B into 8R8G8B8A */
526 const GLint halfWidth
= width
>> 1;
527 const GLint extraPixel
= (width
& 1);
528 for (row
= 0; row
< height
; row
++) {
530 for (col
= 0; col
< halfWidth
; col
++) {
531 const GLuint pixel
= ((const GLuint
*) src
)[col
];
532 const GLint pixel0
= pixel
& 0xffff;
533 const GLint pixel1
= pixel
>> 16;
534 *d
++ = FX_PixelToR
[pixel0
];
535 *d
++ = FX_PixelToG
[pixel0
];
536 *d
++ = FX_PixelToB
[pixel0
];
538 *d
++ = FX_PixelToR
[pixel1
];
539 *d
++ = FX_PixelToG
[pixel1
];
540 *d
++ = FX_PixelToB
[pixel1
];
544 const GLushort pixel
= src
[width
- 1];
545 *d
++ = FX_PixelToR
[pixel
];
546 *d
++ = FX_PixelToG
[pixel
];
547 *d
++ = FX_PixelToB
[pixel
];
554 else if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
555 /* directly memcpy 5R6G5B pixels into client's buffer */
556 const GLint widthInBytes
= width
* 2;
558 for (row
= 0; row
< height
; row
++) {
559 MEMCPY(dst
, src
, widthInBytes
);
565 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
567 _swrast_ReadPixels(ctx
, x
, y
, width
, height
, format
, type
,
572 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
581 fxDDFinish(GLcontext
* ctx
)
590 /* KW: Put the word Mesa in the render string because quakeworld
591 * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
594 static const GLubyte
*
595 fxDDGetString(GLcontext
* ctx
, GLenum name
)
602 if (glbHWConfig
.SSTs
[glbCurrentBoard
].type
== GR_SSTTYPE_VOODOO
) {
603 GrVoodooConfig_t
*vc
=
604 &glbHWConfig
.SSTs
[glbCurrentBoard
].sstBoard
.VoodooConfig
;
607 "Mesa Glide v0.30 Voodoo_Graphics %d "
608 "CARD/%d FB/%d TM/%d TMU/%s",
610 (vc
->sliDetect
? (vc
->fbRam
* 2) : vc
->fbRam
),
611 (vc
->tmuConfig
[GR_TMU0
].tmuRam
+
612 ((vc
->nTexelfx
> 1) ? vc
->tmuConfig
[GR_TMU1
].
613 tmuRam
: 0)), vc
->nTexelfx
,
614 (vc
->sliDetect
? "SLI" : "NOSLI"));
616 else if (glbHWConfig
.SSTs
[glbCurrentBoard
].type
== GR_SSTTYPE_SST96
) {
617 GrSst96Config_t
*sc
=
618 &glbHWConfig
.SSTs
[glbCurrentBoard
].sstBoard
.SST96Config
;
621 "Glide v0.30 Voodoo_Rush %d "
622 "CARD/%d FB/%d TM/%d TMU/NOSLI",
624 sc
->fbRam
, sc
->tmuConfig
.tmuRam
, sc
->nTexelfx
);
627 strcpy(buf
, "Glide v0.30 UNKNOWN");
629 return (GLubyte
*) buf
;
636 static const struct gl_pipeline_stage
*fx_pipeline
[] = {
637 &_tnl_vertex_transform_stage
, /* TODO: Add the fastpath here */
638 &_tnl_normal_transform_stage
,
639 &_tnl_lighting_stage
,
640 &_tnl_fog_coordinate_stage
, /* TODO: Omit fog stage */
642 &_tnl_texture_transform_stage
,
643 &_tnl_point_attenuation_stage
,
652 fxDDInitFxMesaContext(fxMesaContext fxMesa
)
656 for (i
= 0; i
< 256; i
++) {
657 gl_ubyte_to_float_255_color_tab
[i
] = (float) i
;
660 FX_setupGrVertexLayout();
662 if (getenv("FX_EMULATE_SINGLE_TMU"))
663 fxMesa
->haveTwoTMUs
= GL_FALSE
;
665 if (getenv("FX_GLIDE_SWAPINTERVAL"))
666 fxMesa
->swapInterval
= atoi(getenv("FX_GLIDE_SWAPINTERVAL"));
668 fxMesa
->swapInterval
= 1;
670 if (getenv("MESA_FX_SWAP_PENDING"))
671 fxMesa
->maxPendingSwapBuffers
= atoi(getenv("MESA_FX_SWAP_PENDING"));
673 fxMesa
->maxPendingSwapBuffers
= 2;
675 if (getenv("MESA_FX_INFO"))
676 fxMesa
->verbose
= GL_TRUE
;
678 fxMesa
->verbose
= GL_FALSE
;
680 fxMesa
->color
= 0xffffffff;
684 fxMesa
->stats
.swapBuffer
= 0;
685 fxMesa
->stats
.reqTexUpload
= 0;
686 fxMesa
->stats
.texUpload
= 0;
687 fxMesa
->stats
.memTexUpload
= 0;
689 fxMesa
->tmuSrc
= FX_TMU_NONE
;
690 fxMesa
->lastUnitsMode
= FX_UM_NONE
;
695 fxMesa
->unitsState
.alphaTestEnabled
= GL_FALSE
;
696 fxMesa
->unitsState
.alphaTestFunc
= GR_CMP_ALWAYS
;
697 fxMesa
->unitsState
.alphaTestRefValue
= 0;
699 fxMesa
->unitsState
.blendEnabled
= GL_FALSE
;
700 fxMesa
->unitsState
.blendSrcFuncRGB
= GR_BLEND_ONE
;
701 fxMesa
->unitsState
.blendDstFuncRGB
= GR_BLEND_ZERO
;
702 fxMesa
->unitsState
.blendSrcFuncAlpha
= GR_BLEND_ONE
;
703 fxMesa
->unitsState
.blendDstFuncAlpha
= GR_BLEND_ZERO
;
705 fxMesa
->unitsState
.depthTestEnabled
= GL_FALSE
;
706 fxMesa
->unitsState
.depthMask
= GL_TRUE
;
707 fxMesa
->unitsState
.depthTestFunc
= GR_CMP_LESS
;
709 FX_grColorMask(FXTRUE
, fxMesa
->haveAlphaBuffer
? FXTRUE
: FXFALSE
);
710 if (fxMesa
->haveDoubleBuffer
) {
711 fxMesa
->currentFB
= GR_BUFFER_BACKBUFFER
;
712 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
715 fxMesa
->currentFB
= GR_BUFFER_FRONTBUFFER
;
716 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
719 fxMesa
->state
= malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE
));
720 fxMesa
->fogTable
= malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES
) *
723 if (!fxMesa
->state
|| !fxMesa
->fogTable
) {
726 if (fxMesa
->fogTable
)
727 free(fxMesa
->fogTable
);
731 if (fxMesa
->haveZBuffer
)
732 FX_grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER
);
734 #ifndef FXMESA_USE_ARGB
735 FX_grLfbWriteColorFormat(GR_COLORFORMAT_ABGR
); /* Not every Glide has this */
738 fxMesa
->textureAlign
= FX_grGetInteger(FX_TEXTURE_ALIGN
);
739 fxMesa
->glCtx
->Const
.MaxTextureLevels
= 9;
740 fxMesa
->glCtx
->Const
.MaxTextureUnits
= fxMesa
->haveTwoTMUs
? 2 : 1;
741 fxMesa
->new_state
= _NEW_ALL
;
743 /* Initialize the software rasterizer and helper modules.
745 _swrast_CreateContext(fxMesa
->glCtx
);
746 _ac_CreateContext(fxMesa
->glCtx
);
747 _tnl_CreateContext(fxMesa
->glCtx
);
748 _swsetup_CreateContext(fxMesa
->glCtx
);
750 _tnl_destroy_pipeline(fxMesa
->glCtx
);
751 _tnl_install_pipeline(fxMesa
->glCtx
, fx_pipeline
);
753 fxAllocVB(fxMesa
->glCtx
);
755 fxSetupDDPointers(fxMesa
->glCtx
);
756 fxDDInitTriFuncs(fxMesa
->glCtx
);
758 /* Tell the software rasterizer to use pixel fog always.
760 _swrast_allow_vertex_fog(fxMesa
->glCtx
, GL_FALSE
);
761 _swrast_allow_pixel_fog(fxMesa
->glCtx
, GL_TRUE
);
763 /* Tell tnl not to calculate or use vertex fog factors. (Needed to
764 * tell render stage not to clip fog coords).
766 /* _tnl_calculate_vertex_fog( fxMesa->glCtx, GL_FALSE ); */
768 fxDDInitExtensions(fxMesa
->glCtx
);
770 FX_grGlideGetState((GrState
*) fxMesa
->state
);
778 fxDDDestroyFxMesaContext(fxMesaContext fxMesa
)
780 _swsetup_DestroyContext(fxMesa
->glCtx
);
781 _tnl_DestroyContext(fxMesa
->glCtx
);
782 _ac_DestroyContext(fxMesa
->glCtx
);
783 _swrast_DestroyContext(fxMesa
->glCtx
);
787 if (fxMesa
->fogTable
)
788 free(fxMesa
->fogTable
);
790 fxFreeVB(fxMesa
->glCtx
);
797 fxDDInitExtensions(GLcontext
* ctx
)
799 fxMesaContext fxMesa
= (fxMesaContext
) ctx
->DriverCtx
;
801 _mesa_add_extension(ctx
, GL_TRUE
, "3DFX_set_global_palette", 0);
802 _mesa_enable_extension(ctx
, "GL_EXT_point_parameters");
803 _mesa_enable_extension(ctx
, "GL_EXT_paletted_texture");
804 _mesa_enable_extension(ctx
, "GL_EXT_texture_lod_bias");
805 _mesa_enable_extension(ctx
, "GL_EXT_shared_texture_palette");
807 if (fxMesa
->haveTwoTMUs
)
808 _mesa_enable_extension(ctx
, "GL_EXT_texture_env_add");
810 if (fxMesa
->haveTwoTMUs
)
811 _mesa_enable_extension(ctx
, "GL_ARB_multitexture");
815 /************************************************************************/
816 /************************************************************************/
817 /************************************************************************/
819 /* Check if the hardware supports the current context
821 * Performs similar work to fxDDChooseRenderState() - should be merged.
824 fx_check_IsInHardware(GLcontext
* ctx
)
826 fxMesaContext fxMesa
= (fxMesaContext
) ctx
->DriverCtx
;
828 if (ctx
->RenderMode
!= GL_RENDER
)
831 if (ctx
->Stencil
.Enabled
||
832 (ctx
->Color
._DrawDestMask
!= FRONT_LEFT_BIT
&&
833 ctx
->Color
._DrawDestMask
!= BACK_LEFT_BIT
) ||
834 ((ctx
->Color
.BlendEnabled
)
835 && (ctx
->Color
.BlendEquation
!= GL_FUNC_ADD_EXT
))
836 || ((ctx
->Color
.ColorLogicOpEnabled
)
837 && (ctx
->Color
.LogicOp
!= GL_COPY
))
838 || (ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
)
841 Color
.ColorMask
[RCOMP
] == ctx
->Color
.ColorMask
[GCOMP
])
842 && (ctx
->Color
.ColorMask
[GCOMP
] == ctx
->Color
.ColorMask
[BCOMP
])
843 && (ctx
->Color
.ColorMask
[ACOMP
] == ctx
->Color
.ColorMask
[ACOMP
])))
847 /* Unsupported texture/multitexture cases */
849 if (fxMesa
->haveTwoTMUs
) {
850 /* we can only do 2D textures */
851 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
& ~TEXTURE_2D_BIT
)
853 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
& ~TEXTURE_2D_BIT
)
856 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
& TEXTURE_2D_BIT
) {
857 if (ctx
->Texture
.Unit
[0].EnvMode
== GL_BLEND
&&
858 (ctx
->Texture
.Unit
[1]._ReallyEnabled
& TEXTURE_2D_BIT
||
859 ctx
->Texture
.Unit
[0].EnvColor
[0] != 0 ||
860 ctx
->Texture
.Unit
[0].EnvColor
[1] != 0 ||
861 ctx
->Texture
.Unit
[0].EnvColor
[2] != 0 ||
862 ctx
->Texture
.Unit
[0].EnvColor
[3] != 1)) {
865 if (ctx
->Texture
.Unit
[0]._Current
->Image
[0]->Border
> 0)
869 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
& TEXTURE_2D_BIT
) {
870 if (ctx
->Texture
.Unit
[1].EnvMode
== GL_BLEND
)
872 if (ctx
->Texture
.Unit
[1]._Current
->Image
[0]->Border
> 0)
876 if (MESA_VERBOSE
& (VERBOSE_DRIVER
| VERBOSE_TEXTURE
))
877 fprintf(stderr
, "fxMesa: fxIsInHardware, envmode is %s/%s\n",
878 _mesa_lookup_enum_by_nr(ctx
->Texture
.Unit
[0].EnvMode
),
879 _mesa_lookup_enum_by_nr(ctx
->Texture
.Unit
[1].EnvMode
));
881 /* KW: This was wrong (I think) and I changed it... which doesn't mean
882 * it is now correct...
883 * BP: The old condition just seemed to test if both texture units
884 * were enabled. That's easy!
886 if (ctx
->Texture
._EnabledUnits
== 0x3) {
887 /* Can't use multipass to blend a multitextured triangle - fall
890 if (!fxMesa
->haveTwoTMUs
&& ctx
->Color
.BlendEnabled
) {
894 if ((ctx
->Texture
.Unit
[0].EnvMode
!= ctx
->Texture
.Unit
[1].EnvMode
) &&
895 (ctx
->Texture
.Unit
[0].EnvMode
!= GL_MODULATE
) &&
896 (ctx
->Texture
.Unit
[0].EnvMode
!= GL_REPLACE
)) { /* q2, seems ok... */
897 if (MESA_VERBOSE
& VERBOSE_DRIVER
)
898 fprintf(stderr
, "fxMesa: unsupported multitex env mode\n");
904 /* we have just one texture unit */
905 if (ctx
->Texture
._EnabledUnits
> 0x1) {
909 if ((ctx
->Texture
.Unit
[0]._ReallyEnabled
& TEXTURE_2D_BIT
) &&
910 (ctx
->Texture
.Unit
[0].EnvMode
== GL_BLEND
)) {
921 update_texture_scales(GLcontext
* ctx
)
923 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
924 struct gl_texture_unit
*t0
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[0]];
925 struct gl_texture_unit
*t1
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[1]];
927 if (t0
&& t0
->_Current
&& FX_TEXTURE_DATA(t0
)) {
928 fxMesa
->s0scale
= FX_TEXTURE_DATA(t0
)->sScale
;
929 fxMesa
->t0scale
= FX_TEXTURE_DATA(t0
)->tScale
;
930 fxMesa
->inv_s0scale
= 1.0 / fxMesa
->s0scale
;
931 fxMesa
->inv_t0scale
= 1.0 / fxMesa
->t0scale
;
934 if (t1
&& t1
->_Current
&& FX_TEXTURE_DATA(t1
)) {
935 fxMesa
->s1scale
= FX_TEXTURE_DATA(t1
)->sScale
;
936 fxMesa
->t1scale
= FX_TEXTURE_DATA(t1
)->tScale
;
937 fxMesa
->inv_s1scale
= 1.0 / fxMesa
->s1scale
;
938 fxMesa
->inv_t1scale
= 1.0 / fxMesa
->t1scale
;
943 fxDDUpdateDDPointers(GLcontext
* ctx
, GLuint new_state
)
945 /* TNLcontext *tnl = TNL_CONTEXT(ctx);*/
946 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
948 _swrast_InvalidateState(ctx
, new_state
);
949 _ac_InvalidateState(ctx
, new_state
);
950 _tnl_InvalidateState(ctx
, new_state
);
951 _swsetup_InvalidateState(ctx
, new_state
);
953 /* Recalculate fog table on projection matrix changes. This used to
954 * be triggered by the NearFar callback.
956 if (new_state
& _NEW_PROJECTION
)
957 fxMesa
->new_state
|= FX_NEW_FOG
;
959 if (new_state
& (_FX_NEW_IS_IN_HARDWARE
|
960 _FX_NEW_RENDERSTATE
|
961 _FX_NEW_SETUP_FUNCTION
|
964 if (new_state
& _FX_NEW_IS_IN_HARDWARE
)
965 fxCheckIsInHardware(ctx
);
967 if (fxMesa
->new_state
)
970 if (fxMesa
->is_in_hardware
) {
971 if (new_state
& _FX_NEW_RENDERSTATE
)
972 fxDDChooseRenderState(ctx
);
974 if (new_state
& _FX_NEW_SETUP_FUNCTION
)
975 fxChooseVertexState(ctx
);
978 if (new_state
& _NEW_TEXTURE
)
979 update_texture_scales(ctx
);
987 fxSetupDDPointers(GLcontext
* ctx
)
989 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
991 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
992 fprintf(stderr
, "fxmesa: fxSetupDDPointers()\n");
995 ctx
->Driver
.UpdateState
= fxDDUpdateDDPointers
;
996 ctx
->Driver
.GetString
= fxDDGetString
;
997 ctx
->Driver
.ClearIndex
= NULL
;
998 ctx
->Driver
.ClearColor
= fxDDClearColor
;
999 ctx
->Driver
.Clear
= fxDDClear
;
1000 ctx
->Driver
.DrawBuffer
= fxDDSetDrawBuffer
;
1001 ctx
->Driver
.GetBufferSize
= fxDDBufferSize
;
1002 ctx
->Driver
.Accum
= _swrast_Accum
;
1003 ctx
->Driver
.Bitmap
= fxDDDrawBitmap
;
1004 ctx
->Driver
.CopyPixels
= _swrast_CopyPixels
;
1005 ctx
->Driver
.DrawPixels
= _swrast_DrawPixels
;
1006 ctx
->Driver
.ReadPixels
= fxDDReadPixels
;
1007 ctx
->Driver
.ResizeBuffers
= _swrast_alloc_buffers
;
1008 ctx
->Driver
.Finish
= fxDDFinish
;
1009 ctx
->Driver
.Flush
= NULL
;
1010 ctx
->Driver
.ChooseTextureFormat
= fxDDChooseTextureFormat
;
1011 ctx
->Driver
.TexImage1D
= _mesa_store_teximage1d
;
1012 ctx
->Driver
.TexImage2D
= fxDDTexImage2D
;
1013 ctx
->Driver
.TexImage3D
= _mesa_store_teximage3d
;
1014 ctx
->Driver
.TexSubImage1D
= _mesa_store_texsubimage1d
;
1015 ctx
->Driver
.TexSubImage2D
= fxDDTexSubImage2D
;
1016 ctx
->Driver
.TexSubImage3D
= _mesa_store_texsubimage3d
;
1017 ctx
->Driver
.CompressedTexImage1D
= _mesa_store_compressed_teximage1d
;
1018 ctx
->Driver
.CompressedTexImage2D
= _mesa_store_compressed_teximage2d
;
1019 ctx
->Driver
.CompressedTexImage3D
= _mesa_store_compressed_teximage3d
;
1020 ctx
->Driver
.CompressedTexSubImage1D
= _mesa_store_compressed_texsubimage1d
;
1021 ctx
->Driver
.CompressedTexSubImage2D
= _mesa_store_compressed_texsubimage2d
;
1022 ctx
->Driver
.CompressedTexSubImage3D
= _mesa_store_compressed_texsubimage3d
;
1023 ctx
->Driver
.CopyTexImage1D
= _swrast_copy_teximage1d
;
1024 ctx
->Driver
.CopyTexImage2D
= _swrast_copy_teximage2d
;
1025 ctx
->Driver
.CopyTexSubImage1D
= _swrast_copy_texsubimage1d
;
1026 ctx
->Driver
.CopyTexSubImage2D
= _swrast_copy_texsubimage2d
;
1027 ctx
->Driver
.CopyTexSubImage3D
= _swrast_copy_texsubimage3d
;
1028 ctx
->Driver
.TestProxyTexImage
= _mesa_test_proxy_teximage
;
1029 ctx
->Driver
.CopyColorTable
= _swrast_CopyColorTable
;
1030 ctx
->Driver
.CopyColorSubTable
= _swrast_CopyColorSubTable
;
1031 ctx
->Driver
.CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
1032 ctx
->Driver
.CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
1033 ctx
->Driver
.TexEnv
= fxDDTexEnv
;
1034 ctx
->Driver
.TexParameter
= fxDDTexParam
;
1035 ctx
->Driver
.BindTexture
= fxDDTexBind
;
1036 ctx
->Driver
.DeleteTexture
= fxDDTexDel
;
1037 ctx
->Driver
.UpdateTexturePalette
= fxDDTexPalette
;
1038 ctx
->Driver
.AlphaFunc
= fxDDAlphaFunc
;
1039 ctx
->Driver
.BlendFunc
= fxDDBlendFunc
;
1040 ctx
->Driver
.DepthFunc
= fxDDDepthFunc
;
1041 ctx
->Driver
.DepthMask
= fxDDDepthMask
;
1042 ctx
->Driver
.ColorMask
= fxDDColorMask
;
1043 ctx
->Driver
.Fogfv
= fxDDFogfv
;
1044 ctx
->Driver
.Scissor
= fxDDScissor
;
1045 ctx
->Driver
.FrontFace
= fxDDFrontFace
;
1046 ctx
->Driver
.CullFace
= fxDDCullFace
;
1047 ctx
->Driver
.ShadeModel
= fxDDShadeModel
;
1048 ctx
->Driver
.Enable
= fxDDEnable
;
1050 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
1052 fxSetupDDSpanPointers(ctx
);
1053 fxDDUpdateDDPointers(ctx
, ~0);
1061 * Need this to provide at least one external definition.
1064 extern int gl_fx_dummy_function_dd(void);
1066 gl_fx_dummy_function_dd(void)