42cb5dfaa383f94e4bc1c73e0f28b7cc2c2e199d
[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 "vbo/vbo.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 dstRGB = GR_BLEND_SAME_COLOR_EXT;
193 break;
194 }
195 case GL_ONE_MINUS_DST_COLOR:
196 if (isNapalm) {
197 dstRGB = 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->DrawBuffer->_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] & 0xff;
466 fxMesa->Stencil.ValueMask = ctx->Stencil.ValueMask[0] & 0xff;
467 fxMesa->Stencil.WriteMask = ctx->Stencil.WriteMask[0] & 0xff;
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
479 tdfxDDStencilFuncSeparate( GLcontext *ctx, GLenum face, 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
489 tdfxDDStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
490 {
491 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
492
493 FLUSH_BATCH( fxMesa );
494 fxMesa->new_state |= TDFX_NEW_STENCIL;
495 }
496
497 static void
498 tdfxDDStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum sfail,
499 GLenum zfail, GLenum zpass )
500 {
501 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
502
503 FLUSH_BATCH( fxMesa );
504 fxMesa->new_state |= TDFX_NEW_STENCIL;
505 }
506
507
508 /* =============================================================
509 * Fog - orthographic fog still not working
510 */
511
512 static void tdfxUpdateFogAttrib( GLcontext *ctx )
513 {
514 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
515 GrFogMode_t mode;
516 GrColor_t color;
517
518 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
519 fprintf( stderr, "%s()\n", __FUNCTION__ );
520 }
521
522 if ( ctx->Fog.Enabled ) {
523 if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) {
524 mode = GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT;
525 } else {
526 mode = GR_FOG_WITH_TABLE_ON_Q;
527 }
528 } else {
529 mode = GR_FOG_DISABLE;
530 }
531
532 color = TDFXPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F),
533 (GLubyte)(ctx->Fog.Color[1]*255.0F),
534 (GLubyte)(ctx->Fog.Color[2]*255.0F));
535
536 if ( fxMesa->Fog.Mode != mode ) {
537 fxMesa->Fog.Mode = mode;
538 fxMesa->dirty |= TDFX_UPLOAD_FOG_MODE;
539 fxMesa->dirty |= TDFX_UPLOAD_VERTEX_LAYOUT;/*JJJ*/
540 }
541 if ( fxMesa->Fog.Color != color ) {
542 fxMesa->Fog.Color = color;
543 fxMesa->dirty |= TDFX_UPLOAD_FOG_COLOR;
544 }
545 if ( fxMesa->Fog.TableMode != ctx->Fog.Mode ||
546 fxMesa->Fog.Density != ctx->Fog.Density ||
547 fxMesa->Fog.Near != ctx->Fog.Start ||
548 fxMesa->Fog.Far != ctx->Fog.End )
549 {
550 switch( ctx->Fog.Mode ) {
551 case GL_EXP:
552 fxMesa->Glide.guFogGenerateExp( fxMesa->Fog.Table, ctx->Fog.Density );
553 break;
554 case GL_EXP2:
555 fxMesa->Glide.guFogGenerateExp2( fxMesa->Fog.Table, ctx->Fog.Density);
556 break;
557 case GL_LINEAR:
558 fxMesa->Glide.guFogGenerateLinear( fxMesa->Fog.Table,
559 ctx->Fog.Start, ctx->Fog.End );
560 break;
561 }
562
563 fxMesa->Fog.TableMode = ctx->Fog.Mode;
564 fxMesa->Fog.Density = ctx->Fog.Density;
565 fxMesa->Fog.Near = ctx->Fog.Start;
566 fxMesa->Fog.Far = ctx->Fog.End;
567 fxMesa->dirty |= TDFX_UPLOAD_FOG_TABLE;
568 }
569 }
570
571 static void tdfxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
572 {
573 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
574
575 FLUSH_BATCH( fxMesa );
576 fxMesa->new_state |= TDFX_NEW_FOG;
577
578 switch (pname) {
579 case GL_FOG_COORDINATE_SOURCE_EXT: {
580 GLenum p = (GLenum)*param;
581 if (p == GL_FOG_COORDINATE_EXT) {
582 _swrast_allow_vertex_fog(ctx, GL_TRUE);
583 _swrast_allow_pixel_fog(ctx, GL_FALSE);
584 _tnl_allow_vertex_fog( ctx, GL_TRUE);
585 _tnl_allow_pixel_fog( ctx, GL_FALSE);
586 } else {
587 _swrast_allow_vertex_fog(ctx, GL_FALSE);
588 _swrast_allow_pixel_fog(ctx, GL_TRUE);
589 _tnl_allow_vertex_fog( ctx, GL_FALSE);
590 _tnl_allow_pixel_fog( ctx, GL_TRUE);
591 }
592 break;
593 }
594 default:
595 ;
596 }
597 }
598
599
600 /* =============================================================
601 * Clipping
602 */
603
604 static int intersect_rect( drm_clip_rect_t *out,
605 const drm_clip_rect_t *a,
606 const drm_clip_rect_t *b)
607 {
608 *out = *a;
609 if (b->x1 > out->x1) out->x1 = b->x1;
610 if (b->y1 > out->y1) out->y1 = b->y1;
611 if (b->x2 < out->x2) out->x2 = b->x2;
612 if (b->y2 < out->y2) out->y2 = b->y2;
613 if (out->x1 >= out->x2) return 0;
614 if (out->y1 >= out->y2) return 0;
615 return 1;
616 }
617
618
619 /*
620 * Examine XF86 cliprect list and scissor state to recompute our
621 * cliprect list.
622 */
623 void tdfxUpdateClipping( GLcontext *ctx )
624 {
625 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
626 __DRIdrawablePrivate *dPriv = fxMesa->driDrawable;
627
628 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
629 fprintf( stderr, "%s()\n", __FUNCTION__ );
630 }
631
632 assert(ctx);
633 assert(fxMesa);
634 assert(dPriv);
635
636 if ( dPriv->x != fxMesa->x_offset || dPriv->y != fxMesa->y_offset ||
637 dPriv->w != fxMesa->width || dPriv->h != fxMesa->height ) {
638 fxMesa->x_offset = dPriv->x;
639 fxMesa->y_offset = dPriv->y;
640 fxMesa->width = dPriv->w;
641 fxMesa->height = dPriv->h;
642 fxMesa->y_delta =
643 fxMesa->screen_height - fxMesa->y_offset - fxMesa->height;
644 tdfxUpdateViewport( ctx );
645 }
646
647 if (fxMesa->scissoredClipRects && fxMesa->pClipRects) {
648 free(fxMesa->pClipRects);
649 }
650
651 if (ctx->Scissor.Enabled) {
652 /* intersect OpenGL scissor box with all cliprects to make a new
653 * list of cliprects.
654 */
655 drm_clip_rect_t scissor;
656 int x1 = ctx->Scissor.X + fxMesa->x_offset;
657 int y1 = fxMesa->screen_height - fxMesa->y_delta
658 - ctx->Scissor.Y - ctx->Scissor.Height;
659 int x2 = x1 + ctx->Scissor.Width;
660 int y2 = y1 + ctx->Scissor.Height;
661 scissor.x1 = MAX2(x1, 0);
662 scissor.y1 = MAX2(y1, 0);
663 scissor.x2 = MAX2(x2, 0);
664 scissor.y2 = MAX2(y2, 0);
665
666 assert(scissor.x2 >= scissor.x1);
667 assert(scissor.y2 >= scissor.y1);
668
669 fxMesa->pClipRects = malloc(dPriv->numClipRects
670 * sizeof(drm_clip_rect_t));
671 if (fxMesa->pClipRects) {
672 int i;
673 fxMesa->numClipRects = 0;
674 for (i = 0; i < dPriv->numClipRects; i++) {
675 if (intersect_rect(&fxMesa->pClipRects[fxMesa->numClipRects],
676 &scissor, &dPriv->pClipRects[i])) {
677 fxMesa->numClipRects++;
678 }
679 }
680 fxMesa->scissoredClipRects = GL_TRUE;
681 }
682 else {
683 /* out of memory, forgo scissor */
684 fxMesa->numClipRects = dPriv->numClipRects;
685 fxMesa->pClipRects = dPriv->pClipRects;
686 fxMesa->scissoredClipRects = GL_FALSE;
687 }
688 }
689 else {
690 fxMesa->numClipRects = dPriv->numClipRects;
691 fxMesa->pClipRects = dPriv->pClipRects;
692 fxMesa->scissoredClipRects = GL_FALSE;
693 }
694
695 fxMesa->dirty |= TDFX_UPLOAD_CLIP;
696 }
697
698
699
700 /* =============================================================
701 * Culling
702 */
703
704 void tdfxUpdateCull( GLcontext *ctx )
705 {
706 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
707 GrCullMode_t mode = GR_CULL_DISABLE;
708
709 /* KW: don't need to check raster_primitive here as we don't
710 * attempt to draw lines or points with triangles.
711 */
712 if ( ctx->Polygon.CullFlag ) {
713 switch ( ctx->Polygon.CullFaceMode ) {
714 case GL_FRONT:
715 if ( ctx->Polygon.FrontFace == GL_CCW ) {
716 mode = GR_CULL_POSITIVE;
717 } else {
718 mode = GR_CULL_NEGATIVE;
719 }
720 break;
721
722 case GL_BACK:
723 if ( ctx->Polygon.FrontFace == GL_CCW ) {
724 mode = GR_CULL_NEGATIVE;
725 } else {
726 mode = GR_CULL_POSITIVE;
727 }
728 break;
729
730 case GL_FRONT_AND_BACK:
731 /* Handled as a fallback on triangles in tdfx_tris.c */
732 return;
733
734 default:
735 ASSERT(0);
736 break;
737 }
738 }
739
740 if ( fxMesa->CullMode != mode ) {
741 fxMesa->CullMode = mode;
742 fxMesa->dirty |= TDFX_UPLOAD_CULL;
743 }
744 }
745
746 static void tdfxDDCullFace( GLcontext *ctx, GLenum mode )
747 {
748 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
749
750 FLUSH_BATCH( fxMesa );
751 fxMesa->new_state |= TDFX_NEW_CULL;
752 }
753
754 static void tdfxDDFrontFace( GLcontext *ctx, GLenum mode )
755 {
756 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
757
758 FLUSH_BATCH( fxMesa );
759 fxMesa->new_state |= TDFX_NEW_CULL;
760 }
761
762
763 /* =============================================================
764 * Line drawing.
765 */
766
767 static void tdfxUpdateLine( GLcontext *ctx )
768 {
769 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
770
771 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
772 fprintf( stderr, "%s()\n", __FUNCTION__ );
773 }
774
775 FLUSH_BATCH( fxMesa );
776 fxMesa->dirty |= TDFX_UPLOAD_LINE;
777 }
778
779
780 static void tdfxDDLineWidth( GLcontext *ctx, GLfloat width )
781 {
782 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
783 FLUSH_BATCH( fxMesa );
784 fxMesa->new_state |= TDFX_NEW_LINE;
785 }
786
787
788 /* =============================================================
789 * Color Attributes
790 */
791
792 static void tdfxDDColorMask( GLcontext *ctx,
793 GLboolean r, GLboolean g,
794 GLboolean b, GLboolean a )
795 {
796 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
797
798 FLUSH_BATCH( fxMesa );
799
800 if ( fxMesa->Color.ColorMask[RCOMP] != r ||
801 fxMesa->Color.ColorMask[GCOMP] != g ||
802 fxMesa->Color.ColorMask[BCOMP] != b ||
803 fxMesa->Color.ColorMask[ACOMP] != a ) {
804 fxMesa->Color.ColorMask[RCOMP] = r;
805 fxMesa->Color.ColorMask[GCOMP] = g;
806 fxMesa->Color.ColorMask[BCOMP] = b;
807 fxMesa->Color.ColorMask[ACOMP] = a;
808 fxMesa->dirty |= TDFX_UPLOAD_COLOR_MASK;
809
810 if (ctx->Visual.redBits < 8) {
811 /* Can't do RGB colormasking in 16bpp mode. */
812 /* We can completely ignore the alpha mask. */
813 FALLBACK( fxMesa, TDFX_FALLBACK_COLORMASK, (r != g || g != b) );
814 }
815 }
816 }
817
818
819 static void tdfxDDClearColor( GLcontext *ctx,
820 const GLfloat color[4] )
821 {
822 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
823 GLubyte c[4];
824 FLUSH_BATCH( fxMesa );
825 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
826 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
827 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
828 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
829 fxMesa->Color.ClearColor = TDFXPACKCOLOR888( c[0], c[1], c[2] );
830 fxMesa->Color.ClearAlpha = c[3];
831 }
832
833
834 /* =============================================================
835 * Light Model
836 */
837
838 static void tdfxDDLightModelfv( GLcontext *ctx, GLenum pname,
839 const GLfloat *param )
840 {
841 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
842
843 if ( pname == GL_LIGHT_MODEL_COLOR_CONTROL ) {
844 FALLBACK( fxMesa, TDFX_FALLBACK_SPECULAR,
845 (ctx->Light.Enabled &&
846 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ));
847 }
848 }
849
850 static void tdfxDDShadeModel( GLcontext *ctx, GLenum mode )
851 {
852 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
853
854 /* FIXME: Can we implement native flat shading? */
855 FLUSH_BATCH( fxMesa );
856 fxMesa->new_state |= TDFX_NEW_TEXTURE;
857 }
858
859
860 /* =============================================================
861 * Scissor
862 */
863
864 static void
865 tdfxDDScissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h)
866 {
867 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
868 FLUSH_BATCH( fxMesa );
869 fxMesa->new_state |= TDFX_NEW_CLIP;
870 }
871
872 /* =============================================================
873 * Render
874 */
875
876 static void tdfxUpdateRenderAttrib( GLcontext *ctx )
877 {
878 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
879 FLUSH_BATCH( fxMesa );
880 fxMesa->dirty |= TDFX_UPLOAD_RENDER_BUFFER;
881 }
882
883 /* =============================================================
884 * Viewport
885 */
886
887 void tdfxUpdateViewport( GLcontext *ctx )
888 {
889 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
890 const GLfloat *v = ctx->Viewport._WindowMap.m;
891 GLfloat *m = fxMesa->hw_viewport;
892
893 m[MAT_SX] = v[MAT_SX];
894 m[MAT_TX] = v[MAT_TX] + fxMesa->x_offset + TRI_X_OFFSET;
895 m[MAT_SY] = v[MAT_SY];
896 m[MAT_TY] = v[MAT_TY] + fxMesa->y_delta + TRI_Y_OFFSET;
897 m[MAT_SZ] = v[MAT_SZ];
898 m[MAT_TZ] = v[MAT_TZ];
899
900 fxMesa->SetupNewInputs |= VERT_BIT_POS;
901 }
902
903
904 static void tdfxDDViewport( GLcontext *ctx, GLint x, GLint y,
905 GLsizei w, GLsizei h )
906 {
907 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
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 * _ColorDrawBufferMask is easier to cope with than <mode>.
1038 */
1039 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
1040 case BUFFER_BIT_FRONT_LEFT:
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 BUFFER_BIT_BACK_LEFT:
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
1060
1061 static void tdfxDDReadBuffer( GLcontext *ctx, GLenum mode )
1062 {
1063 /* XXX ??? */
1064 }
1065
1066
1067 /* =============================================================
1068 * Polygon stipple
1069 */
1070
1071 static void tdfxDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
1072 {
1073 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1074 const GLubyte *m = mask;
1075 GLubyte q[4];
1076 int i,j,k;
1077 GLboolean allBitsSet;
1078
1079 /* int active = (ctx->Polygon.StippleFlag && */
1080 /* fxMesa->reduced_prim == GL_TRIANGLES); */
1081
1082 FLUSH_BATCH(fxMesa);
1083 fxMesa->Stipple.Pattern = 0xffffffff;
1084 fxMesa->dirty |= TDFX_UPLOAD_STIPPLE;
1085 fxMesa->new_state |= TDFX_NEW_STIPPLE;
1086
1087 /* Check if the stipple pattern is fully opaque. If so, use software
1088 * rendering. This basically a trick to make sure the OpenGL conformance
1089 * test passes.
1090 */
1091 allBitsSet = GL_TRUE;
1092 for (i = 0; i < 32; i++) {
1093 if (((GLuint *) mask)[i] != 0xffffffff) {
1094 allBitsSet = GL_FALSE;
1095 break;
1096 }
1097 }
1098 if (allBitsSet) {
1099 fxMesa->haveHwStipple = GL_FALSE;
1100 return;
1101 }
1102
1103 q[0] = mask[0];
1104 q[1] = mask[4];
1105 q[2] = mask[8];
1106 q[3] = mask[12];
1107
1108 for (k = 0 ; k < 8 ; k++)
1109 for (j = 0 ; j < 4; j++)
1110 for (i = 0 ; i < 4 ; i++,m++) {
1111 if (*m != q[j]) {
1112 fxMesa->haveHwStipple = GL_FALSE;
1113 return;
1114 }
1115 }
1116
1117 fxMesa->haveHwStipple = GL_TRUE;
1118 fxMesa->Stipple.Pattern = ( (q[0] << 0) |
1119 (q[1] << 8) |
1120 (q[2] << 16) |
1121 (q[3] << 24) );
1122 }
1123
1124
1125
1126 static void tdfxDDRenderMode( GLcontext *ctx, GLenum mode )
1127 {
1128 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1129 FALLBACK( fxMesa, TDFX_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1130 }
1131
1132
1133
1134 static void tdfxDDPrintState( const char *msg, GLuint flags )
1135 {
1136 fprintf( stderr,
1137 "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s\n",
1138 msg,
1139 flags,
1140 (flags & TDFX_NEW_COLOR) ? "color, " : "",
1141 (flags & TDFX_NEW_ALPHA) ? "alpha, " : "",
1142 (flags & TDFX_NEW_DEPTH) ? "depth, " : "",
1143 (flags & TDFX_NEW_RENDER) ? "render, " : "",
1144 (flags & TDFX_NEW_FOG) ? "fog, " : "",
1145 (flags & TDFX_NEW_STENCIL) ? "stencil, " : "",
1146 (flags & TDFX_NEW_STIPPLE) ? "stipple, " : "",
1147 (flags & TDFX_NEW_CLIP) ? "clip, " : "",
1148 (flags & TDFX_NEW_VIEWPORT) ? "viewport, " : "",
1149 (flags & TDFX_NEW_CULL) ? "cull, " : "",
1150 (flags & TDFX_NEW_GLIDE) ? "glide, " : "",
1151 (flags & TDFX_NEW_TEXTURE) ? "texture, " : "",
1152 (flags & TDFX_NEW_CONTEXT) ? "context, " : "");
1153 }
1154
1155
1156
1157 void tdfxDDUpdateHwState( GLcontext *ctx )
1158 {
1159 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1160 int new_state = fxMesa->new_state;
1161
1162 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
1163 fprintf( stderr, "%s()\n", __FUNCTION__ );
1164 }
1165
1166 if ( new_state )
1167 {
1168 FLUSH_BATCH( fxMesa );
1169
1170 fxMesa->new_state = 0;
1171
1172 if ( 0 )
1173 tdfxDDPrintState( "tdfxUpdateHwState", new_state );
1174
1175 /* Update the various parts of the context's state.
1176 */
1177 if ( new_state & TDFX_NEW_ALPHA ) {
1178 tdfxUpdateAlphaMode( ctx );
1179 }
1180
1181 if ( new_state & TDFX_NEW_DEPTH )
1182 tdfxUpdateZMode( ctx );
1183
1184 if ( new_state & TDFX_NEW_FOG )
1185 tdfxUpdateFogAttrib( ctx );
1186
1187 if ( new_state & TDFX_NEW_CLIP )
1188 tdfxUpdateClipping( ctx );
1189
1190 if ( new_state & TDFX_NEW_STIPPLE )
1191 tdfxUpdateStipple( ctx );
1192
1193 if ( new_state & TDFX_NEW_CULL )
1194 tdfxUpdateCull( ctx );
1195
1196 if ( new_state & TDFX_NEW_LINE )
1197 tdfxUpdateLine( ctx );
1198
1199 if ( new_state & TDFX_NEW_VIEWPORT )
1200 tdfxUpdateViewport( ctx );
1201
1202 if ( new_state & TDFX_NEW_RENDER )
1203 tdfxUpdateRenderAttrib( ctx );
1204
1205 if ( new_state & TDFX_NEW_STENCIL )
1206 tdfxUpdateStencil( ctx );
1207
1208 if ( new_state & TDFX_NEW_TEXTURE ) {
1209 tdfxUpdateTextureState( ctx );
1210 }
1211 else if ( new_state & TDFX_NEW_TEXTURE_BIND ) {
1212 tdfxUpdateTextureBinding( ctx );
1213 }
1214 }
1215
1216 if ( 0 ) {
1217 FxI32 bias = (FxI32) (ctx->Polygon.OffsetUnits * TDFX_DEPTH_BIAS_SCALE);
1218
1219 if ( fxMesa->Depth.Bias != bias ) {
1220 fxMesa->Depth.Bias = bias;
1221 fxMesa->dirty |= TDFX_UPLOAD_DEPTH_BIAS;
1222 }
1223 }
1224
1225 if ( fxMesa->dirty ) {
1226 LOCK_HARDWARE( fxMesa );
1227 tdfxEmitHwStateLocked( fxMesa );
1228 UNLOCK_HARDWARE( fxMesa );
1229 }
1230 }
1231
1232
1233 static void tdfxDDInvalidateState( GLcontext *ctx, GLuint new_state )
1234 {
1235 _swrast_InvalidateState( ctx, new_state );
1236 _swsetup_InvalidateState( ctx, new_state );
1237 _vbo_InvalidateState( ctx, new_state );
1238 _tnl_InvalidateState( ctx, new_state );
1239 TDFX_CONTEXT(ctx)->new_gl_state |= new_state;
1240 }
1241
1242
1243
1244 /* Initialize the context's Glide state mirror. These values will be
1245 * used as Glide function call parameters when the time comes.
1246 */
1247 void tdfxInitState( tdfxContextPtr fxMesa )
1248 {
1249 GLcontext *ctx = fxMesa->glCtx;
1250 GLint i;
1251
1252 fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1253 fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_NONE;
1254 fxMesa->ColorCombine.Local = GR_COMBINE_LOCAL_ITERATED;
1255 fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_NONE;
1256 fxMesa->ColorCombine.Invert = FXFALSE;
1257 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1258 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE;
1259 fxMesa->AlphaCombine.Local = GR_COMBINE_LOCAL_ITERATED;
1260 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
1261 fxMesa->AlphaCombine.Invert = FXFALSE;
1262
1263 fxMesa->ColorCombineExt.SourceA = GR_CMBX_ITRGB;
1264 fxMesa->ColorCombineExt.ModeA = GR_FUNC_MODE_X;
1265 fxMesa->ColorCombineExt.SourceB = GR_CMBX_ZERO;
1266 fxMesa->ColorCombineExt.ModeB = GR_FUNC_MODE_ZERO;
1267 fxMesa->ColorCombineExt.SourceC = GR_CMBX_ZERO;
1268 fxMesa->ColorCombineExt.InvertC = FXTRUE;
1269 fxMesa->ColorCombineExt.SourceD = GR_CMBX_ZERO;
1270 fxMesa->ColorCombineExt.InvertD = FXFALSE;
1271 fxMesa->ColorCombineExt.Shift = 0;
1272 fxMesa->ColorCombineExt.Invert = FXFALSE;
1273 fxMesa->AlphaCombineExt.SourceA = GR_CMBX_ITALPHA;
1274 fxMesa->AlphaCombineExt.ModeA = GR_FUNC_MODE_X;
1275 fxMesa->AlphaCombineExt.SourceB = GR_CMBX_ZERO;
1276 fxMesa->AlphaCombineExt.ModeB = GR_FUNC_MODE_ZERO;
1277 fxMesa->AlphaCombineExt.SourceC = GR_CMBX_ZERO;
1278 fxMesa->AlphaCombineExt.InvertC = FXTRUE;
1279 fxMesa->AlphaCombineExt.SourceD = GR_CMBX_ZERO;
1280 fxMesa->AlphaCombineExt.InvertD = FXFALSE;
1281 fxMesa->AlphaCombineExt.Shift = 0;
1282 fxMesa->AlphaCombineExt.Invert = FXFALSE;
1283
1284 fxMesa->sScale0 = fxMesa->tScale0 = 1.0;
1285 fxMesa->sScale1 = fxMesa->tScale1 = 1.0;
1286
1287 fxMesa->TexPalette.Type = 0;
1288 fxMesa->TexPalette.Data = NULL;
1289
1290 for ( i = 0 ; i < TDFX_NUM_TMU ; i++ ) {
1291 fxMesa->TexSource[i].StartAddress = 0;
1292 fxMesa->TexSource[i].EvenOdd = GR_MIPMAPLEVELMASK_EVEN;
1293 fxMesa->TexSource[i].Info = NULL;
1294
1295 fxMesa->TexCombine[i].FunctionRGB = 0;
1296 fxMesa->TexCombine[i].FactorRGB = 0;
1297 fxMesa->TexCombine[i].FunctionAlpha = 0;
1298 fxMesa->TexCombine[i].FactorAlpha = 0;
1299 fxMesa->TexCombine[i].InvertRGB = FXFALSE;
1300 fxMesa->TexCombine[i].InvertAlpha = FXFALSE;
1301
1302 fxMesa->TexCombineExt[i].Alpha.SourceA = 0;
1303 /* XXX more state to init here */
1304 fxMesa->TexCombineExt[i].Color.SourceA = 0;
1305 fxMesa->TexCombineExt[i].EnvColor = 0x0;
1306
1307 fxMesa->TexParams[i].sClamp = GR_TEXTURECLAMP_WRAP;
1308 fxMesa->TexParams[i].tClamp = GR_TEXTURECLAMP_WRAP;
1309 fxMesa->TexParams[i].minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
1310 fxMesa->TexParams[i].magFilt = GR_TEXTUREFILTER_BILINEAR;
1311 fxMesa->TexParams[i].mmMode = GR_MIPMAP_DISABLE;
1312 fxMesa->TexParams[i].LODblend = FXFALSE;
1313 fxMesa->TexParams[i].LodBias = 0.0;
1314
1315 fxMesa->TexState.EnvMode[i] = ~0;
1316 fxMesa->TexState.TexFormat[i] = ~0;
1317 fxMesa->TexState.Enabled[i] = 0;
1318 }
1319
1320 if ( ctx->Visual.doubleBufferMode) {
1321 fxMesa->DrawBuffer = GR_BUFFER_BACKBUFFER;
1322 fxMesa->ReadBuffer = GR_BUFFER_BACKBUFFER;
1323 } else {
1324 fxMesa->DrawBuffer = GR_BUFFER_FRONTBUFFER;
1325 fxMesa->ReadBuffer = GR_BUFFER_FRONTBUFFER;
1326 }
1327
1328 fxMesa->Color.ClearColor = 0x00000000;
1329 fxMesa->Color.ClearAlpha = 0x00;
1330 fxMesa->Color.ColorMask[RCOMP] = FXTRUE;
1331 fxMesa->Color.ColorMask[BCOMP] = FXTRUE;
1332 fxMesa->Color.ColorMask[GCOMP] = FXTRUE;
1333 fxMesa->Color.ColorMask[ACOMP] = FXTRUE;
1334 fxMesa->Color.MonoColor = 0xffffffff;
1335
1336 fxMesa->Color.AlphaFunc = GR_CMP_ALWAYS;
1337 fxMesa->Color.AlphaRef = 0x00;
1338 fxMesa->Color.BlendSrcRGB = GR_BLEND_ONE;
1339 fxMesa->Color.BlendDstRGB = GR_BLEND_ZERO;
1340 fxMesa->Color.BlendSrcA = GR_BLEND_ONE;
1341 fxMesa->Color.BlendSrcA = GR_BLEND_ZERO;
1342
1343 fxMesa->Color.Dither = GR_DITHER_2x2;
1344
1345 if ( fxMesa->glCtx->Visual.depthBits > 0 ) {
1346 fxMesa->Depth.Mode = GR_DEPTHBUFFER_ZBUFFER;
1347 } else {
1348 fxMesa->Depth.Mode = GR_DEPTHBUFFER_DISABLE;
1349 }
1350 fxMesa->Depth.Bias = 0;
1351 fxMesa->Depth.Func = GR_CMP_LESS;
1352 fxMesa->Depth.Clear = 0; /* computed later */
1353 fxMesa->Depth.Mask = FXTRUE;
1354
1355
1356 fxMesa->Fog.Mode = GR_FOG_DISABLE;
1357 fxMesa->Fog.Color = 0x00000000;
1358 fxMesa->Fog.Table = NULL;
1359 fxMesa->Fog.Density = 1.0;
1360 fxMesa->Fog.Near = 1.0;
1361 fxMesa->Fog.Far = 1.0;
1362
1363 fxMesa->Stencil.Function = GR_CMP_ALWAYS;
1364 fxMesa->Stencil.RefValue = 0;
1365 fxMesa->Stencil.ValueMask = 0xff;
1366 fxMesa->Stencil.WriteMask = 0xff;
1367 fxMesa->Stencil.FailFunc = 0;
1368 fxMesa->Stencil.ZFailFunc = 0;
1369 fxMesa->Stencil.ZPassFunc = 0;
1370 fxMesa->Stencil.Clear = 0;
1371
1372 fxMesa->Stipple.Mode = GR_STIPPLE_DISABLE;
1373 fxMesa->Stipple.Pattern = 0xffffffff;
1374
1375 fxMesa->Scissor.minX = 0;
1376 fxMesa->Scissor.minY = 0;
1377 fxMesa->Scissor.maxX = 0;
1378 fxMesa->Scissor.maxY = 0;
1379
1380 fxMesa->Viewport.Mode = GR_WINDOW_COORDS;
1381 fxMesa->Viewport.X = 0;
1382 fxMesa->Viewport.Y = 0;
1383 fxMesa->Viewport.Width = 0;
1384 fxMesa->Viewport.Height = 0;
1385 fxMesa->Viewport.Near = 0.0;
1386 fxMesa->Viewport.Far = 0.0;
1387
1388 fxMesa->CullMode = GR_CULL_DISABLE;
1389
1390 fxMesa->Glide.ColorFormat = GR_COLORFORMAT_ABGR;
1391 fxMesa->Glide.Origin = GR_ORIGIN_LOWER_LEFT;
1392 fxMesa->Glide.Initialized = FXFALSE;
1393 }
1394
1395
1396
1397 void tdfxDDInitStateFuncs( GLcontext *ctx )
1398 {
1399 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1400
1401 ctx->Driver.UpdateState = tdfxDDInvalidateState;
1402
1403 ctx->Driver.ClearColor = tdfxDDClearColor;
1404 ctx->Driver.DrawBuffer = tdfxDDDrawBuffer;
1405 ctx->Driver.ReadBuffer = tdfxDDReadBuffer;
1406
1407 ctx->Driver.AlphaFunc = tdfxDDAlphaFunc;
1408 ctx->Driver.BlendEquationSeparate = tdfxDDBlendEquationSeparate;
1409 ctx->Driver.BlendFuncSeparate = tdfxDDBlendFuncSeparate;
1410 ctx->Driver.ClearDepth = tdfxDDClearDepth;
1411 ctx->Driver.ColorMask = tdfxDDColorMask;
1412 ctx->Driver.CullFace = tdfxDDCullFace;
1413 ctx->Driver.FrontFace = tdfxDDFrontFace;
1414 ctx->Driver.DepthFunc = tdfxDDDepthFunc;
1415 ctx->Driver.DepthMask = tdfxDDDepthMask;
1416 ctx->Driver.DepthRange = tdfxDDDepthRange;
1417 ctx->Driver.Enable = tdfxDDEnable;
1418 ctx->Driver.Fogfv = tdfxDDFogfv;
1419 ctx->Driver.LightModelfv = tdfxDDLightModelfv;
1420 ctx->Driver.LineWidth = tdfxDDLineWidth;
1421 ctx->Driver.PolygonStipple = tdfxDDPolygonStipple;
1422 ctx->Driver.RenderMode = tdfxDDRenderMode;
1423 ctx->Driver.Scissor = tdfxDDScissor;
1424 ctx->Driver.ShadeModel = tdfxDDShadeModel;
1425
1426 if ( fxMesa->haveHwStencil ) {
1427 ctx->Driver.StencilFuncSeparate = tdfxDDStencilFuncSeparate;
1428 ctx->Driver.StencilMaskSeparate = tdfxDDStencilMaskSeparate;
1429 ctx->Driver.StencilOpSeparate = tdfxDDStencilOpSeparate;
1430 }
1431
1432 ctx->Driver.Viewport = tdfxDDViewport;
1433 }