1 /* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 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.
27 * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
30 * Thank you for your contribution, David!
32 * Please make note of the above copyright/license statement. If you
33 * contributed code or bug fixes to this code under the previous (GNU
34 * Library) license and object to the new license, your code will be
35 * removed at your request. Please see the Mesa docs/COPYRIGHT file
36 * for more information.
38 * Additional Mesa/3Dfx driver developers:
39 * Daryll Strauss <daryll@precisioninsight.com>
40 * Keith Whitwell <keith@precisioninsight.com>
42 * See fxapi.h for more revision/author details.
46 /* fxdd.c - 3Dfx VooDoo Mesa device driver functions */
59 #include "extensions.h"
62 /* These lookup table are used to extract RGB values in [0,255] from
63 * 16-bit pixel values.
65 GLubyte FX_PixelToR
[0x10000];
66 GLubyte FX_PixelToG
[0x10000];
67 GLubyte FX_PixelToB
[0x10000];
71 * Initialize the FX_PixelTo{RGB} arrays.
72 * Input: bgrOrder - if TRUE, pixels are in BGR order, else RGB order.
74 void fxInitPixelTables(fxMesaContext fxMesa
, GLboolean bgrOrder
)
78 fxMesa
->bgrOrder
=bgrOrder
;
79 for (pixel
= 0; pixel
<= 0xffff; pixel
++) {
82 r
= (pixel
& 0x001F) << 3;
83 g
= (pixel
& 0x07E0) >> 3;
84 b
= (pixel
& 0xF800) >> 8;
87 r
= (pixel
& 0xF800) >> 8;
88 g
= (pixel
& 0x07E0) >> 3;
89 b
= (pixel
& 0x001F) << 3;
91 r
= r
* 255 / 0xF8; /* fill in low-order bits */
94 FX_PixelToR
[pixel
] = r
;
95 FX_PixelToG
[pixel
] = g
;
96 FX_PixelToB
[pixel
] = b
;
101 /**********************************************************************/
102 /***** Miscellaneous functions *****/
103 /**********************************************************************/
105 /* Return buffer size information */
106 static void fxDDBufferSize(GLcontext
*ctx
, GLuint
*width
, GLuint
*height
)
108 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
110 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
111 fprintf(stderr
,"fxmesa: fxDDBufferSize(...) Start\n");
114 *width
=fxMesa
->width
;
115 *height
=fxMesa
->height
;
117 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
118 fprintf(stderr
,"fxmesa: fxDDBufferSize(...) End\n");
123 /* Set current drawing color */
124 static void fxDDSetColor(GLcontext
*ctx
, GLubyte red
, GLubyte green
,
125 GLubyte blue
, GLubyte alpha
)
127 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
129 ASSIGN_4V( col
, red
, green
, blue
, alpha
);
131 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
132 fprintf(stderr
,"fxmesa: fxDDSetColor(%d,%d,%d,%d)\n",red
,green
,blue
,alpha
);
135 fxMesa
->color
=FXCOLOR4(col
);
139 /* Implements glClearColor() */
140 static void fxDDClearColor(GLcontext
*ctx
, GLubyte red
, GLubyte green
,
141 GLubyte blue
, GLubyte alpha
)
143 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
148 ASSIGN_4V( col
, red
, green
, blue
, 255 );
150 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
151 fprintf(stderr
,"fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",red
,green
,blue
,alpha
);
154 fxMesa
->clearC
=FXCOLOR4( col
);
155 fxMesa
->clearA
=alpha
;
159 /* Clear the color and/or depth buffers */
160 static GLbitfield
fxDDClear(GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
161 GLint x
, GLint y
, GLint width
, GLint height
)
163 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
164 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
165 const FxU16 clearD
= (FxU16
) (ctx
->Depth
.Clear
* 0xffff);
166 GLbitfield softwareMask
= mask
& (DD_STENCIL_BIT
| DD_ACCUM_BIT
);
168 /* we can't clear stencil or accum buffers */
169 mask
&= ~(DD_STENCIL_BIT
| DD_ACCUM_BIT
);
171 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
172 fprintf(stderr
,"fxmesa: fxDDClear(%d,%d,%d,%d)\n", (int) x
, (int) y
,
173 (int) width
, (int) height
);
176 if (colorMask
!= 0xffffffff) {
177 /* do masked color buffer clears in software */
178 softwareMask
|= (mask
& (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
));
179 mask
&= ~(DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
);
183 * This could probably be done fancier but doing each possible case
184 * explicitly is less error prone.
187 case DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
:
188 /* back buffer & depth */
189 FX_grDepthMask(FXTRUE
);
190 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
191 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
192 if (!ctx
->Depth
.Mask
) {
193 FX_grDepthMask(FXFALSE
);
196 case DD_FRONT_LEFT_BIT
| DD_DEPTH_BIT
:
197 /* XXX it appears that the depth buffer isn't cleared when
198 * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set.
199 * This is a work-around/
202 FX_grDepthMask(FXTRUE
);
203 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
204 FX_grColorMask(FXFALSE
,FXFALSE
);
205 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
207 FX_grColorMask(FXTRUE
, ctx
->Color
.ColorMask
[ACOMP
] && fxMesa
->haveAlphaBuffer
);
208 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
209 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
211 case DD_BACK_LEFT_BIT
:
212 /* back buffer only */
213 FX_grDepthMask(FXFALSE
);
214 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
215 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
216 if (ctx
->Depth
.Mask
) {
217 FX_grDepthMask(FXTRUE
);
220 case DD_FRONT_LEFT_BIT
:
221 /* front buffer only */
222 FX_grDepthMask(FXFALSE
);
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
:
231 FX_grDepthMask(FXFALSE
);
232 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
233 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
234 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
235 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
236 if (ctx
->Depth
.Mask
) {
237 FX_grDepthMask(FXTRUE
);
240 case DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
:
242 FX_grDepthMask(FXFALSE
);
243 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
244 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
245 /* clear back and depth */
246 FX_grDepthMask(FXTRUE
);
247 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
248 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
249 if (!ctx
->Depth
.Mask
) {
250 FX_grDepthMask(FXFALSE
);
254 /* just the depth buffer */
255 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
256 FX_grColorMask(FXFALSE
,FXFALSE
);
257 FX_grDepthMask(FXTRUE
);
258 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
259 FX_grColorMask(FXTRUE
, ctx
->Color
.ColorMask
[ACOMP
] && fxMesa
->haveAlphaBuffer
);
260 if (ctx
->Color
.DrawDestMask
& FRONT_LEFT_BIT
)
261 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
262 if (!ctx
->Depth
.Test
|| !ctx
->Depth
.Mask
)
263 FX_grDepthMask(FXFALSE
);
274 /* Set the buffer used for drawing */
275 /* XXX support for separate read/draw buffers hasn't been tested */
276 static GLboolean
fxDDSetDrawBuffer(GLcontext
*ctx
, GLenum mode
)
278 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
280 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
281 fprintf(stderr
,"fxmesa: fxDDSetBuffer(%x)\n", (int) mode
);
284 if (mode
== GL_FRONT_LEFT
) {
285 fxMesa
->currentFB
= GR_BUFFER_FRONTBUFFER
;
286 FX_grRenderBuffer(fxMesa
->currentFB
);
289 else if (mode
== GL_BACK_LEFT
) {
290 fxMesa
->currentFB
= GR_BUFFER_BACKBUFFER
;
291 FX_grRenderBuffer(fxMesa
->currentFB
);
294 else if (mode
== GL_NONE
) {
295 FX_grColorMask(FXFALSE
,FXFALSE
);
304 /* Set the buffer used for reading */
305 /* XXX support for separate read/draw buffers hasn't been tested */
306 static void fxDDSetReadBuffer(GLcontext
*ctx
, GLframebuffer
*buffer
,
309 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
312 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
313 fprintf(stderr
,"fxmesa: fxDDSetBuffer(%x)\n", (int) mode
);
316 if (mode
== GL_FRONT_LEFT
) {
317 fxMesa
->currentFB
= GR_BUFFER_FRONTBUFFER
;
318 FX_grRenderBuffer(fxMesa
->currentFB
);
320 else if (mode
== GL_BACK_LEFT
) {
321 fxMesa
->currentFB
= GR_BUFFER_BACKBUFFER
;
322 FX_grRenderBuffer(fxMesa
->currentFB
);
328 /* test if window coord (px,py) is visible */
329 static GLboolean
inClipRects(fxMesaContext fxMesa
, int px
, int py
)
332 for (i
=0; i
<fxMesa
->numClipRects
; i
++) {
333 if ((px
>=fxMesa
->pClipRects
[i
].x1
) &&
334 (px
<fxMesa
->pClipRects
[i
].x2
) &&
335 (py
>=fxMesa
->pClipRects
[i
].y1
) &&
336 (py
<fxMesa
->pClipRects
[i
].y2
)) return GL_TRUE
;
343 static GLboolean
fxDDDrawBitmap(GLcontext
*ctx
, GLint px
, GLint py
,
344 GLsizei width
, GLsizei height
,
345 const struct gl_pixelstore_attrib
*unpack
,
346 const GLubyte
*bitmap
)
348 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
351 const struct gl_pixelstore_attrib
*finalUnpack
;
352 struct gl_pixelstore_attrib scissoredUnpack
;
354 /* check if there's any raster operations enabled which we can't handle */
355 if (ctx
->RasterMask
& (ALPHATEST_BIT
|
367 if (ctx
->Scissor
.Enabled
) {
368 /* This is a bit tricky, but by carefully adjusting the px, py,
369 * width, height, skipPixels and skipRows values we can do
370 * scissoring without special code in the rendering loop.
373 /* we'll construct a new pixelstore struct */
374 finalUnpack
= &scissoredUnpack
;
375 scissoredUnpack
= *unpack
;
376 if (scissoredUnpack
.RowLength
== 0)
377 scissoredUnpack
.RowLength
= width
;
380 if (px
< ctx
->Scissor
.X
) {
381 scissoredUnpack
.SkipPixels
+= (ctx
->Scissor
.X
- px
);
382 width
-= (ctx
->Scissor
.X
- px
);
386 if (px
+ width
>= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
) {
387 width
-= (px
+ width
- (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
));
390 if (py
< ctx
->Scissor
.Y
) {
391 scissoredUnpack
.SkipRows
+= (ctx
->Scissor
.Y
- py
);
392 height
-= (ctx
->Scissor
.Y
- py
);
396 if (py
+ height
>= ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
) {
397 height
-= (py
+ height
- (ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
));
400 if (width
<= 0 || height
<= 0)
401 return GL_TRUE
; /* totally scissored away */
404 finalUnpack
= unpack
;
407 /* compute pixel value */
409 GLint r
= (GLint
) (ctx
->Current
.RasterColor
[0] * 255.0f
);
410 GLint g
= (GLint
) (ctx
->Current
.RasterColor
[1] * 255.0f
);
411 GLint b
= (GLint
) (ctx
->Current
.RasterColor
[2] * 255.0f
);
412 /*GLint a = (GLint)(ctx->Current.RasterColor[3]*255.0f);*/
413 if (fxMesa
->bgrOrder
)
415 ( ((FxU16
)0xf8 & b
) << (11-3)) |
416 ( ((FxU16
)0xfc & g
) << (5-3+1)) |
417 ( ((FxU16
)0xf8 & r
) >> 3);
420 ( ((FxU16
)0xf8 & r
) << (11-3)) |
421 ( ((FxU16
)0xfc & g
) << (5-3+1)) |
422 ( ((FxU16
)0xf8 & b
) >> 3);
425 info
.size
= sizeof(info
);
426 if (!FX_grLfbLock(GR_LFB_WRITE_ONLY
,
429 GR_ORIGIN_UPPER_LEFT
,
433 fprintf(stderr
,"fx Driver: error locking the linear frame buffer\n");
439 #define INSIDE(c, x, y) inClipRects((c), (x), (y))
441 #define INSIDE(c, x, y) (1)
445 const GLint winX
= fxMesa
->x_offset
;
446 const GLint winY
= fxMesa
->y_offset
+ fxMesa
->height
- 1;
447 /* The dest stride depends on the hardware and whether we're drawing
448 * to the front or back buffer. This compile-time test seems to do
452 const GLint dstStride
= (fxMesa
->glCtx
->Color
.DrawBuffer
== GL_FRONT
)
453 ? (fxMesa
->screen_width
) : (info
.strideInBytes
/ 2);
455 const GLint dstStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
458 /* compute dest address of bottom-left pixel in bitmap */
459 GLushort
*dst
= (GLushort
*) info
.lfbPtr
460 + (winY
- py
) * dstStride
463 for (row
= 0; row
< height
; row
++) {
464 const GLubyte
*src
= (const GLubyte
*) _mesa_image_address( finalUnpack
,
465 bitmap
, width
, height
, GL_COLOR_INDEX
, GL_BITMAP
, 0, row
, 0 );
466 if (finalUnpack
->LsbFirst
) {
467 /* least significan bit first */
468 GLubyte mask
= 1U << (finalUnpack
->SkipPixels
& 0x7);
470 for (col
=0; col
<width
; col
++) {
472 if (INSIDE(fxMesa
, winX
+ px
+ col
, winY
- py
- row
))
487 /* most significan bit first */
488 GLubyte mask
= 128U >> (finalUnpack
->SkipPixels
& 0x7);
490 for (col
=0; col
<width
; col
++) {
492 if (INSIDE(fxMesa
, winX
+ px
+ col
, winY
- py
- row
))
512 FX_grLfbUnlock(GR_LFB_WRITE_ONLY
,fxMesa
->currentFB
);
517 static GLboolean
fxDDReadPixels( GLcontext
*ctx
, GLint x
, GLint y
,
518 GLsizei width
, GLsizei height
,
519 GLenum format
, GLenum type
,
520 const struct gl_pixelstore_attrib
*packing
,
523 if (ctx
->ImageTransferState
) {
524 return GL_FALSE
; /* can't do this */
527 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
529 GLboolean result
= GL_FALSE
;
532 if (grLfbLock(GR_LFB_READ_ONLY
,
535 GR_ORIGIN_UPPER_LEFT
,
538 const GLint winX
= fxMesa
->x_offset
;
539 const GLint winY
= fxMesa
->y_offset
+ fxMesa
->height
- 1;
541 const GLint srcStride
= (fxMesa
->glCtx
->Color
.DrawBuffer
== GL_FRONT
)
542 ? (fxMesa
->screen_width
) : (info
.strideInBytes
/ 2);
544 const GLint srcStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
546 const GLushort
*src
= (const GLushort
*) info
.lfbPtr
547 + (winY
- y
) * srcStride
+ (winX
+ x
);
548 GLubyte
*dst
= (GLubyte
*) _mesa_image_address(packing
, dstImage
,
549 width
, height
, format
, type
, 0, 0, 0);
550 GLint dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
552 if (format
== GL_RGB
&& type
== GL_UNSIGNED_BYTE
) {
553 /* convert 5R6G5B into 8R8G8B */
555 const GLint halfWidth
= width
>> 1;
556 const GLint extraPixel
= (width
& 1);
557 for (row
= 0; row
< height
; row
++) {
559 for (col
= 0; col
< halfWidth
; col
++) {
560 const GLuint pixel
= ((const GLuint
*) src
)[col
];
561 const GLint pixel0
= pixel
& 0xffff;
562 const GLint pixel1
= pixel
>> 16;
563 *d
++ = FX_PixelToR
[pixel0
];
564 *d
++ = FX_PixelToG
[pixel0
];
565 *d
++ = FX_PixelToB
[pixel0
];
566 *d
++ = FX_PixelToR
[pixel1
];
567 *d
++ = FX_PixelToG
[pixel1
];
568 *d
++ = FX_PixelToB
[pixel1
];
571 GLushort pixel
= src
[width
-1];
572 *d
++ = FX_PixelToR
[pixel
];
573 *d
++ = FX_PixelToG
[pixel
];
574 *d
++ = FX_PixelToB
[pixel
];
581 else if (format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) {
582 /* convert 5R6G5B into 8R8G8B8A */
584 const GLint halfWidth
= width
>> 1;
585 const GLint extraPixel
= (width
& 1);
586 for (row
= 0; row
< height
; row
++) {
588 for (col
= 0; col
< halfWidth
; col
++) {
589 const GLuint pixel
= ((const GLuint
*) src
)[col
];
590 const GLint pixel0
= pixel
& 0xffff;
591 const GLint pixel1
= pixel
>> 16;
592 *d
++ = FX_PixelToR
[pixel0
];
593 *d
++ = FX_PixelToG
[pixel0
];
594 *d
++ = FX_PixelToB
[pixel0
];
596 *d
++ = FX_PixelToR
[pixel1
];
597 *d
++ = FX_PixelToG
[pixel1
];
598 *d
++ = FX_PixelToB
[pixel1
];
602 const GLushort pixel
= src
[width
-1];
603 *d
++ = FX_PixelToR
[pixel
];
604 *d
++ = FX_PixelToG
[pixel
];
605 *d
++ = FX_PixelToB
[pixel
];
613 else if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
614 /* directly memcpy 5R6G5B pixels into client's buffer */
615 const GLint widthInBytes
= width
* 2;
617 for (row
= 0; row
< height
; row
++) {
618 MEMCPY(dst
, src
, widthInBytes
);
628 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
637 static void fxDDFinish(GLcontext
*ctx
)
643 static GLint
fxDDGetParameteri(const GLcontext
*ctx
, GLint param
)
646 case DD_HAVE_HARDWARE_FOG
:
649 fprintf(stderr
,"fx Driver: internal error in fxDDGetParameteri(): %x\n", (int) param
);
657 void fxDDSetNearFar(GLcontext
*ctx
, GLfloat n
, GLfloat f
)
659 FX_CONTEXT(ctx
)->new_state
|= FX_NEW_FOG
;
660 ctx
->Driver
.RenderStart
= fxSetupFXUnits
;
663 /* KW: Put the word Mesa in the render string because quakeworld
664 * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
667 static const GLubyte
*fxDDGetString(GLcontext
*ctx
, GLenum name
)
669 #if defined(GLX_DIRECT_RENDERING)
670 /* Building for DRI driver */
674 static char buffer
[100];
676 strcpy(hardware
, grGetString(GR_HARDWARE
));
677 if (strcmp(hardware
, "Voodoo3 (tm)") == 0)
678 strcpy(hardware
, "Voodoo3");
679 else if (strcmp(hardware
, "Voodoo Banshee (tm)") == 0)
680 strcpy(hardware
, "VoodooBanshee");
682 /* unexpected result: replace spaces with hyphens */
684 for (i
= 0; hardware
[i
]; i
++) {
685 if (hardware
[i
] == ' ' || hardware
[i
] == '\t')
689 /* now make the GL_RENDERER string */
690 sprintf(buffer
, "Mesa DRI %s 20000510", hardware
);
694 return "Precision Insight, Inc.";
701 /* Building for Voodoo1/2 stand-alone Mesa */
707 if (glbHWConfig
.SSTs
[glbCurrentBoard
].type
==GR_SSTTYPE_VOODOO
) {
708 GrVoodooConfig_t
*vc
=
709 &glbHWConfig
.SSTs
[glbCurrentBoard
].sstBoard
.VoodooConfig
;
712 "Mesa Glide v0.30 Voodoo_Graphics %d "
713 "CARD/%d FB/%d TM/%d TMU/%s",
715 (vc
->sliDetect
? (vc
->fbRam
*2) : vc
->fbRam
),
716 (vc
->tmuConfig
[GR_TMU0
].tmuRam
+
717 ((vc
->nTexelfx
>1) ? vc
->tmuConfig
[GR_TMU1
].tmuRam
: 0)),
719 (vc
->sliDetect
? "SLI" : "NOSLI"));
721 else if (glbHWConfig
.SSTs
[glbCurrentBoard
].type
==GR_SSTTYPE_SST96
) {
722 GrSst96Config_t
*sc
=
723 &glbHWConfig
.SSTs
[glbCurrentBoard
].sstBoard
.SST96Config
;
726 "Glide v0.30 Voodoo_Rush %d "
727 "CARD/%d FB/%d TM/%d TMU/NOSLI",
730 sc
->tmuConfig
.tmuRam
,
734 strcpy(buf
, "Glide v0.30 UNKNOWN");
736 return (GLubyte
*) buf
;
745 int fxDDInitFxMesaContext( fxMesaContext fxMesa
)
748 FX_setupGrVertexLayout();
750 if (getenv("FX_EMULATE_SINGLE_TMU"))
751 fxMesa
->haveTwoTMUs
= GL_FALSE
;
753 fxMesa
->emulateTwoTMUs
= fxMesa
->haveTwoTMUs
;
755 if (!getenv("FX_DONT_FAKE_MULTITEX"))
756 fxMesa
->emulateTwoTMUs
= GL_TRUE
;
758 if(getenv("FX_GLIDE_SWAPINTERVAL"))
759 fxMesa
->swapInterval
=atoi(getenv("FX_GLIDE_SWAPINTERVAL"));
761 fxMesa
->swapInterval
=1;
763 if(getenv("MESA_FX_SWAP_PENDING"))
764 fxMesa
->maxPendingSwapBuffers
=atoi(getenv("MESA_FX_SWAP_PENDING"));
766 fxMesa
->maxPendingSwapBuffers
=2;
768 if(getenv("MESA_FX_INFO"))
769 fxMesa
->verbose
=GL_TRUE
;
771 fxMesa
->verbose
=GL_FALSE
;
773 fxMesa
->color
=0xffffffff;
777 fxMesa
->stats
.swapBuffer
=0;
778 fxMesa
->stats
.reqTexUpload
=0;
779 fxMesa
->stats
.texUpload
=0;
780 fxMesa
->stats
.memTexUpload
=0;
782 fxMesa
->tmuSrc
=FX_TMU_NONE
;
783 fxMesa
->lastUnitsMode
=FX_UM_NONE
;
788 fxMesa
->unitsState
.alphaTestEnabled
=GL_FALSE
;
789 fxMesa
->unitsState
.alphaTestFunc
=GR_CMP_ALWAYS
;
790 fxMesa
->unitsState
.alphaTestRefValue
=0;
792 fxMesa
->unitsState
.blendEnabled
=GL_FALSE
;
793 fxMesa
->unitsState
.blendSrcFuncRGB
=GR_BLEND_ONE
;
794 fxMesa
->unitsState
.blendDstFuncRGB
=GR_BLEND_ZERO
;
795 fxMesa
->unitsState
.blendSrcFuncAlpha
=GR_BLEND_ONE
;
796 fxMesa
->unitsState
.blendDstFuncAlpha
=GR_BLEND_ZERO
;
798 fxMesa
->unitsState
.depthTestEnabled
=GL_FALSE
;
799 fxMesa
->unitsState
.depthMask
=GL_TRUE
;
800 fxMesa
->unitsState
.depthTestFunc
=GR_CMP_LESS
;
802 FX_grColorMask(FXTRUE
, fxMesa
->haveAlphaBuffer
? FXTRUE
: FXFALSE
);
803 if(fxMesa
->haveDoubleBuffer
) {
804 fxMesa
->currentFB
=GR_BUFFER_BACKBUFFER
;
805 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
807 fxMesa
->currentFB
=GR_BUFFER_FRONTBUFFER
;
808 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
811 fxMesa
->state
= NULL
;
812 fxMesa
->fogTable
= NULL
;
814 fxMesa
->state
= malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE
));
815 fxMesa
->fogTable
= malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES
)*sizeof(GrFog_t
));
817 if (!fxMesa
->state
|| !fxMesa
->fogTable
) {
818 if (fxMesa
->state
) free(fxMesa
->state
);
819 if (fxMesa
->fogTable
) free(fxMesa
->fogTable
);
823 if(fxMesa
->haveZBuffer
)
824 FX_grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER
);
826 #if (!FXMESA_USE_ARGB)
827 FX_grLfbWriteColorFormat(GR_COLORFORMAT_ABGR
); /* Not every Glide has this */
830 fxMesa
->textureAlign
=FX_grGetInteger(FX_TEXTURE_ALIGN
);
831 fxMesa
->glCtx
->Const
.MaxTextureLevels
=9;
832 fxMesa
->glCtx
->Const
.MaxTextureSize
=256;
833 fxMesa
->glCtx
->Const
.MaxTextureUnits
=fxMesa
->emulateTwoTMUs
? 2 : 1;
834 fxMesa
->new_state
= _NEW_ALL
;
842 fxSetupDDPointers(fxMesa
->glCtx
);
843 fxDDRenderInit(fxMesa
->glCtx
);
844 fxDDInitExtensions(fxMesa
->glCtx
);
846 fxDDSetNearFar(fxMesa
->glCtx
,1.0,100.0);
848 FX_grGlideGetState((GrState
*)fxMesa
->state
);
850 /* XXX Fix me: callback not registered when main VB is created.
852 if (fxMesa
->glCtx
->VB
)
853 fxDDRegisterVB( fxMesa
->glCtx
->VB
);
855 /* XXX Fix me too: need to have the 'struct dd' prepared prior to
856 * creating the context... The below is broken if you try to insert
859 if (fxMesa
->glCtx
->NrPipelineStages
)
860 fxMesa
->glCtx
->NrPipelineStages
= fxDDRegisterPipelineStages(
861 fxMesa
->glCtx
->PipelineStage
,
862 fxMesa
->glCtx
->PipelineStage
,
863 fxMesa
->glCtx
->NrPipelineStages
);
865 /* Run the config file */
866 _mesa_context_initialize( fxMesa
->glCtx
);
873 /* Example extension function */
874 static void fxFooBarEXT(GLint i
)
876 printf("You called glFooBarEXT(%d)\n", i
);
881 void fxDDInitExtensions( GLcontext
*ctx
)
883 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
885 gl_extensions_disable(ctx
, "GL_EXT_blend_logic_op");
886 gl_extensions_disable(ctx
, "GL_EXT_blend_minmax");
887 gl_extensions_disable(ctx
, "GL_EXT_blend_subtract");
888 gl_extensions_disable(ctx
, "GL_EXT_blend_color");
889 gl_extensions_disable(ctx
, "GL_EXT_fog_coord");
891 gl_extensions_add(ctx
, GL_TRUE
, "3DFX_set_global_palette", 0);
893 if (!fxMesa
->haveTwoTMUs
)
894 gl_extensions_disable(ctx
, "GL_EXT_texture_env_add");
896 if (!fxMesa
->emulateTwoTMUs
)
897 gl_extensions_disable(ctx
, "GL_ARB_multitexture");
900 /* Example of hooking in an extension function.
901 * For DRI-based drivers, also see __driRegisterExtensions in the
906 void **dispatchTable
= (void **) ctx
->Exec
;
907 const int _gloffset_FooBarEXT
= 555; /* just an example number! */
908 const int tabSize
= _glapi_get_dispatch_table_size();
909 assert(_gloffset_FooBarEXT
< tabSize
);
910 dispatchTable
[_gloffset_FooBarEXT
] = (void *) fxFooBarEXT
;
911 /* XXX You would also need to hook into the display list dispatch
912 * table. Really, the implementation of extensions might as well
913 * be in the core of Mesa since core Mesa and the device driver
914 * is one big shared lib.
921 /************************************************************************/
922 /************************************************************************/
923 /************************************************************************/
925 /* Check if the hardware supports the current context
927 * Performs similar work to fxDDChooseRenderState() - should be merged.
929 static GLboolean
fxIsInHardware(GLcontext
*ctx
)
931 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
933 if (!ctx
->Hint
.AllowDrawMem
)
934 return GL_TRUE
; /* you'll take it and like it */
936 if((ctx
->RasterMask
& (STENCIL_BIT
| MULTI_DRAW_BIT
)) ||
937 ((ctx
->Color
.BlendEnabled
) && (ctx
->Color
.BlendEquation
!=GL_FUNC_ADD_EXT
)) ||
938 ((ctx
->Color
.ColorLogicOpEnabled
) && (ctx
->Color
.LogicOp
!=GL_COPY
)) ||
939 (ctx
->Light
.Model
.ColorControl
==GL_SEPARATE_SPECULAR_COLOR
) ||
940 (!((ctx
->Color
.ColorMask
[RCOMP
]==ctx
->Color
.ColorMask
[GCOMP
]) &&
941 (ctx
->Color
.ColorMask
[GCOMP
]==ctx
->Color
.ColorMask
[BCOMP
]) &&
942 (ctx
->Color
.ColorMask
[ACOMP
]==ctx
->Color
.ColorMask
[ACOMP
])))
947 /* Unsupported texture/multitexture cases */
949 if(fxMesa
->emulateTwoTMUs
) {
950 if((ctx
->Enabled
& (TEXTURE0_3D
| TEXTURE1_3D
)) ||
951 /* Not very well written ... */
952 ((ctx
->Enabled
& (TEXTURE0_1D
| TEXTURE1_1D
)) &&
953 ((ctx
->Enabled
& (TEXTURE0_2D
| TEXTURE1_2D
))!=(TEXTURE0_2D
| TEXTURE1_2D
)))
958 if (ctx
->Texture
.ReallyEnabled
& TEXTURE0_2D
) {
959 if (ctx
->Texture
.Unit
[0].EnvMode
== GL_BLEND
&&
960 (ctx
->Texture
.ReallyEnabled
& TEXTURE1_2D
||
961 ctx
->Texture
.Unit
[0].EnvColor
[0] != 0 ||
962 ctx
->Texture
.Unit
[0].EnvColor
[1] != 0 ||
963 ctx
->Texture
.Unit
[0].EnvColor
[2] != 0 ||
964 ctx
->Texture
.Unit
[0].EnvColor
[3] != 1)) {
967 if (ctx
->Texture
.Unit
[0].Current
->Image
[0]->Border
> 0)
971 if (ctx
->Texture
.ReallyEnabled
& TEXTURE1_2D
) {
972 if (ctx
->Texture
.Unit
[1].EnvMode
== GL_BLEND
)
974 if (ctx
->Texture
.Unit
[0].Current
->Image
[0]->Border
> 0)
978 if (MESA_VERBOSE
& (VERBOSE_DRIVER
|VERBOSE_TEXTURE
))
979 fprintf(stderr
, "fxMesa: fxIsInHardware, envmode is %s/%s\n",
980 gl_lookup_enum_by_nr(ctx
->Texture
.Unit
[0].EnvMode
),
981 gl_lookup_enum_by_nr(ctx
->Texture
.Unit
[1].EnvMode
));
983 /* KW: This was wrong (I think) and I changed it... which doesn't mean
984 * it is now correct...
986 if((ctx
->Enabled
& (TEXTURE0_1D
| TEXTURE0_2D
| TEXTURE0_3D
)) &&
987 (ctx
->Enabled
& (TEXTURE1_1D
| TEXTURE1_2D
| TEXTURE1_3D
)))
989 /* Can't use multipass to blend a multitextured triangle - fall
992 if (!fxMesa
->haveTwoTMUs
&& ctx
->Color
.BlendEnabled
) {
996 if ((ctx
->Texture
.Unit
[0].EnvMode
!=ctx
->Texture
.Unit
[1].EnvMode
) &&
997 (ctx
->Texture
.Unit
[0].EnvMode
!=GL_MODULATE
) &&
998 (ctx
->Texture
.Unit
[0].EnvMode
!=GL_REPLACE
)) /* q2, seems ok... */
1000 if (MESA_VERBOSE
&VERBOSE_DRIVER
)
1001 fprintf(stderr
, "fxMesa: unsupported multitex env mode\n");
1006 if((ctx
->Enabled
& (TEXTURE1_1D
| TEXTURE1_2D
| TEXTURE1_3D
)) ||
1007 /* Not very well written ... */
1008 ((ctx
->Enabled
& TEXTURE0_1D
) &&
1009 (!(ctx
->Enabled
& TEXTURE0_2D
)))
1015 if((ctx
->Texture
.ReallyEnabled
& TEXTURE0_2D
) &&
1016 (ctx
->Texture
.Unit
[0].EnvMode
==GL_BLEND
)) {
1025 static void fxDDUpdateDDPointers(GLcontext
*ctx
)
1027 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
1028 GLuint new_state
= ctx
->NewState
;
1030 if (MESA_VERBOSE
&(VERBOSE_DRIVER
|VERBOSE_STATE
))
1031 fprintf(stderr
,"fxmesa: fxDDUpdateDDPointers(...)\n");
1033 if (new_state
& _FX_NEW_FALLBACK
)
1034 fxMesa
->is_in_hardware
= fxIsInHardware(ctx
);
1036 if (fxMesa
->is_in_hardware
) {
1037 if (fxMesa
->new_state
)
1038 fxSetupFXUnits(ctx
);
1040 if (new_state
& _FX_NEW_RENDERSTATE
) {
1041 fxDDChooseRenderState( ctx
);
1043 fxMesa
->RenderVBTables
=fxDDChooseRenderVBTables(ctx
);
1044 fxMesa
->RenderVBClippedTab
=fxMesa
->RenderVBTables
[0];
1045 fxMesa
->RenderVBCulledTab
=fxMesa
->RenderVBTables
[1];
1046 fxMesa
->RenderVBRawTab
=fxMesa
->RenderVBTables
[2];
1049 if (new_state
& _FX_NEW_SETUP_FUNCTION
)
1050 ctx
->Driver
.RasterSetup
=fxDDChooseSetupFunction(ctx
);
1053 ctx
->Driver
.PointsFunc
=fxMesa
->PointsFunc
;
1054 ctx
->Driver
.LineFunc
=fxMesa
->LineFunc
;
1055 ctx
->Driver
.TriangleFunc
=fxMesa
->TriangleFunc
;
1056 ctx
->Driver
.QuadFunc
=fxMesa
->QuadFunc
;
1058 fxMesa
->render_index
= FX_FALLBACK
;
1062 static void fxDDReducedPrimitiveChange(GLcontext
*ctx
, GLenum prim
)
1064 if (ctx
->Polygon
.CullFlag
) {
1065 if (ctx
->PB
->primitive
!= GL_POLYGON
) { /* Lines or Points */
1066 FX_grCullMode(GR_CULL_DISABLE
);
1067 FX_CONTEXT(ctx
)->cullMode
=GR_CULL_DISABLE
;
1072 void fxSetupDDPointers(GLcontext
*ctx
)
1074 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
1075 fprintf(stderr
,"fxmesa: fxSetupDDPointers()\n");
1078 ctx
->Driver
.UpdateStateNotify
= (_FX_NEW_SETUP_FUNCTION
|
1079 _FX_NEW_RENDERSTATE
|
1081 _SWRAST_NEW_TRIANGLE
|
1085 ctx
->Driver
.UpdateState
=fxDDUpdateDDPointers
;
1087 ctx
->Driver
.WriteDepthSpan
=fxDDWriteDepthSpan
;
1088 ctx
->Driver
.WriteDepthPixels
=fxDDWriteDepthPixels
;
1089 ctx
->Driver
.ReadDepthSpan
=fxDDReadDepthSpan
;
1090 ctx
->Driver
.ReadDepthPixels
=fxDDReadDepthPixels
;
1092 ctx
->Driver
.GetString
=fxDDGetString
;
1094 ctx
->Driver
.NearFar
=fxDDSetNearFar
;
1096 ctx
->Driver
.GetParameteri
=fxDDGetParameteri
;
1098 ctx
->Driver
.ClearIndex
=NULL
;
1099 ctx
->Driver
.ClearColor
=fxDDClearColor
;
1100 ctx
->Driver
.Clear
=fxDDClear
;
1102 ctx
->Driver
.Index
=NULL
;
1103 ctx
->Driver
.Color
=fxDDSetColor
;
1105 ctx
->Driver
.SetDrawBuffer
=fxDDSetDrawBuffer
;
1106 ctx
->Driver
.SetReadBuffer
=fxDDSetReadBuffer
;
1107 ctx
->Driver
.GetBufferSize
=fxDDBufferSize
;
1109 ctx
->Driver
.Bitmap
=fxDDDrawBitmap
;
1110 ctx
->Driver
.DrawPixels
=NULL
;
1111 ctx
->Driver
.ReadPixels
=fxDDReadPixels
;
1113 ctx
->Driver
.Finish
=fxDDFinish
;
1114 ctx
->Driver
.Flush
=NULL
;
1116 ctx
->Driver
.RenderStart
=NULL
;
1117 ctx
->Driver
.RenderFinish
=NULL
;
1119 ctx
->Driver
.TexImage2D
= fxDDTexImage2D
;
1120 ctx
->Driver
.TexSubImage2D
= fxDDTexSubImage2D
;
1121 ctx
->Driver
.GetTexImage
= fxDDGetTexImage
;
1122 ctx
->Driver
.TexEnv
=fxDDTexEnv
;
1123 ctx
->Driver
.TexParameter
=fxDDTexParam
;
1124 ctx
->Driver
.BindTexture
=fxDDTexBind
;
1125 ctx
->Driver
.DeleteTexture
=fxDDTexDel
;
1126 ctx
->Driver
.UpdateTexturePalette
=fxDDTexPalette
;
1128 ctx
->Driver
.RectFunc
=NULL
;
1130 ctx
->Driver
.AlphaFunc
=fxDDAlphaFunc
;
1131 ctx
->Driver
.BlendFunc
=fxDDBlendFunc
;
1132 ctx
->Driver
.DepthFunc
=fxDDDepthFunc
;
1133 ctx
->Driver
.DepthMask
=fxDDDepthMask
;
1134 ctx
->Driver
.ColorMask
=fxDDColorMask
;
1135 ctx
->Driver
.Fogfv
=fxDDFogfv
;
1136 ctx
->Driver
.Scissor
=fxDDScissor
;
1137 ctx
->Driver
.FrontFace
=fxDDFrontFace
;
1138 ctx
->Driver
.CullFace
=fxDDCullFace
;
1139 ctx
->Driver
.ShadeModel
=fxDDShadeModel
;
1140 ctx
->Driver
.Enable
=fxDDEnable
;
1141 ctx
->Driver
.ReducedPrimitiveChange
=fxDDReducedPrimitiveChange
;
1143 ctx
->Driver
.RegisterVB
=fxDDRegisterVB
;
1144 ctx
->Driver
.UnregisterVB
=fxDDUnregisterVB
;
1146 ctx
->Driver
.RegisterPipelineStages
= fxDDRegisterPipelineStages
;
1148 ctx
->Driver
.OptimizeImmediatePipeline
= 0; /* nothing done yet */
1149 ctx
->Driver
.OptimizePrecalcPipeline
= 0;
1151 /* if (getenv("MESA_USE_FAST") || getenv("FX_USE_FAST")) */
1152 /* ctx->Driver.OptimizePrecalcPipeline = fxDDOptimizePrecalcPipeline; */
1154 if (!getenv("FX_NO_FAST"))
1155 ctx
->Driver
.BuildPrecalcPipeline
= fxDDBuildPrecalcPipeline
;
1157 ctx
->Driver
.TriangleCaps
= DD_TRI_CULL
|DD_TRI_OFFSET
|DD_TRI_LIGHT_TWOSIDE
;
1159 fxSetupDDSpanPointers(ctx
);
1161 FX_CONTEXT(ctx
)->render_index
= 1; /* force an update */
1162 fxDDUpdateDDPointers(ctx
);
1170 * Need this to provide at least one external definition.
1173 int gl_fx_dummy_function_dd(void)