Remove dd_function_table::BlendFunc. All drivers now use
[mesa.git] / src / mesa / drivers / dri / tdfx / tdfx_state.c
1 /* -*- mode: c; c-basic-offset: 3 -*-
2 *
3 * Copyright 2000 VA Linux Systems Inc., Fremont, California.
4 *
5 * 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 (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26 /* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_state.c,v 1.7 2002/10/30 12:52:00 alanh Exp $ */
27
28 /*
29 * Original rewrite:
30 * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
31 *
32 * Authors:
33 * Gareth Hughes <gareth@valinux.com>
34 * Brian Paul <brianp@valinux.com>
35 * Keith Whitwell <keith@tungstengraphics.com> (port to 3.5)
36 *
37 */
38
39 #include "mtypes.h"
40 #include "colormac.h"
41 #include "texformat.h"
42 #include "texstore.h"
43 #include "teximage.h"
44
45 #include "swrast/swrast.h"
46 #include "array_cache/acache.h"
47 #include "tnl/tnl.h"
48 #include "tnl/t_pipeline.h"
49 #include "swrast_setup/swrast_setup.h"
50
51 #include "tdfx_context.h"
52 #include "tdfx_state.h"
53 #include "tdfx_vb.h"
54 #include "tdfx_tex.h"
55 #include "tdfx_texman.h"
56 #include "tdfx_texstate.h"
57 #include "tdfx_tris.h"
58 #include "tdfx_render.h"
59
60
61
62 /* =============================================================
63 * Alpha blending
64 */
65
66 static void tdfxUpdateAlphaMode( GLcontext *ctx )
67 {
68 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
69 GrCmpFnc_t func;
70 GrAlphaBlendFnc_t srcRGB, dstRGB, srcA, dstA;
71 GrAlpha_t ref = (GLint) (ctx->Color.AlphaRef * 255.0);
72
73 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
74 fprintf( stderr, "%s()\n", __FUNCTION__ );
75 }
76
77 if ( ctx->Color.AlphaEnabled ) {
78 switch ( ctx->Color.AlphaFunc ) {
79 case GL_NEVER:
80 func = GR_CMP_NEVER;
81 break;
82 case GL_LESS:
83 func = GR_CMP_LESS;
84 break;
85 case GL_LEQUAL:
86 func = GR_CMP_LEQUAL;
87 break;
88 case GL_EQUAL:
89 func = GR_CMP_EQUAL;
90 break;
91 case GL_GEQUAL:
92 func = GR_CMP_GEQUAL;
93 break;
94 case GL_GREATER:
95 func = GR_CMP_GREATER;
96 break;
97 case GL_NOTEQUAL:
98 func = GR_CMP_NOTEQUAL;
99 break;
100 case GL_ALWAYS:
101 default:
102 func = GR_CMP_ALWAYS;
103 break;
104 }
105 } else {
106 func = GR_CMP_ALWAYS;
107 }
108
109 if ( ctx->Color.BlendEnabled
110 && (fxMesa->Fallback & TDFX_FALLBACK_BLEND) == 0 ) {
111 switch ( ctx->Color.BlendSrcRGB ) {
112 case GL_ZERO:
113 srcRGB = GR_BLEND_ZERO;
114 break;
115 case GL_ONE:
116 srcRGB = GR_BLEND_ONE;
117 break;
118 case GL_DST_COLOR:
119 srcRGB = GR_BLEND_DST_COLOR;
120 break;
121 case GL_ONE_MINUS_DST_COLOR:
122 srcRGB = GR_BLEND_ONE_MINUS_DST_COLOR;
123 break;
124 case GL_SRC_ALPHA:
125 srcRGB = GR_BLEND_SRC_ALPHA;
126 break;
127 case GL_ONE_MINUS_SRC_ALPHA:
128 srcRGB = GR_BLEND_ONE_MINUS_SRC_ALPHA;
129 break;
130 case GL_DST_ALPHA:
131 srcRGB = GR_BLEND_DST_ALPHA;
132 break;
133 case GL_ONE_MINUS_DST_ALPHA:
134 srcRGB = GR_BLEND_ONE_MINUS_DST_ALPHA;
135 break;
136 case GL_SRC_ALPHA_SATURATE:
137 srcRGB = GR_BLEND_ALPHA_SATURATE;
138 break;
139 default:
140 srcRGB = GR_BLEND_ONE;
141 }
142
143 switch ( ctx->Color.BlendSrcA ) {
144 case GL_ZERO:
145 srcA = GR_BLEND_ZERO;
146 break;
147 case GL_ONE:
148 srcA = GR_BLEND_ONE;
149 break;
150 case GL_DST_COLOR:
151 srcA = GR_BLEND_DST_ALPHA; /* Napalm only */
152 break;
153 case GL_ONE_MINUS_DST_COLOR:
154 srcA = GR_BLEND_ONE_MINUS_DST_ALPHA; /* Napalm only */
155 break;
156 case GL_SRC_ALPHA:
157 srcA = GR_BLEND_SRC_ALPHA; /* Napalm only */
158 break;
159 case GL_ONE_MINUS_SRC_ALPHA:
160 srcA = GR_BLEND_ONE_MINUS_SRC_ALPHA; /* Napalm only */
161 break;
162 case GL_DST_ALPHA:
163 srcA = GR_BLEND_DST_ALPHA; /* Napalm only */
164 break;
165 case GL_ONE_MINUS_DST_ALPHA:
166 srcA = GR_BLEND_ONE_MINUS_DST_ALPHA; /* Napalm only */
167 break;
168 case GL_SRC_ALPHA_SATURATE:
169 srcA = GR_BLEND_ONE;
170 break;
171 default:
172 srcA = GR_BLEND_ONE;
173 }
174
175 switch ( ctx->Color.BlendDstRGB ) {
176 case GL_ZERO:
177 dstRGB = GR_BLEND_ZERO;
178 break;
179 case GL_ONE:
180 dstRGB = GR_BLEND_ONE;
181 break;
182 case GL_SRC_COLOR:
183 dstRGB = GR_BLEND_SRC_COLOR;
184 break;
185 case GL_ONE_MINUS_SRC_COLOR:
186 dstRGB = GR_BLEND_ONE_MINUS_SRC_COLOR;
187 break;
188 case GL_SRC_ALPHA:
189 dstRGB = GR_BLEND_SRC_ALPHA;
190 break;
191 case GL_ONE_MINUS_SRC_ALPHA:
192 dstRGB = GR_BLEND_ONE_MINUS_SRC_ALPHA;
193 break;
194 case GL_DST_ALPHA:
195 dstRGB = GR_BLEND_DST_ALPHA;
196 break;
197 case GL_ONE_MINUS_DST_ALPHA:
198 dstRGB = GR_BLEND_ONE_MINUS_DST_ALPHA;
199 break;
200 default:
201 dstRGB = GR_BLEND_ZERO;
202 }
203
204 switch ( ctx->Color.BlendDstA ) {
205 case GL_ZERO:
206 dstA = GR_BLEND_ZERO;
207 break;
208 case GL_ONE:
209 dstA = GR_BLEND_ONE;
210 break;
211 case GL_SRC_COLOR:
212 dstA = GR_BLEND_SRC_ALPHA; /* Napalm only */
213 break;
214 case GL_ONE_MINUS_SRC_COLOR:
215 dstA = GR_BLEND_ONE_MINUS_SRC_ALPHA; /* Napalm only */
216 break;
217 case GL_SRC_ALPHA:
218 dstA = GR_BLEND_SRC_ALPHA; /* Napalm only */
219 break;
220 case GL_ONE_MINUS_SRC_ALPHA:
221 dstA = GR_BLEND_ONE_MINUS_SRC_ALPHA; /* Napalm only */
222 break;
223 case GL_DST_ALPHA:
224 dstA = GR_BLEND_DST_ALPHA; /* Napalm only */
225 break;
226 case GL_ONE_MINUS_DST_ALPHA:
227 dstA = GR_BLEND_ONE_MINUS_DST_ALPHA; /* Napalm only */
228 break;
229 default:
230 dstA = GR_BLEND_ZERO;
231 }
232 } else {
233 /* blend disabled */
234 srcRGB = GR_BLEND_ONE;
235 dstRGB = GR_BLEND_ZERO;
236 srcA = GR_BLEND_ONE;
237 dstA = GR_BLEND_ZERO;
238 }
239
240 if ( fxMesa->Color.AlphaFunc != func ) {
241 fxMesa->Color.AlphaFunc = func;
242 fxMesa->dirty |= TDFX_UPLOAD_ALPHA_TEST;
243 }
244 if ( fxMesa->Color.AlphaRef != ref ) {
245 fxMesa->Color.AlphaRef = ref;
246 fxMesa->dirty |= TDFX_UPLOAD_ALPHA_REF;
247 }
248
249 if ( fxMesa->Color.BlendSrcRGB != srcRGB ||
250 fxMesa->Color.BlendDstRGB != dstRGB ||
251 fxMesa->Color.BlendSrcA != srcA ||
252 fxMesa->Color.BlendDstA != dstA )
253 {
254 fxMesa->Color.BlendSrcRGB = srcRGB;
255 fxMesa->Color.BlendDstRGB = dstRGB;
256 fxMesa->Color.BlendSrcA = srcA;
257 fxMesa->Color.BlendDstA = dstA;
258 fxMesa->dirty |= TDFX_UPLOAD_BLEND_FUNC;
259 }
260 }
261
262 static void tdfxDDAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
263 {
264 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
265
266 FLUSH_BATCH( fxMesa );
267 fxMesa->new_state |= TDFX_NEW_ALPHA;
268 }
269
270 static void tdfxDDBlendEquation( GLcontext *ctx, GLenum mode )
271 {
272 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
273
274 FLUSH_BATCH( fxMesa );
275 fxMesa->new_state |= TDFX_NEW_ALPHA;
276 }
277
278 static void tdfxDDBlendFuncSeparate( GLcontext *ctx,
279 GLenum sfactorRGB, GLenum dfactorRGB,
280 GLenum sfactorA, GLenum dfactorA )
281 {
282 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
283
284 FLUSH_BATCH( fxMesa );
285 fxMesa->new_state |= TDFX_NEW_ALPHA;
286
287 /*
288 * XXX - Voodoo5 seems to suffer from precision problems in some
289 * blend modes. To pass all the conformance tests we'd have to
290 * fall back to software for many modes. Revisit someday.
291 */
292 }
293
294 /* =============================================================
295 * Stipple
296 */
297
298 void tdfxUpdateStipple( GLcontext *ctx )
299 {
300 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
301 GrStippleMode_t mode = GR_STIPPLE_DISABLE;
302
303 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
304 fprintf( stderr, "%s()\n", __FUNCTION__ );
305 }
306
307 FLUSH_BATCH( fxMesa );
308
309 if (ctx->Polygon.StippleFlag) {
310 mode = GR_STIPPLE_PATTERN;
311 }
312
313 if ( fxMesa->Stipple.Mode != mode ) {
314 fxMesa->Stipple.Mode = mode;
315 fxMesa->dirty |= TDFX_UPLOAD_STIPPLE;
316 }
317 }
318
319
320 /* =============================================================
321 * Depth testing
322 */
323
324 static void tdfxUpdateZMode( GLcontext *ctx )
325 {
326 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
327 GrCmpFnc_t func;
328 FxI32 bias;
329 FxBool mask;
330
331 if ( TDFX_DEBUG & DEBUG_VERBOSE_API )
332 fprintf( stderr, "%s()\n", __FUNCTION__ );
333
334
335 bias = (FxI32) (ctx->Polygon.OffsetUnits * TDFX_DEPTH_BIAS_SCALE);
336
337 if ( ctx->Depth.Test ) {
338 switch ( ctx->Depth.Func ) {
339 case GL_NEVER:
340 func = GR_CMP_NEVER;
341 break;
342 case GL_LESS:
343 func = GR_CMP_LESS;
344 break;
345 case GL_LEQUAL:
346 func = GR_CMP_LEQUAL;
347 break;
348 case GL_EQUAL:
349 func = GR_CMP_EQUAL;
350 break;
351 case GL_GEQUAL:
352 func = GR_CMP_GEQUAL;
353 break;
354 case GL_GREATER:
355 func = GR_CMP_GREATER;
356 break;
357 case GL_NOTEQUAL:
358 func = GR_CMP_NOTEQUAL;
359 break;
360 case GL_ALWAYS:
361 default:
362 func = GR_CMP_ALWAYS;
363 break;
364 }
365
366 if ( ctx->Depth.Mask ) {
367 mask = FXTRUE;
368 }
369 else {
370 mask = FXFALSE;
371 }
372 }
373 else {
374 /* depth testing disabled */
375 func = GR_CMP_ALWAYS; /* fragments always pass */
376 mask = FXFALSE; /* zbuffer is not touched */
377 }
378
379 fxMesa->Depth.Clear = (FxU32) (((1 << fxMesa->glCtx->Visual.depthBits) - 1)
380 * ctx->Depth.Clear);
381
382 if ( fxMesa->Depth.Bias != bias ) {
383 fxMesa->Depth.Bias = bias;
384 fxMesa->dirty |= TDFX_UPLOAD_DEPTH_BIAS;
385 }
386 if ( fxMesa->Depth.Func != func ) {
387 fxMesa->Depth.Func = func;
388 fxMesa->dirty |= TDFX_UPLOAD_DEPTH_FUNC | TDFX_UPLOAD_DEPTH_MASK;
389 }
390 if ( fxMesa->Depth.Mask != mask ) {
391 fxMesa->Depth.Mask = mask;
392 fxMesa->dirty |= TDFX_UPLOAD_DEPTH_MASK;
393 }
394 }
395
396 static void tdfxDDDepthFunc( GLcontext *ctx, GLenum func )
397 {
398 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
399
400 FLUSH_BATCH( fxMesa );
401 fxMesa->new_state |= TDFX_NEW_DEPTH;
402 }
403
404 static void tdfxDDDepthMask( GLcontext *ctx, GLboolean flag )
405 {
406 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
407
408 FLUSH_BATCH( fxMesa );
409 fxMesa->new_state |= TDFX_NEW_DEPTH;
410 }
411
412 static void tdfxDDClearDepth( GLcontext *ctx, GLclampd d )
413 {
414 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
415
416 FLUSH_BATCH( fxMesa );
417 fxMesa->new_state |= TDFX_NEW_DEPTH;
418 }
419
420
421
422 /* =============================================================
423 * Stencil
424 */
425
426
427 /* Evaluate all stencil state and make the Glide calls.
428 */
429 static GrStencil_t convertGLStencilOp( GLenum op )
430 {
431 switch ( op ) {
432 case GL_KEEP:
433 return GR_STENCILOP_KEEP;
434 case GL_ZERO:
435 return GR_STENCILOP_ZERO;
436 case GL_REPLACE:
437 return GR_STENCILOP_REPLACE;
438 case GL_INCR:
439 return GR_STENCILOP_INCR_CLAMP;
440 case GL_DECR:
441 return GR_STENCILOP_DECR_CLAMP;
442 case GL_INVERT:
443 return GR_STENCILOP_INVERT;
444 case GL_INCR_WRAP_EXT:
445 return GR_STENCILOP_INCR_WRAP;
446 case GL_DECR_WRAP_EXT:
447 return GR_STENCILOP_DECR_WRAP;
448 default:
449 _mesa_problem( NULL, "bad stencil op in convertGLStencilOp" );
450 }
451 return GR_STENCILOP_KEEP; /* never get, silence compiler warning */
452 }
453
454
455 static void tdfxUpdateStencil( GLcontext *ctx )
456 {
457 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
458
459 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
460 fprintf( stderr, "%s()\n", __FUNCTION__ );
461 }
462
463 if (fxMesa->haveHwStencil) {
464 if (ctx->Stencil.Enabled) {
465 fxMesa->Stencil.Function = ctx->Stencil.Function[0] - GL_NEVER;
466 fxMesa->Stencil.RefValue = ctx->Stencil.Ref[0];
467 fxMesa->Stencil.ValueMask = ctx->Stencil.ValueMask[0];
468 fxMesa->Stencil.WriteMask = ctx->Stencil.WriteMask[0];
469 fxMesa->Stencil.FailFunc = convertGLStencilOp(ctx->Stencil.FailFunc[0]);
470 fxMesa->Stencil.ZFailFunc = convertGLStencilOp(ctx->Stencil.ZFailFunc[0]);
471 fxMesa->Stencil.ZPassFunc = convertGLStencilOp(ctx->Stencil.ZPassFunc[0]);
472 fxMesa->Stencil.Clear = ctx->Stencil.Clear & 0xff;
473 }
474 fxMesa->dirty |= TDFX_UPLOAD_STENCIL;
475 }
476 }
477
478
479 static void tdfxDDStencilFunc( GLcontext *ctx, GLenum func,
480 GLint ref, GLuint mask )
481 {
482 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
483
484 FLUSH_BATCH( fxMesa );
485 fxMesa->new_state |= TDFX_NEW_STENCIL;
486 }
487
488 static void tdfxDDStencilMask( GLcontext *ctx, GLuint mask )
489 {
490 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
491
492 FLUSH_BATCH( fxMesa );
493 fxMesa->new_state |= TDFX_NEW_STENCIL;
494 }
495
496 static void tdfxDDStencilOp( GLcontext *ctx, GLenum sfail,
497 GLenum zfail, GLenum zpass )
498 {
499 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
500
501 FLUSH_BATCH( fxMesa );
502 fxMesa->new_state |= TDFX_NEW_STENCIL;
503 }
504
505
506 /* =============================================================
507 * Fog - orthographic fog still not working
508 */
509
510 static void tdfxUpdateFogAttrib( GLcontext *ctx )
511 {
512 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
513 GrFogMode_t mode;
514 GrColor_t color;
515
516 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
517 fprintf( stderr, "%s()\n", __FUNCTION__ );
518 }
519
520 if ( ctx->Fog.Enabled ) {
521 mode = GR_FOG_WITH_TABLE_ON_Q;
522 } else {
523 mode = GR_FOG_DISABLE;
524 }
525
526 color = TDFXPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F),
527 (GLubyte)(ctx->Fog.Color[1]*255.0F),
528 (GLubyte)(ctx->Fog.Color[2]*255.0F));
529
530 if ( fxMesa->Fog.Mode != mode ) {
531 fxMesa->Fog.Mode = mode;
532 fxMesa->dirty |= TDFX_UPLOAD_FOG_MODE;
533 }
534 if ( fxMesa->Fog.Color != color ) {
535 fxMesa->Fog.Color = color;
536 fxMesa->dirty |= TDFX_UPLOAD_FOG_COLOR;
537 }
538 if ( fxMesa->Fog.TableMode != ctx->Fog.Mode ||
539 fxMesa->Fog.Density != ctx->Fog.Density ||
540 fxMesa->Fog.Near != ctx->Fog.Start ||
541 fxMesa->Fog.Far != ctx->Fog.End )
542 {
543 switch( ctx->Fog.Mode ) {
544 case GL_EXP:
545 fxMesa->Glide.guFogGenerateExp( fxMesa->Fog.Table, ctx->Fog.Density );
546 break;
547 case GL_EXP2:
548 fxMesa->Glide.guFogGenerateExp2( fxMesa->Fog.Table, ctx->Fog.Density);
549 break;
550 case GL_LINEAR:
551 fxMesa->Glide.guFogGenerateLinear( fxMesa->Fog.Table,
552 ctx->Fog.Start, ctx->Fog.End );
553 break;
554 }
555
556 fxMesa->Fog.TableMode = ctx->Fog.Mode;
557 fxMesa->Fog.Density = ctx->Fog.Density;
558 fxMesa->Fog.Near = ctx->Fog.Start;
559 fxMesa->Fog.Far = ctx->Fog.End;
560 fxMesa->dirty |= TDFX_UPLOAD_FOG_TABLE;
561 }
562 }
563
564 static void tdfxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
565 {
566 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
567
568 FLUSH_BATCH( fxMesa );
569 fxMesa->new_state |= TDFX_NEW_FOG;
570 }
571
572
573 /* =============================================================
574 * Clipping
575 */
576
577 static int intersect_rect( XF86DRIClipRectPtr out,
578 const XF86DRIClipRectPtr a,
579 const XF86DRIClipRectPtr b)
580 {
581 *out = *a;
582 if (b->x1 > out->x1) out->x1 = b->x1;
583 if (b->y1 > out->y1) out->y1 = b->y1;
584 if (b->x2 < out->x2) out->x2 = b->x2;
585 if (b->y2 < out->y2) out->y2 = b->y2;
586 if (out->x1 >= out->x2) return 0;
587 if (out->y1 >= out->y2) return 0;
588 return 1;
589 }
590
591
592 /*
593 * Examine XF86 cliprect list and scissor state to recompute our
594 * cliprect list.
595 */
596 void tdfxUpdateClipping( GLcontext *ctx )
597 {
598 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
599 __DRIdrawablePrivate *dPriv = fxMesa->driDrawable;
600
601 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
602 fprintf( stderr, "%s()\n", __FUNCTION__ );
603 }
604
605 assert(ctx);
606 assert(fxMesa);
607 assert(dPriv);
608
609 if ( dPriv->x != fxMesa->x_offset || dPriv->y != fxMesa->y_offset ||
610 dPriv->w != fxMesa->width || dPriv->h != fxMesa->height ) {
611 fxMesa->x_offset = dPriv->x;
612 fxMesa->y_offset = dPriv->y;
613 fxMesa->width = dPriv->w;
614 fxMesa->height = dPriv->h;
615 fxMesa->y_delta =
616 fxMesa->screen_height - fxMesa->y_offset - fxMesa->height;
617 tdfxUpdateViewport( ctx );
618 }
619
620 if (fxMesa->scissoredClipRects && fxMesa->pClipRects) {
621 free(fxMesa->pClipRects);
622 }
623
624 if (ctx->Scissor.Enabled) {
625 /* intersect OpenGL scissor box with all cliprects to make a new
626 * list of cliprects.
627 */
628 XF86DRIClipRectRec scissor;
629 int x1 = ctx->Scissor.X + fxMesa->x_offset;
630 int y1 = fxMesa->screen_height - fxMesa->y_delta
631 - ctx->Scissor.Y - ctx->Scissor.Height;
632 int x2 = x1 + ctx->Scissor.Width;
633 int y2 = y1 + ctx->Scissor.Height;
634 scissor.x1 = MAX2(x1, 0);
635 scissor.y1 = MAX2(y1, 0);
636 scissor.x2 = MAX2(x2, 0);
637 scissor.y2 = MAX2(y2, 0);
638
639 assert(scissor.x2 >= scissor.x1);
640 assert(scissor.y2 >= scissor.y1);
641
642 fxMesa->pClipRects = malloc(dPriv->numClipRects
643 * sizeof(XF86DRIClipRectRec));
644 if (fxMesa->pClipRects) {
645 int i;
646 fxMesa->numClipRects = 0;
647 for (i = 0; i < dPriv->numClipRects; i++) {
648 if (intersect_rect(&fxMesa->pClipRects[fxMesa->numClipRects],
649 &scissor, &dPriv->pClipRects[i])) {
650 fxMesa->numClipRects++;
651 }
652 }
653 fxMesa->scissoredClipRects = GL_TRUE;
654 }
655 else {
656 /* out of memory, forgo scissor */
657 fxMesa->numClipRects = dPriv->numClipRects;
658 fxMesa->pClipRects = dPriv->pClipRects;
659 fxMesa->scissoredClipRects = GL_FALSE;
660 }
661 }
662 else {
663 fxMesa->numClipRects = dPriv->numClipRects;
664 fxMesa->pClipRects = dPriv->pClipRects;
665 fxMesa->scissoredClipRects = GL_FALSE;
666 }
667
668 fxMesa->dirty |= TDFX_UPLOAD_CLIP;
669 }
670
671
672
673 /* =============================================================
674 * Culling
675 */
676
677 void tdfxUpdateCull( GLcontext *ctx )
678 {
679 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
680 GrCullMode_t mode = GR_CULL_DISABLE;
681
682 /* KW: don't need to check raster_primitive here as we don't
683 * attempt to draw lines or points with triangles.
684 */
685 if ( ctx->Polygon.CullFlag ) {
686 switch ( ctx->Polygon.CullFaceMode ) {
687 case GL_FRONT:
688 if ( ctx->Polygon.FrontFace == GL_CCW ) {
689 mode = GR_CULL_POSITIVE;
690 } else {
691 mode = GR_CULL_NEGATIVE;
692 }
693 break;
694
695 case GL_BACK:
696 if ( ctx->Polygon.FrontFace == GL_CCW ) {
697 mode = GR_CULL_NEGATIVE;
698 } else {
699 mode = GR_CULL_POSITIVE;
700 }
701 break;
702
703 case GL_FRONT_AND_BACK:
704 /* Handled as a fallback on triangles in tdfx_tris.c */
705 return;
706
707 default:
708 ASSERT(0);
709 break;
710 }
711 }
712
713 if ( fxMesa->CullMode != mode ) {
714 fxMesa->CullMode = mode;
715 fxMesa->dirty |= TDFX_UPLOAD_CULL;
716 }
717 }
718
719 static void tdfxDDCullFace( GLcontext *ctx, GLenum mode )
720 {
721 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
722
723 FLUSH_BATCH( fxMesa );
724 fxMesa->new_state |= TDFX_NEW_CULL;
725 }
726
727 static void tdfxDDFrontFace( GLcontext *ctx, GLenum mode )
728 {
729 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
730
731 FLUSH_BATCH( fxMesa );
732 fxMesa->new_state |= TDFX_NEW_CULL;
733 }
734
735
736 /* =============================================================
737 * Line drawing.
738 */
739
740 static void tdfxUpdateLine( GLcontext *ctx )
741 {
742 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
743
744 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
745 fprintf( stderr, "%s()\n", __FUNCTION__ );
746 }
747
748 FLUSH_BATCH( fxMesa );
749 fxMesa->dirty |= TDFX_UPLOAD_LINE;
750 }
751
752
753 static void tdfxDDLineWidth( GLcontext *ctx, GLfloat width )
754 {
755 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
756 FLUSH_BATCH( fxMesa );
757 fxMesa->new_state |= TDFX_NEW_LINE;
758 }
759
760
761 /* =============================================================
762 * Color Attributes
763 */
764
765 static void tdfxDDColorMask( GLcontext *ctx,
766 GLboolean r, GLboolean g,
767 GLboolean b, GLboolean a )
768 {
769 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
770
771 FLUSH_BATCH( fxMesa );
772
773 if ( fxMesa->Color.ColorMask[RCOMP] != r ||
774 fxMesa->Color.ColorMask[GCOMP] != g ||
775 fxMesa->Color.ColorMask[BCOMP] != b ||
776 fxMesa->Color.ColorMask[ACOMP] != a ) {
777 fxMesa->Color.ColorMask[RCOMP] = r;
778 fxMesa->Color.ColorMask[GCOMP] = g;
779 fxMesa->Color.ColorMask[BCOMP] = b;
780 fxMesa->Color.ColorMask[ACOMP] = a;
781 fxMesa->dirty |= TDFX_UPLOAD_COLOR_MASK;
782
783 if (ctx->Visual.redBits < 8) {
784 /* Can't do RGB colormasking in 16bpp mode. */
785 /* We can completely ignore the alpha mask. */
786 FALLBACK( fxMesa, TDFX_FALLBACK_COLORMASK, (r != g || g != b) );
787 }
788 }
789 }
790
791
792 static void tdfxDDClearColor( GLcontext *ctx,
793 const GLfloat color[4] )
794 {
795 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
796 GLubyte c[4];
797 FLUSH_BATCH( fxMesa );
798 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
799 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
800 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
801 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
802 fxMesa->Color.ClearColor = TDFXPACKCOLOR888( c[0], c[1], c[2] );
803 fxMesa->Color.ClearAlpha = c[3];
804 }
805
806
807 /* =============================================================
808 * Light Model
809 */
810
811 static void tdfxDDLightModelfv( GLcontext *ctx, GLenum pname,
812 const GLfloat *param )
813 {
814 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
815
816 if ( pname == GL_LIGHT_MODEL_COLOR_CONTROL ) {
817 FALLBACK( fxMesa, TDFX_FALLBACK_SPECULAR,
818 (ctx->Light.Enabled &&
819 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ));
820 }
821 }
822
823 static void tdfxDDShadeModel( GLcontext *ctx, GLenum mode )
824 {
825 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
826
827 /* FIXME: Can we implement native flat shading? */
828 FLUSH_BATCH( fxMesa );
829 fxMesa->new_state |= TDFX_NEW_TEXTURE;
830 }
831
832
833 /* =============================================================
834 * Scissor
835 */
836
837 static void
838 tdfxDDScissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h)
839 {
840 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
841 FLUSH_BATCH( fxMesa );
842 fxMesa->new_state |= TDFX_NEW_CLIP;
843 }
844
845 /* =============================================================
846 * Render
847 */
848
849 static void tdfxUpdateRenderAttrib( GLcontext *ctx )
850 {
851 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
852 FLUSH_BATCH( fxMesa );
853 fxMesa->dirty |= TDFX_UPLOAD_RENDER_BUFFER;
854 }
855
856 /* =============================================================
857 * Viewport
858 */
859
860 void tdfxUpdateViewport( GLcontext *ctx )
861 {
862 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
863 const GLfloat *v = ctx->Viewport._WindowMap.m;
864 GLfloat *m = fxMesa->hw_viewport;
865
866 m[MAT_SX] = v[MAT_SX];
867 m[MAT_TX] = v[MAT_TX] + fxMesa->x_offset + TRI_X_OFFSET;
868 m[MAT_SY] = v[MAT_SY];
869 m[MAT_TY] = v[MAT_TY] + fxMesa->y_delta + TRI_Y_OFFSET;
870 m[MAT_SZ] = v[MAT_SZ];
871 m[MAT_TZ] = v[MAT_TZ];
872
873 fxMesa->SetupNewInputs |= VERT_BIT_POS;
874 }
875
876
877 static void tdfxDDViewport( GLcontext *ctx, GLint x, GLint y,
878 GLsizei w, GLsizei h )
879 {
880 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
881 FLUSH_BATCH( fxMesa );
882 fxMesa->new_state |= TDFX_NEW_VIEWPORT;
883 }
884
885
886 static void tdfxDDDepthRange( GLcontext *ctx, GLclampd nearVal, GLclampd farVal )
887 {
888 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
889 FLUSH_BATCH( fxMesa );
890 fxMesa->new_state |= TDFX_NEW_VIEWPORT;
891 }
892
893
894 /* =============================================================
895 * State enable/disable
896 */
897
898 static void tdfxDDEnable( GLcontext *ctx, GLenum cap, GLboolean state )
899 {
900 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
901
902 switch ( cap ) {
903 case GL_ALPHA_TEST:
904 FLUSH_BATCH( fxMesa );
905 fxMesa->new_state |= TDFX_NEW_ALPHA;
906 break;
907
908 case GL_BLEND:
909 FLUSH_BATCH( fxMesa );
910 fxMesa->new_state |= TDFX_NEW_ALPHA;
911 FALLBACK( fxMesa, TDFX_FALLBACK_LOGICOP,
912 (ctx->Color.ColorLogicOpEnabled &&
913 ctx->Color.LogicOp != GL_COPY));
914 break;
915
916 case GL_CULL_FACE:
917 FLUSH_BATCH( fxMesa );
918 fxMesa->new_state |= TDFX_NEW_CULL;
919 break;
920
921 case GL_DEPTH_TEST:
922 FLUSH_BATCH( fxMesa );
923 fxMesa->new_state |= TDFX_NEW_DEPTH;
924 break;
925
926 case GL_DITHER:
927 FLUSH_BATCH( fxMesa );
928 if ( state ) {
929 fxMesa->Color.Dither = GR_DITHER_2x2;
930 } else {
931 fxMesa->Color.Dither = GR_DITHER_DISABLE;
932 }
933 fxMesa->dirty |= TDFX_UPLOAD_DITHER;
934 break;
935
936 case GL_FOG:
937 FLUSH_BATCH( fxMesa );
938 fxMesa->new_state |= TDFX_NEW_FOG;
939 break;
940
941 case GL_COLOR_LOGIC_OP:
942 FALLBACK( fxMesa, TDFX_FALLBACK_LOGICOP,
943 (ctx->Color.ColorLogicOpEnabled &&
944 ctx->Color.LogicOp != GL_COPY));
945 break;
946
947 case GL_LIGHTING:
948 FALLBACK( fxMesa, TDFX_FALLBACK_SPECULAR,
949 (ctx->Light.Enabled &&
950 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ));
951 break;
952
953 case GL_LINE_SMOOTH:
954 FLUSH_BATCH( fxMesa );
955 fxMesa->new_state |= TDFX_NEW_LINE;
956 break;
957
958 case GL_LINE_STIPPLE:
959 FALLBACK(fxMesa, TDFX_FALLBACK_LINE_STIPPLE, state);
960 break;
961
962 case GL_POLYGON_STIPPLE:
963 FLUSH_BATCH(fxMesa);
964 fxMesa->new_state |= TDFX_NEW_STIPPLE;
965 break;
966
967 case GL_SCISSOR_TEST:
968 FLUSH_BATCH( fxMesa );
969 fxMesa->new_state |= TDFX_NEW_CLIP;
970 break;
971
972 case GL_STENCIL_TEST:
973 FLUSH_BATCH( fxMesa );
974 FALLBACK( fxMesa, TDFX_FALLBACK_STENCIL, state && !fxMesa->haveHwStencil);
975 break;
976
977 case GL_TEXTURE_1D:
978 case GL_TEXTURE_3D:
979 FLUSH_BATCH( fxMesa );
980 FALLBACK( fxMesa, TDFX_FALLBACK_TEXTURE_1D_3D, state); /* wrong */
981 fxMesa->new_state |= TDFX_NEW_TEXTURE;
982 break;
983
984 case GL_TEXTURE_2D:
985 FLUSH_BATCH( fxMesa );
986 fxMesa->new_state |= TDFX_NEW_TEXTURE;
987 break;
988
989 default:
990 return;
991 }
992 }
993
994
995
996 /* Set the buffer used for drawing */
997 /* XXX support for separate read/draw buffers hasn't been tested */
998 static void tdfxDDDrawBuffer( GLcontext *ctx, GLenum mode )
999 {
1000 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1001
1002 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
1003 fprintf( stderr, "%s()\n", __FUNCTION__ );
1004 }
1005
1006 FLUSH_BATCH( fxMesa );
1007
1008 /*
1009 * _DrawDestMask is easier to cope with than <mode>.
1010 */
1011 switch ( ctx->Color._DrawDestMask ) {
1012 case FRONT_LEFT_BIT:
1013 fxMesa->DrawBuffer = fxMesa->ReadBuffer = GR_BUFFER_FRONTBUFFER;
1014 fxMesa->new_state |= TDFX_NEW_RENDER;
1015 FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_FALSE );
1016 break;
1017 case BACK_LEFT_BIT:
1018 fxMesa->DrawBuffer = fxMesa->ReadBuffer = GR_BUFFER_BACKBUFFER;
1019 fxMesa->new_state |= TDFX_NEW_RENDER;
1020 FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_FALSE );
1021 break;
1022 case 0:
1023 FX_grColorMaskv( ctx, false4 );
1024 FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_FALSE );
1025 break;
1026 default:
1027 FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_TRUE );
1028 break;
1029 }
1030
1031 /* We want to update the s/w rast state too so that tdfxDDSetBuffer()
1032 * gets called.
1033 */
1034 _swrast_DrawBuffer(ctx, mode);
1035 }
1036
1037
1038 static void tdfxDDReadBuffer( GLcontext *ctx, GLenum mode )
1039 {
1040 /* XXX ??? */
1041 }
1042
1043
1044 /* =============================================================
1045 * Polygon stipple
1046 */
1047
1048 static void tdfxDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
1049 {
1050 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1051 const GLubyte *m = mask;
1052 GLubyte q[4];
1053 int i,j,k;
1054 GLboolean allBitsSet;
1055
1056 /* int active = (ctx->Polygon.StippleFlag && */
1057 /* fxMesa->reduced_prim == GL_TRIANGLES); */
1058
1059 FLUSH_BATCH(fxMesa);
1060 fxMesa->Stipple.Pattern = 0xffffffff;
1061 fxMesa->dirty |= TDFX_UPLOAD_STIPPLE;
1062 fxMesa->new_state |= TDFX_NEW_STIPPLE;
1063
1064 /* Check if the stipple pattern is fully opaque. If so, use software
1065 * rendering. This basically a trick to make sure the OpenGL conformance
1066 * test passes.
1067 */
1068 allBitsSet = GL_TRUE;
1069 for (i = 0; i < 32; i++) {
1070 if (((GLuint *) mask)[i] != 0xffffffff) {
1071 allBitsSet = GL_FALSE;
1072 break;
1073 }
1074 }
1075 if (allBitsSet) {
1076 fxMesa->haveHwStipple = GL_FALSE;
1077 return;
1078 }
1079
1080 q[0] = mask[0];
1081 q[1] = mask[4];
1082 q[2] = mask[8];
1083 q[3] = mask[12];
1084
1085 for (k = 0 ; k < 8 ; k++)
1086 for (j = 0 ; j < 4; j++)
1087 for (i = 0 ; i < 4 ; i++,m++) {
1088 if (*m != q[j]) {
1089 fxMesa->haveHwStipple = GL_FALSE;
1090 return;
1091 }
1092 }
1093
1094 fxMesa->haveHwStipple = GL_TRUE;
1095 fxMesa->Stipple.Pattern = ( (q[0] << 0) |
1096 (q[1] << 8) |
1097 (q[2] << 16) |
1098 (q[3] << 24) );
1099 }
1100
1101
1102
1103 static void tdfxDDRenderMode( GLcontext *ctx, GLenum mode )
1104 {
1105 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1106 FALLBACK( fxMesa, TDFX_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1107 }
1108
1109
1110
1111 static void tdfxDDPrintState( const char *msg, GLuint flags )
1112 {
1113 fprintf( stderr,
1114 "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s\n",
1115 msg,
1116 flags,
1117 (flags & TDFX_NEW_COLOR) ? "color, " : "",
1118 (flags & TDFX_NEW_ALPHA) ? "alpha, " : "",
1119 (flags & TDFX_NEW_DEPTH) ? "depth, " : "",
1120 (flags & TDFX_NEW_RENDER) ? "render, " : "",
1121 (flags & TDFX_NEW_FOG) ? "fog, " : "",
1122 (flags & TDFX_NEW_STENCIL) ? "stencil, " : "",
1123 (flags & TDFX_NEW_STIPPLE) ? "stipple, " : "",
1124 (flags & TDFX_NEW_CLIP) ? "clip, " : "",
1125 (flags & TDFX_NEW_VIEWPORT) ? "viewport, " : "",
1126 (flags & TDFX_NEW_CULL) ? "cull, " : "",
1127 (flags & TDFX_NEW_GLIDE) ? "glide, " : "",
1128 (flags & TDFX_NEW_TEXTURE) ? "texture, " : "",
1129 (flags & TDFX_NEW_CONTEXT) ? "context, " : "");
1130 }
1131
1132
1133
1134 void tdfxDDUpdateHwState( GLcontext *ctx )
1135 {
1136 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1137 int new_state = fxMesa->new_state;
1138
1139 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
1140 fprintf( stderr, "%s()\n", __FUNCTION__ );
1141 }
1142
1143 if ( new_state )
1144 {
1145 FLUSH_BATCH( fxMesa );
1146
1147 fxMesa->new_state = 0;
1148
1149 if ( 0 )
1150 tdfxDDPrintState( "tdfxUpdateHwState", new_state );
1151
1152 /* Update the various parts of the context's state.
1153 */
1154 if ( new_state & TDFX_NEW_ALPHA ) {
1155 tdfxUpdateAlphaMode( ctx );
1156 }
1157
1158 if ( new_state & TDFX_NEW_DEPTH )
1159 tdfxUpdateZMode( ctx );
1160
1161 if ( new_state & TDFX_NEW_FOG )
1162 tdfxUpdateFogAttrib( ctx );
1163
1164 if ( new_state & TDFX_NEW_CLIP )
1165 tdfxUpdateClipping( ctx );
1166
1167 if ( new_state & TDFX_NEW_STIPPLE )
1168 tdfxUpdateStipple( ctx );
1169
1170 if ( new_state & TDFX_NEW_CULL )
1171 tdfxUpdateCull( ctx );
1172
1173 if ( new_state & TDFX_NEW_LINE )
1174 tdfxUpdateLine( ctx );
1175
1176 if ( new_state & TDFX_NEW_VIEWPORT )
1177 tdfxUpdateViewport( ctx );
1178
1179 if ( new_state & TDFX_NEW_RENDER )
1180 tdfxUpdateRenderAttrib( ctx );
1181
1182 if ( new_state & TDFX_NEW_STENCIL )
1183 tdfxUpdateStencil( ctx );
1184
1185 if ( new_state & TDFX_NEW_TEXTURE ) {
1186 tdfxUpdateTextureState( ctx );
1187 }
1188 else if ( new_state & TDFX_NEW_TEXTURE_BIND ) {
1189 tdfxUpdateTextureBinding( ctx );
1190 }
1191 }
1192
1193 if ( 0 ) {
1194 FxI32 bias = (FxI32) (ctx->Polygon.OffsetUnits * TDFX_DEPTH_BIAS_SCALE);
1195
1196 if ( fxMesa->Depth.Bias != bias ) {
1197 fxMesa->Depth.Bias = bias;
1198 fxMesa->dirty |= TDFX_UPLOAD_DEPTH_BIAS;
1199 }
1200 }
1201
1202 if ( fxMesa->dirty ) {
1203 LOCK_HARDWARE( fxMesa );
1204 tdfxEmitHwStateLocked( fxMesa );
1205 UNLOCK_HARDWARE( fxMesa );
1206 }
1207 }
1208
1209
1210 static void tdfxDDInvalidateState( GLcontext *ctx, GLuint new_state )
1211 {
1212 _swrast_InvalidateState( ctx, new_state );
1213 _swsetup_InvalidateState( ctx, new_state );
1214 _ac_InvalidateState( ctx, new_state );
1215 _tnl_InvalidateState( ctx, new_state );
1216 TDFX_CONTEXT(ctx)->new_gl_state |= new_state;
1217 }
1218
1219
1220
1221 /* Initialize the context's Glide state mirror. These values will be
1222 * used as Glide function call parameters when the time comes.
1223 */
1224 void tdfxInitState( tdfxContextPtr fxMesa )
1225 {
1226 GLcontext *ctx = fxMesa->glCtx;
1227 GLint i;
1228
1229 fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1230 fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_NONE;
1231 fxMesa->ColorCombine.Local = GR_COMBINE_LOCAL_ITERATED;
1232 fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_NONE;
1233 fxMesa->ColorCombine.Invert = FXFALSE;
1234 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1235 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE;
1236 fxMesa->AlphaCombine.Local = GR_COMBINE_LOCAL_ITERATED;
1237 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
1238 fxMesa->AlphaCombine.Invert = FXFALSE;
1239
1240 fxMesa->ColorCombineExt.SourceA = GR_CMBX_ITRGB;
1241 fxMesa->ColorCombineExt.ModeA = GR_FUNC_MODE_X;
1242 fxMesa->ColorCombineExt.SourceB = GR_CMBX_ZERO;
1243 fxMesa->ColorCombineExt.ModeB = GR_FUNC_MODE_ZERO;
1244 fxMesa->ColorCombineExt.SourceC = GR_CMBX_ZERO;
1245 fxMesa->ColorCombineExt.InvertC = FXTRUE;
1246 fxMesa->ColorCombineExt.SourceD = GR_CMBX_ZERO;
1247 fxMesa->ColorCombineExt.InvertD = FXFALSE;
1248 fxMesa->ColorCombineExt.Shift = 0;
1249 fxMesa->ColorCombineExt.Invert = FXFALSE;
1250 fxMesa->AlphaCombineExt.SourceA = GR_CMBX_ITALPHA;
1251 fxMesa->AlphaCombineExt.ModeA = GR_FUNC_MODE_X;
1252 fxMesa->AlphaCombineExt.SourceB = GR_CMBX_ZERO;
1253 fxMesa->AlphaCombineExt.ModeB = GR_FUNC_MODE_ZERO;
1254 fxMesa->AlphaCombineExt.SourceC = GR_CMBX_ZERO;
1255 fxMesa->AlphaCombineExt.InvertC = FXTRUE;
1256 fxMesa->AlphaCombineExt.SourceD = GR_CMBX_ZERO;
1257 fxMesa->AlphaCombineExt.InvertD = FXFALSE;
1258 fxMesa->AlphaCombineExt.Shift = 0;
1259 fxMesa->AlphaCombineExt.Invert = FXFALSE;
1260
1261 fxMesa->sScale0 = fxMesa->tScale0 = 1.0;
1262 fxMesa->sScale1 = fxMesa->tScale1 = 1.0;
1263
1264 fxMesa->TexPalette.Type = 0;
1265 fxMesa->TexPalette.Data = NULL;
1266
1267 for ( i = 0 ; i < TDFX_NUM_TMU ; i++ ) {
1268 fxMesa->TexSource[i].StartAddress = 0;
1269 fxMesa->TexSource[i].EvenOdd = GR_MIPMAPLEVELMASK_EVEN;
1270 fxMesa->TexSource[i].Info = NULL;
1271
1272 fxMesa->TexCombine[i].FunctionRGB = 0;
1273 fxMesa->TexCombine[i].FactorRGB = 0;
1274 fxMesa->TexCombine[i].FunctionAlpha = 0;
1275 fxMesa->TexCombine[i].FactorAlpha = 0;
1276 fxMesa->TexCombine[i].InvertRGB = FXFALSE;
1277 fxMesa->TexCombine[i].InvertAlpha = FXFALSE;
1278
1279 fxMesa->TexCombineExt[i].Alpha.SourceA = 0;
1280 /* XXX more state to init here */
1281 fxMesa->TexCombineExt[i].Color.SourceA = 0;
1282 fxMesa->TexCombineExt[i].EnvColor = 0x0;
1283
1284 fxMesa->TexParams[i].sClamp = GR_TEXTURECLAMP_WRAP;
1285 fxMesa->TexParams[i].tClamp = GR_TEXTURECLAMP_WRAP;
1286 fxMesa->TexParams[i].minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
1287 fxMesa->TexParams[i].magFilt = GR_TEXTUREFILTER_BILINEAR;
1288 fxMesa->TexParams[i].mmMode = GR_MIPMAP_DISABLE;
1289 fxMesa->TexParams[i].LODblend = FXFALSE;
1290 fxMesa->TexParams[i].LodBias = 0.0;
1291
1292 fxMesa->TexState.EnvMode[i] = ~0;
1293 fxMesa->TexState.TexFormat[i] = ~0;
1294 fxMesa->TexState.Enabled[i] = 0;
1295 }
1296
1297 if ( ctx->Visual.doubleBufferMode) {
1298 fxMesa->DrawBuffer = GR_BUFFER_BACKBUFFER;
1299 fxMesa->ReadBuffer = GR_BUFFER_BACKBUFFER;
1300 } else {
1301 fxMesa->DrawBuffer = GR_BUFFER_FRONTBUFFER;
1302 fxMesa->ReadBuffer = GR_BUFFER_FRONTBUFFER;
1303 }
1304
1305 fxMesa->Color.ClearColor = 0x00000000;
1306 fxMesa->Color.ClearAlpha = 0x00;
1307 fxMesa->Color.ColorMask[RCOMP] = FXTRUE;
1308 fxMesa->Color.ColorMask[BCOMP] = FXTRUE;
1309 fxMesa->Color.ColorMask[GCOMP] = FXTRUE;
1310 fxMesa->Color.ColorMask[ACOMP] = FXTRUE;
1311 fxMesa->Color.MonoColor = 0xffffffff;
1312
1313 fxMesa->Color.AlphaFunc = GR_CMP_ALWAYS;
1314 fxMesa->Color.AlphaRef = 0x00;
1315 fxMesa->Color.BlendSrcRGB = GR_BLEND_ONE;
1316 fxMesa->Color.BlendDstRGB = GR_BLEND_ZERO;
1317 fxMesa->Color.BlendSrcA = GR_BLEND_ONE;
1318 fxMesa->Color.BlendSrcA = GR_BLEND_ZERO;
1319
1320 fxMesa->Color.Dither = GR_DITHER_2x2;
1321
1322 if ( fxMesa->glCtx->Visual.depthBits > 0 ) {
1323 fxMesa->Depth.Mode = GR_DEPTHBUFFER_ZBUFFER;
1324 } else {
1325 fxMesa->Depth.Mode = GR_DEPTHBUFFER_DISABLE;
1326 }
1327 fxMesa->Depth.Bias = 0;
1328 fxMesa->Depth.Func = GR_CMP_LESS;
1329 fxMesa->Depth.Clear = 0; /* computed later */
1330 fxMesa->Depth.Mask = FXTRUE;
1331
1332
1333 fxMesa->Fog.Mode = GR_FOG_DISABLE;
1334 fxMesa->Fog.Color = 0x00000000;
1335 fxMesa->Fog.Table = NULL;
1336 fxMesa->Fog.Density = 1.0;
1337 fxMesa->Fog.Near = 1.0;
1338 fxMesa->Fog.Far = 1.0;
1339
1340 fxMesa->Stencil.Function = GR_CMP_ALWAYS;
1341 fxMesa->Stencil.RefValue = 0;
1342 fxMesa->Stencil.ValueMask = 0xff;
1343 fxMesa->Stencil.WriteMask = 0xff;
1344 fxMesa->Stencil.FailFunc = 0;
1345 fxMesa->Stencil.ZFailFunc = 0;
1346 fxMesa->Stencil.ZPassFunc = 0;
1347 fxMesa->Stencil.Clear = 0;
1348
1349 fxMesa->Stipple.Mode = GR_STIPPLE_DISABLE;
1350 fxMesa->Stipple.Pattern = 0xffffffff;
1351
1352 fxMesa->Scissor.minX = 0;
1353 fxMesa->Scissor.minY = 0;
1354 fxMesa->Scissor.maxX = 0;
1355 fxMesa->Scissor.maxY = 0;
1356
1357 fxMesa->Viewport.Mode = GR_WINDOW_COORDS;
1358 fxMesa->Viewport.X = 0;
1359 fxMesa->Viewport.Y = 0;
1360 fxMesa->Viewport.Width = 0;
1361 fxMesa->Viewport.Height = 0;
1362 fxMesa->Viewport.Near = 0.0;
1363 fxMesa->Viewport.Far = 0.0;
1364
1365 fxMesa->CullMode = GR_CULL_DISABLE;
1366
1367 fxMesa->Glide.ColorFormat = GR_COLORFORMAT_ABGR;
1368 fxMesa->Glide.Origin = GR_ORIGIN_LOWER_LEFT;
1369 fxMesa->Glide.Initialized = FXFALSE;
1370 }
1371
1372
1373
1374 void tdfxDDInitStateFuncs( GLcontext *ctx )
1375 {
1376 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1377
1378 ctx->Driver.UpdateState = tdfxDDInvalidateState;
1379
1380
1381 /* State notification callbacks:
1382 */
1383 ctx->Driver.ClearColor = tdfxDDClearColor;
1384 ctx->Driver.DrawBuffer = tdfxDDDrawBuffer;
1385 ctx->Driver.ReadBuffer = tdfxDDReadBuffer;
1386
1387 ctx->Driver.ColorMask = tdfxDDColorMask;
1388
1389 ctx->Driver.AlphaFunc = tdfxDDAlphaFunc;
1390 ctx->Driver.BlendEquation = tdfxDDBlendEquation;
1391 ctx->Driver.BlendFuncSeparate = tdfxDDBlendFuncSeparate;
1392 ctx->Driver.ClearDepth = tdfxDDClearDepth;
1393 ctx->Driver.CullFace = tdfxDDCullFace;
1394 ctx->Driver.FrontFace = tdfxDDFrontFace;
1395 ctx->Driver.DepthFunc = tdfxDDDepthFunc;
1396 ctx->Driver.DepthMask = tdfxDDDepthMask;
1397 ctx->Driver.DepthRange = tdfxDDDepthRange;
1398 ctx->Driver.Enable = tdfxDDEnable;
1399 ctx->Driver.Fogfv = tdfxDDFogfv;
1400 ctx->Driver.LightModelfv = tdfxDDLightModelfv;
1401 ctx->Driver.LineWidth = tdfxDDLineWidth;
1402 ctx->Driver.PolygonStipple = tdfxDDPolygonStipple;
1403 ctx->Driver.RenderMode = tdfxDDRenderMode;
1404 ctx->Driver.Scissor = tdfxDDScissor;
1405 ctx->Driver.ShadeModel = tdfxDDShadeModel;
1406
1407 /* ctx->Driver.GetTexImage = tdfxDDGetTexImage; */
1408 ctx->Driver.UpdateTexturePalette = tdfxDDTexturePalette;
1409
1410 if ( fxMesa->haveHwStencil ) {
1411 ctx->Driver.StencilFunc = tdfxDDStencilFunc;
1412 ctx->Driver.StencilMask = tdfxDDStencilMask;
1413 ctx->Driver.StencilOp = tdfxDDStencilOp;
1414 }
1415
1416 ctx->Driver.Viewport = tdfxDDViewport;
1417
1418 /* Swrast hooks for imaging extensions:
1419 */
1420 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
1421 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
1422 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
1423 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
1424 }