Changed escaping of double quotes.
[mesa.git] / src / mesa / drivers / glide / fxapi.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 4.0
4 *
5 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /* Authors:
26 * David Bucciarelli
27 * Brian Paul
28 * Daryll Strauss
29 * Keith Whitwell
30 * Daniel Borca
31 * Hiroshi Morii
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 #include "drivers/common/driverfuncs.h"
46
47 #ifndef TDFX_DEBUG
48 int TDFX_DEBUG = (0
49 /* | VERBOSE_VARRAY */
50 /* | VERBOSE_TEXTURE */
51 /* | VERBOSE_IMMEDIATE */
52 /* | VERBOSE_PIPELINE */
53 /* | VERBOSE_DRIVER */
54 /* | VERBOSE_STATE */
55 /* | VERBOSE_API */
56 /* | VERBOSE_DISPLAY_LIST */
57 /* | VERBOSE_LIGHTING */
58 /* | VERBOSE_PRIMS */
59 /* | VERBOSE_VERTS */
60 );
61 #endif
62
63 static fxMesaContext fxMesaCurrentCtx = NULL;
64
65 /*
66 * Status of 3Dfx hardware initialization
67 */
68
69 static int glbGlideInitialized = 0;
70 static int glb3DfxPresent = 0;
71 static int glbTotNumCtx = 0;
72
73 static GrHwConfiguration glbHWConfig;
74 static int glbCurrentBoard = 0;
75
76
77 #if defined(__WIN32__)
78 static int
79 cleangraphics(void)
80 {
81 glbTotNumCtx = 1;
82 fxMesaDestroyContext(fxMesaCurrentCtx);
83
84 return 0;
85 }
86 #elif defined(__linux__)
87 static void
88 cleangraphics(void)
89 {
90 glbTotNumCtx = 1;
91 fxMesaDestroyContext(fxMesaCurrentCtx);
92 }
93
94 static void
95 cleangraphics_handler(int s)
96 {
97 fprintf(stderr, "fxmesa: ERROR: received a not handled signal %d\n", s);
98
99 cleangraphics();
100 /* abort(); */
101 exit(1);
102 }
103 #endif
104
105
106 /*
107 * Query 3Dfx hardware presence/kind
108 */
109 static GLboolean GLAPIENTRY fxQueryHardware (void)
110 {
111 if (TDFX_DEBUG & VERBOSE_DRIVER) {
112 fprintf(stderr, "fxQueryHardware()\n");
113 }
114
115 if (!glbGlideInitialized) {
116 grGlideInit();
117 glb3DfxPresent = FX_grSstQueryHardware(&glbHWConfig);
118
119 glbGlideInitialized = 1;
120
121 #if defined(__WIN32__)
122 _onexit((_onexit_t) cleangraphics);
123 #elif defined(__linux__)
124 /* Only register handler if environment variable is not defined. */
125 if (!getenv("MESA_FX_NO_SIGNALS")) {
126 atexit(cleangraphics);
127 }
128 #endif
129 }
130
131 return glb3DfxPresent;
132 }
133
134
135 /*
136 * Select the Voodoo board to use when creating
137 * a new context.
138 */
139 GLint GLAPIENTRY fxMesaSelectCurrentBoard (int n)
140 {
141 fxQueryHardware();
142
143 if ((n < 0) || (n >= glbHWConfig.num_sst))
144 return -1;
145
146 return glbHWConfig.SSTs[glbCurrentBoard = n].type;
147 }
148
149
150 fxMesaContext GLAPIENTRY fxMesaGetCurrentContext (void)
151 {
152 return fxMesaCurrentCtx;
153 }
154
155
156 void GLAPIENTRY fxGetScreenGeometry (GLint *w, GLint *h)
157 {
158 GLint width = 0;
159 GLint height = 0;
160
161 if (fxMesaCurrentCtx != NULL) {
162 width = fxMesaCurrentCtx->screen_width;
163 height = fxMesaCurrentCtx->screen_height;
164 }
165
166 if (w != NULL) {
167 *w = width;
168 }
169 if (h != NULL) {
170 *h = height;
171 }
172 }
173
174
175 /*
176 * The 3Dfx Global Palette extension for GLQuake.
177 * More a trick than a real extesion, use the shared global
178 * palette extension.
179 */
180 extern void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint * pal); /* silence warning */
181 void GLAPIENTRY
182 gl3DfxSetPaletteEXT(GLuint * pal)
183 {
184 fxMesaContext fxMesa = fxMesaCurrentCtx;
185
186 if (TDFX_DEBUG & VERBOSE_DRIVER) {
187 int i;
188
189 fprintf(stderr, "gl3DfxSetPaletteEXT(...)\n");
190
191 for (i = 0; i < 256; i++) {
192 fprintf(stderr, "\t%x\n", pal[i]);
193 }
194 }
195
196 if (fxMesa) {
197 fxMesa->haveGlobalPaletteTexture = 1;
198
199 grTexDownloadTable(GR_TEXTABLE_PALETTE, (GuTexPalette *) pal);
200 }
201 }
202
203
204 static GrScreenResolution_t fxBestResolution (int width, int height)
205 {
206 static int resolutions[][3] = {
207 { GR_RESOLUTION_320x200, 320, 200 },
208 { GR_RESOLUTION_320x240, 320, 240 },
209 { GR_RESOLUTION_400x256, 400, 256 },
210 { GR_RESOLUTION_512x384, 512, 384 },
211 { GR_RESOLUTION_640x200, 640, 200 },
212 { GR_RESOLUTION_640x350, 640, 350 },
213 { GR_RESOLUTION_640x400, 640, 400 },
214 { GR_RESOLUTION_640x480, 640, 480 },
215 { GR_RESOLUTION_800x600, 800, 600 },
216 { GR_RESOLUTION_960x720, 960, 720 },
217 { GR_RESOLUTION_856x480, 856, 480 },
218 { GR_RESOLUTION_512x256, 512, 256 },
219 { GR_RESOLUTION_1024x768, 1024, 768 },
220 { GR_RESOLUTION_1280x1024, 1280, 1024 },
221 { GR_RESOLUTION_1600x1200, 1600, 1200 },
222 { GR_RESOLUTION_400x300, 400, 300 },
223 { GR_RESOLUTION_1152x864, 1152, 864 },
224 { GR_RESOLUTION_1280x960, 1280, 960 },
225 { GR_RESOLUTION_1600x1024, 1600, 1024 },
226 { GR_RESOLUTION_1792x1344, 1792, 1344 },
227 { GR_RESOLUTION_1856x1392, 1856, 1392 },
228 { GR_RESOLUTION_1920x1440, 1920, 1440 },
229 { GR_RESOLUTION_2048x1536, 2048, 1536 },
230 { GR_RESOLUTION_2048x2048, 2048, 2048 }
231 };
232
233 int i, size;
234 int lastvalidres = GR_RESOLUTION_640x480;
235 int min = 2048 * 2048; /* max is GR_RESOLUTION_2048x2048 */
236 GrResolution resTemplate = {
237 GR_QUERY_ANY,
238 GR_QUERY_ANY,
239 2 /*GR_QUERY_ANY */,
240 GR_QUERY_ANY
241 };
242 GrResolution *presSupported;
243
244 fxQueryHardware();
245
246 size = grQueryResolutions(&resTemplate, NULL);
247 presSupported = malloc(size);
248
249 size /= sizeof(GrResolution);
250 grQueryResolutions(&resTemplate, presSupported);
251
252 for (i = 0; i < size; i++) {
253 int r = presSupported[i].resolution;
254 if ((width <= resolutions[r][1]) && (height <= resolutions[r][2])) {
255 if (min > (resolutions[r][1] * resolutions[r][2])) {
256 min = resolutions[r][1] * resolutions[r][2];
257 lastvalidres = r;
258 }
259 }
260 }
261
262 free(presSupported);
263
264 return resolutions[lastvalidres][0];
265 }
266
267
268 fxMesaContext GLAPIENTRY
269 fxMesaCreateBestContext(GLuint win, GLint width, GLint height,
270 const GLint attribList[])
271 {
272 int res = fxBestResolution(width, height);
273
274 if (res == -1) {
275 return NULL;
276 }
277
278 return fxMesaCreateContext(win, res, GR_REFRESH_60Hz, attribList);
279 }
280
281
282 /*
283 * Create a new FX/Mesa context and return a handle to it.
284 */
285 fxMesaContext GLAPIENTRY
286 fxMesaCreateContext(GLuint win,
287 GrScreenResolution_t res,
288 GrScreenRefresh_t ref, const GLint attribList[])
289 {
290 fxMesaContext fxMesa = NULL;
291 GLcontext *ctx = NULL, *shareCtx = NULL;
292 struct dd_function_table functions;
293
294 int i;
295 const char *str;
296 int sliaa, numSLI, samplesPerChip;
297 struct SstCard_St *voodoo;
298 struct tdfx_glide *Glide;
299
300 GLboolean aux;
301 GLboolean doubleBuffer;
302 GLuint colDepth;
303 GLuint depthSize, alphaSize, stencilSize, accumSize;
304 GLuint redBits, greenBits, blueBits, alphaBits;
305 GrPixelFormat_t pixFmt;
306
307 if (TDFX_DEBUG & VERBOSE_DRIVER) {
308 fprintf(stderr, "fxMesaCreateContext(...)\n");
309 }
310
311 /* Okay, first process the user flags */
312 aux = GL_FALSE;
313 doubleBuffer = GL_FALSE;
314 colDepth = 16;
315 depthSize = alphaSize = stencilSize = accumSize = 0;
316
317 i = 0;
318 while (attribList[i] != FXMESA_NONE) {
319 switch (attribList[i]) {
320 case FXMESA_COLORDEPTH:
321 colDepth = attribList[++i];
322 break;
323 case FXMESA_DOUBLEBUFFER:
324 doubleBuffer = GL_TRUE;
325 break;
326 case FXMESA_ALPHA_SIZE:
327 if ((alphaSize = attribList[++i])) {
328 aux = GL_TRUE;
329 }
330 break;
331 case FXMESA_DEPTH_SIZE:
332 if ((depthSize = attribList[++i])) {
333 aux = GL_TRUE;
334 }
335 break;
336 case FXMESA_STENCIL_SIZE:
337 stencilSize = attribList[++i];
338 break;
339 case FXMESA_ACCUM_SIZE:
340 accumSize = attribList[++i];
341 break;
342 /* XXX ugly hack here for sharing display lists */
343 case FXMESA_SHARE_CONTEXT:
344 shareCtx = (GLcontext *)attribList[++i];
345 break;
346 default:
347 fprintf(stderr, "fxMesaCreateContext: ERROR: wrong parameter (%d) passed\n", attribList[i]);
348 return NULL;
349 }
350 i++;
351 }
352
353 if (!fxQueryHardware()) {
354 str = "no Voodoo hardware!";
355 goto errorhandler;
356 }
357
358 grSstSelect(glbCurrentBoard);
359 /*grEnable(GR_OPENGL_MODE_EXT);*/ /* [koolsmoky] */
360 voodoo = &glbHWConfig.SSTs[glbCurrentBoard];
361
362 fxMesa = (fxMesaContext)CALLOC_STRUCT(tfxMesaContext);
363 if (!fxMesa) {
364 str = "private context";
365 goto errorhandler;
366 }
367
368 if (getenv("MESA_FX_INFO")) {
369 fxMesa->verbose = GL_TRUE;
370 }
371
372 fxMesa->type = voodoo->type;
373 fxMesa->HavePalExt = voodoo->HavePalExt && !getenv("MESA_FX_IGNORE_PALEXT");
374 fxMesa->HavePixExt = voodoo->HavePixExt && !getenv("MESA_FX_IGNORE_PIXEXT");
375 fxMesa->HaveTexFmt = voodoo->HaveTexFmt && !getenv("MESA_FX_IGNORE_TEXFMT");
376 fxMesa->HaveCmbExt = voodoo->HaveCmbExt && !getenv("MESA_FX_IGNORE_CMBEXT");
377 fxMesa->HaveMirExt = voodoo->HaveMirExt && !getenv("MESA_FX_IGNORE_MIREXT");
378 fxMesa->HaveTexUma = voodoo->HaveTexUma && !getenv("MESA_FX_IGNORE_TEXUMA");
379 fxMesa->Glide = glbHWConfig.Glide;
380 Glide = &fxMesa->Glide;
381 fxMesa->HaveTexus2 = Glide->txImgQuantize &&
382 Glide->txMipQuantize &&
383 Glide->txPalToNcc && !getenv("MESA_FX_IGNORE_TEXUS2");
384
385 /* Determine if we need vertex swapping, RGB order and SLI/AA */
386 sliaa = 0;
387 switch (fxMesa->type) {
388 case GR_SSTTYPE_VOODOO:
389 case GR_SSTTYPE_SST96:
390 case GR_SSTTYPE_Banshee:
391 fxMesa->bgrOrder = GL_TRUE;
392 fxMesa->snapVertices = (getenv("MESA_FX_NOSNAP") == NULL);
393 break;
394 case GR_SSTTYPE_Voodoo2:
395 fxMesa->bgrOrder = GL_TRUE;
396 fxMesa->snapVertices = GL_FALSE;
397 break;
398 case GR_SSTTYPE_Voodoo4:
399 case GR_SSTTYPE_Voodoo5:
400 /* number of SLI units and AA Samples per chip */
401 if ((str = Glide->grGetRegistryOrEnvironmentStringExt("SSTH3_SLI_AA_CONFIGURATION")) != NULL) {
402 sliaa = atoi(str);
403 }
404 case GR_SSTTYPE_Voodoo3:
405 default:
406 fxMesa->bgrOrder = GL_FALSE;
407 fxMesa->snapVertices = GL_FALSE;
408 break;
409 }
410 /* XXX todo - Add the old SLI/AA settings for Napalm. */
411 switch(voodoo->numChips) {
412 case 4: /* 4 chips */
413 switch(sliaa) {
414 case 8: /* 8 Sample AA */
415 numSLI = 1;
416 samplesPerChip = 2;
417 break;
418 case 7: /* 4 Sample AA */
419 numSLI = 1;
420 samplesPerChip = 1;
421 break;
422 case 6: /* 2 Sample AA */
423 numSLI = 2;
424 samplesPerChip = 1;
425 break;
426 default:
427 numSLI = 4;
428 samplesPerChip = 1;
429 }
430 break;
431 case 2: /* 2 chips */
432 switch(sliaa) {
433 case 4: /* 4 Sample AA */
434 numSLI = 1;
435 samplesPerChip = 2;
436 break;
437 case 3: /* 2 Sample AA */
438 numSLI = 1;
439 samplesPerChip = 1;
440 break;
441 default:
442 numSLI = 2;
443 samplesPerChip = 1;
444 }
445 break;
446 default: /* 1 chip */
447 switch(sliaa) {
448 case 1: /* 2 Sample AA */
449 numSLI = 1;
450 samplesPerChip = 2;
451 break;
452 default:
453 numSLI = 1;
454 samplesPerChip = 1;
455 }
456 }
457
458 fxMesa->fsaa = samplesPerChip * voodoo->numChips / numSLI; /* 1:noFSAA, 2:2xFSAA, 4:4xFSAA, 8:8xFSAA */
459
460 switch (fxMesa->colDepth = colDepth) {
461 case 15:
462 redBits = 5;
463 greenBits = 5;
464 blueBits = 5;
465 alphaBits = depthSize ? 1 : 8;
466 switch(fxMesa->fsaa) {
467 case 8:
468 pixFmt = GR_PIXFMT_AA_8_ARGB_1555;
469 break;
470 case 4:
471 pixFmt = GR_PIXFMT_AA_4_ARGB_1555;
472 break;
473 case 2:
474 pixFmt = GR_PIXFMT_AA_2_ARGB_1555;
475 break;
476 default:
477 pixFmt = GR_PIXFMT_ARGB_1555;
478 }
479 break;
480 case 16:
481 redBits = 5;
482 greenBits = 6;
483 blueBits = 5;
484 alphaBits = depthSize ? 0 : 8;
485 switch(fxMesa->fsaa) {
486 case 8:
487 pixFmt = GR_PIXFMT_AA_8_RGB_565;
488 break;
489 case 4:
490 pixFmt = GR_PIXFMT_AA_4_RGB_565;
491 break;
492 case 2:
493 pixFmt = GR_PIXFMT_AA_2_RGB_565;
494 break;
495 default:
496 pixFmt = GR_PIXFMT_RGB_565;
497 }
498 break;
499 case 24:
500 fxMesa->colDepth = 32;
501 case 32:
502 redBits = 8;
503 greenBits = 8;
504 blueBits = 8;
505 alphaBits = 8;
506 switch(fxMesa->fsaa) {
507 case 8:
508 pixFmt = GR_PIXFMT_AA_8_ARGB_8888;
509 break;
510 case 4:
511 pixFmt = GR_PIXFMT_AA_4_ARGB_8888;
512 break;
513 case 2:
514 pixFmt = GR_PIXFMT_AA_2_ARGB_8888;
515 break;
516 default:
517 pixFmt = GR_PIXFMT_ARGB_8888;
518 }
519 break;
520 default:
521 str = "pixelFormat";
522 goto errorhandler;
523 }
524
525 /* Tips:
526 * 1. we don't bother setting/checking AUX for stencil, because we'll decide
527 * later whether we have HW stencil, based on depth buffer (thus AUX is
528 * properly set)
529 * 2. when both DEPTH and ALPHA are enabled, depth should win. However, it is
530 * not clear whether 15bpp and 32bpp require AUX alpha buffer. Furthermore,
531 * alpha buffering is required only if destination alpha is used in alpha
532 * blending; alpha blending modes that do not use destination alpha can be
533 * used w/o alpha buffer.
534 * 3. `alphaBits' is what we can provide
535 * `alphaSize' is what app requests
536 * if we cannot provide enough bits for alpha buffer, we should fallback to
537 * SW alpha. However, setting `alphaBits' to `alphaSize' might confuse some
538 * of the span functions...
539 */
540
541 fxMesa->haveHwAlpha = GL_FALSE;
542 if (alphaSize && (alphaSize <= alphaBits)) {
543 alphaSize = alphaBits;
544 fxMesa->haveHwAlpha = GL_TRUE;
545 }
546
547 fxMesa->haveHwStencil = (fxMesa->HavePixExt && stencilSize && depthSize == 24);
548
549 fxMesa->haveZBuffer = depthSize > 0;
550 fxMesa->haveDoubleBuffer = doubleBuffer;
551 fxMesa->haveGlobalPaletteTexture = GL_FALSE;
552 fxMesa->board = glbCurrentBoard;
553
554 fxMesa->haveTwoTMUs = (voodoo->nTexelfx > 1);
555
556 if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_NUM_TMU"))) {
557 if (atoi(str) <= 1) {
558 fxMesa->haveTwoTMUs = GL_FALSE;
559 }
560 }
561
562 if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_SWAPPENDINGCOUNT"))) {
563 fxMesa->maxPendingSwapBuffers = atoi(str);
564 if (fxMesa->maxPendingSwapBuffers > 6) {
565 fxMesa->maxPendingSwapBuffers = 6;
566 } else if (fxMesa->maxPendingSwapBuffers < 0) {
567 fxMesa->maxPendingSwapBuffers = 0;
568 }
569 } else {
570 fxMesa->maxPendingSwapBuffers = 2;
571 }
572
573 if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_SWAPINTERVAL"))) {
574 fxMesa->swapInterval = atoi(str);
575 } else {
576 fxMesa->swapInterval = 0;
577 }
578
579 BEGIN_BOARD_LOCK();
580 if (fxMesa->HavePixExt) {
581 fxMesa->glideContext = Glide->grSstWinOpenExt((FxU32)win, res, ref,
582 GR_COLORFORMAT_ABGR, GR_ORIGIN_LOWER_LEFT,
583 pixFmt,
584 2, aux);
585 } else if (pixFmt == GR_PIXFMT_RGB_565) {
586 fxMesa->glideContext = grSstWinOpen((FxU32)win, res, ref,
587 GR_COLORFORMAT_ABGR, GR_ORIGIN_LOWER_LEFT,
588 2, aux);
589 } else {
590 fxMesa->glideContext = 0;
591 }
592 END_BOARD_LOCK();
593 if (!fxMesa->glideContext) {
594 str = "grSstWinOpen";
595 goto errorhandler;
596 }
597
598 /* screen */
599 fxMesa->screen_width = FX_grSstScreenWidth();
600 fxMesa->screen_height = FX_grSstScreenHeight();
601
602 /* window inside screen */
603 fxMesa->width = fxMesa->screen_width;
604 fxMesa->height = fxMesa->screen_height;
605
606 /* scissor inside window */
607 fxMesa->clipMinX = 0;
608 fxMesa->clipMaxX = fxMesa->width;
609 fxMesa->clipMinY = 0;
610 fxMesa->clipMaxY = fxMesa->height;
611
612 if (fxMesa->verbose) {
613 FxI32 tmuRam, fbRam;
614
615 /* Not that it matters, but tmuRam and fbRam change after grSstWinOpen. */
616 tmuRam = voodoo->tmuConfig[GR_TMU0].tmuRam;
617 fbRam = voodoo->fbRam;
618 BEGIN_BOARD_LOCK();
619 grGet(GR_MEMORY_TMU, 4, &tmuRam);
620 grGet(GR_MEMORY_FB, 4, &fbRam);
621 END_BOARD_LOCK();
622
623 fprintf(stderr, "Voodoo Using Glide %s\n", grGetString(GR_VERSION));
624 fprintf(stderr, "Voodoo Board: %d/%d, %s, %d GPU\n",
625 fxMesa->board + 1,
626 glbHWConfig.num_sst,
627 grGetString(GR_HARDWARE),
628 voodoo->numChips);
629 fprintf(stderr, "Voodoo Memory: FB = %ld, TM = %d x %ld\n",
630 fbRam,
631 voodoo->nTexelfx,
632 tmuRam);
633 fprintf(stderr, "Voodoo Screen: %dx%d:%d %s, %svertex snapping\n",
634 fxMesa->screen_width,
635 fxMesa->screen_height,
636 colDepth,
637 fxMesa->bgrOrder ? "BGR" : "RGB",
638 fxMesa->snapVertices ? "" : "no ");
639 }
640
641 sprintf(fxMesa->rendererString, "Mesa %s v0.63 %s%s",
642 grGetString(GR_RENDERER),
643 grGetString(GR_HARDWARE),
644 ((fxMesa->type < GR_SSTTYPE_Voodoo4) && (voodoo->numChips > 1)) ? " SLI" : "");
645
646 fxMesa->glVis = _mesa_create_visual(GL_TRUE, /* RGB mode */
647 doubleBuffer,
648 GL_FALSE, /* stereo */
649 redBits, /* RGBA.R bits */
650 greenBits, /* RGBA.G bits */
651 blueBits, /* RGBA.B bits */
652 alphaSize, /* RGBA.A bits */
653 0, /* index bits */
654 depthSize, /* depth_size */
655 stencilSize, /* stencil_size */
656 accumSize,
657 accumSize,
658 accumSize,
659 alphaSize ? accumSize : 0,
660 1);
661 if (!fxMesa->glVis) {
662 str = "_mesa_create_visual";
663 goto errorhandler;
664 }
665
666 _mesa_init_driver_functions(&functions);
667 ctx = fxMesa->glCtx = _mesa_create_context(fxMesa->glVis, shareCtx,
668 &functions, (void *) fxMesa);
669 if (!ctx) {
670 str = "_mesa_create_context";
671 goto errorhandler;
672 }
673
674
675 if (!fxDDInitFxMesaContext(fxMesa)) {
676 str = "fxDDInitFxMesaContext";
677 goto errorhandler;
678 }
679
680
681 fxMesa->glBuffer = _mesa_create_framebuffer(fxMesa->glVis,
682 GL_FALSE, /* no software depth */
683 stencilSize && !fxMesa->haveHwStencil,
684 fxMesa->glVis->accumRedBits > 0,
685 alphaSize && !fxMesa->haveHwAlpha);
686 if (!fxMesa->glBuffer) {
687 str = "_mesa_create_framebuffer";
688 goto errorhandler;
689 }
690
691 glbTotNumCtx++;
692
693 /* install signal handlers */
694 #if defined(__linux__)
695 /* Only install if environment var. is not set. */
696 if (!getenv("MESA_FX_NO_SIGNALS")) {
697 signal(SIGINT, cleangraphics_handler);
698 signal(SIGHUP, cleangraphics_handler);
699 signal(SIGPIPE, cleangraphics_handler);
700 signal(SIGFPE, cleangraphics_handler);
701 signal(SIGBUS, cleangraphics_handler);
702 signal(SIGILL, cleangraphics_handler);
703 signal(SIGSEGV, cleangraphics_handler);
704 signal(SIGTERM, cleangraphics_handler);
705 }
706 #endif
707
708 return fxMesa;
709
710 errorhandler:
711 if (fxMesa) {
712 if (fxMesa->glideContext) {
713 grSstWinClose(fxMesa->glideContext);
714 fxMesa->glideContext = 0;
715 }
716
717 if (fxMesa->state) {
718 FREE(fxMesa->state);
719 }
720 if (fxMesa->fogTable) {
721 FREE(fxMesa->fogTable);
722 }
723 if (fxMesa->glBuffer) {
724 _mesa_destroy_framebuffer(fxMesa->glBuffer);
725 }
726 if (fxMesa->glVis) {
727 _mesa_destroy_visual(fxMesa->glVis);
728 }
729 if (fxMesa->glCtx) {
730 _mesa_destroy_context(fxMesa->glCtx);
731 }
732 FREE(fxMesa);
733 }
734
735 fprintf(stderr, "fxMesaCreateContext: ERROR: %s\n", str);
736 return NULL;
737 }
738
739
740 /*
741 * Function to set the new window size in the context (mainly for the Voodoo Rush)
742 */
743 void GLAPIENTRY
744 fxMesaUpdateScreenSize(fxMesaContext fxMesa)
745 {
746 fxMesa->width = FX_grSstScreenWidth();
747 fxMesa->height = FX_grSstScreenHeight();
748 }
749
750
751 /*
752 * Destroy the given FX/Mesa context.
753 */
754 void GLAPIENTRY
755 fxMesaDestroyContext(fxMesaContext fxMesa)
756 {
757 if (TDFX_DEBUG & VERBOSE_DRIVER) {
758 fprintf(stderr, "fxMesaDestroyContext(...)\n");
759 }
760
761 if (!fxMesa)
762 return;
763
764 if (fxMesa->verbose) {
765 fprintf(stderr, "Misc Stats:\n");
766 fprintf(stderr, " # swap buffer: %u\n", fxMesa->stats.swapBuffer);
767
768 if (!fxMesa->stats.swapBuffer)
769 fxMesa->stats.swapBuffer = 1;
770
771 fprintf(stderr, "Textures Stats:\n");
772 fprintf(stderr, " Free texture memory on TMU0: %d\n",
773 fxMesa->freeTexMem[FX_TMU0]);
774 if (fxMesa->haveTwoTMUs)
775 fprintf(stderr, " Free texture memory on TMU1: %d\n",
776 fxMesa->freeTexMem[FX_TMU1]);
777 fprintf(stderr, " # request to TMM to upload a texture objects: %u\n",
778 fxMesa->stats.reqTexUpload);
779 fprintf(stderr,
780 " # request to TMM to upload a texture objects per swapbuffer: %.2f\n",
781 fxMesa->stats.reqTexUpload / (float) fxMesa->stats.swapBuffer);
782 fprintf(stderr, " # texture objects uploaded: %u\n",
783 fxMesa->stats.texUpload);
784 fprintf(stderr, " # texture objects uploaded per swapbuffer: %.2f\n",
785 fxMesa->stats.texUpload / (float) fxMesa->stats.swapBuffer);
786 fprintf(stderr, " # MBs uploaded to texture memory: %.2f\n",
787 fxMesa->stats.memTexUpload / (float) (1 << 20));
788 fprintf(stderr,
789 " # MBs uploaded to texture memory per swapbuffer: %.2f\n",
790 (fxMesa->stats.memTexUpload /
791 (float) fxMesa->stats.swapBuffer) / (float) (1 << 20));
792 }
793
794 glbTotNumCtx--;
795
796 if (!glbTotNumCtx && getenv("MESA_FX_INFO")) {
797 GrSstPerfStats_t st;
798
799 FX_grSstPerfStats(&st);
800
801 fprintf(stderr, "Pixels Stats:\n");
802 fprintf(stderr, " # pixels processed (minus buffer clears): %u\n",
803 (unsigned) st.pixelsIn);
804 fprintf(stderr, " # pixels not drawn due to chroma key test failure: %u\n",
805 (unsigned) st.chromaFail);
806 fprintf(stderr, " # pixels not drawn due to depth test failure: %u\n",
807 (unsigned) st.zFuncFail);
808 fprintf(stderr,
809 " # pixels not drawn due to alpha test failure: %u\n",
810 (unsigned) st.aFuncFail);
811 fprintf(stderr, " # pixels drawn (including buffer clears and LFB writes): %u\n",
812 (unsigned) st.pixelsOut);
813 }
814
815 /* close the hardware first,
816 * so we can debug atexit problems (memory leaks, etc).
817 */
818 grSstWinClose(fxMesa->glideContext);
819 fxCloseHardware();
820
821 fxDDDestroyFxMesaContext(fxMesa); /* must be before _mesa_destroy_context */
822 _mesa_destroy_visual(fxMesa->glVis);
823 _mesa_destroy_context(fxMesa->glCtx);
824 _mesa_destroy_framebuffer(fxMesa->glBuffer);
825 fxTMClose(fxMesa); /* must be after _mesa_destroy_context */
826
827 FREE(fxMesa);
828
829 if (fxMesa == fxMesaCurrentCtx)
830 fxMesaCurrentCtx = NULL;
831 }
832
833
834 /*
835 * Make the specified FX/Mesa context the current one.
836 */
837 void GLAPIENTRY
838 fxMesaMakeCurrent(fxMesaContext fxMesa)
839 {
840 if (!fxMesa) {
841 _mesa_make_current(NULL, NULL);
842 fxMesaCurrentCtx = NULL;
843
844 if (TDFX_DEBUG & VERBOSE_DRIVER) {
845 fprintf(stderr, "fxMesaMakeCurrent(NULL)\n");
846 }
847
848 return;
849 }
850
851 /* if this context is already the current one, we can return early */
852 if (fxMesaCurrentCtx == fxMesa
853 && fxMesaCurrentCtx->glCtx == _mesa_get_current_context()) {
854 if (TDFX_DEBUG & VERBOSE_DRIVER) {
855 fprintf(stderr, "fxMesaMakeCurrent(NOP)\n");
856 }
857
858 return;
859 }
860
861 if (TDFX_DEBUG & VERBOSE_DRIVER) {
862 fprintf(stderr, "fxMesaMakeCurrent(...)\n");
863 }
864
865 if (fxMesaCurrentCtx)
866 grGlideGetState((GrState *) fxMesaCurrentCtx->state);
867
868 fxMesaCurrentCtx = fxMesa;
869
870 grSstSelect(fxMesa->board);
871 grGlideSetState((GrState *) fxMesa->state);
872
873 _mesa_make_current(fxMesa->glCtx, fxMesa->glBuffer);
874
875 fxSetupDDPointers(fxMesa->glCtx);
876 }
877
878
879 /*
880 * Swap front/back buffers for current context if double buffered.
881 */
882 void GLAPIENTRY
883 fxMesaSwapBuffers(void)
884 {
885 if (TDFX_DEBUG & VERBOSE_DRIVER) {
886 fprintf(stderr, "fxMesaSwapBuffers()\n");
887 }
888
889 if (fxMesaCurrentCtx) {
890 _mesa_notifySwapBuffers(fxMesaCurrentCtx->glCtx);
891
892 if (fxMesaCurrentCtx->haveDoubleBuffer) {
893
894 grBufferSwap(fxMesaCurrentCtx->swapInterval);
895
896 #if 0
897 /*
898 * Don't allow swap buffer commands to build up!
899 */
900 while (FX_grGetInteger(GR_PENDING_BUFFERSWAPS) >
901 fxMesaCurrentCtx->maxPendingSwapBuffers)
902 /* The driver is able to sleep when waiting for the completation
903 of multiple swapbuffer operations instead of wasting
904 CPU time (NOTE: you must uncomment the following line in the
905 in order to enable this option) */
906 /* usleep(10000); */
907 ;
908 #endif
909
910 fxMesaCurrentCtx->stats.swapBuffer++;
911 }
912 }
913 }
914
915
916 /*
917 * Shutdown Glide library
918 */
919 void GLAPIENTRY
920 fxCloseHardware(void)
921 {
922 if (glbGlideInitialized) {
923 if (glbTotNumCtx == 0) {
924 grGlideShutdown();
925 glbGlideInitialized = 0;
926 }
927 }
928 }
929
930
931 #else
932
933
934 /*
935 * Need this to provide at least one external definition.
936 */
937 extern int gl_fx_dummy_function_api(void);
938 int
939 gl_fx_dummy_function_api(void)
940 {
941 return 0;
942 }
943
944 #endif /* FX */