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