New _mesa_debug() function to replace fprintf() calls.
[mesa.git] / src / mesa / drivers / glide / fxdd.c
1 /* $Id: fxdd.c,v 1.86 2002/06/13 04:28:30 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.0
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27 /* Authors:
28 * David Bucciarelli
29 * Brian Paul
30 * Daryll Strauss
31 * Keith Whitwell
32 */
33
34 /* fxdd.c - 3Dfx VooDoo Mesa device driver functions */
35
36
37 #ifdef HAVE_CONFIG_H
38 #include "conf.h"
39 #endif
40
41 #if defined(FX)
42
43 #include "image.h"
44 #include "mtypes.h"
45 #include "fxdrv.h"
46 #include "enums.h"
47 #include "extensions.h"
48 #include "texstore.h"
49 #include "swrast/swrast.h"
50 #include "swrast_setup/swrast_setup.h"
51 #include "tnl/tnl.h"
52 #include "tnl/t_context.h"
53 #include "tnl/t_pipeline.h"
54 #include "array_cache/acache.h"
55
56
57
58 float gl_ubyte_to_float_255_color_tab[256];
59
60 /* These lookup table are used to extract RGB values in [0,255] from
61 * 16-bit pixel values.
62 */
63 GLubyte FX_PixelToR[0x10000];
64 GLubyte FX_PixelToG[0x10000];
65 GLubyte FX_PixelToB[0x10000];
66
67
68 /*
69 * Initialize the FX_PixelTo{RGB} arrays.
70 * Input: bgrOrder - if TRUE, pixels are in BGR order, else RGB order.
71 */
72 void
73 fxInitPixelTables(fxMesaContext fxMesa, GLboolean bgrOrder)
74 {
75 GLuint pixel;
76
77 fxMesa->bgrOrder = bgrOrder;
78 for (pixel = 0; pixel <= 0xffff; pixel++) {
79 GLuint r, g, b;
80 if (bgrOrder) {
81 r = (pixel & 0x001F) << 3;
82 g = (pixel & 0x07E0) >> 3;
83 b = (pixel & 0xF800) >> 8;
84 }
85 else {
86 r = (pixel & 0xF800) >> 8;
87 g = (pixel & 0x07E0) >> 3;
88 b = (pixel & 0x001F) << 3;
89 }
90 r = r * 255 / 0xF8; /* fill in low-order bits */
91 g = g * 255 / 0xFC;
92 b = b * 255 / 0xF8;
93 FX_PixelToR[pixel] = r;
94 FX_PixelToG[pixel] = g;
95 FX_PixelToB[pixel] = b;
96 }
97 }
98
99
100 /**********************************************************************/
101 /***** Miscellaneous functions *****/
102 /**********************************************************************/
103
104 /* Return buffer size information */
105 static void
106 fxDDBufferSize(GLframebuffer *buffer, GLuint * width, GLuint * height)
107 {
108 GET_CURRENT_CONTEXT(ctx);
109 if (ctx && ctx->DriverCtx) {
110 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
111
112 if (MESA_VERBOSE & VERBOSE_DRIVER) {
113 fprintf(stderr, "fxmesa: fxDDBufferSize(...) Start\n");
114 }
115
116 *width = fxMesa->width;
117 *height = fxMesa->height;
118
119 if (MESA_VERBOSE & VERBOSE_DRIVER) {
120 fprintf(stderr, "fxmesa: fxDDBufferSize(...) End\n");
121 }
122 }
123 }
124
125
126 /* Implements glClearColor() */
127 static void
128 fxDDClearColor(GLcontext * ctx, const GLchan color[4])
129 {
130 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
131 GLubyte col[4];
132
133 if (MESA_VERBOSE & VERBOSE_DRIVER) {
134 fprintf(stderr, "fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",
135 color[0], color[1], color[2], color[3]);
136 }
137
138 ASSIGN_4V(col, color[0], color[1], color[2], 255);
139 fxMesa->clearC = FXCOLOR4(col);
140 fxMesa->clearA = color[3];
141 }
142
143
144 /* Clear the color and/or depth buffers */
145 static void
146 fxDDClear(GLcontext * ctx, GLbitfield mask, GLboolean all,
147 GLint x, GLint y, GLint width, GLint height)
148 {
149 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
150 const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
151 const FxU16 clearD = (FxU16) (ctx->Depth.Clear * 0xffff);
152 GLbitfield softwareMask = mask & (DD_STENCIL_BIT | DD_ACCUM_BIT);
153
154 /* we can't clear stencil or accum buffers */
155 mask &= ~(DD_STENCIL_BIT | DD_ACCUM_BIT);
156
157 if (MESA_VERBOSE & VERBOSE_DRIVER) {
158 fprintf(stderr, "fxmesa: fxDDClear(%d,%d,%d,%d)\n", (int) x, (int) y,
159 (int) width, (int) height);
160 }
161
162 if (colorMask != 0xffffffff) {
163 /* do masked color buffer clears in software */
164 softwareMask |= (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT));
165 mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
166 }
167
168 /*
169 * This could probably be done fancier but doing each possible case
170 * explicitly is less error prone.
171 */
172 switch (mask) {
173 case DD_BACK_LEFT_BIT | DD_DEPTH_BIT:
174 /* back buffer & depth */
175 FX_grDepthMask(FXTRUE);
176 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER);
177 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD);
178 if (!ctx->Depth.Mask) {
179 FX_grDepthMask(FXFALSE);
180 }
181 break;
182 case DD_FRONT_LEFT_BIT | DD_DEPTH_BIT:
183 /* XXX it appears that the depth buffer isn't cleared when
184 * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set.
185 * This is a work-around/
186 */
187 /* clear depth */
188 FX_grDepthMask(FXTRUE);
189 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER);
190 FX_grColorMask(FXFALSE, FXFALSE);
191 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD);
192 /* clear front */
193 FX_grColorMask(FXTRUE, ctx->Color.ColorMask[ACOMP]
194 && fxMesa->haveAlphaBuffer);
195 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER);
196 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD);
197 break;
198 case DD_BACK_LEFT_BIT:
199 /* back buffer only */
200 FX_grDepthMask(FXFALSE);
201 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER);
202 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD);
203 if (ctx->Depth.Mask) {
204 FX_grDepthMask(FXTRUE);
205 }
206 break;
207 case DD_FRONT_LEFT_BIT:
208 /* front buffer only */
209 FX_grDepthMask(FXFALSE);
210 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER);
211 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD);
212 if (ctx->Depth.Mask) {
213 FX_grDepthMask(FXTRUE);
214 }
215 break;
216 case DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT:
217 /* front and back */
218 FX_grDepthMask(FXFALSE);
219 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER);
220 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD);
221 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER);
222 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD);
223 if (ctx->Depth.Mask) {
224 FX_grDepthMask(FXTRUE);
225 }
226 break;
227 case DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | DD_DEPTH_BIT:
228 /* clear front */
229 FX_grDepthMask(FXFALSE);
230 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER);
231 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD);
232 /* clear back and depth */
233 FX_grDepthMask(FXTRUE);
234 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER);
235 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD);
236 if (!ctx->Depth.Mask) {
237 FX_grDepthMask(FXFALSE);
238 }
239 break;
240 case DD_DEPTH_BIT:
241 /* just the depth buffer */
242 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER);
243 FX_grColorMask(FXFALSE, FXFALSE);
244 FX_grDepthMask(FXTRUE);
245 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, clearD);
246 FX_grColorMask(FXTRUE, ctx->Color.ColorMask[ACOMP]
247 && fxMesa->haveAlphaBuffer);
248 if (ctx->Color.DrawDestMask & FRONT_LEFT_BIT)
249 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER);
250 if (!ctx->Depth.Test || !ctx->Depth.Mask)
251 FX_grDepthMask(FXFALSE);
252 break;
253 default:
254 /* error */
255 ;
256 }
257
258 /* Clear any remaining buffers:
259 */
260 if (softwareMask)
261 _swrast_Clear(ctx, softwareMask, all, x, y, width, height);
262 }
263
264
265 /* Set the buffer used for drawing */
266 /* XXX support for separate read/draw buffers hasn't been tested */
267 static GLboolean
268 fxDDSetDrawBuffer(GLcontext * ctx, GLenum mode)
269 {
270 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
271
272 if (MESA_VERBOSE & VERBOSE_DRIVER) {
273 fprintf(stderr, "fxmesa: fxDDSetBuffer(%x)\n", (int) mode);
274 }
275
276 if (mode == GL_FRONT_LEFT) {
277 fxMesa->currentFB = GR_BUFFER_FRONTBUFFER;
278 FX_grRenderBuffer(fxMesa->currentFB);
279 return GL_TRUE;
280 }
281 else if (mode == GL_BACK_LEFT) {
282 fxMesa->currentFB = GR_BUFFER_BACKBUFFER;
283 FX_grRenderBuffer(fxMesa->currentFB);
284 return GL_TRUE;
285 }
286 else if (mode == GL_NONE) {
287 FX_grColorMask(FXFALSE, FXFALSE);
288 return GL_TRUE;
289 }
290 else {
291 return GL_FALSE;
292 }
293 }
294
295
296
297
298
299 static void
300 fxDDDrawBitmap(GLcontext * ctx, GLint px, GLint py,
301 GLsizei width, GLsizei height,
302 const struct gl_pixelstore_attrib *unpack,
303 const GLubyte * bitmap)
304 {
305 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
306 GrLfbInfo_t info;
307 FxU16 color;
308 const struct gl_pixelstore_attrib *finalUnpack;
309 struct gl_pixelstore_attrib scissoredUnpack;
310
311 /* check if there's any raster operations enabled which we can't handle */
312 if (ctx->Color.AlphaEnabled ||
313 ctx->Color.BlendEnabled ||
314 ctx->Depth.Test ||
315 ctx->Fog.Enabled ||
316 ctx->Color.ColorLogicOpEnabled ||
317 ctx->Stencil.Enabled ||
318 ctx->Scissor.Enabled ||
319 (ctx->DrawBuffer->UseSoftwareAlphaBuffers &&
320 ctx->Color.ColorMask[ACOMP]) || ctx->Color.MultiDrawBuffer) {
321 _swrast_Bitmap(ctx, px, py, width, height, unpack, bitmap);
322 return;
323 }
324
325
326 if (ctx->Scissor.Enabled) {
327 /* This is a bit tricky, but by carefully adjusting the px, py,
328 * width, height, skipPixels and skipRows values we can do
329 * scissoring without special code in the rendering loop.
330 *
331 * KW: This code is never reached, see the test above.
332 */
333
334 /* we'll construct a new pixelstore struct */
335 finalUnpack = &scissoredUnpack;
336 scissoredUnpack = *unpack;
337 if (scissoredUnpack.RowLength == 0)
338 scissoredUnpack.RowLength = width;
339
340 /* clip left */
341 if (px < ctx->Scissor.X) {
342 scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
343 width -= (ctx->Scissor.X - px);
344 px = ctx->Scissor.X;
345 }
346 /* clip right */
347 if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
348 width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
349 }
350 /* clip bottom */
351 if (py < ctx->Scissor.Y) {
352 scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
353 height -= (ctx->Scissor.Y - py);
354 py = ctx->Scissor.Y;
355 }
356 /* clip top */
357 if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
358 height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
359 }
360
361 if (width <= 0 || height <= 0)
362 return;
363 }
364 else {
365 finalUnpack = unpack;
366 }
367
368 /* compute pixel value */
369 {
370 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0f);
371 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0f);
372 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0f);
373 /*GLint a = (GLint)(ctx->Current.RasterColor[3]*255.0f); */
374 if (fxMesa->bgrOrder)
375 color = (FxU16)
376 (((FxU16) 0xf8 & b) << (11 - 3)) |
377 (((FxU16) 0xfc & g) << (5 - 3 + 1)) | (((FxU16) 0xf8 & r) >> 3);
378 else
379 color = (FxU16)
380 (((FxU16) 0xf8 & r) << (11 - 3)) |
381 (((FxU16) 0xfc & g) << (5 - 3 + 1)) | (((FxU16) 0xf8 & b) >> 3);
382 }
383
384 info.size = sizeof(info);
385 if (!FX_grLfbLock(GR_LFB_WRITE_ONLY,
386 fxMesa->currentFB,
387 GR_LFBWRITEMODE_565,
388 GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
389 #ifndef FX_SILENT
390 fprintf(stderr, "fx Driver: error locking the linear frame buffer\n");
391 #endif
392 return;
393 }
394
395 {
396 const GLint winX = 0;
397 const GLint winY = fxMesa->height - 1;
398 /* The dest stride depends on the hardware and whether we're drawing
399 * to the front or back buffer. This compile-time test seems to do
400 * the job for now.
401 */
402 const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */
403
404 GLint row;
405 /* compute dest address of bottom-left pixel in bitmap */
406 GLushort *dst = (GLushort *) info.lfbPtr
407 + (winY - py) * dstStride + (winX + px);
408
409 for (row = 0; row < height; row++) {
410 const GLubyte *src =
411 (const GLubyte *) _mesa_image_address(finalUnpack,
412 bitmap, width, height,
413 GL_COLOR_INDEX, GL_BITMAP,
414 0, row, 0);
415 if (finalUnpack->LsbFirst) {
416 /* least significan bit first */
417 GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
418 GLint col;
419 for (col = 0; col < width; col++) {
420 if (*src & mask) {
421 dst[col] = color;
422 }
423 if (mask == 128U) {
424 src++;
425 mask = 1U;
426 }
427 else {
428 mask = mask << 1;
429 }
430 }
431 if (mask != 1)
432 src++;
433 }
434 else {
435 /* most significan bit first */
436 GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
437 GLint col;
438 for (col = 0; col < width; col++) {
439 if (*src & mask) {
440 dst[col] = color;
441 }
442 if (mask == 1U) {
443 src++;
444 mask = 128U;
445 }
446 else {
447 mask = mask >> 1;
448 }
449 }
450 if (mask != 128)
451 src++;
452 }
453 dst -= dstStride;
454 }
455 }
456
457 FX_grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
458 }
459
460
461 static void
462 fxDDReadPixels(GLcontext * ctx, GLint x, GLint y,
463 GLsizei width, GLsizei height,
464 GLenum format, GLenum type,
465 const struct gl_pixelstore_attrib *packing, GLvoid * dstImage)
466 {
467 if (ctx->_ImageTransferState) {
468 _swrast_ReadPixels(ctx, x, y, width, height, format, type,
469 packing, dstImage);
470 return;
471 }
472 else {
473 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
474 GrLfbInfo_t info;
475
476 BEGIN_BOARD_LOCK();
477 if (grLfbLock(GR_LFB_READ_ONLY,
478 fxMesa->currentFB,
479 GR_LFBWRITEMODE_ANY,
480 GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
481 const GLint winX = 0;
482 const GLint winY = fxMesa->height - 1;
483 const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
484 const GLushort *src = (const GLushort *) info.lfbPtr
485 + (winY - y) * srcStride + (winX + x);
486 GLubyte *dst = (GLubyte *) _mesa_image_address(packing, dstImage,
487 width, height, format,
488 type, 0, 0, 0);
489 GLint dstStride =
490 _mesa_image_row_stride(packing, width, format, type);
491
492 if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
493 /* convert 5R6G5B into 8R8G8B */
494 GLint row, col;
495 const GLint halfWidth = width >> 1;
496 const GLint extraPixel = (width & 1);
497 for (row = 0; row < height; row++) {
498 GLubyte *d = dst;
499 for (col = 0; col < halfWidth; col++) {
500 const GLuint pixel = ((const GLuint *) src)[col];
501 const GLint pixel0 = pixel & 0xffff;
502 const GLint pixel1 = pixel >> 16;
503 *d++ = FX_PixelToR[pixel0];
504 *d++ = FX_PixelToG[pixel0];
505 *d++ = FX_PixelToB[pixel0];
506 *d++ = FX_PixelToR[pixel1];
507 *d++ = FX_PixelToG[pixel1];
508 *d++ = FX_PixelToB[pixel1];
509 }
510 if (extraPixel) {
511 GLushort pixel = src[width - 1];
512 *d++ = FX_PixelToR[pixel];
513 *d++ = FX_PixelToG[pixel];
514 *d++ = FX_PixelToB[pixel];
515 }
516 dst += dstStride;
517 src -= srcStride;
518 }
519 }
520 else if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
521 /* convert 5R6G5B into 8R8G8B8A */
522 GLint row, col;
523 const GLint halfWidth = width >> 1;
524 const GLint extraPixel = (width & 1);
525 for (row = 0; row < height; row++) {
526 GLubyte *d = dst;
527 for (col = 0; col < halfWidth; col++) {
528 const GLuint pixel = ((const GLuint *) src)[col];
529 const GLint pixel0 = pixel & 0xffff;
530 const GLint pixel1 = pixel >> 16;
531 *d++ = FX_PixelToR[pixel0];
532 *d++ = FX_PixelToG[pixel0];
533 *d++ = FX_PixelToB[pixel0];
534 *d++ = 255;
535 *d++ = FX_PixelToR[pixel1];
536 *d++ = FX_PixelToG[pixel1];
537 *d++ = FX_PixelToB[pixel1];
538 *d++ = 255;
539 }
540 if (extraPixel) {
541 const GLushort pixel = src[width - 1];
542 *d++ = FX_PixelToR[pixel];
543 *d++ = FX_PixelToG[pixel];
544 *d++ = FX_PixelToB[pixel];
545 *d++ = 255;
546 }
547 dst += dstStride;
548 src -= srcStride;
549 }
550 }
551 else if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
552 /* directly memcpy 5R6G5B pixels into client's buffer */
553 const GLint widthInBytes = width * 2;
554 GLint row;
555 for (row = 0; row < height; row++) {
556 MEMCPY(dst, src, widthInBytes);
557 dst += dstStride;
558 src -= srcStride;
559 }
560 }
561 else {
562 grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
563 END_BOARD_LOCK();
564 _swrast_ReadPixels(ctx, x, y, width, height, format, type,
565 packing, dstImage);
566 return;
567 }
568
569 grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
570 }
571 END_BOARD_LOCK();
572 }
573 }
574
575
576
577 static void
578 fxDDFinish(GLcontext * ctx)
579 {
580 FX_grFlush();
581 }
582
583
584
585
586
587 /* KW: Put the word Mesa in the render string because quakeworld
588 * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
589 * Why?
590 */
591 static const GLubyte *
592 fxDDGetString(GLcontext * ctx, GLenum name)
593 {
594 switch (name) {
595 case GL_RENDERER:
596 {
597 static char buf[80];
598
599 if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_VOODOO) {
600 GrVoodooConfig_t *vc =
601 &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig;
602
603 sprintf(buf,
604 "Mesa Glide v0.30 Voodoo_Graphics %d "
605 "CARD/%d FB/%d TM/%d TMU/%s",
606 glbCurrentBoard,
607 (vc->sliDetect ? (vc->fbRam * 2) : vc->fbRam),
608 (vc->tmuConfig[GR_TMU0].tmuRam +
609 ((vc->nTexelfx > 1) ? vc->tmuConfig[GR_TMU1].
610 tmuRam : 0)), vc->nTexelfx,
611 (vc->sliDetect ? "SLI" : "NOSLI"));
612 }
613 else if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_SST96) {
614 GrSst96Config_t *sc =
615 &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config;
616
617 sprintf(buf,
618 "Glide v0.30 Voodoo_Rush %d "
619 "CARD/%d FB/%d TM/%d TMU/NOSLI",
620 glbCurrentBoard,
621 sc->fbRam, sc->tmuConfig.tmuRam, sc->nTexelfx);
622 }
623 else {
624 strcpy(buf, "Glide v0.30 UNKNOWN");
625 }
626 return (GLubyte *) buf;
627 }
628 default:
629 return NULL;
630 }
631 }
632
633 static const struct gl_pipeline_stage *fx_pipeline[] = {
634 &_tnl_vertex_transform_stage, /* TODO: Add the fastpath here */
635 &_tnl_normal_transform_stage,
636 &_tnl_lighting_stage,
637 &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage */
638 &_tnl_texgen_stage,
639 &_tnl_texture_transform_stage,
640 &_tnl_point_attenuation_stage,
641 &_tnl_render_stage,
642 0,
643 };
644
645
646
647
648 int
649 fxDDInitFxMesaContext(fxMesaContext fxMesa)
650 {
651 int i;
652
653 for (i = 0; i < 256; i++) {
654 gl_ubyte_to_float_255_color_tab[i] = (float) i;
655 }
656
657 FX_setupGrVertexLayout();
658
659 if (getenv("FX_EMULATE_SINGLE_TMU"))
660 fxMesa->haveTwoTMUs = GL_FALSE;
661
662 if (getenv("FX_GLIDE_SWAPINTERVAL"))
663 fxMesa->swapInterval = atoi(getenv("FX_GLIDE_SWAPINTERVAL"));
664 else
665 fxMesa->swapInterval = 1;
666
667 if (getenv("MESA_FX_SWAP_PENDING"))
668 fxMesa->maxPendingSwapBuffers = atoi(getenv("MESA_FX_SWAP_PENDING"));
669 else
670 fxMesa->maxPendingSwapBuffers = 2;
671
672 if (getenv("MESA_FX_INFO"))
673 fxMesa->verbose = GL_TRUE;
674 else
675 fxMesa->verbose = GL_FALSE;
676
677 fxMesa->color = 0xffffffff;
678 fxMesa->clearC = 0;
679 fxMesa->clearA = 0;
680
681 fxMesa->stats.swapBuffer = 0;
682 fxMesa->stats.reqTexUpload = 0;
683 fxMesa->stats.texUpload = 0;
684 fxMesa->stats.memTexUpload = 0;
685
686 fxMesa->tmuSrc = FX_TMU_NONE;
687 fxMesa->lastUnitsMode = FX_UM_NONE;
688 fxTMInit(fxMesa);
689
690 /* FX units setup */
691
692 fxMesa->unitsState.alphaTestEnabled = GL_FALSE;
693 fxMesa->unitsState.alphaTestFunc = GR_CMP_ALWAYS;
694 fxMesa->unitsState.alphaTestRefValue = 0;
695
696 fxMesa->unitsState.blendEnabled = GL_FALSE;
697 fxMesa->unitsState.blendSrcFuncRGB = GR_BLEND_ONE;
698 fxMesa->unitsState.blendDstFuncRGB = GR_BLEND_ZERO;
699 fxMesa->unitsState.blendSrcFuncAlpha = GR_BLEND_ONE;
700 fxMesa->unitsState.blendDstFuncAlpha = GR_BLEND_ZERO;
701
702 fxMesa->unitsState.depthTestEnabled = GL_FALSE;
703 fxMesa->unitsState.depthMask = GL_TRUE;
704 fxMesa->unitsState.depthTestFunc = GR_CMP_LESS;
705
706 FX_grColorMask(FXTRUE, fxMesa->haveAlphaBuffer ? FXTRUE : FXFALSE);
707 if (fxMesa->haveDoubleBuffer) {
708 fxMesa->currentFB = GR_BUFFER_BACKBUFFER;
709 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER);
710 }
711 else {
712 fxMesa->currentFB = GR_BUFFER_FRONTBUFFER;
713 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER);
714 }
715
716 fxMesa->state = malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE));
717 fxMesa->fogTable = malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES) *
718 sizeof(GrFog_t));
719
720 if (!fxMesa->state || !fxMesa->fogTable) {
721 if (fxMesa->state)
722 free(fxMesa->state);
723 if (fxMesa->fogTable)
724 free(fxMesa->fogTable);
725 return 0;
726 }
727
728 if (fxMesa->haveZBuffer)
729 FX_grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER);
730
731 #ifndef FXMESA_USE_ARGB
732 FX_grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); /* Not every Glide has this */
733 #endif
734
735 fxMesa->textureAlign = FX_grGetInteger(FX_TEXTURE_ALIGN);
736 fxMesa->glCtx->Const.MaxTextureLevels = 9;
737 fxMesa->glCtx->Const.MaxTextureUnits = fxMesa->haveTwoTMUs ? 2 : 1;
738 fxMesa->new_state = _NEW_ALL;
739
740 /* Initialize the software rasterizer and helper modules.
741 */
742 _swrast_CreateContext(fxMesa->glCtx);
743 _ac_CreateContext(fxMesa->glCtx);
744 _tnl_CreateContext(fxMesa->glCtx);
745 _swsetup_CreateContext(fxMesa->glCtx);
746
747 _tnl_destroy_pipeline(fxMesa->glCtx);
748 _tnl_install_pipeline(fxMesa->glCtx, fx_pipeline);
749
750 fxAllocVB(fxMesa->glCtx);
751
752 fxSetupDDPointers(fxMesa->glCtx);
753 fxDDInitTriFuncs(fxMesa->glCtx);
754
755 /* Tell the software rasterizer to use pixel fog always.
756 */
757 _swrast_allow_vertex_fog(fxMesa->glCtx, GL_FALSE);
758 _swrast_allow_pixel_fog(fxMesa->glCtx, GL_TRUE);
759
760 /* Tell tnl not to calculate or use vertex fog factors. (Needed to
761 * tell render stage not to clip fog coords).
762 */
763 /* _tnl_calculate_vertex_fog( fxMesa->glCtx, GL_FALSE ); */
764
765 fxDDInitExtensions(fxMesa->glCtx);
766
767 FX_grGlideGetState((GrState *) fxMesa->state);
768
769 return 1;
770 }
771
772 /* Undo the above.
773 */
774 void
775 fxDDDestroyFxMesaContext(fxMesaContext fxMesa)
776 {
777 _swsetup_DestroyContext(fxMesa->glCtx);
778 _tnl_DestroyContext(fxMesa->glCtx);
779 _ac_DestroyContext(fxMesa->glCtx);
780 _swrast_DestroyContext(fxMesa->glCtx);
781
782 if (fxMesa->state)
783 free(fxMesa->state);
784 if (fxMesa->fogTable)
785 free(fxMesa->fogTable);
786 fxTMClose(fxMesa);
787 fxFreeVB(fxMesa->glCtx);
788 }
789
790
791
792
793 void
794 fxDDInitExtensions(GLcontext * ctx)
795 {
796 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
797
798 _mesa_add_extension(ctx, GL_TRUE, "3DFX_set_global_palette", 0);
799 _mesa_enable_extension(ctx, "GL_EXT_point_parameters");
800 _mesa_enable_extension(ctx, "GL_EXT_paletted_texture");
801 _mesa_enable_extension(ctx, "GL_EXT_texture_lod_bias");
802 _mesa_enable_extension(ctx, "GL_EXT_shared_texture_palette");
803
804 if (fxMesa->haveTwoTMUs)
805 _mesa_enable_extension(ctx, "GL_EXT_texture_env_add");
806
807 if (fxMesa->haveTwoTMUs)
808 _mesa_enable_extension(ctx, "GL_ARB_multitexture");
809 }
810
811
812 /************************************************************************/
813 /************************************************************************/
814 /************************************************************************/
815
816 /* Check if the hardware supports the current context
817 *
818 * Performs similar work to fxDDChooseRenderState() - should be merged.
819 */
820 GLboolean
821 fx_check_IsInHardware(GLcontext * ctx)
822 {
823 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
824
825 if (ctx->RenderMode != GL_RENDER)
826 return GL_FALSE;
827
828 if (ctx->Stencil.Enabled ||
829 ctx->Color.MultiDrawBuffer ||
830 ((ctx->Color.BlendEnabled)
831 && (ctx->Color.BlendEquation != GL_FUNC_ADD_EXT))
832 || ((ctx->Color.ColorLogicOpEnabled)
833 && (ctx->Color.LogicOp != GL_COPY))
834 || (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
835 ||
836 (!((ctx->
837 Color.ColorMask[RCOMP] == ctx->Color.ColorMask[GCOMP])
838 && (ctx->Color.ColorMask[GCOMP] == ctx->Color.ColorMask[BCOMP])
839 && (ctx->Color.ColorMask[ACOMP] == ctx->Color.ColorMask[ACOMP])))
840 ) {
841 return GL_FALSE;
842 }
843 /* Unsupported texture/multitexture cases */
844
845 if (fxMesa->haveTwoTMUs) {
846 if (ctx->Texture._ReallyEnabled & (TEXTURE0_3D | TEXTURE1_3D))
847 return GL_FALSE; /* can't do 3D textures */
848 if (ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE1_1D))
849 return GL_FALSE; /* can't do 1D textures */
850
851 if (ctx->Texture._ReallyEnabled & TEXTURE0_2D) {
852 if (ctx->Texture.Unit[0].EnvMode == GL_BLEND &&
853 (ctx->Texture._ReallyEnabled & TEXTURE1_2D ||
854 ctx->Texture.Unit[0].EnvColor[0] != 0 ||
855 ctx->Texture.Unit[0].EnvColor[1] != 0 ||
856 ctx->Texture.Unit[0].EnvColor[2] != 0 ||
857 ctx->Texture.Unit[0].EnvColor[3] != 1)) {
858 return GL_FALSE;
859 }
860 if (ctx->Texture.Unit[0]._Current->Image[0]->Border > 0)
861 return GL_FALSE;
862 }
863
864 if (ctx->Texture._ReallyEnabled & TEXTURE1_2D) {
865 if (ctx->Texture.Unit[1].EnvMode == GL_BLEND)
866 return GL_FALSE;
867 if (ctx->Texture.Unit[1]._Current->Image[0]->Border > 0)
868 return GL_FALSE;
869 }
870
871 if (MESA_VERBOSE & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
872 fprintf(stderr, "fxMesa: fxIsInHardware, envmode is %s/%s\n",
873 _mesa_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
874 _mesa_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
875
876 /* KW: This was wrong (I think) and I changed it... which doesn't mean
877 * it is now correct...
878 */
879 if ((ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D)) &&
880 (ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D))) {
881 /* Can't use multipass to blend a multitextured triangle - fall
882 * back to software.
883 */
884 if (!fxMesa->haveTwoTMUs && ctx->Color.BlendEnabled) {
885 return GL_FALSE;
886 }
887
888 if ((ctx->Texture.Unit[0].EnvMode != ctx->Texture.Unit[1].EnvMode) &&
889 (ctx->Texture.Unit[0].EnvMode != GL_MODULATE) &&
890 (ctx->Texture.Unit[0].EnvMode != GL_REPLACE)) { /* q2, seems ok... */
891 if (MESA_VERBOSE & VERBOSE_DRIVER)
892 fprintf(stderr, "fxMesa: unsupported multitex env mode\n");
893 return GL_FALSE;
894 }
895 }
896 }
897 else {
898 if ((ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)) ||
899 /* Not very well written ... */
900 ((ctx->Texture._ReallyEnabled & TEXTURE0_1D) &&
901 (!(ctx->Texture._ReallyEnabled & TEXTURE0_2D)))
902 ) {
903 return GL_FALSE;
904 }
905
906
907 if ((ctx->Texture._ReallyEnabled & TEXTURE0_2D) &&
908 (ctx->Texture.Unit[0].EnvMode == GL_BLEND)) {
909 return GL_FALSE;
910 }
911 }
912
913 return GL_TRUE;
914 }
915
916
917
918 static void
919 update_texture_scales(GLcontext * ctx)
920 {
921 fxMesaContext fxMesa = FX_CONTEXT(ctx);
922 struct gl_texture_unit *t0 = &ctx->Texture.Unit[fxMesa->tmu_source[0]];
923 struct gl_texture_unit *t1 = &ctx->Texture.Unit[fxMesa->tmu_source[1]];
924
925 if (t0 && t0->_Current && FX_TEXTURE_DATA(t0)) {
926 fxMesa->s0scale = FX_TEXTURE_DATA(t0)->sScale;
927 fxMesa->t0scale = FX_TEXTURE_DATA(t0)->tScale;
928 fxMesa->inv_s0scale = 1.0 / fxMesa->s0scale;
929 fxMesa->inv_t0scale = 1.0 / fxMesa->t0scale;
930 }
931
932 if (t1 && t1->_Current && FX_TEXTURE_DATA(t1)) {
933 fxMesa->s1scale = FX_TEXTURE_DATA(t1)->sScale;
934 fxMesa->t1scale = FX_TEXTURE_DATA(t1)->tScale;
935 fxMesa->inv_s1scale = 1.0 / fxMesa->s1scale;
936 fxMesa->inv_t1scale = 1.0 / fxMesa->t1scale;
937 }
938 }
939
940 static void
941 fxDDUpdateDDPointers(GLcontext * ctx, GLuint new_state)
942 {
943 /* TNLcontext *tnl = TNL_CONTEXT(ctx);*/
944 fxMesaContext fxMesa = FX_CONTEXT(ctx);
945
946 _swrast_InvalidateState(ctx, new_state);
947 _ac_InvalidateState(ctx, new_state);
948 _tnl_InvalidateState(ctx, new_state);
949 _swsetup_InvalidateState(ctx, new_state);
950
951 /* Recalculate fog table on projection matrix changes. This used to
952 * be triggered by the NearFar callback.
953 */
954 if (new_state & _NEW_PROJECTION)
955 fxMesa->new_state |= FX_NEW_FOG;
956
957 if (new_state & (_FX_NEW_IS_IN_HARDWARE |
958 _FX_NEW_RENDERSTATE |
959 _FX_NEW_SETUP_FUNCTION |
960 _NEW_TEXTURE)) {
961
962 if (new_state & _FX_NEW_IS_IN_HARDWARE)
963 fxCheckIsInHardware(ctx);
964
965 if (fxMesa->new_state)
966 fxSetupFXUnits(ctx);
967
968 if (fxMesa->is_in_hardware) {
969 if (new_state & _FX_NEW_RENDERSTATE)
970 fxDDChooseRenderState(ctx);
971
972 if (new_state & _FX_NEW_SETUP_FUNCTION)
973 fxChooseVertexState(ctx);
974 }
975
976 if (new_state & _NEW_TEXTURE)
977 update_texture_scales(ctx);
978 }
979 }
980
981
982
983
984 void
985 fxSetupDDPointers(GLcontext * ctx)
986 {
987 TNLcontext *tnl = TNL_CONTEXT(ctx);
988
989 if (MESA_VERBOSE & VERBOSE_DRIVER) {
990 fprintf(stderr, "fxmesa: fxSetupDDPointers()\n");
991 }
992
993 ctx->Driver.UpdateState = fxDDUpdateDDPointers;
994 ctx->Driver.GetString = fxDDGetString;
995 ctx->Driver.ClearIndex = NULL;
996 ctx->Driver.ClearColor = fxDDClearColor;
997 ctx->Driver.Clear = fxDDClear;
998 ctx->Driver.SetDrawBuffer = fxDDSetDrawBuffer;
999 ctx->Driver.GetBufferSize = fxDDBufferSize;
1000 ctx->Driver.Accum = _swrast_Accum;
1001 ctx->Driver.Bitmap = fxDDDrawBitmap;
1002 ctx->Driver.CopyPixels = _swrast_CopyPixels;
1003 ctx->Driver.DrawPixels = _swrast_DrawPixels;
1004 ctx->Driver.ReadPixels = fxDDReadPixels;
1005 ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
1006 ctx->Driver.Finish = fxDDFinish;
1007 ctx->Driver.Flush = NULL;
1008 ctx->Driver.ChooseTextureFormat = fxDDChooseTextureFormat;
1009 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
1010 ctx->Driver.TexImage2D = fxDDTexImage2D;
1011 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
1012 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
1013 ctx->Driver.TexSubImage2D = fxDDTexSubImage2D;
1014 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
1015 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
1016 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
1017 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
1018 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
1019 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
1020 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
1021 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
1022 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
1023 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
1024 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
1025 ctx->Driver.TexEnv = fxDDTexEnv;
1026 ctx->Driver.TexParameter = fxDDTexParam;
1027 ctx->Driver.BindTexture = fxDDTexBind;
1028 ctx->Driver.DeleteTexture = fxDDTexDel;
1029 ctx->Driver.UpdateTexturePalette = fxDDTexPalette;
1030 ctx->Driver.AlphaFunc = fxDDAlphaFunc;
1031 ctx->Driver.BlendFunc = fxDDBlendFunc;
1032 ctx->Driver.DepthFunc = fxDDDepthFunc;
1033 ctx->Driver.DepthMask = fxDDDepthMask;
1034 ctx->Driver.ColorMask = fxDDColorMask;
1035 ctx->Driver.Fogfv = fxDDFogfv;
1036 ctx->Driver.Scissor = fxDDScissor;
1037 ctx->Driver.FrontFace = fxDDFrontFace;
1038 ctx->Driver.CullFace = fxDDCullFace;
1039 ctx->Driver.ShadeModel = fxDDShadeModel;
1040 ctx->Driver.Enable = fxDDEnable;
1041
1042 tnl->Driver.RunPipeline = _tnl_run_pipeline;
1043
1044 fxSetupDDSpanPointers(ctx);
1045 fxDDUpdateDDPointers(ctx, ~0);
1046 }
1047
1048
1049 #else
1050
1051
1052 /*
1053 * Need this to provide at least one external definition.
1054 */
1055
1056 extern int gl_fx_dummy_function_dd(void);
1057 int
1058 gl_fx_dummy_function_dd(void)
1059 {
1060 return 0;
1061 }
1062
1063 #endif /* FX */