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