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