new depth buffer functions
[mesa.git] / src / mesa / drivers / glide / fxdd.c
1 /* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 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 /* fxdd.c - 3Dfx VooDoo Mesa device driver functions */
47
48
49 #ifdef HAVE_CONFIG_H
50 #include "conf.h"
51 #endif
52
53 #if defined(FX)
54
55 #include "types.h"
56 #include "fxdrv.h"
57 #include "enums.h"
58 #include "extensions.h"
59
60
61 /* These lookup table are used to extract RGB values in [0,255] from
62 * 16-bit pixel values.
63 */
64 GLubyte FX_PixelToR[0x10000];
65 GLubyte FX_PixelToG[0x10000];
66 GLubyte FX_PixelToB[0x10000];
67
68
69 /*
70 * Initialize the FX_PixelTo{RGB} arrays.
71 * Input: bgrOrder - if TRUE, pixels are in BGR order, else RGB order.
72 */
73 void fxInitPixelTables(GLboolean bgrOrder)
74 {
75 GLuint pixel;
76 for (pixel = 0; pixel <= 0xffff; pixel++) {
77 GLuint r, g, b;
78 if (bgrOrder) {
79 r = (pixel & 0x001F) << 3;
80 g = (pixel & 0x07E0) >> 3;
81 b = (pixel & 0xF800) >> 8;
82 }
83 else {
84 r = (pixel & 0xF800) >> 8;
85 g = (pixel & 0x07E0) >> 3;
86 b = (pixel & 0x001F) << 3;
87 }
88 r = r * 255 / 0xF8; /* fill in low-order bits */
89 g = g * 255 / 0xFC;
90 b = b * 255 / 0xF8;
91 FX_PixelToR[pixel] = r;
92 FX_PixelToG[pixel] = g;
93 FX_PixelToB[pixel] = b;
94 }
95 }
96
97
98 /**********************************************************************/
99 /***** Miscellaneous functions *****/
100 /**********************************************************************/
101
102 /* Enalbe/Disable dithering */
103 void fxDDDither(GLcontext *ctx, GLboolean enable)
104 {
105 if (MESA_VERBOSE&VERBOSE_DRIVER) {
106 fprintf(stderr,"fxmesa: fxDDDither()\n");
107 }
108
109 if (enable) {
110 FX_grDitherMode(GR_DITHER_4x4);
111 } else {
112 FX_grDitherMode(GR_DITHER_DISABLE);
113 }
114 }
115
116
117 /* Return buffer size information */
118 void fxDDBufferSize(GLcontext *ctx, GLuint *width, GLuint *height)
119 {
120 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
121
122 if (MESA_VERBOSE&VERBOSE_DRIVER) {
123 fprintf(stderr,"fxmesa: fxDDBufferSize(...) Start\n");
124 }
125
126 *width=fxMesa->width;
127 *height=fxMesa->height;
128
129 if (MESA_VERBOSE&VERBOSE_DRIVER) {
130 fprintf(stderr,"fxmesa: fxDDBufferSize(...) End\n");
131 }
132 }
133
134
135 /* Set current drawing color */
136 static void fxDDSetColor(GLcontext *ctx, GLubyte red, GLubyte green,
137 GLubyte blue, GLubyte alpha )
138 {
139 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
140 GLubyte col[4];
141 ASSIGN_4V( col, red, green, blue, alpha );
142
143 if (MESA_VERBOSE&VERBOSE_DRIVER) {
144 fprintf(stderr,"fxmesa: fxDDSetColor(%d,%d,%d,%d)\n",red,green,blue,alpha);
145 }
146
147 fxMesa->color=FXCOLOR4(col);
148 }
149
150
151 /* Implements glClearColor() */
152 static void fxDDClearColor(GLcontext *ctx, GLubyte red, GLubyte green,
153 GLubyte blue, GLubyte alpha )
154 {
155 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
156 GLubyte col[4];
157
158
159
160 ASSIGN_4V( col, red, green, blue, 255 );
161
162 if (MESA_VERBOSE&VERBOSE_DRIVER) {
163 fprintf(stderr,"fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",red,green,blue,alpha);
164 }
165
166 fxMesa->clearC=FXCOLOR4( col );
167 fxMesa->clearA=alpha;
168 }
169
170 /* Clear the color and/or depth buffers */
171 static GLbitfield fxDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
172 GLint x, GLint y, GLint width, GLint height )
173 {
174 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
175 GLbitfield newmask;
176
177 if (MESA_VERBOSE&VERBOSE_DRIVER) {
178 fprintf(stderr,"fxmesa: fxDDClear(%d,%d,%d,%d)\n",x,y,width,height);
179 }
180
181 switch(mask & (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)) {
182 case (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT):
183 /* clear color and depth buffer */
184
185 if (ctx->Color.DrawDestMask & BACK_LEFT_BIT) {
186 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER);
187 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA,
188 (FxU16)(ctx->Depth.Clear*0xffff));
189 }
190 if (ctx->Color.DrawDestMask & FRONT_LEFT_BIT) {
191 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER);
192 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA,
193 (FxU16)(ctx->Depth.Clear*0xffff));
194 }
195
196 newmask=mask & (~(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT));
197 break;
198 case (GL_COLOR_BUFFER_BIT):
199 /* clear color buffer */
200
201 if(ctx->Color.ColorMask) {
202 FX_grDepthMask(FXFALSE);
203
204 if (ctx->Color.DrawDestMask & BACK_LEFT_BIT) {
205 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER);
206 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, 0);
207 }
208 if (ctx->Color.DrawDestMask & FRONT_LEFT_BIT) {
209 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER);
210 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA, 0);
211 }
212
213 if(ctx->Depth.Mask) {
214 FX_grDepthMask(FXTRUE);
215 }
216 }
217
218 newmask=mask & (~(GL_COLOR_BUFFER_BIT));
219 break;
220 case (GL_DEPTH_BUFFER_BIT):
221 /* clear depth buffer */
222
223 if(ctx->Depth.Mask) {
224 FX_grColorMask(FXFALSE,FXFALSE);
225 FX_grBufferClear(fxMesa->clearC, fxMesa->clearA,
226 (FxU16)(ctx->Depth.Clear*0xffff));
227
228 FX_grColorMask(ctx->Color.ColorMask[RCOMP] ||
229 ctx->Color.ColorMask[GCOMP] ||
230 ctx->Color.ColorMask[BCOMP],
231 ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer);
232 }
233
234 newmask=mask & (~(GL_DEPTH_BUFFER_BIT));
235 break;
236 default:
237 newmask=mask;
238 break;
239 }
240
241 return newmask;
242 }
243
244
245 /* Set the buffer used for drawing */
246 /* XXX support for separate read/draw buffers hasn't been tested */
247 static GLboolean fxDDSetDrawBuffer(GLcontext *ctx, GLenum mode )
248 {
249 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
250
251 if (MESA_VERBOSE&VERBOSE_DRIVER) {
252 fprintf(stderr,"fxmesa: fxDDSetBuffer(%x)\n",mode);
253 }
254
255 if (mode == GL_FRONT_LEFT) {
256 fxMesa->currentFB = GR_BUFFER_FRONTBUFFER;
257 FX_grRenderBuffer(fxMesa->currentFB);
258 return GL_TRUE;
259 }
260 else if (mode == GL_BACK_LEFT) {
261 fxMesa->currentFB = GR_BUFFER_BACKBUFFER;
262 FX_grRenderBuffer(fxMesa->currentFB);
263 return GL_TRUE;
264 }
265 else {
266 return GL_FALSE;
267 }
268 }
269
270
271 /* Set the buffer used for reading */
272 /* XXX support for separate read/draw buffers hasn't been tested */
273 static void fxDDSetReadBuffer(GLcontext *ctx, GLframebuffer *buffer,
274 GLenum mode )
275 {
276 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
277 (void) buffer;
278
279 if (MESA_VERBOSE&VERBOSE_DRIVER) {
280 fprintf(stderr,"fxmesa: fxDDSetBuffer(%x)\n",mode);
281 }
282
283 if (mode == GL_FRONT_LEFT) {
284 fxMesa->currentFB = GR_BUFFER_FRONTBUFFER;
285 FX_grRenderBuffer(fxMesa->currentFB);
286 }
287 else if (mode == GL_BACK_LEFT) {
288 fxMesa->currentFB = GR_BUFFER_BACKBUFFER;
289 FX_grRenderBuffer(fxMesa->currentFB);
290 }
291 }
292
293
294 #ifdef XF86DRI
295 static GLboolean inClipRects(fxMesaContext fxMesa, int px, int py)
296 {
297 int i;
298
299 py=fxMesa->height+fxMesa->y_offset-py;
300 for (i=0; i<fxMesa->numClipRects; i++) {
301 if ((px>=fxMesa->pClipRects[i].x1) &&
302 (px<fxMesa->pClipRects[i].x2) &&
303 (py>=fxMesa->pClipRects[i].y1) &&
304 (py<fxMesa->pClipRects[i].y2)) return GL_TRUE;
305 }
306 return GL_FALSE;
307 }
308 #endif
309
310
311 static GLboolean fxDDDrawBitMap(GLcontext *ctx, GLint px, GLint py,
312 GLsizei width, GLsizei height,
313 const struct gl_pixelstore_attrib *unpack,
314 const GLubyte *bitmap)
315 {
316 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
317 FxU16 *p;
318 GrLfbInfo_t info;
319 const GLubyte *pb;
320 int x,y,xmin,xmax,ymin,ymax;
321 GLint r,g,b,a,scrwidth,scrheight,stride;
322 FxU16 color;
323
324 /* TODO: with a little work, these bitmap unpacking parameter restrictions
325 * could be removed.
326 */
327 if((unpack->Alignment!=1) ||
328 (unpack->RowLength!=0) ||
329 (unpack->SkipPixels!=0) ||
330 (unpack->SkipRows!=0) ||
331 (unpack->SwapBytes) ||
332 (unpack->LsbFirst))
333 return GL_FALSE;
334
335 if (ctx->Scissor.Enabled) {
336 xmin=ctx->Scissor.X;
337 xmax=ctx->Scissor.X+ctx->Scissor.Width;
338 ymin=ctx->Scissor.Y;
339 ymax=ctx->Scissor.Y+ctx->Scissor.Height;
340 } else {
341 xmin=0;
342 xmax=fxMesa->width;
343 ymin=0;
344 ymax=fxMesa->height;
345 }
346
347 xmin+=fxMesa->x_offset;
348 xmax+=fxMesa->x_offset;
349
350 #ifdef XF86DRI
351 #define ISCLIPPED(rx, ry) ( ((rx)<xmin) || ((rx)>=xmax) || !inClipRects(fxMesa, rx, ry))
352 #else
353 #define ISCLIPPED(rx, ry) ( ((rx)<xmin) || ((rx)>=xmax) )
354 #endif
355 #define DRAWBIT(i) { \
356 if(!ISCLIPPED(x+px, y)) \
357 if( (*pb) & (1<<(i)) ) \
358 (*p)=color; \
359 p++; \
360 x++; \
361 if(x>=width) { \
362 pb++; \
363 break; \
364 } \
365 }
366
367 scrwidth=fxMesa->width;
368 scrheight=fxMesa->height;
369
370 if ((px>=scrwidth) || (px+width<=0) || (py>=scrheight) || (py+height<=0))
371 return GL_TRUE;
372
373 pb=bitmap;
374
375 if(py<0) {
376 pb+=(height*(-py)) >> (3+1);
377 height+=py;
378 py=0;
379 }
380
381 if (py+height>=scrheight)
382 height-=(py+height)-scrheight;
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,
389 FXFALSE,
390 &info)) {
391 #ifndef FX_SILENT
392 fprintf(stderr,"fx Driver: error locking the linear frame buffer\n");
393 #endif
394 return GL_TRUE;
395 }
396
397 r=(GLint)(ctx->Current.RasterColor[0]*255.0f);
398 g=(GLint)(ctx->Current.RasterColor[1]*255.0f);
399 b=(GLint)(ctx->Current.RasterColor[2]*255.0f);
400 a=(GLint)(ctx->Current.RasterColor[3]*255.0f);
401 color=(FxU16)
402 ( ((FxU16)0xf8 & b) <<(11-3)) |
403 ( ((FxU16)0xfc & g) <<(5-3+1)) |
404 ( ((FxU16)0xf8 & r) >> 3);
405
406 stride=info.strideInBytes>>1;
407
408 /* This code is a bit slow... */
409
410 if (py>ymin) ymin=py;
411 if (py+height<ymax) ymax=py+height;
412
413 px+=fxMesa->x_offset;
414 scrheight=fxMesa->height+fxMesa->y_offset;
415
416 for(y=ymin; y<ymax; y++) {
417
418 p=((FxU16 *)info.lfbPtr)+px+((scrheight-y)*stride);
419
420 for(x=0;;) {
421 DRAWBIT(7); DRAWBIT(6); DRAWBIT(5); DRAWBIT(4);
422 DRAWBIT(3); DRAWBIT(2); DRAWBIT(1); DRAWBIT(0);
423 pb++;
424 }
425 }
426
427 FX_grLfbUnlock(GR_LFB_WRITE_ONLY,fxMesa->currentFB);
428
429 #undef ISCLIPPED
430 #undef DRAWBIT
431
432 return GL_TRUE;
433 }
434
435 static void fxDDFinish(GLcontext *ctx)
436 {
437 FX_grFlush();
438 }
439
440
441 static GLint fxDDGetParameteri(const GLcontext *ctx, GLint param)
442 {
443 switch(param) {
444 case DD_HAVE_HARDWARE_FOG:
445 return 1;
446 default:
447 fprintf(stderr,"fx Driver: internal error in fxDDGetParameteri(): %x\n",param);
448 fxCloseHardware();
449 exit(-1);
450 return 0;
451 }
452 }
453
454
455 void fxDDSetNearFar(GLcontext *ctx, GLfloat n, GLfloat f)
456 {
457 FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG;
458 ctx->Driver.RenderStart = fxSetupFXUnits;
459 }
460
461 /* KW: Put the word Mesa in the render string because quakeworld
462 * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
463 * Why?
464 */
465 static const GLubyte *fxDDGetString(GLcontext *ctx, GLenum name)
466 {
467 switch (name) {
468 case GL_RENDERER:
469 #if defined(GLX_DIRECT_RENDERING)
470 return "Mesa Glide - DRI VB/V3";
471 #else
472 {
473 static char buf[80];
474
475 if (glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO)
476 {
477 GrVoodooConfig_t *vc =
478 &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig;
479
480 sprintf(buf,
481 "Mesa Glide v0.30 Voodoo_Graphics %d "
482 "CARD/%d FB/%d TM/%d TMU/%s",
483 glbCurrentBoard,
484 (vc->sliDetect ? (vc->fbRam*2) : vc->fbRam),
485 (vc->tmuConfig[GR_TMU0].tmuRam +
486 ((vc->nTexelfx>1) ? vc->tmuConfig[GR_TMU1].tmuRam : 0)),
487 vc->nTexelfx,
488 (vc->sliDetect ? "SLI" : "NOSLI"));
489 }
490 else if (glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96)
491 {
492 GrSst96Config_t *sc =
493 &glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config;
494
495 sprintf(buf,
496 "Glide v0.30 Voodoo_Rush %d "
497 "CARD/%d FB/%d TM/%d TMU/NOSLI",
498 glbCurrentBoard,
499 sc->fbRam,
500 sc->tmuConfig.tmuRam,
501 sc->nTexelfx);
502 }
503 else
504 {
505 strcpy(buf, "Glide v0.30 UNKNOWN");
506 }
507
508 return (GLubyte *) buf;
509 }
510 #endif
511 default:
512 return NULL;
513 }
514 }
515
516
517 int fxDDInitFxMesaContext( fxMesaContext fxMesa )
518 {
519
520 FX_setupGrVertexLayout();
521
522 if (getenv("FX_EMULATE_SINGLE_TMU"))
523 fxMesa->haveTwoTMUs = GL_FALSE;
524
525 fxMesa->emulateTwoTMUs = fxMesa->haveTwoTMUs;
526
527 if (!getenv("FX_DONT_FAKE_MULTITEX"))
528 fxMesa->emulateTwoTMUs = GL_TRUE;
529
530 if(getenv("FX_GLIDE_SWAPINTERVAL"))
531 fxMesa->swapInterval=atoi(getenv("FX_GLIDE_SWAPINTERVAL"));
532 else
533 fxMesa->swapInterval=1;
534
535 if(getenv("MESA_FX_SWAP_PENDING"))
536 fxMesa->maxPendingSwapBuffers=atoi(getenv("MESA_FX_SWAP_PENDING"));
537 else
538 fxMesa->maxPendingSwapBuffers=2;
539
540 fxMesa->color=0xffffffff;
541 fxMesa->clearC=0;
542 fxMesa->clearA=0;
543
544 fxMesa->stats.swapBuffer=0;
545 fxMesa->stats.reqTexUpload=0;
546 fxMesa->stats.texUpload=0;
547 fxMesa->stats.memTexUpload=0;
548
549 fxMesa->tmuSrc=FX_TMU_NONE;
550 fxMesa->lastUnitsMode=FX_UM_NONE;
551 fxTMInit(fxMesa);
552
553 /* FX units setup */
554
555 fxMesa->unitsState.alphaTestEnabled=GL_FALSE;
556 fxMesa->unitsState.alphaTestFunc=GR_CMP_ALWAYS;
557 fxMesa->unitsState.alphaTestRefValue=0;
558
559 fxMesa->unitsState.blendEnabled=GL_FALSE;
560 fxMesa->unitsState.blendSrcFuncRGB=GR_BLEND_ONE;
561 fxMesa->unitsState.blendDstFuncRGB=GR_BLEND_ZERO;
562 fxMesa->unitsState.blendSrcFuncAlpha=GR_BLEND_ONE;
563 fxMesa->unitsState.blendDstFuncAlpha=GR_BLEND_ZERO;
564
565 fxMesa->unitsState.depthTestEnabled =GL_FALSE;
566 fxMesa->unitsState.depthMask =GL_TRUE;
567 fxMesa->unitsState.depthTestFunc =GR_CMP_LESS;
568
569 FX_grColorMask(FXTRUE, fxMesa->haveAlphaBuffer ? FXTRUE : FXFALSE);
570 if(fxMesa->haveDoubleBuffer) {
571 fxMesa->currentFB=GR_BUFFER_BACKBUFFER;
572 FX_grRenderBuffer(GR_BUFFER_BACKBUFFER);
573 } else {
574 fxMesa->currentFB=GR_BUFFER_FRONTBUFFER;
575 FX_grRenderBuffer(GR_BUFFER_FRONTBUFFER);
576 }
577
578 fxMesa->state = NULL;
579 fxMesa->fogTable = NULL;
580
581 fxMesa->state = malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE));
582 fxMesa->fogTable = malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES)*sizeof(GrFog_t));
583
584 if (!fxMesa->state || !fxMesa->fogTable) {
585 if (fxMesa->state) free(fxMesa->state);
586 if (fxMesa->fogTable) free(fxMesa->fogTable);
587 return 0;
588 }
589
590 if(fxMesa->haveZBuffer)
591 FX_grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER);
592
593 #if (!FXMESA_USE_ARGB)
594 FX_grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); /* Not every Glide has this */
595 #endif
596
597 fxMesa->glCtx->Const.MaxTextureLevels=9;
598 fxMesa->glCtx->Const.MaxTextureSize=256;
599 fxMesa->glCtx->Const.MaxTextureUnits=fxMesa->emulateTwoTMUs ? 2 : 1;
600 fxMesa->glCtx->NewState|=NEW_DRVSTATE1;
601 fxMesa->new_state = NEW_ALL;
602
603 fxDDSetupInit();
604 fxDDCvaInit();
605 fxDDClipInit();
606 fxDDTrifuncInit();
607 fxDDFastPathInit();
608
609 fxSetupDDPointers(fxMesa->glCtx);
610 fxDDRenderInit(fxMesa->glCtx);
611 fxDDInitExtensions(fxMesa->glCtx);
612
613 fxDDSetNearFar(fxMesa->glCtx,1.0,100.0);
614
615 FX_grGlideGetState((GrState*)fxMesa->state);
616
617 /* XXX Fix me: callback not registered when main VB is created.
618 */
619 if (fxMesa->glCtx->VB)
620 fxDDRegisterVB( fxMesa->glCtx->VB );
621
622 /* XXX Fix me too: need to have the 'struct dd' prepared prior to
623 * creating the context... The below is broken if you try to insert
624 * new stages.
625 */
626 if (fxMesa->glCtx->NrPipelineStages)
627 fxMesa->glCtx->NrPipelineStages = fxDDRegisterPipelineStages(
628 fxMesa->glCtx->PipelineStage,
629 fxMesa->glCtx->PipelineStage,
630 fxMesa->glCtx->NrPipelineStages);
631
632 /* Run the config file */
633 gl_context_initialize( fxMesa->glCtx );
634
635 return 1;
636 }
637
638
639
640
641
642 void fxDDInitExtensions( GLcontext *ctx )
643 {
644 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
645
646 gl_extensions_add( ctx, DEFAULT_ON, "3DFX_set_global_palette", 0 );
647 gl_extensions_add( ctx, DEFAULT_ON, "GL_FXMESA_global_texture_lod_bias", 0);
648
649 if(fxMesa->haveTwoTMUs)
650 gl_extensions_add( ctx, DEFAULT_ON, "GL_EXT_texture_env_add", 0);
651
652 if (!fxMesa->emulateTwoTMUs)
653 gl_extensions_disable( ctx, "GL_ARB_multitexture" );
654 }
655
656 /*
657 This driver may need to move the drawing operations to a different sub
658 window. This modifies the viewport command to add our X,Y offset to all
659 drawn objects that go through the viewport transformation.
660 */
661
662 /************************************************************************/
663 /************************************************************************/
664 /************************************************************************/
665
666 /* This is a no-op, since the z-buffer is in hardware */
667 static void fxAllocDepthBuffer(GLcontext *ctx)
668 {
669 if (MESA_VERBOSE&VERBOSE_DRIVER) {
670 fprintf(stderr,"fxmesa: fxAllocDepthBuffer()\n");
671 }
672 }
673
674 /************************************************************************/
675 /************************************************************************/
676 /************************************************************************/
677
678 /* Check if the hardware supports the current context
679 *
680 * Performs similar work to fxDDChooseRenderState() - should be merged.
681 */
682 static GLboolean fxIsInHardware(GLcontext *ctx)
683 {
684 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
685
686 if (!ctx->Hint.AllowDrawMem)
687 return GL_TRUE; /* you'll take it and like it */
688
689 if((ctx->RasterMask & STENCIL_BIT) ||
690 ((ctx->Color.BlendEnabled) && (ctx->Color.BlendEquation!=GL_FUNC_ADD_EXT)) ||
691 ((ctx->Color.ColorLogicOpEnabled) && (ctx->Color.LogicOp!=GL_COPY)) ||
692 (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) ||
693 (!((ctx->Color.ColorMask[RCOMP]==ctx->Color.ColorMask[GCOMP]) &&
694 (ctx->Color.ColorMask[GCOMP]==ctx->Color.ColorMask[BCOMP]) &&
695 (ctx->Color.ColorMask[ACOMP]==ctx->Color.ColorMask[ACOMP])))
696 )
697 {
698 return GL_FALSE;
699 }
700 /* Unsupported texture/multitexture cases */
701
702 if(fxMesa->emulateTwoTMUs) {
703 if((ctx->Enabled & (TEXTURE0_3D | TEXTURE1_3D)) ||
704 /* Not very well written ... */
705 ((ctx->Enabled & (TEXTURE0_1D | TEXTURE1_1D)) &&
706 ((ctx->Enabled & (TEXTURE0_2D | TEXTURE1_2D))!=(TEXTURE0_2D | TEXTURE1_2D)))
707 ) {
708 return GL_FALSE;
709 }
710
711 if((ctx->Texture.ReallyEnabled & TEXTURE0_2D) &&
712 (ctx->Texture.Unit[0].EnvMode==GL_BLEND)) {
713 return GL_FALSE;
714 }
715
716 if((ctx->Texture.ReallyEnabled & TEXTURE1_2D) &&
717 (ctx->Texture.Unit[1].EnvMode==GL_BLEND)) {
718 return GL_FALSE;
719 }
720
721
722 if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
723 fprintf(stderr, "fxMesa: fxIsInHardware, envmode is %s/%s\n",
724 gl_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
725 gl_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
726
727 /* KW: This was wrong (I think) and I changed it... which doesn't mean
728 * it is now correct...
729 */
730 if((ctx->Enabled & (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D)) &&
731 (ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)))
732 {
733 /* Can't use multipass to blend a multitextured triangle - fall
734 * back to software.
735 */
736 if (!fxMesa->haveTwoTMUs && ctx->Color.BlendEnabled) {
737 return GL_FALSE;
738 }
739
740 if ((ctx->Texture.Unit[0].EnvMode!=ctx->Texture.Unit[1].EnvMode) &&
741 (ctx->Texture.Unit[0].EnvMode!=GL_MODULATE) &&
742 (ctx->Texture.Unit[0].EnvMode!=GL_REPLACE)) /* q2, seems ok... */
743 {
744 if (MESA_VERBOSE&VERBOSE_DRIVER)
745 fprintf(stderr, "fxMesa: unsupported multitex env mode\n");
746 return GL_FALSE;
747 }
748 }
749 } else {
750 if((ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)) ||
751 /* Not very well written ... */
752 ((ctx->Enabled & TEXTURE0_1D) &&
753 (!(ctx->Enabled & TEXTURE0_2D)))
754 ) {
755 return GL_FALSE;
756 }
757
758
759 if((ctx->Texture.ReallyEnabled & TEXTURE0_2D) &&
760 (ctx->Texture.Unit[0].EnvMode==GL_BLEND)) {
761 return GL_FALSE;
762 }
763 }
764
765 return GL_TRUE;
766 }
767
768
769
770 #define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|NEW_PROJECTION|NEW_TEXTURE_MATRIX|NEW_USER_CLIP|NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE))
771
772 static void fxDDUpdateDDPointers(GLcontext *ctx)
773 {
774 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
775 GLuint new_state = ctx->NewState;
776
777 if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_STATE))
778 fprintf(stderr,"fxmesa: fxDDUpdateDDPointers(...)\n");
779
780 if (new_state & (NEW_RASTER_OPS|NEW_TEXTURING))
781 fxMesa->is_in_hardware = fxIsInHardware(ctx);
782
783 if (fxMesa->is_in_hardware) {
784 if (fxMesa->new_state)
785 fxSetupFXUnits(ctx);
786
787 if(new_state & INTERESTED) {
788 fxDDChooseRenderState( ctx );
789 fxMesa->RenderVBTables=fxDDChooseRenderVBTables(ctx);
790 fxMesa->RenderVBClippedTab=fxMesa->RenderVBTables[0];
791 fxMesa->RenderVBCulledTab=fxMesa->RenderVBTables[1];
792 fxMesa->RenderVBRawTab=fxMesa->RenderVBTables[2];
793
794 ctx->Driver.RasterSetup=fxDDChooseSetupFunction(ctx);
795 }
796
797 ctx->Driver.PointsFunc=fxMesa->PointsFunc;
798 ctx->Driver.LineFunc=fxMesa->LineFunc;
799 ctx->Driver.TriangleFunc=fxMesa->TriangleFunc;
800 ctx->Driver.QuadFunc=fxMesa->QuadFunc;
801 } else {
802 fxMesa->render_index = FX_FALLBACK;
803 }
804 }
805
806 void fxSetupDDPointers(GLcontext *ctx)
807 {
808 if (MESA_VERBOSE&VERBOSE_DRIVER) {
809 fprintf(stderr,"fxmesa: fxSetupDDPointers()\n");
810 }
811
812 ctx->Driver.UpdateState=fxDDUpdateDDPointers;
813
814 ctx->Driver.WriteDepthSpan=fxDDWriteDepthSpan;
815 ctx->Driver.WriteDepthPixels=fxDDWriteDepthPixels;
816 ctx->Driver.ReadDepthSpan=fxDDReadDepthSpan;
817 ctx->Driver.ReadDepthPixels=fxDDReadDepthPixels;
818
819 ctx->Driver.GetString=fxDDGetString;
820
821 ctx->Driver.Dither=fxDDDither;
822
823 ctx->Driver.NearFar=fxDDSetNearFar;
824
825 ctx->Driver.GetParameteri=fxDDGetParameteri;
826
827 ctx->Driver.ClearIndex=NULL;
828 ctx->Driver.ClearColor=fxDDClearColor;
829 ctx->Driver.Clear=fxDDClear;
830
831 ctx->Driver.Index=NULL;
832 ctx->Driver.Color=fxDDSetColor;
833
834 ctx->Driver.SetDrawBuffer=fxDDSetDrawBuffer;
835 ctx->Driver.SetReadBuffer=fxDDSetReadBuffer;
836 ctx->Driver.GetBufferSize=fxDDBufferSize;
837
838 ctx->Driver.Bitmap=fxDDDrawBitMap;
839 ctx->Driver.DrawPixels=NULL;
840
841 ctx->Driver.Finish=fxDDFinish;
842 ctx->Driver.Flush=NULL;
843
844 ctx->Driver.RenderStart=NULL;
845 ctx->Driver.RenderFinish=NULL;
846
847 ctx->Driver.TexEnv=fxDDTexEnv;
848 ctx->Driver.TexImage=fxDDTexImg;
849 ctx->Driver.TexSubImage=fxDDTexSubImg;
850 ctx->Driver.TexParameter=fxDDTexParam;
851 ctx->Driver.BindTexture=fxDDTexBind;
852 ctx->Driver.DeleteTexture=fxDDTexDel;
853 ctx->Driver.UpdateTexturePalette=fxDDTexPalette;
854 ctx->Driver.UseGlobalTexturePalette=fxDDTexUseGlbPalette;
855
856 ctx->Driver.RectFunc=NULL;
857
858 ctx->Driver.AlphaFunc=fxDDAlphaFunc;
859 ctx->Driver.BlendFunc=fxDDBlendFunc;
860 ctx->Driver.DepthFunc=fxDDDepthFunc;
861 ctx->Driver.DepthMask=fxDDDepthMask;
862 ctx->Driver.ColorMask=fxDDColorMask;
863 ctx->Driver.Fogfv=fxDDFogfv;
864 ctx->Driver.Scissor=fxDDScissor;
865 ctx->Driver.FrontFace=fxDDFrontFace;
866 ctx->Driver.CullFace=fxDDCullFace;
867 ctx->Driver.ShadeModel=fxDDShadeModel;
868 ctx->Driver.Enable=fxDDEnable;
869
870 ctx->Driver.RegisterVB=fxDDRegisterVB;
871 ctx->Driver.UnregisterVB=fxDDUnregisterVB;
872
873 ctx->Driver.RegisterPipelineStages = fxDDRegisterPipelineStages;
874
875 ctx->Driver.OptimizeImmediatePipeline = 0; /* nothing done yet */
876 ctx->Driver.OptimizePrecalcPipeline = 0;
877
878 /* if (getenv("MESA_USE_FAST") || getenv("FX_USE_FAST")) */
879 /* ctx->Driver.OptimizePrecalcPipeline = fxDDOptimizePrecalcPipeline; */
880
881 if (!getenv("FX_NO_FAST"))
882 ctx->Driver.BuildPrecalcPipeline = fxDDBuildPrecalcPipeline;
883
884 ctx->Driver.TriangleCaps = DD_TRI_CULL|DD_TRI_OFFSET|DD_TRI_LIGHT_TWOSIDE;
885
886 fxSetupDDSpanPointers(ctx);
887
888 FX_CONTEXT(ctx)->render_index = 1; /* force an update */
889 fxDDUpdateDDPointers(ctx);
890 }
891
892
893 #else
894
895
896 /*
897 * Need this to provide at least one external definition.
898 */
899
900 int gl_fx_dummy_function_dd(void)
901 {
902 return 0;
903 }
904
905 #endif /* FX */
906