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