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