Header file clean-up:
[mesa.git] / src / mesa / drivers / glide / fxapi.c
1 /* $Id: fxapi.c,v 1.35 2002/10/24 23:57:23 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
35 /* fxapi.c - public interface to FX/Mesa functions (fxmesa.h) */
36
37
38 #ifdef HAVE_CONFIG_H
39 #include "conf.h"
40 #endif
41
42 #if defined(FX)
43 #include "fxdrv.h"
44
45 static fxMesaContext fxMesaCurrentCtx = NULL;
46
47 /*
48 * Status of 3Dfx hardware initialization
49 */
50
51 static int glbGlideInitialized = 0;
52 static int glb3DfxPresent = 0;
53 static int glbTotNumCtx = 0;
54
55 GrHwConfiguration glbHWConfig;
56 int glbCurrentBoard = 0;
57
58
59 #if defined(__WIN32__)
60 static int
61 cleangraphics(void)
62 {
63 glbTotNumCtx = 1;
64 fxMesaDestroyContext(fxMesaCurrentCtx);
65
66 return 0;
67 }
68 #elif defined(__linux__)
69 static void
70 cleangraphics(void)
71 {
72 glbTotNumCtx = 1;
73 fxMesaDestroyContext(fxMesaCurrentCtx);
74 }
75
76 static void
77 cleangraphics_handler(int s)
78 {
79 fprintf(stderr, "fxmesa: Received a not handled signal %d\n", s);
80
81 cleangraphics();
82 /* abort(); */
83 exit(1);
84 }
85 #endif
86
87
88 /*
89 * Select the Voodoo board to use when creating
90 * a new context.
91 */
92 GLboolean GLAPIENTRY
93 fxMesaSelectCurrentBoard(int n)
94 {
95 fxQueryHardware();
96
97 if ((n < 0) || (n >= glbHWConfig.num_sst))
98 return GL_FALSE;
99
100 glbCurrentBoard = n;
101
102 return GL_TRUE;
103 }
104
105
106 fxMesaContext GLAPIENTRY
107 fxMesaGetCurrentContext(void)
108 {
109 return fxMesaCurrentCtx;
110 }
111
112
113 /*
114 * The 3Dfx Global Palette extension for GLQuake.
115 * More a trick than a real extesion, use the shared global
116 * palette extension.
117 */
118 extern void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint * pal); /* silence warning */
119 void GLAPIENTRY
120 gl3DfxSetPaletteEXT(GLuint * pal)
121 {
122 fxMesaContext fxMesa = fxMesaCurrentCtx;
123
124 if (MESA_VERBOSE & VERBOSE_DRIVER) {
125 int i;
126
127 fprintf(stderr, "fxmesa: gl3DfxSetPaletteEXT()\n");
128
129 for (i = 0; i < 256; i++)
130 fprintf(stderr, "%x\n", pal[i]);
131 }
132
133 if (fxMesa) {
134 fxMesa->haveGlobalPaletteTexture = 1;
135
136 FX_grTexDownloadTable(GR_TMU0, GR_TEXTABLE_PALETTE,
137 (GuTexPalette *) pal);
138 if (fxMesa->haveTwoTMUs)
139 FX_grTexDownloadTable(GR_TMU1, GR_TEXTABLE_PALETTE,
140 (GuTexPalette *) pal);
141 }
142 }
143
144
145 static GrScreenResolution_t
146 fxBestResolution(int width, int height, int aux)
147 {
148 static int resolutions[][5] = {
149 {320, 200, GR_RESOLUTION_320x200, 2, 2},
150 {320, 240, GR_RESOLUTION_320x240, 2, 2},
151 {512, 384, GR_RESOLUTION_512x384, 2, 2},
152 {640, 400, GR_RESOLUTION_640x400, 2, 2},
153 {640, 480, GR_RESOLUTION_640x480, 2, 2},
154 {800, 600, GR_RESOLUTION_800x600, 4, 2},
155 {960, 720, GR_RESOLUTION_960x720, 6, 4}
156 #ifdef GR_RESOLUTION_1024x768
157 , {1024, 768, GR_RESOLUTION_1024x768, 8, 4}
158 #endif
159 #ifdef GR_RESOLUTION_1280x1024
160 , {1280, 1024, GR_RESOLUTION_1280x1024, 8, 8}
161 #endif
162 #ifdef GR_RESOLUTION_1600x1200
163 , {1600, 1200, GR_RESOLUTION_1600x1200, 16, 8}
164 #endif
165 };
166 int NUM_RESOLUTIONS = sizeof(resolutions) / (sizeof(int) * 5);
167 int i, fbmem;
168 GrScreenResolution_t lastvalidres = resolutions[4][2];
169
170 fxQueryHardware();
171
172 if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_VOODOO) {
173 fbmem = glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam;
174
175 if (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect)
176 fbmem *= 2;
177 }
178 else if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_SST96)
179 fbmem = glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam;
180 else
181 fbmem = 2;
182
183 /* A work around for BZFlag */
184
185 if ((width == 1) && (height == 1)) {
186 width = 640;
187 height = 480;
188 }
189
190 for (i = 0; i < NUM_RESOLUTIONS; i++)
191 if (resolutions[i][4 - aux] <= fbmem) {
192 if ((width <= resolutions[i][0]) && (height <= resolutions[i][1]))
193 return resolutions[i][2];
194
195 lastvalidres = resolutions[i][2];
196 }
197
198 return lastvalidres;
199 }
200
201
202 fxMesaContext GLAPIENTRY
203 fxMesaCreateBestContext(GLuint win, GLint width, GLint height,
204 const GLint attribList[])
205 {
206 GrScreenRefresh_t refresh;
207 int i;
208 int res, aux;
209 refresh = GR_REFRESH_75Hz;
210
211 if (getenv("SST_SCREENREFRESH")) {
212 if (!strcmp(getenv("SST_SCREENREFRESH"), "60"))
213 refresh = GR_REFRESH_60Hz;
214 if (!strcmp(getenv("SST_SCREENREFRESH"), "70"))
215 refresh = GR_REFRESH_70Hz;
216 if (!strcmp(getenv("SST_SCREENREFRESH"), "72"))
217 refresh = GR_REFRESH_72Hz;
218 if (!strcmp(getenv("SST_SCREENREFRESH"), "75"))
219 refresh = GR_REFRESH_75Hz;
220 if (!strcmp(getenv("SST_SCREENREFRESH"), "80"))
221 refresh = GR_REFRESH_80Hz;
222 if (!strcmp(getenv("SST_SCREENREFRESH"), "85"))
223 refresh = GR_REFRESH_85Hz;
224 if (!strcmp(getenv("SST_SCREENREFRESH"), "90"))
225 refresh = GR_REFRESH_90Hz;
226 if (!strcmp(getenv("SST_SCREENREFRESH"), "100"))
227 refresh = GR_REFRESH_100Hz;
228 if (!strcmp(getenv("SST_SCREENREFRESH"), "120"))
229 refresh = GR_REFRESH_120Hz;
230 }
231
232 aux = 0;
233 for (i = 0; attribList[i] != FXMESA_NONE; i++)
234 if ((attribList[i] == FXMESA_ALPHA_SIZE) ||
235 (attribList[i] == FXMESA_DEPTH_SIZE)) {
236 if (attribList[++i] > 0) {
237 aux = 1;
238 break;
239 }
240 }
241
242 res = fxBestResolution(width, height, aux);
243
244 return fxMesaCreateContext(win, res, refresh, attribList);
245 }
246
247
248 #if 0
249 void
250 fxsignals()
251 {
252 signal(SIGINT, SIG_IGN);
253 signal(SIGHUP, SIG_IGN);
254 signal(SIGPIPE, SIG_IGN);
255 signal(SIGFPE, SIG_IGN);
256 signal(SIGBUS, SIG_IGN);
257 signal(SIGILL, SIG_IGN);
258 signal(SIGSEGV, SIG_IGN);
259 signal(SIGTERM, SIG_IGN);
260 }
261 #endif
262
263 /*
264 * Create a new FX/Mesa context and return a handle to it.
265 */
266 fxMesaContext GLAPIENTRY
267 fxMesaCreateContext(GLuint win,
268 GrScreenResolution_t res,
269 GrScreenRefresh_t ref, const GLint attribList[])
270 {
271 fxMesaContext fxMesa = NULL;
272 int i, type;
273 int aux;
274 GLboolean doubleBuffer = GL_FALSE;
275 GLboolean alphaBuffer = GL_FALSE;
276 GLboolean verbose = GL_FALSE;
277 GLint depthSize = 0;
278 GLint stencilSize = 0;
279 GLint accumSize = 0;
280 GLcontext *shareCtx = NULL;
281 GLcontext *ctx = 0;
282 /*FX_GrContext_t glideContext = 0; */
283 char *errorstr;
284 GLboolean useBGR;
285 char *system = NULL;
286
287 if (MESA_VERBOSE & VERBOSE_DRIVER) {
288 fprintf(stderr, "fxmesa: fxMesaCreateContext() Start\n");
289 }
290
291 if (getenv("MESA_FX_INFO"))
292 verbose = GL_TRUE;
293
294 aux = 0;
295 i = 0;
296 while (attribList[i] != FXMESA_NONE) {
297 switch (attribList[i]) {
298 case FXMESA_DOUBLEBUFFER:
299 doubleBuffer = GL_TRUE;
300 break;
301 case FXMESA_ALPHA_SIZE:
302 i++;
303 alphaBuffer = attribList[i] > 0;
304 if (alphaBuffer)
305 aux = 1;
306 break;
307 case FXMESA_DEPTH_SIZE:
308 i++;
309 depthSize = attribList[i];
310 if (depthSize) {
311 aux = 1;
312 depthSize = 16;
313 }
314 break;
315 case FXMESA_STENCIL_SIZE:
316 i++;
317 stencilSize = attribList[i];
318 break;
319 case FXMESA_ACCUM_SIZE:
320 i++;
321 accumSize = attribList[i];
322 break;
323 /* XXX ugly hack here for sharing display lists */
324 #define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with xmesa1.c! */
325 case FXMESA_SHARE_CONTEXT:
326 i++;
327 {
328 const void *vPtr = &attribList[i];
329 GLcontext **ctx = (GLcontext **) vPtr;
330 shareCtx = *ctx;
331 }
332 break;
333 default:
334 if (MESA_VERBOSE & VERBOSE_DRIVER) {
335 fprintf(stderr, "fxmesa: fxMesaCreateContext() End (defualt)\n");
336 }
337 return NULL;
338 }
339 i++;
340 }
341
342 /* A workaround for Linux GLQuake */
343 if (depthSize && alphaBuffer)
344 alphaBuffer = 0;
345
346 if ((type = fxQueryHardware()) < 0) {
347 fprintf(stderr,
348 "fx Driver: ERROR no Voodoo1/2 Graphics or Voodoo Rush !\n");
349 return NULL;
350 }
351
352 if (type == GR_SSTTYPE_VOODOO)
353 win = 0;
354
355 grSstSelect(glbCurrentBoard);
356
357 fxMesa = (fxMesaContext) calloc(1, sizeof(struct tfxMesaContext));
358 if (!fxMesa) {
359 errorstr = "malloc";
360 goto errorhandler;
361 }
362
363 if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_VOODOO)
364 fxMesa->haveTwoTMUs =
365 (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx >
366 1);
367 else if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_SST96)
368 fxMesa->haveTwoTMUs =
369 (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx >
370 1);
371 else
372 fxMesa->haveTwoTMUs = GL_FALSE;
373
374 fxMesa->haveDoubleBuffer = doubleBuffer;
375 fxMesa->haveAlphaBuffer = alphaBuffer;
376 fxMesa->haveGlobalPaletteTexture = GL_FALSE;
377 fxMesa->haveZBuffer = depthSize ? 1 : 0;
378 fxMesa->verbose = verbose;
379 fxMesa->board = glbCurrentBoard;
380
381
382 fxMesa->glideContext = FX_grSstWinOpen((FxU32) win, res, ref,
383 #ifdef FXMESA_USE_ARGB
384 GR_COLORFORMAT_ARGB,
385 #else
386 GR_COLORFORMAT_ABGR,
387 #endif
388 GR_ORIGIN_LOWER_LEFT, 2, aux);
389 if (!fxMesa->glideContext) {
390 errorstr = "grSstWinOpen";
391 goto errorhandler;
392 }
393
394 /*
395 * Pixel tables are used during pixel read-back
396 * Either initialize them for RGB or BGR order.
397 * Also determine if we need vertex snapping.
398 */
399
400 fxMesa->snapVertices = GL_TRUE; /* play it safe */
401
402 #ifdef FXMESA_USE_ARGB
403 useBGR = GL_FALSE; /* Force RGB pixel order */
404 system = "FXMESA_USE_ARGB";
405 #else
406 if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_VOODOO) {
407 /* jk991130 - Voodoo 3s don't use BGR. Query the # of TMUs
408 * as Voodoo3s have 2 TMUs on board, Banshee has only 1
409 * bk000413 - another suggestion from Joseph Kain is using
410 * VendorID 0x121a for all 3dfx boards
411 * DeviceID VG 1/V2 2/VB 3/V3 5
412 * For now we cehck for known BGR devices, and presume
413 * everything else to be a V3/RGB.
414 */
415 GrVoodooConfig_t *voodoo;
416 voodoo = &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig;
417
418 if (voodoo->nTexelfx == 1) {
419 /* Voodoo1 or Banshee */
420 useBGR = GL_TRUE;
421 system = "Voodoo1";
422 }
423 else if (voodoo->nTexelfx == 2 &&
424 voodoo->fbiRev == 260 &&
425 voodoo->tmuConfig[0].tmuRev == 4 &&
426 (voodoo->tmuConfig[0].tmuRam == 2 ||
427 voodoo->tmuConfig[0].tmuRam == 4)) {
428 /* Voodoo 2 */
429 useBGR = GL_TRUE;
430 system = "Voodoo2";
431 fxMesa->snapVertices = GL_FALSE;
432 }
433 else if (voodoo->nTexelfx == 2 &&
434 voodoo->fbiRev == 2 &&
435 voodoo->tmuConfig[0].tmuRev == 1 &&
436 voodoo->tmuConfig[0].tmuRam == 4) {
437 /* Quantum3D Obsidian 50/100 */
438 useBGR = GL_TRUE;
439 system = "Quantum3D Obsidian";
440 }
441 else
442 /* Brian
443 * (voodoo->nTexelfx == 2 &&
444 * voodoo->fbiRev == 0 &&
445 * voodoo->tmuConfig[0].tmuRev == 148441048 &&
446 * voodoo->tmuConfig[0].tmuRam == 3)
447 * Bernd
448 * (voodoo->nTexelfx == 2 &&
449 * voodoo->fbiRev == 69634 &&
450 * voodoo->tmuConfig[0].tmuRev == 69634 &&
451 * voodoo->tmuConfig[0].tmuRam == 2 )
452 */
453 {
454 /* Presumed Voodoo3 */
455 useBGR = GL_FALSE;
456 system = "Voodoo3";
457 fxMesa->snapVertices = GL_FALSE;
458 }
459 if (verbose) {
460 fprintf(stderr,
461 "Voodoo: Texelfx: %d / FBI Rev.: %d / TMU Rev.: %d / TMU RAM: %d\n",
462 voodoo->nTexelfx, voodoo->fbiRev, voodoo->tmuConfig[0].tmuRev,
463 voodoo->tmuConfig[0].tmuRam);
464 }
465 }
466 else {
467 useBGR = GL_FALSE; /* use RGB pixel order otherwise */
468 system = "non-voodoo";
469 fxMesa->snapVertices = GL_FALSE;
470 }
471 #endif /*FXMESA_USE_ARGB */
472
473 if (verbose) {
474 fprintf(stderr, "Voodoo pixel order: %s (%s)\n",
475 useBGR ? "BGR" : "RGB", system);
476 fprintf(stderr, "Vertex snapping: %d\n", fxMesa->snapVertices);
477 }
478
479 fxInitPixelTables(fxMesa, useBGR);
480
481 fxMesa->width = FX_grSstScreenWidth();
482 fxMesa->height = FX_grSstScreenHeight();
483
484 fxMesa->clipMinX = 0;
485 fxMesa->clipMaxX = fxMesa->width;
486 fxMesa->clipMinY = 0;
487 fxMesa->clipMaxY = fxMesa->height;
488
489 fxMesa->screen_width = fxMesa->width;
490 fxMesa->screen_height = fxMesa->height;
491
492 fxMesa->new_state = ~0;
493
494 if (verbose)
495 fprintf(stderr, "Voodoo Glide screen size: %dx%d\n",
496 (int) FX_grSstScreenWidth(), (int) FX_grSstScreenHeight());
497
498 fxMesa->glVis = _mesa_create_visual(GL_TRUE, /* RGB mode */
499 doubleBuffer, GL_FALSE, /* stereo */
500 5, 6, 5, 0, /* RGBA bits */
501 0, /* index bits */
502 depthSize, /* depth_size */
503 stencilSize, /* stencil_size */
504 accumSize, accumSize, accumSize,
505 accumSize, 1);
506 if (!fxMesa->glVis) {
507 errorstr = "_mesa_create_visual";
508 goto errorhandler;
509 }
510
511 ctx = fxMesa->glCtx = _mesa_create_context(fxMesa->glVis,
512 shareCtx,
513 (void *) fxMesa, GL_TRUE);
514 if (!ctx) {
515 errorstr = "_mesa_create_context";
516 goto errorhandler;
517 }
518
519
520 if (!fxDDInitFxMesaContext(fxMesa)) {
521 errorstr = "fxDDInitFxMesaContext failed";
522 goto errorhandler;
523 }
524
525
526 fxMesa->glBuffer = _mesa_create_framebuffer(fxMesa->glVis, GL_FALSE, /* no software depth */
527 fxMesa->glVis->stencilBits > 0,
528 fxMesa->glVis->accumRedBits >
529 0,
530 fxMesa->glVis->alphaBits > 0);
531 if (!fxMesa->glBuffer) {
532 errorstr = "_mesa_create_framebuffer";
533 goto errorhandler;
534 }
535
536 glbTotNumCtx++;
537
538 /* install signal handlers */
539 #if defined(__linux__)
540 /* Only install if environment var. is not set. */
541 if (fxMesa->glCtx->CatchSignals && !getenv("MESA_FX_NO_SIGNALS")) {
542 signal(SIGINT, cleangraphics_handler);
543 signal(SIGHUP, cleangraphics_handler);
544 signal(SIGPIPE, cleangraphics_handler);
545 signal(SIGFPE, cleangraphics_handler);
546 signal(SIGBUS, cleangraphics_handler);
547 signal(SIGILL, cleangraphics_handler);
548 signal(SIGSEGV, cleangraphics_handler);
549 signal(SIGTERM, cleangraphics_handler);
550 }
551 #endif
552
553 if (MESA_VERBOSE & VERBOSE_DRIVER) {
554 fprintf(stderr, "fxmesa: fxMesaCreateContext() End\n");
555 }
556
557 return fxMesa;
558
559 errorhandler:
560 if (fxMesa) {
561 if (fxMesa->glideContext)
562 FX_grSstWinClose(fxMesa->glideContext);
563 fxMesa->glideContext = 0;
564
565 if (fxMesa->state)
566 free(fxMesa->state);
567 if (fxMesa->fogTable)
568 free(fxMesa->fogTable);
569 if (fxMesa->glBuffer)
570 _mesa_destroy_framebuffer(fxMesa->glBuffer);
571 if (fxMesa->glVis)
572 _mesa_destroy_visual(fxMesa->glVis);
573 if (fxMesa->glCtx)
574 _mesa_destroy_context(fxMesa->glCtx);
575 free(fxMesa);
576 }
577
578 if (MESA_VERBOSE & VERBOSE_DRIVER) {
579 fprintf(stderr, "fxmesa: fxMesaCreateContext() End (%s)\n", errorstr);
580 }
581 return NULL;
582 }
583
584
585 /*
586 * Function to set the new window size in the context (mainly for the Voodoo Rush)
587 */
588 void GLAPIENTRY
589 fxMesaUpdateScreenSize(fxMesaContext fxMesa)
590 {
591 fxMesa->width = FX_grSstScreenWidth();
592 fxMesa->height = FX_grSstScreenHeight();
593 }
594
595
596 /*
597 * Destroy the given FX/Mesa context.
598 */
599 void GLAPIENTRY
600 fxMesaDestroyContext(fxMesaContext fxMesa)
601 {
602 if (MESA_VERBOSE & VERBOSE_DRIVER) {
603 fprintf(stderr, "fxmesa: fxMesaDestroyContext()\n");
604 }
605
606 if (!fxMesa)
607 return;
608
609 if (fxMesa->verbose) {
610 fprintf(stderr, "Misc Stats:\n");
611 fprintf(stderr, " # swap buffer: %u\n", fxMesa->stats.swapBuffer);
612
613 if (!fxMesa->stats.swapBuffer)
614 fxMesa->stats.swapBuffer = 1;
615
616 fprintf(stderr, "Textures Stats:\n");
617 fprintf(stderr, " Free texture memory on TMU0: %d:\n",
618 fxMesa->freeTexMem[FX_TMU0]);
619 if (fxMesa->haveTwoTMUs)
620 fprintf(stderr, " Free texture memory on TMU1: %d:\n",
621 fxMesa->freeTexMem[FX_TMU1]);
622 fprintf(stderr, " # request to TMM to upload a texture objects: %u\n",
623 fxMesa->stats.reqTexUpload);
624 fprintf(stderr,
625 " # request to TMM to upload a texture objects per swapbuffer: %.2f\n",
626 fxMesa->stats.reqTexUpload / (float) fxMesa->stats.swapBuffer);
627 fprintf(stderr, " # texture objects uploaded: %u\n",
628 fxMesa->stats.texUpload);
629 fprintf(stderr, " # texture objects uploaded per swapbuffer: %.2f\n",
630 fxMesa->stats.texUpload / (float) fxMesa->stats.swapBuffer);
631 fprintf(stderr, " # MBs uploaded to texture memory: %.2f\n",
632 fxMesa->stats.memTexUpload / (float) (1 << 20));
633 fprintf(stderr,
634 " # MBs uploaded to texture memory per swapbuffer: %.2f\n",
635 (fxMesa->stats.memTexUpload /
636 (float) fxMesa->stats.swapBuffer) / (float) (1 << 20));
637 }
638
639 glbTotNumCtx--;
640
641 fxDDDestroyFxMesaContext(fxMesa);
642 _mesa_destroy_visual(fxMesa->glVis);
643 _mesa_destroy_context(fxMesa->glCtx);
644 _mesa_destroy_framebuffer(fxMesa->glBuffer);
645
646 fxCloseHardware();
647 FX_grSstWinClose(fxMesa->glideContext);
648
649 free(fxMesa);
650
651 if (fxMesa == fxMesaCurrentCtx)
652 fxMesaCurrentCtx = NULL;
653 }
654
655
656 /*
657 * Make the specified FX/Mesa context the current one.
658 */
659 void GLAPIENTRY
660 fxMesaMakeCurrent(fxMesaContext fxMesa)
661 {
662 if (MESA_VERBOSE & VERBOSE_DRIVER) {
663 fprintf(stderr, "fxmesa: fxMesaMakeCurrent(...) Start\n");
664 }
665
666 if (!fxMesa) {
667 _mesa_make_current(NULL, NULL);
668 fxMesaCurrentCtx = NULL;
669
670 if (MESA_VERBOSE & VERBOSE_DRIVER) {
671 fprintf(stderr, "fxmesa: fxMesaMakeCurrent(NULL) End\n");
672 }
673
674 return;
675 }
676
677 /* if this context is already the current one, we can return early */
678 if (fxMesaCurrentCtx == fxMesa
679 && fxMesaCurrentCtx->glCtx == _mesa_get_current_context()) {
680 if (MESA_VERBOSE & VERBOSE_DRIVER) {
681 fprintf(stderr,
682 "fxmesa: fxMesaMakeCurrent(fxMesaCurrentCtx==fxMesa) End\n");
683 }
684
685 return;
686 }
687
688 if (fxMesaCurrentCtx)
689 grGlideGetState((GrState *) fxMesaCurrentCtx->state);
690
691 fxMesaCurrentCtx = fxMesa;
692
693 grSstSelect(fxMesa->board);
694 grGlideSetState((GrState *) fxMesa->state);
695
696 _mesa_make_current(fxMesa->glCtx, fxMesa->glBuffer);
697
698 fxSetupDDPointers(fxMesa->glCtx);
699
700 /* The first time we call MakeCurrent we set the initial viewport size */
701 if (fxMesa->glCtx->Viewport.Width == 0)
702 _mesa_set_viewport(fxMesa->glCtx, 0, 0, fxMesa->width, fxMesa->height);
703
704 if (MESA_VERBOSE & VERBOSE_DRIVER) {
705 fprintf(stderr, "fxmesa: fxMesaMakeCurrent(...) End\n");
706 }
707 }
708
709
710 #if 0
711 static void
712 QueryCounters(void)
713 {
714 static GLuint prevPassed = 0;
715 static GLuint prevFailed = 0;
716 GLuint failed, passed;
717 GrSstPerfStats_t st;
718
719 FX_grSstPerfStats(&st);
720 failed = st.zFuncFail - st.aFuncFail - st.chromaFail;
721 passed = st.pixelsIn - failed;
722 printf("failed: %d passed: %d\n", failed - prevFailed,
723 passed - prevPassed);
724
725 prevPassed = passed;
726 prevFailed = failed;
727 }
728 #endif
729
730
731 /*
732 * Swap front/back buffers for current context if double buffered.
733 */
734 void GLAPIENTRY
735 fxMesaSwapBuffers(void)
736 {
737 if (MESA_VERBOSE & VERBOSE_DRIVER) {
738 fprintf(stderr,
739 "fxmesa: ------------------------------- fxMesaSwapBuffers() -------------------------------\n");
740 }
741
742 if (fxMesaCurrentCtx) {
743 _mesa_notifySwapBuffers(fxMesaCurrentCtx->glCtx);
744
745 if (fxMesaCurrentCtx->haveDoubleBuffer) {
746
747 grBufferSwap(fxMesaCurrentCtx->swapInterval);
748
749 /*
750 * Don't allow swap buffer commands to build up!
751 */
752 while (FX_grGetInteger(FX_PENDING_BUFFERSWAPS) >
753 fxMesaCurrentCtx->maxPendingSwapBuffers)
754 /* The driver is able to sleep when waiting for the completation
755 of multiple swapbuffer operations instead of wasting
756 CPU time (NOTE: you must uncomment the following line in the
757 in order to enable this option) */
758 /* usleep(10000); */
759 ;
760
761 fxMesaCurrentCtx->stats.swapBuffer++;
762 }
763 }
764 }
765
766
767 /*
768 * Query 3Dfx hardware presence/kind
769 */
770 int GLAPIENTRY
771 fxQueryHardware(void)
772 {
773 if (MESA_VERBOSE & VERBOSE_DRIVER) {
774 fprintf(stderr, "fxmesa: fxQueryHardware() Start\n");
775 }
776
777 if (!glbGlideInitialized) {
778 grGlideInit();
779 if (FX_grSstQueryHardware(&glbHWConfig)) {
780 grSstSelect(glbCurrentBoard);
781 glb3DfxPresent = 1;
782
783 if (getenv("MESA_FX_INFO")) {
784 char buf[80];
785
786 FX_grGlideGetVersion(buf);
787 fprintf(stderr, "Voodoo Using Glide V%s\n", buf);
788 fprintf(stderr, "Voodoo Number of boards: %d\n",
789 glbHWConfig.num_sst);
790
791 if (glbHWConfig.SSTs[glbCurrentBoard].type == GR_SSTTYPE_VOODOO) {
792 GrVoodooConfig_t *voodoo;
793 voodoo =
794 &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig;
795
796 fprintf(stderr, "Voodoo Framebuffer RAM: %d\n",
797 voodoo->sliDetect ? (voodoo->fbRam *
798 2) : voodoo->fbRam);
799 fprintf(stderr, "Voodoo Number of TMUs: %d\n",
800 voodoo->nTexelfx);
801 fprintf(stderr, "Voodoo fbRam: %d\n", voodoo->fbRam);
802 fprintf(stderr, "Voodoo fbiRev: %d\n", voodoo->fbiRev);
803
804 fprintf(stderr, "Voodoo SLI detected: %d\n",
805 voodoo->sliDetect);
806 }
807 else if (glbHWConfig.SSTs[glbCurrentBoard].type ==
808 GR_SSTTYPE_SST96) {
809 GrSst96Config_t *sst96;
810 sst96 =
811 &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config;
812 fprintf(stderr, "Voodoo Framebuffer RAM: %d\n", sst96->fbRam);
813 fprintf(stderr, "Voodoo Number of TMUs: %d\n",
814 sst96->nTexelfx);
815 }
816
817 }
818 }
819 else {
820 glb3DfxPresent = 0;
821 }
822
823 glbGlideInitialized = 1;
824
825 #if defined(__WIN32__)
826 onexit((_onexit_t) cleangraphics);
827 #elif defined(__linux__)
828 /* Only register handler if environment variable is not defined. */
829 if (!getenv("MESA_FX_NO_SIGNALS")) {
830 atexit(cleangraphics);
831 }
832 #endif
833 }
834
835 if (MESA_VERBOSE & VERBOSE_DRIVER) {
836 fprintf(stderr, "fxmesa: fxQueryHardware() End (voodooo)\n");
837 }
838
839 return glbHWConfig.SSTs[glbCurrentBoard].type;
840 }
841
842
843 /*
844 * Shutdown Glide library
845 */
846 void GLAPIENTRY
847 fxCloseHardware(void)
848 {
849 if (glbGlideInitialized) {
850 if (getenv("MESA_FX_INFO")) {
851 GrSstPerfStats_t st;
852
853 FX_grSstPerfStats(&st);
854 fprintf(stderr, "Pixels Stats:\n");
855 fprintf(stderr, " # pixels processed (minus buffer clears): %u\n",
856 (unsigned) st.pixelsIn);
857 fprintf(stderr,
858 " # pixels not drawn due to chroma key test failure: %u\n",
859 (unsigned) st.chromaFail);
860 fprintf(stderr,
861 " # pixels not drawn due to depth test failure: %u\n",
862 (unsigned) st.zFuncFail);
863 fprintf(stderr,
864 " # pixels not drawn due to alpha test failure: %u\n",
865 (unsigned) st.aFuncFail);
866 fprintf(stderr,
867 " # pixels drawn (including buffer clears and LFB writes): %u\n",
868 (unsigned) st.pixelsOut);
869 }
870
871 if (glbTotNumCtx == 0) {
872 grGlideShutdown();
873 glbGlideInitialized = 0;
874 }
875 }
876 }
877
878
879 #else
880
881
882 /*
883 * Need this to provide at least one external definition.
884 */
885 extern int gl_fx_dummy_function_api(void);
886 int
887 gl_fx_dummy_function_api(void)
888 {
889 return 0;
890 }
891
892 #endif /* FX */