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