Merge branch 'nouveau-import'
[mesa.git] / src / mesa / drivers / dri / ffb / ffb_state.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_state.c,v 1.5 2002/10/30 12:51:27 alanh Exp $
2 *
3 * GLX Hardware Device Driver for Sun Creator/Creator3D
4 * Copyright (C) 2000, 2001 David S. Miller
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * DAVID MILLER, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 *
25 * David S. Miller <davem@redhat.com>
26 */
27
28 #include "mtypes.h"
29 #include "colormac.h"
30 #include "mm.h"
31 #include "ffb_dd.h"
32 #include "ffb_span.h"
33 #include "ffb_depth.h"
34 #include "ffb_context.h"
35 #include "ffb_vb.h"
36 #include "ffb_tris.h"
37 #include "ffb_state.h"
38 #include "ffb_lock.h"
39 #include "extensions.h"
40 #include "enums.h"
41
42 #include "swrast/swrast.h"
43 #include "array_cache/acache.h"
44 #include "tnl/tnl.h"
45 #include "swrast_setup/swrast_setup.h"
46
47 #include "tnl/t_pipeline.h"
48
49 #undef STATE_TRACE
50
51 static unsigned int ffbComputeAlphaFunc(GLcontext *ctx)
52 {
53 unsigned int xclip;
54 GLubyte alphaRef;
55
56 #ifdef STATE_TRACE
57 fprintf(stderr, "ffbDDAlphaFunc: func(%s) ref(%02x)\n",
58 _mesa_lookup_enum_by_nr(ctx->Color.AlphaFunc),
59 ctx->Color.AlphaRef & 0xff);
60 #endif
61
62 switch (ctx->Color.AlphaFunc) {
63 case GL_NEVER: xclip = FFB_XCLIP_TEST_NEVER; break;
64 case GL_LESS: xclip = FFB_XCLIP_TEST_LT; break;
65 case GL_EQUAL: xclip = FFB_XCLIP_TEST_EQ; break;
66 case GL_LEQUAL: xclip = FFB_XCLIP_TEST_LE; break;
67 case GL_GREATER: xclip = FFB_XCLIP_TEST_GT; break;
68 case GL_NOTEQUAL: xclip = FFB_XCLIP_TEST_NE; break;
69 case GL_GEQUAL: xclip = FFB_XCLIP_TEST_GE; break;
70 case GL_ALWAYS: xclip = FFB_XCLIP_TEST_ALWAYS; break;
71
72 default:
73 return FFB_XCLIP_TEST_ALWAYS | 0x00;
74 }
75
76 CLAMPED_FLOAT_TO_UBYTE(alphaRef, ctx->Color.AlphaRef);
77 xclip |= (alphaRef & 0xff);
78
79 return xclip;
80 }
81
82 static void ffbDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
83 {
84 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
85
86 if (ctx->Color.AlphaEnabled) {
87 unsigned int xclip = ffbComputeAlphaFunc(ctx);
88
89 if (fmesa->xclip != xclip) {
90 fmesa->xclip = xclip;
91 FFB_MAKE_DIRTY(fmesa, FFB_STATE_XCLIP, 1);
92 }
93 }
94 }
95
96 static void ffbDDBlendEquationSeparate(GLcontext *ctx,
97 GLenum modeRGB, GLenum modeA)
98 {
99
100 #ifdef STATE_TRACE
101 fprintf(stderr, "ffbDDBlendEquation: mode(%s)\n",
102 _mesa_lookup_enum_by_nr(modeRGB));
103 #endif
104 assert( modeRGB == modeA );
105 FALLBACK( ctx, (modeRGB != GL_FUNC_ADD), FFB_BADATTR_BLENDEQN);
106 }
107
108 static void ffbDDBlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB,
109 GLenum dfactorRGB, GLenum sfactorA,
110 GLenum dfactorA)
111 {
112 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
113 unsigned int blendc = 1 << 4;
114
115 #ifdef STATE_TRACE
116 fprintf(stderr, "ffbDDBlendFuncSeparate: sRGB(%s) dRGB(%s) sA(%s) dA(%s)\n",
117 _mesa_lookup_enum_by_nr(sfactorRGB),
118 _mesa_lookup_enum_by_nr(dfactorRGB),
119 _mesa_lookup_enum_by_nr(sfactorA),
120 _mesa_lookup_enum_by_nr(dfactorA));
121 #endif
122 switch (ctx->Color.BlendSrcRGB) {
123 case GL_ZERO:
124 blendc |= (0 << 0);
125 break;
126
127 case GL_ONE:
128 blendc |= (1 << 0);
129 break;
130
131 case GL_ONE_MINUS_SRC_ALPHA:
132 blendc |= (2 << 0);
133 break;
134
135 case GL_SRC_ALPHA:
136 blendc |= (3 << 0);
137 break;
138
139 default:
140 if (ctx->Color.BlendEnabled)
141 FALLBACK( ctx, FFB_BADATTR_BLENDFUNC, GL_TRUE );
142 return;
143 };
144
145 switch (ctx->Color.BlendDstRGB) {
146 case GL_ZERO:
147 blendc |= (0 << 2);
148 break;
149
150 case GL_ONE:
151 blendc |= (1 << 2);
152 break;
153
154 case GL_ONE_MINUS_SRC_ALPHA:
155 blendc |= (2 << 2);
156 break;
157
158 case GL_SRC_ALPHA:
159 blendc |= (3 << 2);
160 break;
161
162 default:
163 if (ctx->Color.BlendEnabled)
164 FALLBACK( ctx, FFB_BADATTR_BLENDFUNC, GL_TRUE );
165 return;
166 };
167
168 if (ctx->Color.BlendEnabled &&
169 ctx->Color.ColorLogicOpEnabled &&
170 ctx->Color.LogicOp != GL_COPY) {
171 /* We could avoid this if sfactor is GL_ONE and
172 * dfactor is GL_ZERO. I do not think that is even
173 * worthwhile to check because if someone is using
174 * blending they use more interesting settings and
175 * also it would add more state tracking to a lot
176 * of the code in this file.
177 */
178 FALLBACK(ctx, FFB_BADATTR_BLENDROP, GL_TRUE);
179 return;
180 }
181
182 FALLBACK( ctx, (FFB_BADATTR_BLENDFUNC|FFB_BADATTR_BLENDROP), GL_FALSE );
183
184 if (blendc != fmesa->blendc) {
185 fmesa->blendc = blendc;
186 FFB_MAKE_DIRTY(fmesa, FFB_STATE_BLEND, 1);
187 }
188 }
189
190 static void ffbDDDepthFunc(GLcontext *ctx, GLenum func)
191 {
192 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
193 GLuint cmp;
194
195 #ifdef STATE_TRACE
196 fprintf(stderr, "ffbDDDepthFunc: func(%s)\n",
197 _mesa_lookup_enum_by_nr(func));
198 #endif
199
200 switch (func) {
201 case GL_NEVER:
202 cmp = FFB_CMP_MAGN_NEVER;
203 break;
204 case GL_ALWAYS:
205 cmp = FFB_CMP_MAGN_ALWAYS;
206 break;
207 case GL_LESS:
208 cmp = FFB_CMP_MAGN_LT;
209 break;
210 case GL_LEQUAL:
211 cmp = FFB_CMP_MAGN_LE;
212 break;
213 case GL_EQUAL:
214 cmp = FFB_CMP_MAGN_EQ;
215 break;
216 case GL_GREATER:
217 cmp = FFB_CMP_MAGN_GT;
218 break;
219 case GL_GEQUAL:
220 cmp = FFB_CMP_MAGN_GE;
221 break;
222 case GL_NOTEQUAL:
223 cmp = FFB_CMP_MAGN_NE;
224 break;
225 default:
226 return;
227 };
228
229 if (! ctx->Depth.Test)
230 cmp = FFB_CMP_MAGN_ALWAYS;
231
232 cmp <<= 16;
233 cmp = (fmesa->cmp & ~(0xff<<16)) | cmp;
234 if (cmp != fmesa->cmp) {
235 fmesa->cmp = cmp;
236 FFB_MAKE_DIRTY(fmesa, FFB_STATE_CMP, 1);
237 }
238 }
239
240 static void ffbDDDepthMask(GLcontext *ctx, GLboolean flag)
241 {
242 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
243 GLuint fbc = fmesa->fbc;
244 GLboolean enabled_now;
245
246 #ifdef STATE_TRACE
247 fprintf(stderr, "ffbDDDepthMask: flag(%d)\n", flag);
248 #endif
249
250 if ((fbc & FFB_FBC_ZE_MASK) == FFB_FBC_ZE_OFF)
251 enabled_now = GL_FALSE;
252 else
253 enabled_now = GL_TRUE;
254
255 if (flag != enabled_now) {
256 fbc &= ~FFB_FBC_ZE_MASK;
257 if (flag) {
258 fbc |= FFB_FBC_WB_C | FFB_FBC_ZE_ON;
259 } else {
260 fbc |= FFB_FBC_ZE_OFF;
261 fbc &= ~FFB_FBC_WB_C;
262 }
263 fmesa->fbc = fbc;
264 FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
265 }
266 }
267
268 static void
269 ffbDDStencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
270 GLint ref, GLuint mask)
271 {
272 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
273 unsigned int stencil, stencilctl, consty;
274
275 /* We will properly update sw/hw state when stenciling is
276 * enabled.
277 */
278 if (! ctx->Stencil.Enabled)
279 return;
280
281 stencilctl = fmesa->stencilctl;
282 stencilctl &= ~(7 << 16);
283
284 switch (func) {
285 case GL_ALWAYS: stencilctl |= (0 << 16); break;
286 case GL_GREATER: stencilctl |= (1 << 16); break;
287 case GL_EQUAL: stencilctl |= (2 << 16); break;
288 case GL_GEQUAL: stencilctl |= (3 << 16); break;
289 case GL_NEVER: stencilctl |= (4 << 16); break;
290 case GL_LEQUAL: stencilctl |= (5 << 16); break;
291 case GL_NOTEQUAL: stencilctl |= (6 << 16); break;
292 case GL_LESS: stencilctl |= (7 << 16); break;
293
294 default:
295 return;
296 };
297
298 consty = ref & 0xf;
299
300 stencil = fmesa->stencil;
301 stencil &= ~(0xf << 20);
302 stencil |= (mask & 0xf) << 20;
303
304 if (fmesa->stencil != stencil ||
305 fmesa->stencilctl != stencilctl ||
306 fmesa->consty != consty) {
307 fmesa->stencil = stencil;
308 fmesa->stencilctl = stencilctl;
309 fmesa->consty = consty;
310 FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6);
311 }
312 }
313
314 static void
315 ffbDDStencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
316 {
317 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
318
319 mask &= 0xf;
320 if (fmesa->ypmask != mask) {
321 fmesa->ypmask = mask;
322 FFB_MAKE_DIRTY(fmesa, FFB_STATE_YPMASK, 1);
323 }
324 }
325
326 static void
327 ffbDDStencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
328 GLenum zfail, GLenum zpass)
329 {
330 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
331 unsigned int stencilctl;
332
333 /* We will properly update sw/hw state when stenciling is
334 * enabled.
335 */
336 if (! ctx->Stencil.Enabled)
337 return;
338
339 stencilctl = fmesa->stencilctl;
340 stencilctl &= ~(0xfff00000);
341
342 switch (fail) {
343 case GL_ZERO: stencilctl |= (0 << 28); break;
344 case GL_KEEP: stencilctl |= (1 << 28); break;
345 case GL_INVERT: stencilctl |= (2 << 28); break;
346 case GL_REPLACE: stencilctl |= (3 << 28); break;
347 case GL_INCR: stencilctl |= (4 << 28); break;
348 case GL_DECR: stencilctl |= (5 << 28); break;
349
350 default:
351 return;
352 };
353
354 switch (zfail) {
355 case GL_ZERO: stencilctl |= (0 << 24); break;
356 case GL_KEEP: stencilctl |= (1 << 24); break;
357 case GL_INVERT: stencilctl |= (2 << 24); break;
358 case GL_REPLACE: stencilctl |= (3 << 24); break;
359 case GL_INCR: stencilctl |= (4 << 24); break;
360 case GL_DECR: stencilctl |= (5 << 24); break;
361
362 default:
363 return;
364 };
365
366 switch (zpass) {
367 case GL_ZERO: stencilctl |= (0 << 20); break;
368 case GL_KEEP: stencilctl |= (1 << 20); break;
369 case GL_INVERT: stencilctl |= (2 << 20); break;
370 case GL_REPLACE: stencilctl |= (3 << 20); break;
371 case GL_INCR: stencilctl |= (4 << 20); break;
372 case GL_DECR: stencilctl |= (5 << 20); break;
373
374 default:
375 return;
376 };
377
378 if (fmesa->stencilctl != stencilctl) {
379 fmesa->stencilctl = stencilctl;
380 FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6);
381 }
382 }
383
384 static void ffbCalcViewportRegs(GLcontext *ctx)
385 {
386 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
387 __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
388 GLuint xmin, xmax, ymin, ymax, zmin, zmax;
389 unsigned int vcmin, vcmax;
390
391 xmin = ctx->Viewport.X + dPriv->x;
392 xmax = xmin + ctx->Viewport.Width;
393 ymax = dPriv->y + dPriv->h - ctx->Viewport.Y;
394 ymin = ymax - ctx->Viewport.Height;
395 if (ctx->Scissor.Enabled) {
396 GLuint sc_xmin, sc_xmax, sc_ymin, sc_ymax;
397
398 sc_xmin = ctx->Viewport.X + dPriv->x;
399 sc_xmax = sc_xmin + ctx->Viewport.Width;
400 sc_ymax = dPriv->y + dPriv->h - ctx->Viewport.Y;
401 sc_ymin = sc_ymax - ctx->Viewport.Height;
402 if (sc_xmin > xmin)
403 xmin = sc_xmin;
404 if (sc_xmax < xmax)
405 xmax = sc_xmax;
406 if (sc_ymin > ymin)
407 ymin = sc_ymin;
408 if (sc_ymax < ymax)
409 ymax = sc_ymax;
410 }
411 zmin = ((GLdouble)ctx->Viewport.Near * 0x0fffffff);
412 zmax = ((GLdouble)ctx->Viewport.Far * 0x0fffffff);
413
414 vcmin = ((ymin & 0xffff) << 16) | (xmin & 0xffff);
415 vcmax = ((ymax & 0xffff) << 16) | (xmax & 0xffff);
416 if (fmesa->vclipmin != vcmin ||
417 fmesa->vclipmax != vcmax ||
418 fmesa->vclipzmin != zmin ||
419 fmesa->vclipzmax != zmax) {
420 fmesa->vclipmin = vcmin;
421 fmesa->vclipmax = vcmax;
422 fmesa->vclipzmin = zmin;
423 fmesa->vclipzmax = zmax;
424 FFB_MAKE_DIRTY(fmesa, FFB_STATE_CLIP, (4 + (4 * 2)));
425 }
426 }
427
428 void ffbCalcViewport(GLcontext *ctx)
429 {
430 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
431 const GLfloat *v = ctx->Viewport._WindowMap.m;
432 GLfloat *m = fmesa->hw_viewport;
433 __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
434
435 m[MAT_SX] = v[MAT_SX];
436 m[MAT_TX] = v[MAT_TX] + dPriv->x + SUBPIXEL_X;
437 m[MAT_SY] = - v[MAT_SY];
438 m[MAT_TY] = - v[MAT_TY] + dPriv->h + dPriv->y + SUBPIXEL_Y;
439 m[MAT_SZ] = v[MAT_SZ] * ((GLdouble)1.0 / (GLdouble)0x0fffffff);
440 m[MAT_TZ] = v[MAT_TZ] * ((GLdouble)1.0 / (GLdouble)0x0fffffff);
441
442 fmesa->depth_scale = ((GLdouble)1.0 / (GLdouble)0x0fffffff);
443
444 ffbCalcViewportRegs(ctx);
445
446 fmesa->setupnewinputs |= VERT_BIT_POS;
447 }
448
449 static void ffbDDViewport(GLcontext *ctx, GLint x, GLint y,
450 GLsizei width, GLsizei height)
451 {
452 ffbCalcViewport(ctx);
453 }
454
455 static void ffbDDDepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
456 {
457 ffbCalcViewport(ctx);
458 }
459
460 static void ffbDDScissor(GLcontext *ctx, GLint cx, GLint cy,
461 GLsizei cw, GLsizei ch)
462 {
463 ffbCalcViewport(ctx);
464 }
465
466 static void ffbDDDrawBuffer(GLcontext *ctx, GLenum buffer)
467 {
468 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
469 unsigned int fbc = fmesa->fbc;
470
471 #ifdef STATE_TRACE
472 fprintf(stderr, "ffbDDDrawBuffer: mode(%s)\n",
473 _mesa_lookup_enum_by_nr(buffer));
474 #endif
475 fbc &= ~(FFB_FBC_WB_AB | FFB_FBC_RB_MASK);
476 switch (buffer) {
477 case GL_FRONT:
478 if (fmesa->back_buffer == 0)
479 fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B;
480 else
481 fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
482 break;
483
484 case GL_BACK:
485 if (fmesa->back_buffer == 0)
486 fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
487 else
488 fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B;
489 break;
490
491 case GL_FRONT_AND_BACK:
492 fbc |= FFB_FBC_WB_AB;
493 break;
494
495 default:
496 return;
497 };
498
499 if (fbc != fmesa->fbc) {
500 fmesa->fbc = fbc;
501 FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
502 }
503 }
504
505
506 static void ffbDDReadBuffer(GLcontext *ctx, GLenum buffer)
507 {
508 /* no-op, unless you implement h/w glRead/CopyPixels */
509 }
510
511
512 /*
513 * Specifies buffer for sw fallbacks (spans)
514 */
515 #if 000
516 /* XXX
517 * This function is obsolete. It's not clear how this really effected
518 * span reading/writing above. The span functions should use the
519 * incoming driRenderbuffer (gl_renderbuffer) pointer to determine how
520 * to read from the specified bufer.
521 */
522 static void ffbDDSetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer,
523 GLuint bufferBit)
524 {
525 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
526 unsigned int fbc = fmesa->fbc;
527
528 #ifdef STATE_TRACE
529 fprintf(stderr, "ffbDDSetReadBuffer: mode(%s)\n",
530 _mesa_lookup_enum_by_nr(buffer));
531 #endif
532 fbc &= ~(FFB_FBC_RB_MASK);
533 switch (bufferBit) {
534 case BUFFER_BIT_FRONT_LEFT:
535 if (fmesa->back_buffer == 0)
536 fbc |= FFB_FBC_RB_B;
537 else
538 fbc |= FFB_FBC_RB_A;
539 break;
540
541 case BUFFER_BIT_BACK_LEFT:
542 if (fmesa->back_buffer == 0)
543 fbc |= FFB_FBC_RB_A;
544 else
545 fbc |= FFB_FBC_RB_B;
546 break;
547
548 default:
549 _mesa_problem(ctx, "Unexpected buffer in ffbDDSetBuffer()");
550 return;
551 };
552
553 if (fbc != fmesa->fbc) {
554 fmesa->fbc = fbc;
555 FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
556 }
557 }
558 #endif
559
560
561 static void ffbDDClearColor(GLcontext *ctx, const GLfloat color[4])
562 {
563 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
564 GLubyte c[4];
565 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
566 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
567 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
568
569 fmesa->clear_pixel = ((c[0] << 0) |
570 (c[1] << 8) |
571 (c[2] << 16));
572 }
573
574 static void ffbDDClearDepth(GLcontext *ctx, GLclampd depth)
575 {
576 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
577
578 fmesa->clear_depth = Z_FROM_MESA(depth * 4294967295.0f);
579 }
580
581 static void ffbDDClearStencil(GLcontext *ctx, GLint stencil)
582 {
583 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
584
585 fmesa->clear_stencil = stencil & 0xf;
586 }
587
588 /* XXX Actually, should I be using FBC controls for this? -DaveM */
589 static void ffbDDColorMask(GLcontext *ctx,
590 GLboolean r, GLboolean g,
591 GLboolean b, GLboolean a)
592 {
593 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
594 unsigned int new_pmask = 0x0;
595
596 #ifdef STATE_TRACE
597 fprintf(stderr, "ffbDDColorMask: r(%d) g(%d) b(%d) a(%d)\n",
598 r, g, b, a);
599 #endif
600 if (r)
601 new_pmask |= 0x000000ff;
602 if (g)
603 new_pmask |= 0x0000ff00;
604 if (b)
605 new_pmask |= 0x00ff0000;
606 if (a)
607 new_pmask |= 0xff000000;
608
609 if (fmesa->pmask != new_pmask) {
610 fmesa->pmask = new_pmask;
611 FFB_MAKE_DIRTY(fmesa, FFB_STATE_PMASK, 1);
612 }
613 }
614
615 static void ffbDDLogicOp(GLcontext *ctx, GLenum op)
616 {
617 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
618 unsigned int rop;
619
620 #ifdef STATE_TRACE
621 fprintf(stderr, "ffbDDLogicOp: op(%s)\n",
622 _mesa_lookup_enum_by_nr(op));
623 #endif
624 switch (op) {
625 case GL_CLEAR: rop = FFB_ROP_ZERO; break;
626 case GL_SET: rop = FFB_ROP_ONES; break;
627 case GL_COPY: rop = FFB_ROP_NEW; break;
628 case GL_AND: rop = FFB_ROP_NEW_AND_OLD; break;
629 case GL_NAND: rop = FFB_ROP_NEW_AND_NOLD; break;
630 case GL_OR: rop = FFB_ROP_NEW_OR_OLD; break;
631 case GL_NOR: rop = FFB_ROP_NEW_OR_NOLD; break;
632 case GL_XOR: rop = FFB_ROP_NEW_XOR_OLD; break;
633 case GL_NOOP: rop = FFB_ROP_OLD; break;
634 case GL_COPY_INVERTED: rop = FFB_ROP_NNEW; break;
635 case GL_INVERT: rop = FFB_ROP_NOLD; break;
636 case GL_EQUIV: rop = FFB_ROP_NNEW_XOR_NOLD; break;
637 case GL_AND_REVERSE: rop = FFB_ROP_NEW_AND_NOLD; break;
638 case GL_AND_INVERTED: rop = FFB_ROP_NNEW_AND_OLD; break;
639 case GL_OR_REVERSE: rop = FFB_ROP_NEW_OR_NOLD; break;
640 case GL_OR_INVERTED: rop = FFB_ROP_NNEW_OR_OLD; break;
641
642 default:
643 return;
644 };
645
646 rop |= fmesa->rop & ~0xff;
647 if (rop != fmesa->rop) {
648 fmesa->rop = rop;
649 FFB_MAKE_DIRTY(fmesa, FFB_STATE_ROP, 1);
650
651 if (op == GL_COPY)
652 FALLBACK( ctx, FFB_BADATTR_BLENDROP, GL_FALSE );
653 }
654 }
655
656 #if 0
657 /* XXX Also need to track near/far just like 3dfx driver.
658 * XXX
659 * XXX Actually, that won't work, because the 3dfx chip works by
660 * XXX having 1/w coordinates fed to it for each primitive, and
661 * XXX it uses this to index it's 64 entry fog table.
662 */
663 static void ffb_fog_linear(GLcontext *ctx, ffbContextPtr fmesa)
664 {
665 GLfloat c = ctx->ProjectionMatrix.m[10];
666 GLfloat d = ctx->ProjectionMatrix.m[14];
667 GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
668 GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
669 GLfloat fogEnd = ctx->Fog.End;
670 GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
671 GLfloat ndcz;
672 GLfloat eyez;
673 GLfloat Zzero, Zone;
674 unsigned int zb, zf;
675
676 /* Compute the Z at which f reaches 0.0, this is the full
677 * saturation point.
678 *
679 * Thus compute Z (as seen by the chip during rendering),
680 * such that:
681 *
682 * 0.0 = (fogEnd - eyez) * fogScale
683 *
684 * fogScale is usually not zero, thus we are looking for:
685 *
686 * fogEnd = eyez
687 *
688 * fogEnd = -d / (c + ((Z - tz) * szInv))
689 * fogEnd * (c + ((Z - tz) * szInv)) = -d
690 * (c + ((Z - tz) * szInv)) = -d / fogEnd
691 * (Z - tz) * szInv = (-d / fogEnd) - c
692 * (Z - tz) = ((-d / fogEnd) - c) / szInv
693 * Z = (((-d / fogEnd) - c) / szInv) + tz
694 */
695 Zzero = (((-d / fogEnd) - c) / szInv) + tz;
696
697 /* Compute the Z at which f reaches 1.0, this is where
698 * the incoming frag's full intensity is shown. This
699 * equation is:
700 *
701 * 1.0 = (fogEnd - eyez)
702 *
703 * We are looking for:
704 *
705 * 1.0 + eyez = fogEnd
706 *
707 * 1.0 + (-d / (c + ((Z - tz) * szInv))) = fogEnd
708 * -d / (c + ((Z - tz) * szInv)) = fogEnd - 1.0
709 * -d / (FogEnd - 1.0) = (c + ((Z - tz) * szInv))
710 * (-d / (fogEnd - 1.0)) - c = ((Z - tz) * szInv)
711 * ((-d / (fogEnd - 1.0)) - c) / szInv = (Z - tz)
712 * (((-d / (fogEnd - 1.0)) - c) / szInv) + tz = Z
713 */
714 Zone = (((-d / (fogEnd - 1.0)) - c) / szInv) + tz;
715
716 /* FFB's Zfront must be less than Zback, thus we may have
717 * to invert Sf/Sb to satisfy this constraint.
718 */
719 if (Zzero < Zone) {
720 sf = 0.0;
721 sb = 1.0;
722 zf = Z_FROM_MESA(Zzero);
723 zb = Z_FROM_MESA(Zone);
724 } else {
725 sf = 1.0;
726 sb = 0.0;
727 zf = Z_FROM_MESA(Zone);
728 zb = Z_FROM_MESA(Zzero);
729 }
730 }
731 #endif
732
733 static void ffbDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
734 {
735 #ifdef STATE_TRACE
736 fprintf(stderr, "ffbDDFogfv: pname(%s)\n", _mesa_lookup_enum_by_nr(pname));
737 #endif
738 }
739
740 static void ffbDDLineStipple(GLcontext *ctx, GLint factor, GLushort pattern)
741 {
742 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
743
744 #ifdef STATE_TRACE
745 fprintf(stderr, "ffbDDLineStipple: factor(%d) pattern(%04x)\n",
746 factor, pattern);
747 #endif
748 if (ctx->Line.StippleFlag) {
749 factor = ctx->Line.StippleFactor;
750 pattern = ctx->Line.StipplePattern;
751 if ((GLuint) factor > 15) {
752 fmesa->lpat = FFB_LPAT_BAD;
753 } else {
754 fmesa->lpat = ((factor << FFB_LPAT_SCALEVAL_SHIFT) |
755 (0 << FFB_LPAT_PATLEN_SHIFT) |
756 ((pattern & 0xffff) << FFB_LPAT_PATTERN_SHIFT));
757 }
758 } else {
759 fmesa->lpat = 0;
760 }
761 }
762
763 void ffbXformAreaPattern(ffbContextPtr fmesa, const GLubyte *mask)
764 {
765 __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
766 int i, lines, xoff;
767
768 lines = 0;
769 i = (dPriv->y + dPriv->h) & (32 - 1);
770 xoff = dPriv->x & (32 - 1);
771 while (lines++ < 32) {
772 GLuint raw =
773 (((GLuint)mask[0] << 24) |
774 ((GLuint)mask[1] << 16) |
775 ((GLuint)mask[2] << 8) |
776 ((GLuint)mask[3] << 0));
777
778 fmesa->pattern[i] =
779 (raw << xoff) | (raw >> (32 - xoff));
780 i = (i - 1) & (32 - 1);
781 mask += 4;
782 }
783
784 FFB_MAKE_DIRTY(fmesa, FFB_STATE_APAT, 32);
785 }
786
787 static void ffbDDPolygonStipple(GLcontext *ctx, const GLubyte *mask)
788 {
789 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
790
791 #ifdef STATE_TRACE
792 fprintf(stderr, "ffbDDPolygonStipple: state(%d)\n",
793 ctx->Polygon.StippleFlag);
794 #endif
795 ffbXformAreaPattern(fmesa, mask);
796 }
797
798 static void ffbDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
799 {
800 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
801 unsigned int tmp;
802
803 #ifdef STATE_TRACE
804 fprintf(stderr, "ffbDDEnable: %s state(%d)\n",
805 _mesa_lookup_enum_by_nr(cap), state);
806 #endif
807 switch (cap) {
808 case GL_ALPHA_TEST:
809 if (state)
810 tmp = ffbComputeAlphaFunc(ctx);
811 else
812 tmp = FFB_XCLIP_TEST_ALWAYS;
813
814 if (tmp != fmesa->xclip) {
815 fmesa->xclip = tmp;
816 FFB_MAKE_DIRTY(fmesa, FFB_STATE_XCLIP, 1);
817 }
818 break;
819
820 case GL_BLEND:
821 tmp = (fmesa->ppc & ~FFB_PPC_ABE_MASK);
822 if (state) {
823 tmp |= FFB_PPC_ABE_ENABLE;
824 } else {
825 tmp |= FFB_PPC_ABE_DISABLE;
826 }
827 if (fmesa->ppc != tmp) {
828 fmesa->ppc = tmp;
829 FFB_MAKE_DIRTY(fmesa, FFB_STATE_PPC, 1);
830 ffbDDBlendFuncSeparate(ctx, 0, 0, 0, 0 );
831 }
832 break;
833
834 case GL_DEPTH_TEST:
835 if (state)
836 tmp = 0x0fffffff;
837 else
838 tmp = 0x00000000;
839 if (tmp != fmesa->magnc) {
840 unsigned int fbc = fmesa->fbc;
841 fbc &= ~FFB_FBC_ZE_MASK;
842 if (state)
843 fbc |= FFB_FBC_ZE_ON;
844 else
845 fbc |= FFB_FBC_ZE_OFF;
846 fmesa->fbc = fbc;
847 ffbDDDepthFunc(ctx, ctx->Depth.Func);
848 fmesa->magnc = tmp;
849 FFB_MAKE_DIRTY(fmesa, (FFB_STATE_MAGNC | FFB_STATE_FBC), 2);
850 }
851 break;
852
853 case GL_SCISSOR_TEST:
854 ffbDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
855 ctx->Scissor.Width, ctx->Scissor.Height);
856 break;
857
858 case GL_STENCIL_TEST:
859 if (!(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)) {
860 FALLBACK( ctx, FFB_BADATTR_STENCIL, state );
861 }
862
863 tmp = fmesa->fbc & ~FFB_FBC_YE_MASK;
864 if (state) {
865 ffbDDStencilFuncSeparate(ctx, GL_FRONT,
866 ctx->Stencil.Function[0],
867 ctx->Stencil.Ref[0],
868 ctx->Stencil.ValueMask[0]);
869 ffbDDStencilMaskSeparate(ctx, GL_FRONT,
870 ctx->Stencil.WriteMask[0]);
871 ffbDDStencilOpSeparate(ctx, GL_FRONT,
872 ctx->Stencil.FailFunc[0],
873 ctx->Stencil.ZFailFunc[0],
874 ctx->Stencil.ZPassFunc[0]);
875 tmp |= FFB_FBC_YE_MASK;
876 } else {
877 fmesa->stencil = 0xf0000000;
878 fmesa->stencilctl = 0x33300000;
879 FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6);
880 tmp |= FFB_FBC_YE_OFF;
881 }
882 if (tmp != fmesa->fbc) {
883 fmesa->fbc = tmp;
884 FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
885 }
886 break;
887
888 case GL_FOG:
889 /* Until I implement the fog support... */
890 FALLBACK( ctx, FFB_BADATTR_FOG, state );
891 break;
892
893 case GL_LINE_STIPPLE:
894 if (! state)
895 fmesa->lpat = 0;
896 else
897 ffbDDLineStipple(ctx,
898 ctx->Line.StippleFactor,
899 ctx->Line.StipplePattern);
900 break;
901
902 case GL_POLYGON_STIPPLE:
903 /* Do nothing, we interrogate the state during
904 * reduced primitive changes. Since our caller
905 * will set NEW_POLYGON in the ctx NewState this
906 * will cause the driver rasterization functions
907 * to be reevaluated, which will cause us to force
908 * a reduced primitive change next rendering pass
909 * and it all works out.
910 */
911 break;
912
913 default:
914 break;
915 };
916 }
917
918 void ffbSyncHardware(ffbContextPtr fmesa)
919 {
920 ffb_fbcPtr ffb = fmesa->regs;
921 unsigned int dirty;
922 int i;
923
924 FFBFifo(fmesa, fmesa->state_fifo_ents);
925
926 dirty = fmesa->state_dirty;
927 if (dirty & (FFB_STATE_FBC | FFB_STATE_PPC | FFB_STATE_DRAWOP |
928 FFB_STATE_ROP | FFB_STATE_LPAT | FFB_STATE_WID)) {
929 if (dirty & FFB_STATE_FBC)
930 ffb->fbc = fmesa->fbc;
931 if (dirty & FFB_STATE_PPC)
932 ffb->ppc = fmesa->ppc;
933 if (dirty & FFB_STATE_DRAWOP)
934 ffb->drawop = fmesa->drawop;
935 if (dirty & FFB_STATE_ROP)
936 ffb->rop = fmesa->rop;
937 if (dirty & FFB_STATE_LPAT)
938 ffb->rop = fmesa->lpat;
939 if (dirty & FFB_STATE_WID)
940 ffb->wid = fmesa->wid;
941 }
942 if (dirty & (FFB_STATE_PMASK | FFB_STATE_XPMASK | FFB_STATE_YPMASK |
943 FFB_STATE_ZPMASK | FFB_STATE_XCLIP | FFB_STATE_CMP |
944 FFB_STATE_MATCHAB | FFB_STATE_MAGNAB | FFB_STATE_MATCHC |
945 FFB_STATE_MAGNC)) {
946 if (dirty & FFB_STATE_PMASK)
947 ffb->pmask = fmesa->pmask;
948 if (dirty & FFB_STATE_XPMASK)
949 ffb->xpmask = fmesa->xpmask;
950 if (dirty & FFB_STATE_YPMASK)
951 ffb->ypmask = fmesa->ypmask;
952 if (dirty & FFB_STATE_ZPMASK)
953 ffb->zpmask = fmesa->zpmask;
954 if (dirty & FFB_STATE_XCLIP)
955 ffb->xclip = fmesa->xclip;
956 if (dirty & FFB_STATE_CMP)
957 ffb->cmp = fmesa->cmp;
958 if (dirty & FFB_STATE_MATCHAB)
959 ffb->matchab = fmesa->matchab;
960 if (dirty & FFB_STATE_MAGNAB)
961 ffb->magnab = fmesa->magnab;
962 if (dirty & FFB_STATE_MATCHC)
963 ffb->matchc = fmesa->matchc;
964 if (dirty & FFB_STATE_MAGNC)
965 ffb->magnc = fmesa->magnc;
966 }
967
968 if (dirty & FFB_STATE_DCUE) {
969 ffb->dcss = fmesa->dcss;
970 ffb->dcsf = fmesa->dcsf;
971 ffb->dcsb = fmesa->dcsb;
972 ffb->dczf = fmesa->dczf;
973 ffb->dczb = fmesa->dczb;
974 if (fmesa->ffb_sarea->flags & (FFB_DRI_FFB2 | FFB_DRI_FFB2PLUS)) {
975 ffb->dcss1 = fmesa->dcss1;
976 ffb->dcss2 = fmesa->dcss2;
977 ffb->dcss3 = fmesa->dcss3;
978 ffb->dcs2 = fmesa->dcs2;
979 ffb->dcs3 = fmesa->dcs3;
980 ffb->dcs4 = fmesa->dcs4;
981 ffb->dcd2 = fmesa->dcd2;
982 ffb->dcd3 = fmesa->dcd3;
983 ffb->dcd4 = fmesa->dcd4;
984 }
985 }
986
987 if (dirty & FFB_STATE_BLEND) {
988 ffb->blendc = fmesa->blendc;
989 ffb->blendc1 = fmesa->blendc1;
990 ffb->blendc2 = fmesa->blendc2;
991 }
992
993 if (dirty & FFB_STATE_CLIP) {
994 ffb->vclipmin = fmesa->vclipmin;
995 ffb->vclipmax = fmesa->vclipmax;
996 ffb->vclipzmin = fmesa->vclipzmin;
997 ffb->vclipzmax = fmesa->vclipzmax;
998 for (i = 0; i < 4; i++) {
999 ffb->auxclip[i].min = fmesa->aux_clips[i].min;
1000 ffb->auxclip[i].max = fmesa->aux_clips[i].max;
1001 }
1002 }
1003
1004 if ((dirty & FFB_STATE_STENCIL) &&
1005 (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)) {
1006 ffb->stencil = fmesa->stencil;
1007 ffb->stencilctl = fmesa->stencilctl;
1008 ffb->fbc = FFB_FBC_WB_C;
1009 ffb->rawstencilctl = (fmesa->stencilctl | (1 << 19));
1010 ffb->fbc = fmesa->fbc;
1011 ffb->consty = fmesa->consty;
1012 }
1013
1014 if (dirty & FFB_STATE_APAT) {
1015 for (i = 0; i < 32; i++)
1016 ffb->pattern[i] = fmesa->pattern[i];
1017 }
1018
1019 fmesa->state_dirty = 0;
1020 fmesa->state_fifo_ents = 0;
1021 fmesa->ffbScreen->rp_active = 1;
1022 }
1023
1024 static void ffbDDUpdateState(GLcontext *ctx, GLuint newstate)
1025 {
1026 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
1027
1028 /* When we are hw rendering, changing certain kinds of
1029 * state does not require flushing all of our context.
1030 */
1031 if (fmesa->bad_fragment_attrs == 0 &&
1032 (newstate & ~_NEW_COLOR) == 0)
1033 return;
1034
1035 _swrast_InvalidateState( ctx, newstate );
1036 _swsetup_InvalidateState( ctx, newstate );
1037 _ac_InvalidateState( ctx, newstate );
1038 _tnl_InvalidateState( ctx, newstate );
1039
1040 if (newstate & _NEW_TEXTURE)
1041 FALLBACK( ctx, FFB_BADATTR_TEXTURE,
1042 (ctx->Texture._EnabledUnits != 0));
1043
1044 #ifdef STATE_TRACE
1045 fprintf(stderr, "ffbDDUpdateState: newstate(%08x)\n", newstate);
1046 #endif
1047
1048 fmesa->new_gl_state |= newstate;
1049
1050 /* Force a reduced primitive change next rendering
1051 * pass.
1052 */
1053 fmesa->raster_primitive = GL_POLYGON + 1;
1054
1055 #if 0
1056 /* When the modelview matrix changes, this changes what
1057 * the eye coordinates will be so we have to recompute
1058 * the depth cueing parameters.
1059 *
1060 * XXX DD_HAVE_HARDWARE_FOG.
1061 */
1062 if (ctx->Fog.Enabled && (newstate & _NEW_MODELVIEW))
1063 ffb_update_fog();
1064 #endif
1065 }
1066
1067
1068 void ffbDDInitStateFuncs(GLcontext *ctx)
1069 {
1070 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
1071
1072 ctx->Driver.UpdateState = ffbDDUpdateState;
1073
1074 ctx->Driver.Enable = ffbDDEnable;
1075 ctx->Driver.AlphaFunc = ffbDDAlphaFunc;
1076 ctx->Driver.BlendEquationSeparate = ffbDDBlendEquationSeparate;
1077 ctx->Driver.BlendFuncSeparate = ffbDDBlendFuncSeparate;
1078 ctx->Driver.DepthFunc = ffbDDDepthFunc;
1079 ctx->Driver.DepthMask = ffbDDDepthMask;
1080 ctx->Driver.Fogfv = ffbDDFogfv;
1081 ctx->Driver.LineStipple = ffbDDLineStipple;
1082 ctx->Driver.PolygonStipple = ffbDDPolygonStipple;
1083 ctx->Driver.Scissor = ffbDDScissor;
1084 ctx->Driver.ColorMask = ffbDDColorMask;
1085 ctx->Driver.LogicOpcode = ffbDDLogicOp;
1086 ctx->Driver.Viewport = ffbDDViewport;
1087 ctx->Driver.DepthRange = ffbDDDepthRange;
1088
1089 if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS) {
1090 ctx->Driver.StencilFuncSeparate = ffbDDStencilFuncSeparate;
1091 ctx->Driver.StencilMaskSeparate = ffbDDStencilMaskSeparate;
1092 ctx->Driver.StencilOpSeparate = ffbDDStencilOpSeparate;
1093 }
1094
1095 ctx->Driver.DrawBuffer = ffbDDDrawBuffer;
1096 ctx->Driver.ReadBuffer = ffbDDReadBuffer;
1097 ctx->Driver.ClearColor = ffbDDClearColor;
1098 ctx->Driver.ClearDepth = ffbDDClearDepth;
1099 ctx->Driver.ClearStencil = ffbDDClearStencil;
1100
1101 /* We will support color index modes later... -DaveM */
1102 /*
1103 ctx->Driver.ClearIndex = 0;
1104 ctx->Driver.IndexMask = 0;
1105 */
1106 }
1107
1108 void ffbDDInitContextHwState(GLcontext *ctx)
1109 {
1110 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
1111 int fifo_count = 0;
1112 int i;
1113
1114 fmesa->hw_locked = 0;
1115
1116 fmesa->bad_fragment_attrs = 0;
1117 fmesa->state_dirty = FFB_STATE_ALL;
1118 fmesa->new_gl_state = ~0;
1119
1120 fifo_count = 1;
1121 fmesa->fbc = (FFB_FBC_WE_FORCEON | FFB_FBC_WM_COMBINED |
1122 FFB_FBC_SB_BOTH | FFB_FBC_ZE_MASK |
1123 FFB_FBC_YE_OFF | FFB_FBC_XE_OFF |
1124 FFB_FBC_RGBE_MASK);
1125 if (ctx->Visual.doubleBufferMode) {
1126 /* Buffer B is the initial back buffer. */
1127 fmesa->back_buffer = 1;
1128 fmesa->fbc |= FFB_FBC_WB_BC | FFB_FBC_RB_B;
1129 } else {
1130 fmesa->back_buffer = 0;
1131 fmesa->fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
1132 }
1133
1134 fifo_count += 1;
1135 fmesa->ppc = (FFB_PPC_ACE_DISABLE | FFB_PPC_DCE_DISABLE |
1136 FFB_PPC_ABE_DISABLE | FFB_PPC_VCE_3D |
1137 FFB_PPC_APE_DISABLE | FFB_PPC_TBE_OPAQUE |
1138 FFB_PPC_ZS_CONST | FFB_PPC_YS_CONST |
1139 FFB_PPC_XS_WID | FFB_PPC_CS_VAR);
1140
1141 fifo_count += 3;
1142 fmesa->drawop = FFB_DRAWOP_RECTANGLE;
1143
1144 /* GL_COPY is the default LogicOp. */
1145 fmesa->rop = (FFB_ROP_NEW << 16) | (FFB_ROP_NEW << 8) | FFB_ROP_NEW;
1146
1147 /* No line patterning enabled. */
1148 fmesa->lpat = 0x00000000;
1149
1150 /* We do not know the WID value until the first context switch. */
1151 fifo_count += 1;
1152 fmesa->wid = ~0;
1153
1154 fifo_count += 5;
1155
1156 /* ColorMask, all enabled. */
1157 fmesa->pmask = 0xffffffff;
1158
1159 fmesa->xpmask = 0x000000ff;
1160 fmesa->ypmask = 0x0000000f;
1161 fmesa->zpmask = 0x0fffffff;
1162
1163 /* AlphaFunc GL_ALWAYS, AlphaRef 0 */
1164 fmesa->xclip = FFB_XCLIP_TEST_ALWAYS | 0x00;
1165
1166 /* This sets us up to use WID clipping (so the DRI clipping
1167 * rectangle is unneeded by us). All other match and magnitude
1168 * tests are set to pass.
1169 */
1170 fifo_count += 5;
1171 fmesa->cmp = ((FFB_CMP_MATCH_ALWAYS << 24) | /* MATCH C */
1172 (FFB_CMP_MAGN_ALWAYS << 16) | /* MAGN C */
1173 (FFB_CMP_MATCH_EQ << 8) | /* MATCH AB */
1174 (FFB_CMP_MAGN_ALWAYS << 0)); /* MAGN AB */
1175 fmesa->matchab = 0xff000000;
1176 fmesa->magnab = 0x00000000;
1177 fmesa->matchc = 0x00000000;
1178 fmesa->magnc = 0x00000000;
1179
1180 /* Depth cue parameters, all zeros to start. */
1181 fifo_count += 14;
1182 fmesa->dcss = 0x00000000;
1183 fmesa->dcsf = 0x00000000;
1184 fmesa->dcsb = 0x00000000;
1185 fmesa->dczf = 0x00000000;
1186 fmesa->dczb = 0x00000000;
1187 fmesa->dcss1 = 0x00000000;
1188 fmesa->dcss2 = 0x00000000;
1189 fmesa->dcss3 = 0x00000000;
1190 fmesa->dcs2 = 0x00000000;
1191 fmesa->dcs3 = 0x00000000;
1192 fmesa->dcs4 = 0x00000000;
1193 fmesa->dcd2 = 0x00000000;
1194 fmesa->dcd3 = 0x00000000;
1195 fmesa->dcd4 = 0x00000000;
1196
1197 /* Alpha blending unit state. */
1198 fifo_count += 3;
1199 fmesa->blendc = (1 << 0) | (0 << 2); /* src(GL_ONE) | dst(GL_ZERO) */
1200 fmesa->blendc1 = 0x00000000;
1201 fmesa->blendc2 = 0x00000000;
1202
1203 /* ViewPort clip state. */
1204 fifo_count += 4 + (4 * 2);
1205 fmesa->vclipmin = 0x00000000;
1206 fmesa->vclipmax = 0xffffffff;
1207 fmesa->vclipzmin = 0x00000000;
1208 fmesa->vclipzmax = 0x0fffffff;
1209 for (i = 0; i < 4; i++) {
1210 fmesa->aux_clips[0].min = 0x00000000;
1211 fmesa->aux_clips[0].max = 0x00000000;
1212 }
1213
1214 /* Stenciling state. */
1215 fifo_count += 6;
1216 fmesa->stencil = 0xf0000000; /* Stencil MASK, Y plane */
1217 fmesa->stencilctl = 0x33300000; /* All stencil tests disabled */
1218 fmesa->consty = 0x0;
1219
1220 /* Area pattern, used for polygon stipples. */
1221 fifo_count += 32;
1222 for (i = 0; i < 32; i++)
1223 fmesa->pattern[i] = 0x00000000;
1224
1225 fmesa->state_fifo_ents = fifo_count;
1226 fmesa->state_all_fifo_ents = fifo_count;
1227 }