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