2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * 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"
51 #include "swrast/swrast.h"
52 #include "swrast/s_context.h"
53 #include "swrast_setup/swrast_setup.h"
55 #include "tnl/t_context.h"
56 #include "tnl/t_pipeline.h"
57 #include "array_cache/acache.h"
61 /* lookup table for scaling 4 bit colors up to 8 bits */
62 GLuint FX_rgb_scale_4
[16] = {
63 0, 17, 34, 51, 68, 85, 102, 119,
64 136, 153, 170, 187, 204, 221, 238, 255
67 /* lookup table for scaling 5 bit colors up to 8 bits */
68 GLuint FX_rgb_scale_5
[32] = {
69 0, 8, 16, 25, 33, 41, 49, 58,
70 66, 74, 82, 90, 99, 107, 115, 123,
71 132, 140, 148, 156, 165, 173, 181, 189,
72 197, 206, 214, 222, 230, 239, 247, 255
75 /* lookup table for scaling 6 bit colors up to 8 bits */
76 GLuint FX_rgb_scale_6
[64] = {
77 0, 4, 8, 12, 16, 20, 24, 28,
78 32, 36, 40, 45, 49, 53, 57, 61,
79 65, 69, 73, 77, 81, 85, 89, 93,
80 97, 101, 105, 109, 113, 117, 121, 125,
81 130, 134, 138, 142, 146, 150, 154, 158,
82 162, 166, 170, 174, 178, 182, 186, 190,
83 194, 198, 202, 206, 210, 215, 219, 223,
84 227, 231, 235, 239, 243, 247, 251, 255
89 * Disable color by masking out R, G, B, A
91 static void fxDisableColor (fxMesaContext fxMesa
)
93 if (fxMesa
->colDepth
!= 16) {
94 /* 32bpp mode or 15bpp mode */
95 fxMesa
->Glide
.grColorMaskExt(FXFALSE
, FXFALSE
, FXFALSE
, FXFALSE
);
98 grColorMask(FXFALSE
, FXFALSE
);
103 /**********************************************************************/
104 /***** Miscellaneous functions *****/
105 /**********************************************************************/
107 /* Return buffer size information */
109 fxDDBufferSize(GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
111 GET_CURRENT_CONTEXT(ctx
);
112 if (ctx
&& FX_CONTEXT(ctx
)) {
113 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
115 if (TDFX_DEBUG
& VERBOSE_DRIVER
) {
116 fprintf(stderr
, "%s(...)\n", __FUNCTION__
);
119 *width
= fxMesa
->width
;
120 *height
= fxMesa
->height
;
125 /* Implements glClearColor() */
127 fxDDClearColor(GLcontext
* ctx
, const GLfloat color
[4])
129 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
132 if (TDFX_DEBUG
& VERBOSE_DRIVER
) {
133 fprintf(stderr
, "%s(%f, %f, %f, %f)\n", __FUNCTION__
,
134 color
[0], color
[1], color
[2], color
[3]);
137 CLAMPED_FLOAT_TO_UBYTE(col
[0], color
[0]);
138 CLAMPED_FLOAT_TO_UBYTE(col
[1], color
[1]);
139 CLAMPED_FLOAT_TO_UBYTE(col
[2], color
[2]);
140 CLAMPED_FLOAT_TO_UBYTE(col
[3], color
[3]);
142 fxMesa
->clearC
= FXCOLOR4(col
);
143 fxMesa
->clearA
= col
[3];
147 /* Clear the color and/or depth buffers */
148 static void fxDDClear( GLcontext
*ctx
,
149 GLbitfield mask
, GLboolean all
,
150 GLint x
, GLint y
, GLint width
, GLint height
)
152 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
153 GLbitfield softwareMask
= mask
& (DD_ACCUM_BIT
);
154 const GLuint stencil_size
= fxMesa
->haveHwStencil
? ctx
->Visual
.stencilBits
: 0;
155 const FxU32 clearD
= (FxU32
) (((1 << ctx
->Visual
.depthBits
) - 1) * ctx
->Depth
.Clear
);
156 const FxU8 clearS
= (FxU8
) (ctx
->Stencil
.Clear
& 0xff);
158 /* [dBorca] Hack alert:
159 * if we set Mesa for 32bit depth, we'll get
161 * due to 32bit integer overflow!
164 if ( TDFX_DEBUG
& MESA_VERBOSE
) {
165 fprintf( stderr
, "%s( %d, %d, %d, %d )\n",
166 __FUNCTION__
, (int) x
, (int) y
, (int) width
, (int) height
);
169 /* Need this check to respond to glScissor and clipping updates */
170 /* should also take care of FX_NEW_COLOR_MASK, FX_NEW_STENCIL, depth? */
171 if (fxMesa
->new_state
& FX_NEW_SCISSOR
) {
173 fxMesa
->new_state
&= ~FX_NEW_SCISSOR
;
176 /* we can't clear accum buffers */
177 mask
&= ~(DD_ACCUM_BIT
);
180 * As per GL spec, stencil masking should be obeyed when clearing
182 if (mask
& DD_STENCIL_BIT
) {
183 if (!fxMesa
->haveHwStencil
|| fxMesa
->unitsState
.stencilWriteMask
!= 0xff) {
184 /* Napalm seems to have trouble with stencil write masks != 0xff */
185 /* do stencil clear in software */
186 softwareMask
|= DD_STENCIL_BIT
;
187 mask
&= ~(DD_STENCIL_BIT
);
192 * As per GL spec, color masking should be obeyed when clearing
194 if (ctx
->Visual
.greenBits
!= 8 && ctx
->Visual
.greenBits
!= 5) {
195 /* can only do color masking if running in 24/32bpp on Napalm */
196 if (ctx
->Color
.ColorMask
[RCOMP
] != ctx
->Color
.ColorMask
[GCOMP
] ||
197 ctx
->Color
.ColorMask
[GCOMP
] != ctx
->Color
.ColorMask
[BCOMP
]) {
198 softwareMask
|= (mask
& (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
));
199 mask
&= ~(DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
);
203 if (fxMesa
->haveHwStencil
) {
205 * If we want to clear stencil, it must be enabled
206 * in the HW, even if the stencil test is not enabled
210 if (mask
& DD_STENCIL_BIT
) {
211 fxMesa
->Glide
.grStencilMaskExt(0xff /*fxMesa->unitsState.stencilWriteMask*/);
212 /* set stencil ref value = desired clear value */
213 fxMesa
->Glide
.grStencilFuncExt(GR_CMP_ALWAYS
, clearS
, 0xff);
214 fxMesa
->Glide
.grStencilOpExt(GR_STENCILOP_REPLACE
,
215 GR_STENCILOP_REPLACE
, GR_STENCILOP_REPLACE
);
216 grEnable(GR_STENCIL_MODE_EXT
);
219 grDisable(GR_STENCIL_MODE_EXT
);
225 * This may be ugly, but it's needed in order to work around a number
231 * This could probably be done fancier but doing each possible case
232 * explicitly is less error prone.
234 switch (mask
& ~DD_STENCIL_BIT
) {
235 case DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
:
236 /* back buffer & depth */
237 /* FX_grColorMaskv_NoLock(ctx, true4); */ /* work around Voodoo3 bug */
239 grRenderBuffer(GR_BUFFER_BACKBUFFER
);
240 if (stencil_size
> 0) {
241 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
246 grBufferClear(fxMesa
->clearC
,
249 if (!fxMesa
->unitsState
.depthTestEnabled
) {
250 grDepthMask(FXFALSE
);
253 case DD_FRONT_LEFT_BIT
| DD_DEPTH_BIT
:
254 /* XXX it appears that the depth buffer isn't cleared when
255 * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set.
256 * This is a work-around/
260 grRenderBuffer(GR_BUFFER_BACKBUFFER
);
261 fxDisableColor(fxMesa
);
262 if (stencil_size
> 0)
263 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
267 grBufferClear(fxMesa
->clearC
,
271 fxSetupColorMask(ctx
);
272 grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
273 if (stencil_size
> 0)
274 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
278 grBufferClear(fxMesa
->clearC
,
281 if (!fxMesa
->unitsState
.depthTestEnabled
) {
282 grDepthMask(FXFALSE
);
285 case DD_BACK_LEFT_BIT
:
286 /* back buffer only */
287 grDepthMask(FXFALSE
);
288 grRenderBuffer(GR_BUFFER_BACKBUFFER
);
289 if (stencil_size
> 0)
290 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
294 grBufferClear(fxMesa
->clearC
,
297 if (fxMesa
->unitsState
.depthTestEnabled
) {
301 case DD_FRONT_LEFT_BIT
:
302 /* front buffer only */
303 grDepthMask(FXFALSE
);
304 grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
305 if (stencil_size
> 0)
306 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
310 grBufferClear(fxMesa
->clearC
,
313 if (fxMesa
->unitsState
.depthTestEnabled
) {
317 case DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
:
319 grDepthMask(FXFALSE
);
320 grRenderBuffer(GR_BUFFER_BACKBUFFER
);
321 if (stencil_size
> 0)
322 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
326 grBufferClear(fxMesa
->clearC
,
329 grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
330 if (stencil_size
> 0)
331 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
335 grBufferClear(fxMesa
->clearC
,
338 if (fxMesa
->unitsState
.depthTestEnabled
) {
342 case DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
:
344 grDepthMask(FXFALSE
);
345 grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
346 if (stencil_size
> 0)
347 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
351 grBufferClear(fxMesa
->clearC
,
354 /* clear back and depth */
356 grRenderBuffer(GR_BUFFER_BACKBUFFER
);
357 if (stencil_size
> 0)
358 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
362 grBufferClear(fxMesa
->clearC
,
365 if (!fxMesa
->unitsState
.depthTestEnabled
) {
366 grDepthMask(FXFALSE
);
370 /* just the depth buffer */
371 grRenderBuffer(GR_BUFFER_BACKBUFFER
);
372 fxDisableColor(fxMesa
);
374 if (stencil_size
> 0)
375 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
379 grBufferClear(fxMesa
->clearC
,
382 fxSetupColorMask(ctx
);
383 if (ctx
->Color
._DrawDestMask
& FRONT_LEFT_BIT
) {
384 grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
386 if (!fxMesa
->unitsState
.depthTestEnabled
) {
387 grDepthMask(FXFALSE
);
391 /* clear no color buffers or depth buffer but might clear stencil */
392 if (stencil_size
> 0 && (mask
& DD_STENCIL_BIT
)) {
393 /* XXX need this RenderBuffer call to work around Glide bug */
394 grRenderBuffer(GR_BUFFER_BACKBUFFER
);
395 grDepthMask(FXFALSE
);
396 fxDisableColor(fxMesa
);
397 fxMesa
->Glide
.grBufferClearExt(fxMesa
->clearC
,
400 if (fxMesa
->unitsState
.depthTestEnabled
) {
403 fxSetupColorMask(ctx
);
404 if (ctx
->Color
._DrawDestMask
& FRONT_LEFT_BIT
) {
405 grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
412 if (fxMesa
->haveHwStencil
&& (mask
& DD_STENCIL_BIT
)) {
413 /* We changed the stencil state above. Signal that we need to
416 fxMesa
->new_state
|= FX_NEW_STENCIL
;
420 _swrast_Clear( ctx
, softwareMask
, all
, x
, y
, width
, height
);
424 /* Set the buffer used for drawing */
425 /* XXX support for separate read/draw buffers hasn't been tested */
427 fxDDSetDrawBuffer(GLcontext
* ctx
, GLenum mode
)
429 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
431 if (TDFX_DEBUG
& VERBOSE_DRIVER
) {
432 fprintf(stderr
, "%s(%x)\n", __FUNCTION__
, (int)mode
);
435 if (mode
== GL_FRONT_LEFT
) {
436 fxMesa
->currentFB
= GR_BUFFER_FRONTBUFFER
;
437 grRenderBuffer(fxMesa
->currentFB
);
439 else if (mode
== GL_BACK_LEFT
) {
440 fxMesa
->currentFB
= GR_BUFFER_BACKBUFFER
;
441 grRenderBuffer(fxMesa
->currentFB
);
443 else if (mode
== GL_NONE
) {
444 fxDisableColor(fxMesa
);
447 /* we'll need a software fallback */
448 /* XXX not implemented */
451 /* update s/w fallback state */
452 _swrast_DrawBuffer(ctx
, mode
);
457 fxDDDrawBitmap2 (GLcontext
*ctx
, GLint px
, GLint py
,
458 GLsizei width
, GLsizei height
,
459 const struct gl_pixelstore_attrib
*unpack
,
460 const GLubyte
*bitmap
)
462 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
463 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
465 GrLfbWriteMode_t mode
;
467 const struct gl_pixelstore_attrib
*finalUnpack
;
468 struct gl_pixelstore_attrib scissoredUnpack
;
470 /* check if there's any raster operations enabled which we can't handle */
471 if ((swrast
->_RasterMask
& (ALPHATEST_BIT
|
472 /*BLEND_BIT |*/ /* blending ok, through pixpipe */
473 DEPTH_BIT
| /* could be done with RGB:DEPTH */
474 FOG_BIT
| /* could be done with RGB:DEPTH */
476 /*CLIP_BIT |*/ /* clipping ok, below */
478 /*MASKING_BIT |*/ /* masking ok, test follows */
479 ALPHABUF_BIT
| /* nope! see 565 span kludge */
481 OCCLUSION_BIT
| /* nope! at least not yet */
485 ((swrast
->_RasterMask
& MASKING_BIT
) /*&& (ctx->Visual.greenBits != 8)*/ && (ctx
->Visual
.greenBits
!= 5))
487 _swrast_Bitmap(ctx
, px
, py
, width
, height
, unpack
, bitmap
);
491 /* make sure the pixelpipe is configured correctly */
494 if (ctx
->Scissor
.Enabled
) {
495 /* This is a bit tricky, but by carefully adjusting the px, py,
496 * width, height, skipPixels and skipRows values we can do
497 * scissoring without special code in the rendering loop.
500 /* we'll construct a new pixelstore struct */
501 finalUnpack
= &scissoredUnpack
;
502 scissoredUnpack
= *unpack
;
503 if (scissoredUnpack
.RowLength
== 0)
504 scissoredUnpack
.RowLength
= width
;
507 if (px
< ctx
->Scissor
.X
) {
508 scissoredUnpack
.SkipPixels
+= (ctx
->Scissor
.X
- px
);
509 width
-= (ctx
->Scissor
.X
- px
);
513 if (px
+ width
>= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
) {
514 width
-= (px
+ width
- (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
));
517 if (py
< ctx
->Scissor
.Y
) {
518 scissoredUnpack
.SkipRows
+= (ctx
->Scissor
.Y
- py
);
519 height
-= (ctx
->Scissor
.Y
- py
);
523 if (py
+ height
>= ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
) {
524 height
-= (py
+ height
- (ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
));
527 if (width
<= 0 || height
<= 0)
531 finalUnpack
= unpack
;
534 /* compute pixel value */
536 GLint r
= (GLint
) (ctx
->Current
.RasterColor
[RCOMP
] * 255.0f
);
537 GLint g
= (GLint
) (ctx
->Current
.RasterColor
[GCOMP
] * 255.0f
);
538 GLint b
= (GLint
) (ctx
->Current
.RasterColor
[BCOMP
] * 255.0f
);
539 GLint a
= (GLint
) (ctx
->Current
.RasterColor
[ACOMP
] * 255.0f
);
540 if (fxMesa
->colDepth
== 15) {
541 color
= TDFXPACKCOLOR1555(b
, g
, r
, a
);
542 mode
= GR_LFBWRITEMODE_1555
;
544 color
= fxMesa
->bgrOrder
? TDFXPACKCOLOR565(r
, g
, b
) : TDFXPACKCOLOR565(b
, g
, r
);
545 mode
= GR_LFBWRITEMODE_565
;
549 info
.size
= sizeof(info
);
550 if (!grLfbLock(GR_LFB_WRITE_ONLY
,
553 GR_ORIGIN_UPPER_LEFT
, FXTRUE
, &info
)) {
554 _swrast_Bitmap(ctx
, px
, py
, width
, height
, unpack
, bitmap
);
559 const GLint winX
= 0;
560 const GLint winY
= fxMesa
->height
- 1;
561 /* The dest stride depends on the hardware and whether we're drawing
562 * to the front or back buffer. This compile-time test seems to do
565 const GLint dstStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
568 /* compute dest address of bottom-left pixel in bitmap */
569 GLushort
*dst
= (GLushort
*) info
.lfbPtr
570 + (winY
- py
) * dstStride
+ (winX
+ px
);
572 for (row
= 0; row
< height
; row
++) {
574 (const GLubyte
*) _mesa_image_address(finalUnpack
,
575 bitmap
, width
, height
,
576 GL_COLOR_INDEX
, GL_BITMAP
,
578 if (finalUnpack
->LsbFirst
) {
579 /* least significan bit first */
580 GLubyte mask
= 1U << (finalUnpack
->SkipPixels
& 0x7);
582 for (col
= 0; col
< width
; col
++) {
598 /* most significan bit first */
599 GLubyte mask
= 128U >> (finalUnpack
->SkipPixels
& 0x7);
601 for (col
= 0; col
< width
; col
++) {
620 grLfbUnlock(GR_LFB_WRITE_ONLY
, fxMesa
->currentFB
);
624 fxDDDrawBitmap4 (GLcontext
*ctx
, GLint px
, GLint py
,
625 GLsizei width
, GLsizei height
,
626 const struct gl_pixelstore_attrib
*unpack
,
627 const GLubyte
*bitmap
)
629 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
630 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
633 const struct gl_pixelstore_attrib
*finalUnpack
;
634 struct gl_pixelstore_attrib scissoredUnpack
;
636 /* check if there's any raster operations enabled which we can't handle */
637 if ((swrast
->_RasterMask
& (ALPHATEST_BIT
|
638 /*BLEND_BIT |*/ /* blending ok, through pixpipe */
639 DEPTH_BIT
| /* could be done with RGB:DEPTH */
640 FOG_BIT
| /* could be done with RGB:DEPTH */
642 /*CLIP_BIT |*/ /* clipping ok, below */
644 /*MASKING_BIT |*/ /* masking ok, we're in 32bpp */
645 /*ALPHABUF_BIT |*//* alpha ok, we're in 32bpp */
647 OCCLUSION_BIT
| /* nope! at least not yet */
651 _swrast_Bitmap(ctx
, px
, py
, width
, height
, unpack
, bitmap
);
655 /* make sure the pixelpipe is configured correctly */
658 if (ctx
->Scissor
.Enabled
) {
659 /* This is a bit tricky, but by carefully adjusting the px, py,
660 * width, height, skipPixels and skipRows values we can do
661 * scissoring without special code in the rendering loop.
664 /* we'll construct a new pixelstore struct */
665 finalUnpack
= &scissoredUnpack
;
666 scissoredUnpack
= *unpack
;
667 if (scissoredUnpack
.RowLength
== 0)
668 scissoredUnpack
.RowLength
= width
;
671 if (px
< ctx
->Scissor
.X
) {
672 scissoredUnpack
.SkipPixels
+= (ctx
->Scissor
.X
- px
);
673 width
-= (ctx
->Scissor
.X
- px
);
677 if (px
+ width
>= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
) {
678 width
-= (px
+ width
- (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
));
681 if (py
< ctx
->Scissor
.Y
) {
682 scissoredUnpack
.SkipRows
+= (ctx
->Scissor
.Y
- py
);
683 height
-= (ctx
->Scissor
.Y
- py
);
687 if (py
+ height
>= ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
) {
688 height
-= (py
+ height
- (ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
));
691 if (width
<= 0 || height
<= 0)
695 finalUnpack
= unpack
;
698 /* compute pixel value */
700 GLint r
= (GLint
) (ctx
->Current
.RasterColor
[RCOMP
] * 255.0f
);
701 GLint g
= (GLint
) (ctx
->Current
.RasterColor
[GCOMP
] * 255.0f
);
702 GLint b
= (GLint
) (ctx
->Current
.RasterColor
[BCOMP
] * 255.0f
);
703 GLint a
= (GLint
) (ctx
->Current
.RasterColor
[ACOMP
] * 255.0f
);
704 color
= TDFXPACKCOLOR8888(b
, g
, r
, a
);
707 info
.size
= sizeof(info
);
708 if (!grLfbLock(GR_LFB_WRITE_ONLY
,
710 GR_LFBWRITEMODE_8888
,
711 GR_ORIGIN_UPPER_LEFT
, FXTRUE
, &info
)) {
712 _swrast_Bitmap(ctx
, px
, py
, width
, height
, unpack
, bitmap
);
717 const GLint winX
= 0;
718 const GLint winY
= fxMesa
->height
- 1;
719 /* The dest stride depends on the hardware and whether we're drawing
720 * to the front or back buffer. This compile-time test seems to do
723 const GLint dstStride
= info
.strideInBytes
/ 4; /* stride in GLuints */
726 /* compute dest address of bottom-left pixel in bitmap */
727 GLuint
*dst
= (GLuint
*) info
.lfbPtr
728 + (winY
- py
) * dstStride
+ (winX
+ px
);
730 for (row
= 0; row
< height
; row
++) {
732 (const GLubyte
*) _mesa_image_address(finalUnpack
,
733 bitmap
, width
, height
,
734 GL_COLOR_INDEX
, GL_BITMAP
,
736 if (finalUnpack
->LsbFirst
) {
737 /* least significan bit first */
738 GLubyte mask
= 1U << (finalUnpack
->SkipPixels
& 0x7);
740 for (col
= 0; col
< width
; col
++) {
756 /* most significan bit first */
757 GLubyte mask
= 128U >> (finalUnpack
->SkipPixels
& 0x7);
759 for (col
= 0; col
< width
; col
++) {
778 grLfbUnlock(GR_LFB_WRITE_ONLY
, fxMesa
->currentFB
);
783 fxDDReadPixels565 (GLcontext
* ctx
,
785 GLsizei width
, GLsizei height
,
786 GLenum format
, GLenum type
,
787 const struct gl_pixelstore_attrib
*packing
,
790 if (ctx
->_ImageTransferState
/* & (IMAGE_SCALE_BIAS_BIT|IMAGE_MAP_COLOR_BIT)*/) {
791 _swrast_ReadPixels(ctx
, x
, y
, width
, height
, format
, type
,
796 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
800 if (grLfbLock(GR_LFB_READ_ONLY
,
803 GR_ORIGIN_UPPER_LEFT
, FXFALSE
, &info
)) {
804 const GLint winX
= 0;
805 const GLint winY
= fxMesa
->height
- 1;
806 const GLint srcStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
807 const GLushort
*src
= (const GLushort
*) info
.lfbPtr
808 + (winY
- y
) * srcStride
+ (winX
+ x
);
809 GLubyte
*dst
= (GLubyte
*) _mesa_image_address(packing
, dstImage
,
810 width
, height
, format
,
813 _mesa_image_row_stride(packing
, width
, format
, type
);
815 if (format
== GL_RGB
&& type
== GL_UNSIGNED_BYTE
) {
816 /* convert 5R6G5B into 8R8G8B */
818 const GLint halfWidth
= width
>> 1;
819 const GLint extraPixel
= (width
& 1);
820 for (row
= 0; row
< height
; row
++) {
822 for (col
= 0; col
< halfWidth
; col
++) {
823 const GLuint pixel
= ((const GLuint
*) src
)[col
];
824 *d
++ = FX_rgb_scale_5
[(pixel
>> 11) & 0x1f];
825 *d
++ = FX_rgb_scale_6
[(pixel
>> 5) & 0x3f];
826 *d
++ = FX_rgb_scale_5
[ pixel
& 0x1f];
827 *d
++ = FX_rgb_scale_5
[(pixel
>> 27) & 0x1f];
828 *d
++ = FX_rgb_scale_6
[(pixel
>> 21) & 0x3f];
829 *d
++ = FX_rgb_scale_5
[(pixel
>> 16) & 0x1f];
832 GLushort pixel
= src
[width
- 1];
833 *d
++ = FX_rgb_scale_5
[(pixel
>> 11) & 0x1f];
834 *d
++ = FX_rgb_scale_6
[(pixel
>> 5) & 0x3f];
835 *d
++ = FX_rgb_scale_5
[ pixel
& 0x1f];
841 else if (format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) {
842 /* convert 5R6G5B into 8R8G8B8A */
844 const GLint halfWidth
= width
>> 1;
845 const GLint extraPixel
= (width
& 1);
846 for (row
= 0; row
< height
; row
++) {
848 for (col
= 0; col
< halfWidth
; col
++) {
849 const GLuint pixel
= ((const GLuint
*) src
)[col
];
850 *d
++ = FX_rgb_scale_5
[(pixel
>> 11) & 0x1f];
851 *d
++ = FX_rgb_scale_6
[(pixel
>> 5) & 0x3f];
852 *d
++ = FX_rgb_scale_5
[ pixel
& 0x1f];
854 *d
++ = FX_rgb_scale_5
[(pixel
>> 27) & 0x1f];
855 *d
++ = FX_rgb_scale_6
[(pixel
>> 21) & 0x3f];
856 *d
++ = FX_rgb_scale_5
[(pixel
>> 16) & 0x1f];
860 const GLushort pixel
= src
[width
- 1];
861 *d
++ = FX_rgb_scale_5
[(pixel
>> 11) & 0x1f];
862 *d
++ = FX_rgb_scale_6
[(pixel
>> 5) & 0x3f];
863 *d
++ = FX_rgb_scale_5
[ pixel
& 0x1f];
870 else if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
871 /* directly memcpy 5R6G5B pixels into client's buffer */
872 const GLint widthInBytes
= width
* 2;
874 for (row
= 0; row
< height
; row
++) {
875 MEMCPY(dst
, src
, widthInBytes
);
881 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
883 _swrast_ReadPixels(ctx
, x
, y
, width
, height
, format
, type
,
888 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
895 fxDDReadPixels555 (GLcontext
* ctx
,
897 GLsizei width
, GLsizei height
,
898 GLenum format
, GLenum type
,
899 const struct gl_pixelstore_attrib
*packing
,
902 if (ctx
->_ImageTransferState
/* & (IMAGE_SCALE_BIAS_BIT|IMAGE_MAP_COLOR_BIT)*/) {
903 _swrast_ReadPixels(ctx
, x
, y
, width
, height
, format
, type
,
908 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
912 if (grLfbLock(GR_LFB_READ_ONLY
,
915 GR_ORIGIN_UPPER_LEFT
, FXFALSE
, &info
)) {
916 const GLint winX
= 0;
917 const GLint winY
= fxMesa
->height
- 1;
918 const GLint srcStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
919 const GLushort
*src
= (const GLushort
*) info
.lfbPtr
920 + (winY
- y
) * srcStride
+ (winX
+ x
);
921 GLubyte
*dst
= (GLubyte
*) _mesa_image_address(packing
, dstImage
,
922 width
, height
, format
,
925 _mesa_image_row_stride(packing
, width
, format
, type
);
927 if (format
== GL_RGB
&& type
== GL_UNSIGNED_BYTE
) {
928 /* convert 5R5G5B into 8R8G8B */
930 const GLint halfWidth
= width
>> 1;
931 const GLint extraPixel
= (width
& 1);
932 for (row
= 0; row
< height
; row
++) {
934 for (col
= 0; col
< halfWidth
; col
++) {
935 const GLuint pixel
= ((const GLuint
*) src
)[col
];
936 *d
++ = FX_rgb_scale_5
[(pixel
>> 10) & 0x1f];
937 *d
++ = FX_rgb_scale_5
[(pixel
>> 5) & 0x1f];
938 *d
++ = FX_rgb_scale_5
[ pixel
& 0x1f];
939 *d
++ = FX_rgb_scale_5
[(pixel
>> 26) & 0x1f];
940 *d
++ = FX_rgb_scale_5
[(pixel
>> 21) & 0x1f];
941 *d
++ = FX_rgb_scale_5
[(pixel
>> 16) & 0x1f];
944 GLushort pixel
= src
[width
- 1];
945 *d
++ = FX_rgb_scale_5
[(pixel
>> 10) & 0x1f];
946 *d
++ = FX_rgb_scale_5
[(pixel
>> 5) & 0x1f];
947 *d
++ = FX_rgb_scale_5
[ pixel
& 0x1f];
953 else if (format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) {
954 /* convert 5R6G5B into 8R8G8B8A */
956 const GLint halfWidth
= width
>> 1;
957 const GLint extraPixel
= (width
& 1);
958 for (row
= 0; row
< height
; row
++) {
960 for (col
= 0; col
< halfWidth
; col
++) {
961 const GLuint pixel
= ((const GLuint
*) src
)[col
];
962 *d
++ = FX_rgb_scale_5
[(pixel
>> 10) & 0x1f];
963 *d
++ = FX_rgb_scale_5
[(pixel
>> 5) & 0x1f];
964 *d
++ = FX_rgb_scale_5
[ pixel
& 0x1f];
965 *d
++ = (pixel
& 0x8000) ? 255 : 0;
966 *d
++ = FX_rgb_scale_5
[(pixel
>> 26) & 0x1f];
967 *d
++ = FX_rgb_scale_5
[(pixel
>> 21) & 0x1f];
968 *d
++ = FX_rgb_scale_5
[(pixel
>> 16) & 0x1f];
969 *d
++ = (pixel
& 0x80000000) ? 255 : 0;
972 const GLushort pixel
= src
[width
- 1];
973 *d
++ = FX_rgb_scale_5
[(pixel
>> 10) & 0x1f];
974 *d
++ = FX_rgb_scale_5
[(pixel
>> 5) & 0x1f];
975 *d
++ = FX_rgb_scale_5
[ pixel
& 0x1f];
976 *d
++ = (pixel
& 0x8000) ? 255 : 0;
982 else if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
983 /* directly memcpy 5R5G5B pixels into client's buffer */
984 const GLint widthInBytes
= width
* 2;
986 for (row
= 0; row
< height
; row
++) {
987 MEMCPY(dst
, src
, widthInBytes
);
993 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
995 _swrast_ReadPixels(ctx
, x
, y
, width
, height
, format
, type
,
1000 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
1007 fxDDReadPixels8888 (GLcontext
* ctx
,
1009 GLsizei width
, GLsizei height
,
1010 GLenum format
, GLenum type
,
1011 const struct gl_pixelstore_attrib
*packing
,
1014 if (ctx
->_ImageTransferState
/* & (IMAGE_SCALE_BIAS_BIT|IMAGE_MAP_COLOR_BIT)*/) {
1015 _swrast_ReadPixels(ctx
, x
, y
, width
, height
, format
, type
,
1020 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1024 if (grLfbLock(GR_LFB_READ_ONLY
,
1026 GR_LFBWRITEMODE_ANY
,
1027 GR_ORIGIN_UPPER_LEFT
, FXFALSE
, &info
)) {
1028 const GLint winX
= 0;
1029 const GLint winY
= fxMesa
->height
- 1;
1030 const GLint srcStride
= info
.strideInBytes
/ 4; /* stride in GLuints */
1031 const GLuint
*src
= (const GLuint
*) info
.lfbPtr
1032 + (winY
- y
) * srcStride
+ (winX
+ x
);
1033 GLubyte
*dst
= (GLubyte
*) _mesa_image_address(packing
, dstImage
,
1034 width
, height
, format
,
1037 _mesa_image_row_stride(packing
, width
, format
, type
);
1039 if (format
== GL_RGB
&& type
== GL_UNSIGNED_BYTE
) {
1040 /* convert 8A8R8G8B into 8R8G8B */
1042 for (row
= 0; row
< height
; row
++) {
1044 for (col
= 0; col
< width
; col
++) {
1045 const GLuint pixel
= ((const GLuint
*) src
)[col
];
1054 else if (format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) {
1055 /* 8A8R8G8B pixels into client's buffer */
1057 for (row
= 0; row
< height
; row
++) {
1059 for (col
= 0; col
< width
; col
++) {
1060 const GLuint pixel
= ((const GLuint
*) src
)[col
];
1070 else if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
1071 /* convert 8A8R8G8B into 5R6G5B */
1073 for (row
= 0; row
< height
; row
++) {
1074 GLushort
*d
= (GLushort
*)dst
;
1075 for (col
= 0; col
< width
; col
++) {
1076 const GLuint pixel
= ((const GLuint
*) src
)[col
];
1077 *d
++ = (((pixel
>> 16) & 0xf8) << 8) |
1078 (((pixel
>> 8) & 0xfc) << 3) |
1079 ((pixel
& 0xf8) >> 3);
1086 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
1088 _swrast_ReadPixels(ctx
, x
, y
, width
, height
, format
, type
,
1093 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
1100 /* [dBorca] Hack alert:
1102 * revise fallback tests and fix scissor; implement new formats
1103 * also write its siblings: 565 and 1555
1106 fxDDDrawPixels8888 (GLcontext
* ctx
, GLint x
, GLint y
,
1107 GLsizei width
, GLsizei height
,
1108 GLenum format
, GLenum type
,
1109 const struct gl_pixelstore_attrib
*unpack
,
1110 const GLvoid
* pixels
)
1112 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1115 if (ctx
->Pixel
.ZoomX
!= 1.0F
||
1116 ctx
->Pixel
.ZoomY
!= 1.0F
||
1117 (ctx
->_ImageTransferState
& (IMAGE_SCALE_BIAS_BIT
|
1118 IMAGE_MAP_COLOR_BIT
)) ||
1119 ctx
->Color
.AlphaEnabled
||
1122 ctx
->Scissor
.Enabled
||
1123 ctx
->Stencil
.Enabled
||
1124 !ctx
->Color
.ColorMask
[0] ||
1125 !ctx
->Color
.ColorMask
[1] ||
1126 !ctx
->Color
.ColorMask
[2] ||
1127 !ctx
->Color
.ColorMask
[3] ||
1128 ctx
->Color
.ColorLogicOpEnabled
||
1129 ctx
->Texture
._EnabledUnits
||
1130 ctx
->Depth
.OcclusionTest
||
1133 _swrast_DrawPixels( ctx
, x
, y
, width
, height
, format
, type
,
1138 /* lock early to make sure cliprects are right */
1141 /* make sure the pixelpipe is configured correctly */
1142 fxSetupFXUnits(ctx
);
1144 /* look for clipmasks, giveup if region obscured */
1146 if (ctx
->Color
.DrawBuffer
== GL_FRONT
) {
1147 if (!inClipRects_Region(fxMesa
, scrX
, scrY
, width
, height
)) {
1148 END_BOARD_LOCK(fxMesa
);
1149 _swrast_DrawPixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
);
1155 info
.size
= sizeof(info
);
1156 if (!grLfbLock(GR_LFB_WRITE_ONLY
,
1158 GR_LFBWRITEMODE_8888
,
1159 GR_ORIGIN_UPPER_LEFT
, FXTRUE
, &info
)) {
1160 _swrast_DrawPixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
);
1165 const GLint winX
= 0;
1166 const GLint winY
= fxMesa
->height
- 1;
1168 const GLint dstStride
= info
.strideInBytes
/ 4; /* stride in GLuints */
1169 GLuint
*dst
= (GLuint
*) info
.lfbPtr
+ (winY
- y
) * dstStride
+ (winX
+ x
);
1170 const GLubyte
*src
= (GLubyte
*)_mesa_image_address(unpack
, pixels
,
1171 width
, height
, format
,
1173 const GLint srcStride
= _mesa_image_row_stride(unpack
, width
, format
, type
);
1175 if (format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) {
1176 /* directly memcpy 8A8R8G8B pixels to screen */
1177 const GLint widthInBytes
= width
* 4;
1179 for (row
= 0; row
< height
; row
++) {
1180 MEMCPY(dst
, src
, widthInBytes
);
1186 grLfbUnlock(GR_LFB_WRITE_ONLY
, fxMesa
->currentFB
);
1188 _swrast_DrawPixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
);
1194 grLfbUnlock(GR_LFB_WRITE_ONLY
, fxMesa
->currentFB
);
1200 fxDDFinish(GLcontext
* ctx
)
1209 /* KW: Put the word Mesa in the render string because quakeworld
1210 * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
1213 static const GLubyte
*
1214 fxDDGetString(GLcontext
* ctx
, GLenum name
)
1216 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1220 return (GLubyte
*)fxMesa
->rendererString
;
1221 #if 0 /* hack to advertise vanilla extension names */
1223 if (ctx
->Extensions
.String
== NULL
) {
1224 GLubyte
*ext
= _mesa_make_extension_string(ctx
);
1226 ctx
->Extensions
.String
= _mesa_malloc(strlen((char *)ext
) + 256);
1227 if (ctx
->Extensions
.String
!= NULL
) {
1228 strcpy((char *)ctx
->Extensions
.String
, (char *)ext
);
1229 #if 0 /* put any additional extension names here */
1230 strcat((char *)ctx
->Extensions
.String
, " 3DFX_set_global_palette");
1234 ctx
->Extensions
.String
= ext
;
1238 return ctx
->Extensions
.String
;
1245 static const struct gl_pipeline_stage
*fx_pipeline
[] = {
1246 &_tnl_vertex_transform_stage
, /* TODO: Add the fastpath here */
1247 &_tnl_normal_transform_stage
,
1248 &_tnl_lighting_stage
,
1249 /*&_tnl_fog_coordinate_stage,*/ /* TODO: Omit fog stage ZZZ ZZZ ZZZ */
1251 &_tnl_texture_transform_stage
,
1252 /*&_tnl_point_attenuation_stage,*/ /* TODO: For AA primitives ZZZ ZZZ ZZZ */
1261 fxDDInitFxMesaContext(fxMesaContext fxMesa
)
1264 GLcontext
*ctx
= fxMesa
->glCtx
;
1266 FX_setupGrVertexLayout();
1268 fxMesa
->color
= 0xffffffff;
1272 fxMesa
->stats
.swapBuffer
= 0;
1273 fxMesa
->stats
.reqTexUpload
= 0;
1274 fxMesa
->stats
.texUpload
= 0;
1275 fxMesa
->stats
.memTexUpload
= 0;
1277 fxMesa
->tmuSrc
= FX_TMU_NONE
;
1278 fxMesa
->lastUnitsMode
= FX_UM_NONE
;
1281 /* FX units setup */
1283 fxMesa
->unitsState
.alphaTestEnabled
= GL_FALSE
;
1284 fxMesa
->unitsState
.alphaTestFunc
= GL_ALWAYS
;
1285 fxMesa
->unitsState
.alphaTestRefValue
= 0.0;
1287 fxMesa
->unitsState
.blendEnabled
= GL_FALSE
;
1288 fxMesa
->unitsState
.blendSrcFuncRGB
= GR_BLEND_ONE
;
1289 fxMesa
->unitsState
.blendDstFuncRGB
= GR_BLEND_ZERO
;
1290 fxMesa
->unitsState
.blendSrcFuncAlpha
= GR_BLEND_ONE
;
1291 fxMesa
->unitsState
.blendDstFuncAlpha
= GR_BLEND_ZERO
;
1292 fxMesa
->unitsState
.blendEq
= GR_BLEND_OP_ADD
;
1294 fxMesa
->unitsState
.depthTestEnabled
= GL_FALSE
;
1295 fxMesa
->unitsState
.depthMask
= GL_TRUE
;
1296 fxMesa
->unitsState
.depthTestFunc
= GL_LESS
;
1297 fxMesa
->unitsState
.depthBias
= 0;
1299 fxMesa
->unitsState
.stencilWriteMask
= 0xff;
1301 if (fxMesa
->colDepth
!= 16) {
1302 /* 32bpp mode or 15bpp mode */
1303 fxMesa
->Glide
.grColorMaskExt(FXTRUE
, FXTRUE
, FXTRUE
, fxMesa
->haveHwAlpha
);
1306 grColorMask(FXTRUE
, fxMesa
->haveHwAlpha
);
1309 fxMesa
->currentFB
= fxMesa
->haveDoubleBuffer
? GR_BUFFER_BACKBUFFER
: GR_BUFFER_FRONTBUFFER
;
1310 grRenderBuffer(fxMesa
->currentFB
);
1312 fxMesa
->state
= MALLOC(FX_grGetInteger(GR_GLIDE_STATE_SIZE
));
1313 fxMesa
->fogTable
= (GrFog_t
*) MALLOC(FX_grGetInteger(GR_FOG_TABLE_ENTRIES
) *
1316 if (!fxMesa
->state
|| !fxMesa
->fogTable
) {
1318 FREE(fxMesa
->state
);
1319 if (fxMesa
->fogTable
)
1320 FREE(fxMesa
->fogTable
);
1324 if (fxMesa
->haveZBuffer
)
1325 grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER
);
1327 if (!fxMesa
->bgrOrder
) {
1328 grLfbWriteColorFormat(GR_COLORFORMAT_ABGR
);
1331 fxMesa
->textureAlign
= FX_grGetInteger(GR_TEXTURE_ALIGN
);
1334 int textureLevels
= 0;
1335 int textureSize
= FX_grGetInteger(GR_MAX_TEXTURE_SIZE
);
1338 } while ((textureSize
>>= 0x1) & 0x7ff);
1339 ctx
->Const
.MaxTextureLevels
= textureLevels
;
1341 ctx
->Const
.MaxTextureCoordUnits
= fxMesa
->haveTwoTMUs
? 2 : 1;
1342 ctx
->Const
.MaxTextureImageUnits
= fxMesa
->haveTwoTMUs
? 2 : 1;
1343 ctx
->Const
.MaxTextureUnits
= MAX2(ctx
->Const
.MaxTextureImageUnits
, ctx
->Const
.MaxTextureCoordUnits
);
1345 fxMesa
->new_state
= _NEW_ALL
;
1346 if (!fxMesa
->haveHwStencil
) {
1347 /* don't touch stencil if there is none */
1348 fxMesa
->new_state
&= ~FX_NEW_STENCIL
;
1351 /* Initialize the software rasterizer and helper modules.
1353 _swrast_CreateContext(ctx
);
1354 _ac_CreateContext(ctx
);
1355 _tnl_CreateContext(ctx
);
1356 _swsetup_CreateContext(ctx
);
1358 /* Install customized pipeline */
1359 _tnl_destroy_pipeline(ctx
);
1360 _tnl_install_pipeline(ctx
, fx_pipeline
);
1364 fxSetupDDPointers(ctx
);
1365 fxDDInitTriFuncs(ctx
);
1367 /* Tell the software rasterizer to use pixel fog always.
1369 _swrast_allow_vertex_fog(ctx
, GL_FALSE
);
1370 _swrast_allow_pixel_fog(ctx
, GL_TRUE
);
1372 /* Tell tnl not to calculate or use vertex fog factors. (Needed to
1373 * tell render stage not to clip fog coords).
1375 /* _tnl_calculate_vertex_fog( ctx, GL_FALSE ); */
1377 fxDDInitExtensions(ctx
);
1380 /* [dBorca] Hack alert:
1381 * do we want dither? It just looks bad...
1383 grEnable(GR_ALLOW_MIPMAP_DITHER
);
1384 grTexNccTable(GR_NCCTABLE_NCC0
); /* set this once... no multipass */
1386 grGlideGetState((GrState
*) fxMesa
->state
);
1394 fxDDDestroyFxMesaContext(fxMesaContext fxMesa
)
1396 _swsetup_DestroyContext(fxMesa
->glCtx
);
1397 _tnl_DestroyContext(fxMesa
->glCtx
);
1398 _ac_DestroyContext(fxMesa
->glCtx
);
1399 _swrast_DestroyContext(fxMesa
->glCtx
);
1402 FREE(fxMesa
->state
);
1403 if (fxMesa
->fogTable
)
1404 FREE(fxMesa
->fogTable
);
1406 fxFreeVB(fxMesa
->glCtx
);
1413 fxDDInitExtensions(GLcontext
* ctx
)
1415 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1417 _mesa_enable_extension(ctx
, "GL_EXT_point_parameters");
1418 _mesa_enable_extension(ctx
, "GL_EXT_paletted_texture");
1419 _mesa_enable_extension(ctx
, "GL_EXT_texture_lod_bias");
1420 _mesa_enable_extension(ctx
, "GL_EXT_shared_texture_palette");
1421 _mesa_enable_extension(ctx
, "GL_EXT_blend_func_separate");
1423 if (fxMesa
->haveTwoTMUs
) {
1424 _mesa_enable_extension(ctx
, "GL_EXT_texture_env_add");
1425 _mesa_enable_extension(ctx
, "GL_ARB_multitexture");
1428 if (fxMesa
->haveHwStencil
) {
1429 _mesa_enable_extension( ctx
, "GL_EXT_stencil_wrap" );
1432 /* [dBorca] Hack alert:
1433 * True texture compression can be done only on Napalm.
1434 * We will advertise, however, generic texture compression
1435 * on all Voodoo cards; the Mesa logic allows us to eventually
1436 * fallback to uncompressed. This will fix those dumb applications
1437 * which refuse to run w/o texture compression! We actually _can_
1438 * do texture compression for pre-Napalm cores, through NCC. But
1439 * NCC poses many issues:
1440 * 1) NCC w/o DITHER_ERR has poor quality and NCC w/ DITHER_ERR is
1442 * 2) NCC compression cannot be used with multitexturing, because
1443 * the decompression tables are not per TMU anymore (bear in mind
1444 * that earlier Voodoos could handle 2 NCC tables for each TMU --
1445 * just look for POINTCAST_PALETTE). As a last resort, we could
1446 * fake NCC multitexturing through multipass rendering, but...
1447 * ohwell, it's not worth the effort...
1448 * This stand true for multitexturing palletized textures.
1449 * 3) since NCC is not an OpenGL standard (as opposed to FXT1), we
1450 * would need to plug deeper into the core... First, we would need to
1451 * bind NCC to GL_COMPRESSED_RGB[A]. Then, we would need to trick
1452 * Mesa into reporting our texture as compressed. Last, we would need
1453 * to stash the NCC decompression table into the mipmap data and adjust
1454 * CompressedSize accordingly!
1456 _mesa_enable_extension(ctx
, "GL_ARB_texture_compression");
1458 if (fxMesa
->type
>= GR_SSTTYPE_Voodoo4
) {
1459 _mesa_enable_extension(ctx
, "GL_3DFX_texture_compression_FXT1");
1460 _mesa_enable_extension(ctx
, "GL_EXT_texture_compression_s3tc");
1461 /*_mesa_enable_extension(ctx, "GL_S3_s3tc");*/
1464 if (fxMesa
->HaveCmbExt
) {
1465 _mesa_enable_extension(ctx
, "GL_EXT_texture_env_combine");
1468 if (fxMesa
->HavePixExt
) {
1469 _mesa_enable_extension(ctx
, "GL_EXT_blend_subtract");
1472 if (fxMesa
->HaveMirExt
) {
1473 _mesa_enable_extension(ctx
, "GL_ARB_texture_mirrored_repeat");
1478 /************************************************************************/
1479 /************************************************************************/
1480 /************************************************************************/
1482 /* Check if the hardware supports the current context
1484 * Performs similar work to fxDDChooseRenderState() - should be merged.
1487 fx_check_IsInHardware(GLcontext
* ctx
)
1489 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1491 if (ctx
->RenderMode
!= GL_RENDER
) {
1492 return FX_FALLBACK_RENDER_MODE
;
1495 if (ctx
->Stencil
.Enabled
&& !fxMesa
->haveHwStencil
) {
1496 return FX_FALLBACK_STENCIL
;
1499 if (ctx
->Color
._DrawDestMask
!= FRONT_LEFT_BIT
&& ctx
->Color
._DrawDestMask
!= BACK_LEFT_BIT
) {
1500 return FX_FALLBACK_DRAW_BUFFER
;
1503 if (ctx
->Color
.BlendEnabled
) {
1504 if (ctx
->Color
.BlendEquation
!= GL_FUNC_ADD_EXT
) {
1505 if (fxMesa
->HavePixExt
) {
1506 if ((ctx
->Color
.BlendEquation
!= GL_FUNC_SUBTRACT_EXT
) &&
1507 (ctx
->Color
.BlendEquation
!= GL_FUNC_REVERSE_SUBTRACT_EXT
)) {
1508 return FX_FALLBACK_BLEND
;
1511 return FX_FALLBACK_BLEND
;
1516 if (ctx
->Color
.ColorLogicOpEnabled
&& (ctx
->Color
.LogicOp
!= GL_COPY
)) {
1517 return FX_FALLBACK_LOGICOP
;
1520 if (ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
1521 return FX_FALLBACK_SPECULAR
;
1524 if ((ctx
->Color
.ColorMask
[RCOMP
] != ctx
->Color
.ColorMask
[GCOMP
])
1526 (ctx
->Color
.ColorMask
[GCOMP
] != ctx
->Color
.ColorMask
[BCOMP
])
1528 (ctx
->Color
.ColorMask
[BCOMP
] != ctx
->Color
.ColorMask
[ACOMP
])
1530 return FX_FALLBACK_COLORMASK
;
1533 /* Unsupported texture/multitexture cases */
1535 if (fxMesa
->haveTwoTMUs
) {
1536 /* we can only do 2D textures */
1537 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
& ~TEXTURE_2D_BIT
)
1538 return FX_FALLBACK_TEXTURE_1D_3D
;
1539 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
& ~TEXTURE_2D_BIT
)
1540 return FX_FALLBACK_TEXTURE_1D_3D
;
1542 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
& TEXTURE_2D_BIT
) {
1543 if (fxMesa
->type
< GR_SSTTYPE_Voodoo2
)
1544 if (ctx
->Texture
.Unit
[0].EnvMode
== GL_BLEND
&&
1545 (ctx
->Texture
.Unit
[1]._ReallyEnabled
& TEXTURE_2D_BIT
||
1546 ctx
->Texture
.Unit
[0].EnvColor
[0] != 0 ||
1547 ctx
->Texture
.Unit
[0].EnvColor
[1] != 0 ||
1548 ctx
->Texture
.Unit
[0].EnvColor
[2] != 0 ||
1549 ctx
->Texture
.Unit
[0].EnvColor
[3] != 1)) {
1550 return FX_FALLBACK_TEXTURE_ENV
;
1552 if (ctx
->Texture
.Unit
[0]._Current
->Image
[0]->Border
> 0)
1553 return FX_FALLBACK_TEXTURE_BORDER
;
1556 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
& TEXTURE_2D_BIT
) {
1557 if (fxMesa
->type
< GR_SSTTYPE_Voodoo2
)
1558 if (ctx
->Texture
.Unit
[1].EnvMode
== GL_BLEND
)
1559 return FX_FALLBACK_TEXTURE_ENV
;
1560 if (ctx
->Texture
.Unit
[1]._Current
->Image
[0]->Border
> 0)
1561 return FX_FALLBACK_TEXTURE_BORDER
;
1564 if (TDFX_DEBUG
& (VERBOSE_DRIVER
| VERBOSE_TEXTURE
))
1565 fprintf(stderr
, "%s: envmode is %s/%s\n", __FUNCTION__
,
1566 _mesa_lookup_enum_by_nr(ctx
->Texture
.Unit
[0].EnvMode
),
1567 _mesa_lookup_enum_by_nr(ctx
->Texture
.Unit
[1].EnvMode
));
1569 /* KW: This was wrong (I think) and I changed it... which doesn't mean
1570 * it is now correct...
1571 * BP: The old condition just seemed to test if both texture units
1572 * were enabled. That's easy!
1574 if (ctx
->Texture
._EnabledUnits
== 0x3) {
1575 /* Can't use multipass to blend a multitextured triangle - fall
1578 if (!fxMesa
->haveTwoTMUs
&& ctx
->Color
.BlendEnabled
) {
1579 return FX_FALLBACK_TEXTURE_MULTI
;
1582 if ((ctx
->Texture
.Unit
[0].EnvMode
!= ctx
->Texture
.Unit
[1].EnvMode
) &&
1583 (ctx
->Texture
.Unit
[0].EnvMode
!= GL_MODULATE
) &&
1584 (ctx
->Texture
.Unit
[0].EnvMode
!= GL_REPLACE
)) { /* q2, seems ok... */
1585 if (TDFX_DEBUG
& VERBOSE_DRIVER
)
1586 fprintf(stderr
, "%s: unsupported multitex env mode\n", __FUNCTION__
);
1587 return FX_FALLBACK_TEXTURE_MULTI
;
1592 /* we have just one texture unit */
1593 if (ctx
->Texture
._EnabledUnits
> 0x1) {
1594 return FX_FALLBACK_TEXTURE_MULTI
;
1597 if (fxMesa
->type
< GR_SSTTYPE_Voodoo2
)
1598 if ((ctx
->Texture
.Unit
[0]._ReallyEnabled
& TEXTURE_2D_BIT
) &&
1599 (ctx
->Texture
.Unit
[0].EnvMode
== GL_BLEND
)) {
1600 return FX_FALLBACK_TEXTURE_ENV
;
1610 fxDDUpdateDDPointers(GLcontext
* ctx
, GLuint new_state
)
1612 /* TNLcontext *tnl = TNL_CONTEXT(ctx);*/
1613 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1615 if (TDFX_DEBUG
& VERBOSE_DRIVER
) {
1616 fprintf(stderr
, "fxDDUpdateDDPointers(%08x)\n", new_state
);
1619 _swrast_InvalidateState(ctx
, new_state
);
1620 _ac_InvalidateState(ctx
, new_state
);
1621 _tnl_InvalidateState(ctx
, new_state
);
1622 _swsetup_InvalidateState(ctx
, new_state
);
1624 fxMesa
->new_gl_state
|= new_state
;
1631 fxSetupDDPointers(GLcontext
* ctx
)
1633 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1634 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1636 if (TDFX_DEBUG
& VERBOSE_DRIVER
) {
1637 fprintf(stderr
, "%s()\n", __FUNCTION__
);
1640 ctx
->Driver
.UpdateState
= fxDDUpdateDDPointers
;
1641 ctx
->Driver
.GetString
= fxDDGetString
;
1642 ctx
->Driver
.ClearIndex
= NULL
;
1643 ctx
->Driver
.ClearColor
= fxDDClearColor
;
1644 ctx
->Driver
.Clear
= fxDDClear
;
1645 ctx
->Driver
.DrawBuffer
= fxDDSetDrawBuffer
;
1646 ctx
->Driver
.GetBufferSize
= fxDDBufferSize
;
1647 ctx
->Driver
.Accum
= _swrast_Accum
;
1648 ctx
->Driver
.CopyPixels
= _swrast_CopyPixels
;
1649 ctx
->Driver
.DrawPixels
= _swrast_DrawPixels
;
1650 switch (fxMesa
->colDepth
) {
1652 ctx
->Driver
.ReadPixels
= fxDDReadPixels555
;
1653 ctx
->Driver
.Bitmap
= fxDDDrawBitmap2
;
1656 ctx
->Driver
.ReadPixels
= fxDDReadPixels565
;
1657 ctx
->Driver
.Bitmap
= fxDDDrawBitmap2
;
1660 ctx
->Driver
.DrawPixels
= fxDDDrawPixels8888
;
1661 ctx
->Driver
.ReadPixels
= fxDDReadPixels8888
;
1662 ctx
->Driver
.Bitmap
= fxDDDrawBitmap4
;
1665 ctx
->Driver
.ResizeBuffers
= _swrast_alloc_buffers
;
1666 ctx
->Driver
.Finish
= fxDDFinish
;
1667 ctx
->Driver
.Flush
= NULL
;
1668 ctx
->Driver
.ChooseTextureFormat
= fxDDChooseTextureFormat
;
1669 ctx
->Driver
.TexImage1D
= _mesa_store_teximage1d
;
1670 ctx
->Driver
.TexImage2D
= fxDDTexImage2D
;
1671 ctx
->Driver
.TexImage3D
= _mesa_store_teximage3d
;
1672 ctx
->Driver
.TexSubImage1D
= _mesa_store_texsubimage1d
;
1673 ctx
->Driver
.TexSubImage2D
= fxDDTexSubImage2D
;
1674 ctx
->Driver
.TexSubImage3D
= _mesa_store_texsubimage3d
;
1675 ctx
->Driver
.CompressedTexImage1D
= _mesa_store_compressed_teximage1d
;
1676 ctx
->Driver
.CompressedTexImage2D
= fxDDCompressedTexImage2D
;
1677 ctx
->Driver
.CompressedTexImage3D
= _mesa_store_compressed_teximage3d
;
1678 ctx
->Driver
.CompressedTexSubImage1D
= _mesa_store_compressed_texsubimage1d
;
1679 ctx
->Driver
.CompressedTexSubImage2D
= fxDDCompressedTexSubImage2D
;
1680 ctx
->Driver
.CompressedTexSubImage3D
= _mesa_store_compressed_texsubimage3d
;
1681 ctx
->Driver
.IsCompressedFormat
= fxDDIsCompressedFormat
;
1682 ctx
->Driver
.CompressedTextureSize
= fxDDCompressedTextureSize
;
1683 ctx
->Driver
.CopyTexImage1D
= _swrast_copy_teximage1d
;
1684 ctx
->Driver
.CopyTexImage2D
= _swrast_copy_teximage2d
;
1685 ctx
->Driver
.CopyTexSubImage1D
= _swrast_copy_texsubimage1d
;
1686 ctx
->Driver
.CopyTexSubImage2D
= _swrast_copy_texsubimage2d
;
1687 ctx
->Driver
.CopyTexSubImage3D
= _swrast_copy_texsubimage3d
;
1688 ctx
->Driver
.TestProxyTexImage
= _mesa_test_proxy_teximage
;
1689 ctx
->Driver
.CopyColorTable
= _swrast_CopyColorTable
;
1690 ctx
->Driver
.CopyColorSubTable
= _swrast_CopyColorSubTable
;
1691 ctx
->Driver
.CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
1692 ctx
->Driver
.CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
1693 ctx
->Driver
.TexEnv
= fxDDTexEnv
;
1694 ctx
->Driver
.TexParameter
= fxDDTexParam
;
1695 ctx
->Driver
.BindTexture
= fxDDTexBind
;
1696 ctx
->Driver
.DeleteTexture
= fxDDTexDel
;
1697 ctx
->Driver
.IsTextureResident
= fxDDIsTextureResident
;
1698 ctx
->Driver
.UpdateTexturePalette
= fxDDTexPalette
;
1699 ctx
->Driver
.AlphaFunc
= fxDDAlphaFunc
;
1700 ctx
->Driver
.BlendFunc
= fxDDBlendFunc
;
1701 ctx
->Driver
.BlendFuncSeparate
= fxDDBlendFuncSeparate
;
1702 ctx
->Driver
.BlendEquation
= fxDDBlendEquation
;
1703 ctx
->Driver
.DepthFunc
= fxDDDepthFunc
;
1704 ctx
->Driver
.DepthMask
= fxDDDepthMask
;
1705 ctx
->Driver
.ColorMask
= fxDDColorMask
;
1706 ctx
->Driver
.Fogfv
= fxDDFogfv
;
1707 ctx
->Driver
.Scissor
= fxDDScissor
;
1708 ctx
->Driver
.FrontFace
= fxDDFrontFace
;
1709 ctx
->Driver
.CullFace
= fxDDCullFace
;
1710 ctx
->Driver
.ShadeModel
= fxDDShadeModel
;
1711 ctx
->Driver
.Enable
= fxDDEnable
;
1712 if (fxMesa
->haveHwStencil
) {
1713 ctx
->Driver
.StencilFunc
= fxDDStencilFunc
;
1714 ctx
->Driver
.StencilMask
= fxDDStencilMask
;
1715 ctx
->Driver
.StencilOp
= fxDDStencilOp
;
1718 fxSetupDDSpanPointers(ctx
);
1719 fxDDUpdateDDPointers(ctx
, ~0);
1727 * Need this to provide at least one external definition.
1730 extern int gl_fx_dummy_function_dd(void);
1732 gl_fx_dummy_function_dd(void)