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