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