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 /* Enalbe/Disable dithering */
106 static void fxDDDither(GLcontext
*ctx
, GLboolean enable
)
108 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
109 fprintf(stderr
,"fxmesa: fxDDDither()\n");
113 FX_grDitherMode(GR_DITHER_4x4
);
115 FX_grDitherMode(GR_DITHER_DISABLE
);
120 /* Return buffer size information */
121 static void fxDDBufferSize(GLcontext
*ctx
, GLuint
*width
, GLuint
*height
)
123 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
125 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
126 fprintf(stderr
,"fxmesa: fxDDBufferSize(...) Start\n");
129 *width
=fxMesa
->width
;
130 *height
=fxMesa
->height
;
132 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
133 fprintf(stderr
,"fxmesa: fxDDBufferSize(...) End\n");
138 /* Set current drawing color */
139 static void fxDDSetColor(GLcontext
*ctx
, GLubyte red
, GLubyte green
,
140 GLubyte blue
, GLubyte alpha
)
142 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
144 ASSIGN_4V( col
, red
, green
, blue
, alpha
);
146 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
147 fprintf(stderr
,"fxmesa: fxDDSetColor(%d,%d,%d,%d)\n",red
,green
,blue
,alpha
);
150 fxMesa
->color
=FXCOLOR4(col
);
154 /* Implements glClearColor() */
155 static void fxDDClearColor(GLcontext
*ctx
, GLubyte red
, GLubyte green
,
156 GLubyte blue
, GLubyte alpha
)
158 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
163 ASSIGN_4V( col
, red
, green
, blue
, 255 );
165 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
166 fprintf(stderr
,"fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",red
,green
,blue
,alpha
);
169 fxMesa
->clearC
=FXCOLOR4( col
);
170 fxMesa
->clearA
=alpha
;
174 /* Clear the color and/or depth buffers */
175 static GLbitfield
fxDDClear(GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
176 GLint x
, GLint y
, GLint width
, GLint height
)
178 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
179 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
180 const FxU16 clearD
= (FxU16
) (ctx
->Depth
.Clear
* 0xffff);
181 GLbitfield softwareMask
= mask
& (DD_STENCIL_BIT
| DD_ACCUM_BIT
);
183 /* we can't clear stencil or accum buffers */
184 mask
&= ~(DD_STENCIL_BIT
| DD_ACCUM_BIT
);
186 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
187 fprintf(stderr
,"fxmesa: fxDDClear(%d,%d,%d,%d)\n", (int) x
, (int) y
,
188 (int) width
, (int) height
);
191 if (colorMask
!= 0xffffffff) {
192 /* do masked color buffer clears in software */
193 softwareMask
|= (mask
& (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
));
194 mask
&= ~(DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
);
198 * This could probably be done fancier but doing each possible case
199 * explicitly is less error prone.
202 case DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
:
203 /* back buffer & depth */
204 FX_grDepthMask(FXTRUE
);
205 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
206 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
207 if (!ctx
->Depth
.Mask
) {
208 FX_grDepthMask(FXFALSE
);
211 case DD_FRONT_LEFT_BIT
| DD_DEPTH_BIT
:
212 /* XXX it appears that the depth buffer isn't cleared when
213 * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set.
214 * This is a work-around/
217 FX_grDepthMask(FXTRUE
);
218 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
219 FX_grColorMask(FXFALSE
,FXFALSE
);
220 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
222 FX_grColorMask(FXTRUE
, ctx
->Color
.ColorMask
[ACOMP
] && fxMesa
->haveAlphaBuffer
);
223 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
224 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
226 case DD_BACK_LEFT_BIT
:
227 /* back buffer only */
228 FX_grDepthMask(FXFALSE
);
229 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
230 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
231 if (ctx
->Depth
.Mask
) {
232 FX_grDepthMask(FXTRUE
);
235 case DD_FRONT_LEFT_BIT
:
236 /* front buffer only */
237 FX_grDepthMask(FXFALSE
);
238 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
239 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
240 if (ctx
->Depth
.Mask
) {
241 FX_grDepthMask(FXTRUE
);
244 case DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
:
246 FX_grDepthMask(FXFALSE
);
247 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
248 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
249 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
250 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
251 if (ctx
->Depth
.Mask
) {
252 FX_grDepthMask(FXTRUE
);
255 case DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
| DD_DEPTH_BIT
:
257 FX_grDepthMask(FXFALSE
);
258 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
259 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
260 /* clear back and depth */
261 FX_grDepthMask(FXTRUE
);
262 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
263 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
264 if (!ctx
->Depth
.Mask
) {
265 FX_grDepthMask(FXFALSE
);
269 /* just the depth buffer */
270 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
271 FX_grColorMask(FXFALSE
,FXFALSE
);
272 FX_grDepthMask(FXTRUE
);
273 FX_grBufferClear(fxMesa
->clearC
, fxMesa
->clearA
, clearD
);
274 FX_grColorMask(FXTRUE
, ctx
->Color
.ColorMask
[ACOMP
] && fxMesa
->haveAlphaBuffer
);
275 if (ctx
->Color
.DrawDestMask
& FRONT_LEFT_BIT
)
276 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
287 /* Set the buffer used for drawing */
288 /* XXX support for separate read/draw buffers hasn't been tested */
289 static GLboolean
fxDDSetDrawBuffer(GLcontext
*ctx
, GLenum mode
)
291 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
293 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
294 fprintf(stderr
,"fxmesa: fxDDSetBuffer(%x)\n", (int) mode
);
297 if (mode
== GL_FRONT_LEFT
) {
298 fxMesa
->currentFB
= GR_BUFFER_FRONTBUFFER
;
299 FX_grRenderBuffer(fxMesa
->currentFB
);
302 else if (mode
== GL_BACK_LEFT
) {
303 fxMesa
->currentFB
= GR_BUFFER_BACKBUFFER
;
304 FX_grRenderBuffer(fxMesa
->currentFB
);
307 else if (mode
== GL_NONE
) {
308 FX_grColorMask(FXFALSE
,FXFALSE
);
317 /* Set the buffer used for reading */
318 /* XXX support for separate read/draw buffers hasn't been tested */
319 static void fxDDSetReadBuffer(GLcontext
*ctx
, GLframebuffer
*buffer
,
322 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
325 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
326 fprintf(stderr
,"fxmesa: fxDDSetBuffer(%x)\n", (int) mode
);
329 if (mode
== GL_FRONT_LEFT
) {
330 fxMesa
->currentFB
= GR_BUFFER_FRONTBUFFER
;
331 FX_grRenderBuffer(fxMesa
->currentFB
);
333 else if (mode
== GL_BACK_LEFT
) {
334 fxMesa
->currentFB
= GR_BUFFER_BACKBUFFER
;
335 FX_grRenderBuffer(fxMesa
->currentFB
);
341 /* test if window coord (px,py) is visible */
342 static GLboolean
inClipRects(fxMesaContext fxMesa
, int px
, int py
)
345 for (i
=0; i
<fxMesa
->numClipRects
; i
++) {
346 if ((px
>=fxMesa
->pClipRects
[i
].x1
) &&
347 (px
<fxMesa
->pClipRects
[i
].x2
) &&
348 (py
>=fxMesa
->pClipRects
[i
].y1
) &&
349 (py
<fxMesa
->pClipRects
[i
].y2
)) return GL_TRUE
;
356 static GLboolean
fxDDDrawBitmap(GLcontext
*ctx
, GLint px
, GLint py
,
357 GLsizei width
, GLsizei height
,
358 const struct gl_pixelstore_attrib
*unpack
,
359 const GLubyte
*bitmap
)
361 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
364 const struct gl_pixelstore_attrib
*finalUnpack
;
365 struct gl_pixelstore_attrib scissoredUnpack
;
367 /* check if there's any raster operations enabled which we can't handle */
368 if (ctx
->RasterMask
& (ALPHATEST_BIT
|
380 if (ctx
->Scissor
.Enabled
) {
381 /* This is a bit tricky, but by carefully adjusting the px, py,
382 * width, height, skipPixels and skipRows values we can do
383 * scissoring without special code in the rendering loop.
386 /* we'll construct a new pixelstore struct */
387 finalUnpack
= &scissoredUnpack
;
388 scissoredUnpack
= *unpack
;
389 if (scissoredUnpack
.RowLength
== 0)
390 scissoredUnpack
.RowLength
= width
;
393 if (px
< ctx
->Scissor
.X
) {
394 scissoredUnpack
.SkipPixels
+= (ctx
->Scissor
.X
- px
);
395 width
-= (ctx
->Scissor
.X
- px
);
399 if (px
+ width
>= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
) {
400 width
-= (px
+ width
- (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
));
403 if (py
< ctx
->Scissor
.Y
) {
404 scissoredUnpack
.SkipRows
+= (ctx
->Scissor
.Y
- py
);
405 height
-= (ctx
->Scissor
.Y
- py
);
409 if (py
+ height
>= ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
) {
410 height
-= (py
+ height
- (ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
));
413 if (width
<= 0 || height
<= 0)
414 return GL_TRUE
; /* totally scissored away */
417 finalUnpack
= unpack
;
420 /* compute pixel value */
422 GLint r
= (GLint
) (ctx
->Current
.RasterColor
[0] * 255.0f
);
423 GLint g
= (GLint
) (ctx
->Current
.RasterColor
[1] * 255.0f
);
424 GLint b
= (GLint
) (ctx
->Current
.RasterColor
[2] * 255.0f
);
425 /*GLint a = (GLint)(ctx->Current.RasterColor[3]*255.0f);*/
426 if (fxMesa
->bgrOrder
)
428 ( ((FxU16
)0xf8 & b
) << (11-3)) |
429 ( ((FxU16
)0xfc & g
) << (5-3+1)) |
430 ( ((FxU16
)0xf8 & r
) >> 3);
433 ( ((FxU16
)0xf8 & r
) << (11-3)) |
434 ( ((FxU16
)0xfc & g
) << (5-3+1)) |
435 ( ((FxU16
)0xf8 & b
) >> 3);
438 info
.size
= sizeof(info
);
439 if (!FX_grLfbLock(GR_LFB_WRITE_ONLY
,
442 GR_ORIGIN_UPPER_LEFT
,
446 fprintf(stderr
,"fx Driver: error locking the linear frame buffer\n");
452 #define INSIDE(c, x, y) inClipRects((c), (x), (y))
454 #define INSIDE(c, x, y) (1)
458 const GLint winX
= fxMesa
->x_offset
;
459 const GLint winY
= fxMesa
->y_offset
+ fxMesa
->height
- 1;
460 /* The dest stride depends on the hardware and whether we're drawing
461 * to the front or back buffer. This compile-time test seems to do
465 const GLint dstStride
= (fxMesa
->glCtx
->Color
.DrawBuffer
== GL_FRONT
)
466 ? (fxMesa
->screen_width
) : (info
.strideInBytes
/ 2);
468 const GLint dstStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
471 /* compute dest address of bottom-left pixel in bitmap */
472 GLushort
*dst
= (GLushort
*) info
.lfbPtr
473 + (winY
- py
) * dstStride
476 for (row
= 0; row
< height
; row
++) {
477 const GLubyte
*src
= (const GLubyte
*) _mesa_image_address( finalUnpack
,
478 bitmap
, width
, height
, GL_COLOR_INDEX
, GL_BITMAP
, 0, row
, 0 );
479 if (finalUnpack
->LsbFirst
) {
480 /* least significan bit first */
481 GLubyte mask
= 1U << (finalUnpack
->SkipPixels
& 0x7);
483 for (col
=0; col
<width
; col
++) {
485 if (INSIDE(fxMesa
, winX
+ px
+ col
, winY
- py
- row
))
500 /* most significan bit first */
501 GLubyte mask
= 128U >> (finalUnpack
->SkipPixels
& 0x7);
503 for (col
=0; col
<width
; col
++) {
505 if (INSIDE(fxMesa
, winX
+ px
+ col
, winY
- py
- row
))
525 FX_grLfbUnlock(GR_LFB_WRITE_ONLY
,fxMesa
->currentFB
);
530 static GLboolean
fxDDReadPixels( GLcontext
*ctx
, GLint x
, GLint y
,
531 GLsizei width
, GLsizei height
,
532 GLenum format
, GLenum type
,
533 const struct gl_pixelstore_attrib
*packing
,
536 if (ctx
->Pixel
.ScaleOrBiasRGBA
|| ctx
->Pixel
.MapColorFlag
) {
537 return GL_FALSE
; /* can't do this */
540 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
542 GLboolean result
= GL_FALSE
;
545 if (grLfbLock(GR_LFB_READ_ONLY
,
548 GR_ORIGIN_UPPER_LEFT
,
551 const GLint winX
= fxMesa
->x_offset
;
552 const GLint winY
= fxMesa
->y_offset
+ fxMesa
->height
- 1;
554 const GLint srcStride
= (fxMesa
->glCtx
->Color
.DrawBuffer
== GL_FRONT
)
555 ? (fxMesa
->screen_width
) : (info
.strideInBytes
/ 2);
557 const GLint srcStride
= info
.strideInBytes
/ 2; /* stride in GLushorts */
559 const GLushort
*src
= (const GLushort
*) info
.lfbPtr
560 + (winY
- y
) * srcStride
+ (winX
+ x
);
561 GLubyte
*dst
= (GLubyte
*) _mesa_image_address(packing
, dstImage
,
562 width
, height
, format
, type
, 0, 0, 0);
563 GLint dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
565 if (format
== GL_RGB
&& type
== GL_UNSIGNED_BYTE
) {
566 /* convert 5R6G5B into 8R8G8B */
568 const GLint halfWidth
= width
>> 1;
569 const GLint extraPixel
= (width
& 1);
570 for (row
= 0; row
< height
; row
++) {
572 for (col
= 0; col
< halfWidth
; col
++) {
573 const GLuint pixel
= ((const GLuint
*) src
)[col
];
574 const GLint pixel0
= pixel
& 0xffff;
575 const GLint pixel1
= pixel
>> 16;
576 *d
++ = FX_PixelToR
[pixel0
];
577 *d
++ = FX_PixelToG
[pixel0
];
578 *d
++ = FX_PixelToB
[pixel0
];
579 *d
++ = FX_PixelToR
[pixel1
];
580 *d
++ = FX_PixelToG
[pixel1
];
581 *d
++ = FX_PixelToB
[pixel1
];
584 GLushort pixel
= src
[width
-1];
585 *d
++ = FX_PixelToR
[pixel
];
586 *d
++ = FX_PixelToG
[pixel
];
587 *d
++ = FX_PixelToB
[pixel
];
594 else if (format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) {
595 /* convert 5R6G5B into 8R8G8B8A */
597 const GLint halfWidth
= width
>> 1;
598 const GLint extraPixel
= (width
& 1);
599 for (row
= 0; row
< height
; row
++) {
601 for (col
= 0; col
< halfWidth
; col
++) {
602 const GLuint pixel
= ((const GLuint
*) src
)[col
];
603 const GLint pixel0
= pixel
& 0xffff;
604 const GLint pixel1
= pixel
>> 16;
605 *d
++ = FX_PixelToR
[pixel0
];
606 *d
++ = FX_PixelToG
[pixel0
];
607 *d
++ = FX_PixelToB
[pixel0
];
609 *d
++ = FX_PixelToR
[pixel1
];
610 *d
++ = FX_PixelToG
[pixel1
];
611 *d
++ = FX_PixelToB
[pixel1
];
615 const GLushort pixel
= src
[width
-1];
616 *d
++ = FX_PixelToR
[pixel
];
617 *d
++ = FX_PixelToG
[pixel
];
618 *d
++ = FX_PixelToB
[pixel
];
626 else if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
627 /* directly memcpy 5R6G5B pixels into client's buffer */
628 const GLint widthInBytes
= width
* 2;
630 for (row
= 0; row
< height
; row
++) {
631 MEMCPY(dst
, src
, widthInBytes
);
641 grLfbUnlock(GR_LFB_READ_ONLY
, fxMesa
->currentFB
);
650 static void fxDDFinish(GLcontext
*ctx
)
656 static GLint
fxDDGetParameteri(const GLcontext
*ctx
, GLint param
)
659 case DD_HAVE_HARDWARE_FOG
:
662 fprintf(stderr
,"fx Driver: internal error in fxDDGetParameteri(): %x\n", (int) param
);
670 void fxDDSetNearFar(GLcontext
*ctx
, GLfloat n
, GLfloat f
)
672 FX_CONTEXT(ctx
)->new_state
|= FX_NEW_FOG
;
673 ctx
->Driver
.RenderStart
= fxSetupFXUnits
;
676 /* KW: Put the word Mesa in the render string because quakeworld
677 * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
680 static const GLubyte
*fxDDGetString(GLcontext
*ctx
, GLenum name
)
682 #if defined(GLX_DIRECT_RENDERING)
683 /* Building for DRI driver */
687 static char buffer
[100];
689 strcpy(hardware
, grGetString(GR_HARDWARE
));
690 if (strcmp(hardware
, "Voodoo3 (tm)") == 0)
691 strcpy(hardware
, "Voodoo3");
692 else if (strcmp(hardware
, "Voodoo Banshee (tm)") == 0)
693 strcpy(hardware
, "VoodooBanshee");
695 /* unexpected result: replace spaces with hyphens */
697 for (i
= 0; hardware
[i
]; i
++) {
698 if (hardware
[i
] == ' ' || hardware
[i
] == '\t')
702 /* now make the GL_RENDERER string */
703 sprintf(buffer
, "Mesa DRI %s 20000510", hardware
);
707 return "Precision Insight, Inc.";
714 /* Building for Voodoo1/2 stand-alone Mesa */
720 if (glbHWConfig
.SSTs
[glbCurrentBoard
].type
==GR_SSTTYPE_VOODOO
) {
721 GrVoodooConfig_t
*vc
=
722 &glbHWConfig
.SSTs
[glbCurrentBoard
].sstBoard
.VoodooConfig
;
725 "Mesa Glide v0.30 Voodoo_Graphics %d "
726 "CARD/%d FB/%d TM/%d TMU/%s",
728 (vc
->sliDetect
? (vc
->fbRam
*2) : vc
->fbRam
),
729 (vc
->tmuConfig
[GR_TMU0
].tmuRam
+
730 ((vc
->nTexelfx
>1) ? vc
->tmuConfig
[GR_TMU1
].tmuRam
: 0)),
732 (vc
->sliDetect
? "SLI" : "NOSLI"));
734 else if (glbHWConfig
.SSTs
[glbCurrentBoard
].type
==GR_SSTTYPE_SST96
) {
735 GrSst96Config_t
*sc
=
736 &glbHWConfig
.SSTs
[glbCurrentBoard
].sstBoard
.SST96Config
;
739 "Glide v0.30 Voodoo_Rush %d "
740 "CARD/%d FB/%d TM/%d TMU/NOSLI",
743 sc
->tmuConfig
.tmuRam
,
747 strcpy(buf
, "Glide v0.30 UNKNOWN");
749 return (GLubyte
*) buf
;
758 int fxDDInitFxMesaContext( fxMesaContext fxMesa
)
761 FX_setupGrVertexLayout();
763 if (getenv("FX_EMULATE_SINGLE_TMU"))
764 fxMesa
->haveTwoTMUs
= GL_FALSE
;
766 fxMesa
->emulateTwoTMUs
= fxMesa
->haveTwoTMUs
;
768 if (!getenv("FX_DONT_FAKE_MULTITEX"))
769 fxMesa
->emulateTwoTMUs
= GL_TRUE
;
771 if(getenv("FX_GLIDE_SWAPINTERVAL"))
772 fxMesa
->swapInterval
=atoi(getenv("FX_GLIDE_SWAPINTERVAL"));
774 fxMesa
->swapInterval
=1;
776 if(getenv("MESA_FX_SWAP_PENDING"))
777 fxMesa
->maxPendingSwapBuffers
=atoi(getenv("MESA_FX_SWAP_PENDING"));
779 fxMesa
->maxPendingSwapBuffers
=2;
781 if(getenv("MESA_FX_INFO"))
782 fxMesa
->verbose
=GL_TRUE
;
784 fxMesa
->verbose
=GL_FALSE
;
786 fxMesa
->color
=0xffffffff;
790 fxMesa
->stats
.swapBuffer
=0;
791 fxMesa
->stats
.reqTexUpload
=0;
792 fxMesa
->stats
.texUpload
=0;
793 fxMesa
->stats
.memTexUpload
=0;
795 fxMesa
->tmuSrc
=FX_TMU_NONE
;
796 fxMesa
->lastUnitsMode
=FX_UM_NONE
;
801 fxMesa
->unitsState
.alphaTestEnabled
=GL_FALSE
;
802 fxMesa
->unitsState
.alphaTestFunc
=GR_CMP_ALWAYS
;
803 fxMesa
->unitsState
.alphaTestRefValue
=0;
805 fxMesa
->unitsState
.blendEnabled
=GL_FALSE
;
806 fxMesa
->unitsState
.blendSrcFuncRGB
=GR_BLEND_ONE
;
807 fxMesa
->unitsState
.blendDstFuncRGB
=GR_BLEND_ZERO
;
808 fxMesa
->unitsState
.blendSrcFuncAlpha
=GR_BLEND_ONE
;
809 fxMesa
->unitsState
.blendDstFuncAlpha
=GR_BLEND_ZERO
;
811 fxMesa
->unitsState
.depthTestEnabled
=GL_FALSE
;
812 fxMesa
->unitsState
.depthMask
=GL_TRUE
;
813 fxMesa
->unitsState
.depthTestFunc
=GR_CMP_LESS
;
815 FX_grColorMask(FXTRUE
, fxMesa
->haveAlphaBuffer
? FXTRUE
: FXFALSE
);
816 if(fxMesa
->haveDoubleBuffer
) {
817 fxMesa
->currentFB
=GR_BUFFER_BACKBUFFER
;
818 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER
);
820 fxMesa
->currentFB
=GR_BUFFER_FRONTBUFFER
;
821 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER
);
824 fxMesa
->state
= NULL
;
825 fxMesa
->fogTable
= NULL
;
827 fxMesa
->state
= malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE
));
828 fxMesa
->fogTable
= malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES
)*sizeof(GrFog_t
));
830 if (!fxMesa
->state
|| !fxMesa
->fogTable
) {
831 if (fxMesa
->state
) free(fxMesa
->state
);
832 if (fxMesa
->fogTable
) free(fxMesa
->fogTable
);
836 if(fxMesa
->haveZBuffer
)
837 FX_grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER
);
839 #if (!FXMESA_USE_ARGB)
840 FX_grLfbWriteColorFormat(GR_COLORFORMAT_ABGR
); /* Not every Glide has this */
843 fxMesa
->textureAlign
=FX_grGetInteger(FX_TEXTURE_ALIGN
);
844 fxMesa
->glCtx
->Const
.MaxTextureLevels
=9;
845 fxMesa
->glCtx
->Const
.MaxTextureSize
=256;
846 fxMesa
->glCtx
->Const
.MaxTextureUnits
=fxMesa
->emulateTwoTMUs
? 2 : 1;
847 fxMesa
->glCtx
->NewState
|=NEW_DRVSTATE1
;
848 fxMesa
->new_state
= NEW_ALL
;
856 fxSetupDDPointers(fxMesa
->glCtx
);
857 fxDDRenderInit(fxMesa
->glCtx
);
858 fxDDInitExtensions(fxMesa
->glCtx
);
860 fxDDSetNearFar(fxMesa
->glCtx
,1.0,100.0);
862 FX_grGlideGetState((GrState
*)fxMesa
->state
);
864 /* XXX Fix me: callback not registered when main VB is created.
866 if (fxMesa
->glCtx
->VB
)
867 fxDDRegisterVB( fxMesa
->glCtx
->VB
);
869 /* XXX Fix me too: need to have the 'struct dd' prepared prior to
870 * creating the context... The below is broken if you try to insert
873 if (fxMesa
->glCtx
->NrPipelineStages
)
874 fxMesa
->glCtx
->NrPipelineStages
= fxDDRegisterPipelineStages(
875 fxMesa
->glCtx
->PipelineStage
,
876 fxMesa
->glCtx
->PipelineStage
,
877 fxMesa
->glCtx
->NrPipelineStages
);
879 /* Run the config file */
880 gl_context_initialize( fxMesa
->glCtx
);
887 /* Example extension function */
888 static void fxFooBarEXT(GLint i
)
890 printf("You called glFooBarEXT(%d)\n", i
);
895 void fxDDInitExtensions( GLcontext
*ctx
)
897 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
899 gl_extensions_disable(ctx
, "GL_EXT_blend_logic_op");
900 gl_extensions_disable(ctx
, "GL_EXT_blend_minmax");
901 gl_extensions_disable(ctx
, "GL_EXT_blend_subtract");
902 gl_extensions_disable(ctx
, "GL_EXT_blend_color");
904 gl_extensions_add(ctx
, DEFAULT_ON
, "3DFX_set_global_palette", 0);
906 if (!fxMesa
->haveTwoTMUs
)
907 gl_extensions_disable(ctx
, "GL_EXT_texture_env_add");
909 if (!fxMesa
->emulateTwoTMUs
)
910 gl_extensions_disable(ctx
, "GL_ARB_multitexture");
913 /* Example of hooking in an extension function.
914 * For DRI-based drivers, also see __driRegisterExtensions in the
919 void **dispatchTable
= (void **) ctx
->Exec
;
920 const int _gloffset_FooBarEXT
= 555; /* just an example number! */
921 const int tabSize
= _glapi_get_dispatch_table_size();
922 assert(_gloffset_FooBarEXT
< tabSize
);
923 dispatchTable
[_gloffset_FooBarEXT
] = (void *) fxFooBarEXT
;
924 /* XXX You would also need to hook into the display list dispatch
925 * table. Really, the implementation of extensions might as well
926 * be in the core of Mesa since core Mesa and the device driver
927 * is one big shared lib.
934 /************************************************************************/
935 /************************************************************************/
936 /************************************************************************/
938 /* Check if the hardware supports the current context
940 * Performs similar work to fxDDChooseRenderState() - should be merged.
942 static GLboolean
fxIsInHardware(GLcontext
*ctx
)
944 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
946 if (!ctx
->Hint
.AllowDrawMem
)
947 return GL_TRUE
; /* you'll take it and like it */
949 if((ctx
->RasterMask
& (STENCIL_BIT
| MULTI_DRAW_BIT
)) ||
950 ((ctx
->Color
.BlendEnabled
) && (ctx
->Color
.BlendEquation
!=GL_FUNC_ADD_EXT
)) ||
951 ((ctx
->Color
.ColorLogicOpEnabled
) && (ctx
->Color
.LogicOp
!=GL_COPY
)) ||
952 (ctx
->Light
.Model
.ColorControl
==GL_SEPARATE_SPECULAR_COLOR
) ||
953 (!((ctx
->Color
.ColorMask
[RCOMP
]==ctx
->Color
.ColorMask
[GCOMP
]) &&
954 (ctx
->Color
.ColorMask
[GCOMP
]==ctx
->Color
.ColorMask
[BCOMP
]) &&
955 (ctx
->Color
.ColorMask
[ACOMP
]==ctx
->Color
.ColorMask
[ACOMP
])))
960 /* Unsupported texture/multitexture cases */
962 if(fxMesa
->emulateTwoTMUs
) {
963 if((ctx
->Enabled
& (TEXTURE0_3D
| TEXTURE1_3D
)) ||
964 /* Not very well written ... */
965 ((ctx
->Enabled
& (TEXTURE0_1D
| TEXTURE1_1D
)) &&
966 ((ctx
->Enabled
& (TEXTURE0_2D
| TEXTURE1_2D
))!=(TEXTURE0_2D
| TEXTURE1_2D
)))
971 if (ctx
->Texture
.ReallyEnabled
& TEXTURE0_2D
) {
972 if (ctx
->Texture
.Unit
[0].EnvMode
== GL_BLEND
&&
973 (ctx
->Texture
.ReallyEnabled
& TEXTURE1_2D
||
974 ctx
->Texture
.Unit
[0].EnvColor
[0] != 0 ||
975 ctx
->Texture
.Unit
[0].EnvColor
[1] != 0 ||
976 ctx
->Texture
.Unit
[0].EnvColor
[2] != 0 ||
977 ctx
->Texture
.Unit
[0].EnvColor
[3] != 1)) {
980 if (ctx
->Texture
.Unit
[0].Current
->Image
[0]->Border
> 0)
984 if (ctx
->Texture
.ReallyEnabled
& TEXTURE1_2D
) {
985 if (ctx
->Texture
.Unit
[1].EnvMode
== GL_BLEND
)
987 if (ctx
->Texture
.Unit
[0].Current
->Image
[0]->Border
> 0)
991 if (MESA_VERBOSE
& (VERBOSE_DRIVER
|VERBOSE_TEXTURE
))
992 fprintf(stderr
, "fxMesa: fxIsInHardware, envmode is %s/%s\n",
993 gl_lookup_enum_by_nr(ctx
->Texture
.Unit
[0].EnvMode
),
994 gl_lookup_enum_by_nr(ctx
->Texture
.Unit
[1].EnvMode
));
996 /* KW: This was wrong (I think) and I changed it... which doesn't mean
997 * it is now correct...
999 if((ctx
->Enabled
& (TEXTURE0_1D
| TEXTURE0_2D
| TEXTURE0_3D
)) &&
1000 (ctx
->Enabled
& (TEXTURE1_1D
| TEXTURE1_2D
| TEXTURE1_3D
)))
1002 /* Can't use multipass to blend a multitextured triangle - fall
1005 if (!fxMesa
->haveTwoTMUs
&& ctx
->Color
.BlendEnabled
) {
1009 if ((ctx
->Texture
.Unit
[0].EnvMode
!=ctx
->Texture
.Unit
[1].EnvMode
) &&
1010 (ctx
->Texture
.Unit
[0].EnvMode
!=GL_MODULATE
) &&
1011 (ctx
->Texture
.Unit
[0].EnvMode
!=GL_REPLACE
)) /* q2, seems ok... */
1013 if (MESA_VERBOSE
&VERBOSE_DRIVER
)
1014 fprintf(stderr
, "fxMesa: unsupported multitex env mode\n");
1019 if((ctx
->Enabled
& (TEXTURE1_1D
| TEXTURE1_2D
| TEXTURE1_3D
)) ||
1020 /* Not very well written ... */
1021 ((ctx
->Enabled
& TEXTURE0_1D
) &&
1022 (!(ctx
->Enabled
& TEXTURE0_2D
)))
1028 if((ctx
->Texture
.ReallyEnabled
& TEXTURE0_2D
) &&
1029 (ctx
->Texture
.Unit
[0].EnvMode
==GL_BLEND
)) {
1039 #define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|NEW_PROJECTION|NEW_TEXTURE_MATRIX|NEW_USER_CLIP|NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE))
1041 static void fxDDUpdateDDPointers(GLcontext
*ctx
)
1043 fxMesaContext fxMesa
=(fxMesaContext
)ctx
->DriverCtx
;
1044 GLuint new_state
= ctx
->NewState
;
1046 if (MESA_VERBOSE
&(VERBOSE_DRIVER
|VERBOSE_STATE
))
1047 fprintf(stderr
,"fxmesa: fxDDUpdateDDPointers(...)\n");
1049 if (new_state
& (NEW_RASTER_OPS
|NEW_TEXTURING
))
1050 fxMesa
->is_in_hardware
= fxIsInHardware(ctx
);
1052 if (fxMesa
->is_in_hardware
) {
1053 if (fxMesa
->new_state
)
1054 fxSetupFXUnits(ctx
);
1056 if(new_state
& INTERESTED
) {
1057 fxDDChooseRenderState( ctx
);
1058 fxMesa
->RenderVBTables
=fxDDChooseRenderVBTables(ctx
);
1059 fxMesa
->RenderVBClippedTab
=fxMesa
->RenderVBTables
[0];
1060 fxMesa
->RenderVBCulledTab
=fxMesa
->RenderVBTables
[1];
1061 fxMesa
->RenderVBRawTab
=fxMesa
->RenderVBTables
[2];
1063 ctx
->Driver
.RasterSetup
=fxDDChooseSetupFunction(ctx
);
1066 ctx
->Driver
.PointsFunc
=fxMesa
->PointsFunc
;
1067 ctx
->Driver
.LineFunc
=fxMesa
->LineFunc
;
1068 ctx
->Driver
.TriangleFunc
=fxMesa
->TriangleFunc
;
1069 ctx
->Driver
.QuadFunc
=fxMesa
->QuadFunc
;
1071 fxMesa
->render_index
= FX_FALLBACK
;
1075 static void fxDDReducedPrimitiveChange(GLcontext
*ctx
, GLenum prim
)
1077 if (ctx
->Polygon
.CullFlag
) {
1078 if (ctx
->PB
->primitive
!= GL_POLYGON
) { /* Lines or Points */
1079 FX_grCullMode(GR_CULL_DISABLE
);
1080 FX_CONTEXT(ctx
)->cullMode
=GR_CULL_DISABLE
;
1085 void fxSetupDDPointers(GLcontext
*ctx
)
1087 if (MESA_VERBOSE
&VERBOSE_DRIVER
) {
1088 fprintf(stderr
,"fxmesa: fxSetupDDPointers()\n");
1091 ctx
->Driver
.UpdateState
=fxDDUpdateDDPointers
;
1093 ctx
->Driver
.WriteDepthSpan
=fxDDWriteDepthSpan
;
1094 ctx
->Driver
.WriteDepthPixels
=fxDDWriteDepthPixels
;
1095 ctx
->Driver
.ReadDepthSpan
=fxDDReadDepthSpan
;
1096 ctx
->Driver
.ReadDepthPixels
=fxDDReadDepthPixels
;
1098 ctx
->Driver
.GetString
=fxDDGetString
;
1100 ctx
->Driver
.Dither
=fxDDDither
;
1102 ctx
->Driver
.NearFar
=fxDDSetNearFar
;
1104 ctx
->Driver
.GetParameteri
=fxDDGetParameteri
;
1106 ctx
->Driver
.ClearIndex
=NULL
;
1107 ctx
->Driver
.ClearColor
=fxDDClearColor
;
1108 ctx
->Driver
.Clear
=fxDDClear
;
1110 ctx
->Driver
.Index
=NULL
;
1111 ctx
->Driver
.Color
=fxDDSetColor
;
1113 ctx
->Driver
.SetDrawBuffer
=fxDDSetDrawBuffer
;
1114 ctx
->Driver
.SetReadBuffer
=fxDDSetReadBuffer
;
1115 ctx
->Driver
.GetBufferSize
=fxDDBufferSize
;
1117 ctx
->Driver
.Bitmap
=fxDDDrawBitmap
;
1118 ctx
->Driver
.DrawPixels
=NULL
;
1119 ctx
->Driver
.ReadPixels
=fxDDReadPixels
;
1121 ctx
->Driver
.Finish
=fxDDFinish
;
1122 ctx
->Driver
.Flush
=NULL
;
1124 ctx
->Driver
.RenderStart
=NULL
;
1125 ctx
->Driver
.RenderFinish
=NULL
;
1127 ctx
->Driver
.TexImage2D
= fxDDTexImage2D
;
1128 ctx
->Driver
.TexSubImage2D
= fxDDTexSubImage2D
;
1129 ctx
->Driver
.GetTexImage
= fxDDGetTexImage
;
1130 ctx
->Driver
.TexEnv
=fxDDTexEnv
;
1131 ctx
->Driver
.TexParameter
=fxDDTexParam
;
1132 ctx
->Driver
.BindTexture
=fxDDTexBind
;
1133 ctx
->Driver
.DeleteTexture
=fxDDTexDel
;
1134 ctx
->Driver
.UpdateTexturePalette
=fxDDTexPalette
;
1136 ctx
->Driver
.RectFunc
=NULL
;
1138 ctx
->Driver
.AlphaFunc
=fxDDAlphaFunc
;
1139 ctx
->Driver
.BlendFunc
=fxDDBlendFunc
;
1140 ctx
->Driver
.DepthFunc
=fxDDDepthFunc
;
1141 ctx
->Driver
.DepthMask
=fxDDDepthMask
;
1142 ctx
->Driver
.ColorMask
=fxDDColorMask
;
1143 ctx
->Driver
.Fogfv
=fxDDFogfv
;
1144 ctx
->Driver
.Scissor
=fxDDScissor
;
1145 ctx
->Driver
.FrontFace
=fxDDFrontFace
;
1146 ctx
->Driver
.CullFace
=fxDDCullFace
;
1147 ctx
->Driver
.ShadeModel
=fxDDShadeModel
;
1148 ctx
->Driver
.Enable
=fxDDEnable
;
1149 ctx
->Driver
.ReducedPrimitiveChange
=fxDDReducedPrimitiveChange
;
1151 ctx
->Driver
.RegisterVB
=fxDDRegisterVB
;
1152 ctx
->Driver
.UnregisterVB
=fxDDUnregisterVB
;
1154 ctx
->Driver
.RegisterPipelineStages
= fxDDRegisterPipelineStages
;
1156 ctx
->Driver
.OptimizeImmediatePipeline
= 0; /* nothing done yet */
1157 ctx
->Driver
.OptimizePrecalcPipeline
= 0;
1159 /* if (getenv("MESA_USE_FAST") || getenv("FX_USE_FAST")) */
1160 /* ctx->Driver.OptimizePrecalcPipeline = fxDDOptimizePrecalcPipeline; */
1162 if (!getenv("FX_NO_FAST"))
1163 ctx
->Driver
.BuildPrecalcPipeline
= fxDDBuildPrecalcPipeline
;
1165 ctx
->Driver
.TriangleCaps
= DD_TRI_CULL
|DD_TRI_OFFSET
|DD_TRI_LIGHT_TWOSIDE
;
1167 fxSetupDDSpanPointers(ctx
);
1169 FX_CONTEXT(ctx
)->render_index
= 1; /* force an update */
1170 fxDDUpdateDDPointers(ctx
);
1178 * Need this to provide at least one external definition.
1181 int gl_fx_dummy_function_dd(void)