1 /* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_state.c,v 1.5 2002/10/30 12:51:27 alanh Exp $
3 * GLX Hardware Device Driver for Sun Creator/Creator3D
4 * Copyright (C) 2000, 2001 David S. Miller
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
25 * David S. Miller <davem@redhat.com>
33 #include "ffb_depth.h"
34 #include "ffb_context.h"
37 #include "ffb_state.h"
39 #include "extensions.h"
42 #include "swrast/swrast.h"
43 #include "array_cache/acache.h"
45 #include "swrast_setup/swrast_setup.h"
47 #include "tnl/t_pipeline.h"
51 static unsigned int ffbComputeAlphaFunc(GLcontext
*ctx
)
57 fprintf(stderr
, "ffbDDAlphaFunc: func(%s) ref(%02x)\n",
58 _mesa_lookup_enum_by_nr(ctx
->Color
.AlphaFunc
),
59 ctx
->Color
.AlphaRef
& 0xff);
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;
73 return FFB_XCLIP_TEST_ALWAYS
| 0x00;
76 CLAMPED_FLOAT_TO_UBYTE(alphaRef
, ctx
->Color
.AlphaRef
);
77 xclip
|= (alphaRef
& 0xff);
82 static void ffbDDAlphaFunc(GLcontext
*ctx
, GLenum func
, GLfloat ref
)
84 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
86 if (ctx
->Color
.AlphaEnabled
) {
87 unsigned int xclip
= ffbComputeAlphaFunc(ctx
);
89 if (fmesa
->xclip
!= xclip
) {
91 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_XCLIP
, 1);
96 static void ffbDDBlendEquationSeparate(GLcontext
*ctx
,
97 GLenum modeRGB
, GLenum modeA
)
101 fprintf(stderr
, "ffbDDBlendEquation: mode(%s)\n",
102 _mesa_lookup_enum_by_nr(modeRGB
));
104 assert( modeRGB
== modeA
);
105 FALLBACK( ctx
, (modeRGB
!= GL_FUNC_ADD
), FFB_BADATTR_BLENDEQN
);
108 static void ffbDDBlendFuncSeparate(GLcontext
*ctx
, GLenum sfactorRGB
,
109 GLenum dfactorRGB
, GLenum sfactorA
,
112 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
113 unsigned int blendc
= 1 << 4;
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
));
122 switch (ctx
->Color
.BlendSrcRGB
) {
131 case GL_ONE_MINUS_SRC_ALPHA
:
140 if (ctx
->Color
.BlendEnabled
)
141 FALLBACK( ctx
, FFB_BADATTR_BLENDFUNC
, GL_TRUE
);
145 switch (ctx
->Color
.BlendDstRGB
) {
154 case GL_ONE_MINUS_SRC_ALPHA
:
163 if (ctx
->Color
.BlendEnabled
)
164 FALLBACK( ctx
, FFB_BADATTR_BLENDFUNC
, GL_TRUE
);
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.
178 FALLBACK(ctx
, FFB_BADATTR_BLENDROP
, GL_TRUE
);
182 FALLBACK( ctx
, (FFB_BADATTR_BLENDFUNC
|FFB_BADATTR_BLENDROP
), GL_FALSE
);
184 if (blendc
!= fmesa
->blendc
) {
185 fmesa
->blendc
= blendc
;
186 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_BLEND
, 1);
190 static void ffbDDDepthFunc(GLcontext
*ctx
, GLenum func
)
192 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
196 fprintf(stderr
, "ffbDDDepthFunc: func(%s)\n",
197 _mesa_lookup_enum_by_nr(func
));
202 cmp
= FFB_CMP_MAGN_NEVER
;
205 cmp
= FFB_CMP_MAGN_ALWAYS
;
208 cmp
= FFB_CMP_MAGN_LT
;
211 cmp
= FFB_CMP_MAGN_LE
;
214 cmp
= FFB_CMP_MAGN_EQ
;
217 cmp
= FFB_CMP_MAGN_GT
;
220 cmp
= FFB_CMP_MAGN_GE
;
223 cmp
= FFB_CMP_MAGN_NE
;
229 if (! ctx
->Depth
.Test
)
230 cmp
= FFB_CMP_MAGN_ALWAYS
;
233 cmp
= (fmesa
->cmp
& ~(0xff<<16)) | cmp
;
234 if (cmp
!= fmesa
->cmp
) {
236 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_CMP
, 1);
240 static void ffbDDDepthMask(GLcontext
*ctx
, GLboolean flag
)
242 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
243 GLuint fbc
= fmesa
->fbc
;
244 GLboolean enabled_now
;
247 fprintf(stderr
, "ffbDDDepthMask: flag(%d)\n", flag
);
250 if ((fbc
& FFB_FBC_ZE_MASK
) == FFB_FBC_ZE_OFF
)
251 enabled_now
= GL_FALSE
;
253 enabled_now
= GL_TRUE
;
255 if (flag
!= enabled_now
) {
256 fbc
&= ~FFB_FBC_ZE_MASK
;
258 fbc
|= FFB_FBC_WB_C
| FFB_FBC_ZE_ON
;
260 fbc
|= FFB_FBC_ZE_OFF
;
261 fbc
&= ~FFB_FBC_WB_C
;
264 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
268 static void ffbDDStencilFunc(GLcontext
*ctx
, GLenum func
, GLint ref
, GLuint mask
)
270 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
271 unsigned int stencil
, stencilctl
, consty
;
273 /* We will properly update sw/hw state when stenciling is
276 if (! ctx
->Stencil
.Enabled
)
279 stencilctl
= fmesa
->stencilctl
;
280 stencilctl
&= ~(7 << 16);
283 case GL_ALWAYS
: stencilctl
|= (0 << 16); break;
284 case GL_GREATER
: stencilctl
|= (1 << 16); break;
285 case GL_EQUAL
: stencilctl
|= (2 << 16); break;
286 case GL_GEQUAL
: stencilctl
|= (3 << 16); break;
287 case GL_NEVER
: stencilctl
|= (4 << 16); break;
288 case GL_LEQUAL
: stencilctl
|= (5 << 16); break;
289 case GL_NOTEQUAL
: stencilctl
|= (6 << 16); break;
290 case GL_LESS
: stencilctl
|= (7 << 16); break;
298 stencil
= fmesa
->stencil
;
299 stencil
&= ~(0xf << 20);
300 stencil
|= (mask
& 0xf) << 20;
302 if (fmesa
->stencil
!= stencil
||
303 fmesa
->stencilctl
!= stencilctl
||
304 fmesa
->consty
!= consty
) {
305 fmesa
->stencil
= stencil
;
306 fmesa
->stencilctl
= stencilctl
;
307 fmesa
->consty
= consty
;
308 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_STENCIL
, 6);
312 static void ffbDDStencilMask(GLcontext
*ctx
, GLuint mask
)
314 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
317 if (fmesa
->ypmask
!= mask
) {
318 fmesa
->ypmask
= mask
;
319 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_YPMASK
, 1);
323 static void ffbDDStencilOp(GLcontext
*ctx
, GLenum fail
, GLenum zfail
, GLenum zpass
)
325 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
326 unsigned int stencilctl
;
328 /* We will properly update sw/hw state when stenciling is
331 if (! ctx
->Stencil
.Enabled
)
334 stencilctl
= fmesa
->stencilctl
;
335 stencilctl
&= ~(0xfff00000);
338 case GL_ZERO
: stencilctl
|= (0 << 28); break;
339 case GL_KEEP
: stencilctl
|= (1 << 28); break;
340 case GL_INVERT
: stencilctl
|= (2 << 28); break;
341 case GL_REPLACE
: stencilctl
|= (3 << 28); break;
342 case GL_INCR
: stencilctl
|= (4 << 28); break;
343 case GL_DECR
: stencilctl
|= (5 << 28); break;
350 case GL_ZERO
: stencilctl
|= (0 << 24); break;
351 case GL_KEEP
: stencilctl
|= (1 << 24); break;
352 case GL_INVERT
: stencilctl
|= (2 << 24); break;
353 case GL_REPLACE
: stencilctl
|= (3 << 24); break;
354 case GL_INCR
: stencilctl
|= (4 << 24); break;
355 case GL_DECR
: stencilctl
|= (5 << 24); break;
362 case GL_ZERO
: stencilctl
|= (0 << 20); break;
363 case GL_KEEP
: stencilctl
|= (1 << 20); break;
364 case GL_INVERT
: stencilctl
|= (2 << 20); break;
365 case GL_REPLACE
: stencilctl
|= (3 << 20); break;
366 case GL_INCR
: stencilctl
|= (4 << 20); break;
367 case GL_DECR
: stencilctl
|= (5 << 20); break;
373 if (fmesa
->stencilctl
!= stencilctl
) {
374 fmesa
->stencilctl
= stencilctl
;
375 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_STENCIL
, 6);
379 static void ffbCalcViewportRegs(GLcontext
*ctx
)
381 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
382 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
383 GLuint xmin
, xmax
, ymin
, ymax
, zmin
, zmax
;
384 unsigned int vcmin
, vcmax
;
386 xmin
= ctx
->Viewport
.X
+ dPriv
->x
;
387 xmax
= xmin
+ ctx
->Viewport
.Width
;
388 ymax
= dPriv
->y
+ dPriv
->h
- ctx
->Viewport
.Y
;
389 ymin
= ymax
- ctx
->Viewport
.Height
;
390 if (ctx
->Scissor
.Enabled
) {
391 GLuint sc_xmin
, sc_xmax
, sc_ymin
, sc_ymax
;
393 sc_xmin
= ctx
->Viewport
.X
+ dPriv
->x
;
394 sc_xmax
= sc_xmin
+ ctx
->Viewport
.Width
;
395 sc_ymax
= dPriv
->y
+ dPriv
->h
- ctx
->Viewport
.Y
;
396 sc_ymin
= sc_ymax
- ctx
->Viewport
.Height
;
406 zmin
= ((GLdouble
)ctx
->Viewport
.Near
* 0x0fffffff);
407 zmax
= ((GLdouble
)ctx
->Viewport
.Far
* 0x0fffffff);
409 vcmin
= ((ymin
& 0xffff) << 16) | (xmin
& 0xffff);
410 vcmax
= ((ymax
& 0xffff) << 16) | (xmax
& 0xffff);
411 if (fmesa
->vclipmin
!= vcmin
||
412 fmesa
->vclipmax
!= vcmax
||
413 fmesa
->vclipzmin
!= zmin
||
414 fmesa
->vclipzmax
!= zmax
) {
415 fmesa
->vclipmin
= vcmin
;
416 fmesa
->vclipmax
= vcmax
;
417 fmesa
->vclipzmin
= zmin
;
418 fmesa
->vclipzmax
= zmax
;
419 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_CLIP
, (4 + (4 * 2)));
423 void ffbCalcViewport(GLcontext
*ctx
)
425 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
426 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
427 GLfloat
*m
= fmesa
->hw_viewport
;
428 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
430 m
[MAT_SX
] = v
[MAT_SX
];
431 m
[MAT_TX
] = v
[MAT_TX
] + dPriv
->x
+ SUBPIXEL_X
;
432 m
[MAT_SY
] = - v
[MAT_SY
];
433 m
[MAT_TY
] = - v
[MAT_TY
] + dPriv
->h
+ dPriv
->y
+ SUBPIXEL_Y
;
434 m
[MAT_SZ
] = v
[MAT_SZ
] * ((GLdouble
)1.0 / (GLdouble
)0x0fffffff);
435 m
[MAT_TZ
] = v
[MAT_TZ
] * ((GLdouble
)1.0 / (GLdouble
)0x0fffffff);
437 fmesa
->depth_scale
= ((GLdouble
)1.0 / (GLdouble
)0x0fffffff);
439 ffbCalcViewportRegs(ctx
);
441 fmesa
->setupnewinputs
|= VERT_BIT_POS
;
444 static void ffbDDViewport(GLcontext
*ctx
, GLint x
, GLint y
,
445 GLsizei width
, GLsizei height
)
447 ffbCalcViewport(ctx
);
450 static void ffbDDDepthRange(GLcontext
*ctx
, GLclampd nearval
, GLclampd farval
)
452 ffbCalcViewport(ctx
);
455 static void ffbDDScissor(GLcontext
*ctx
, GLint cx
, GLint cy
,
456 GLsizei cw
, GLsizei ch
)
458 ffbCalcViewport(ctx
);
461 static void ffbDDDrawBuffer(GLcontext
*ctx
, GLenum buffer
)
463 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
464 unsigned int fbc
= fmesa
->fbc
;
467 fprintf(stderr
, "ffbDDDrawBuffer: mode(%s)\n",
468 _mesa_lookup_enum_by_nr(buffer
));
470 fbc
&= ~(FFB_FBC_WB_AB
| FFB_FBC_RB_MASK
);
473 if (fmesa
->back_buffer
== 0)
474 fbc
|= FFB_FBC_WB_B
| FFB_FBC_RB_B
;
476 fbc
|= FFB_FBC_WB_A
| FFB_FBC_RB_A
;
480 if (fmesa
->back_buffer
== 0)
481 fbc
|= FFB_FBC_WB_A
| FFB_FBC_RB_A
;
483 fbc
|= FFB_FBC_WB_B
| FFB_FBC_RB_B
;
486 case GL_FRONT_AND_BACK
:
487 fbc
|= FFB_FBC_WB_AB
;
494 if (fbc
!= fmesa
->fbc
) {
496 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
501 static void ffbDDReadBuffer(GLcontext
*ctx
, GLenum buffer
)
503 /* no-op, unless you implement h/w glRead/CopyPixels */
508 * Specifies buffer for sw fallbacks (spans)
510 static void ffbDDSetBuffer(GLcontext
*ctx
, GLframebuffer
*colorBuffer
,
513 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
514 unsigned int fbc
= fmesa
->fbc
;
517 fprintf(stderr
, "ffbDDSetReadBuffer: mode(%s)\n",
518 _mesa_lookup_enum_by_nr(buffer
));
520 fbc
&= ~(FFB_FBC_RB_MASK
);
522 case DD_FRONT_LEFT_BIT
:
523 if (fmesa
->back_buffer
== 0)
529 case DD_BACK_LEFT_BIT
:
530 if (fmesa
->back_buffer
== 0)
537 _mesa_problem(ctx
, "Unexpected buffer in ffbDDSetBuffer()");
541 if (fbc
!= fmesa
->fbc
) {
543 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
547 static void ffbDDClearColor(GLcontext
*ctx
, const GLfloat color
[4])
549 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
551 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
552 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
553 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
555 fmesa
->clear_pixel
= ((c
[0] << 0) |
560 static void ffbDDClearDepth(GLcontext
*ctx
, GLclampd depth
)
562 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
564 fmesa
->clear_depth
= Z_FROM_MESA(depth
* 4294967295.0f
);
567 static void ffbDDClearStencil(GLcontext
*ctx
, GLint stencil
)
569 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
571 fmesa
->clear_stencil
= stencil
& 0xf;
574 /* XXX Actually, should I be using FBC controls for this? -DaveM */
575 static void ffbDDColorMask(GLcontext
*ctx
,
576 GLboolean r
, GLboolean g
,
577 GLboolean b
, GLboolean a
)
579 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
580 unsigned int new_pmask
= 0x0;
583 fprintf(stderr
, "ffbDDColorMask: r(%d) g(%d) b(%d) a(%d)\n",
587 new_pmask
|= 0x000000ff;
589 new_pmask
|= 0x0000ff00;
591 new_pmask
|= 0x00ff0000;
593 if (fmesa
->pmask
!= new_pmask
) {
594 fmesa
->pmask
= new_pmask
;
595 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_PMASK
, 1);
599 static void ffbDDLogicOp(GLcontext
*ctx
, GLenum op
)
601 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
605 fprintf(stderr
, "ffbDDLogicOp: op(%s)\n",
606 _mesa_lookup_enum_by_nr(op
));
609 case GL_CLEAR
: rop
= FFB_ROP_ZERO
; break;
610 case GL_SET
: rop
= FFB_ROP_ONES
; break;
611 case GL_COPY
: rop
= FFB_ROP_NEW
; break;
612 case GL_AND
: rop
= FFB_ROP_NEW_AND_OLD
; break;
613 case GL_NAND
: rop
= FFB_ROP_NEW_AND_NOLD
; break;
614 case GL_OR
: rop
= FFB_ROP_NEW_OR_OLD
; break;
615 case GL_NOR
: rop
= FFB_ROP_NEW_OR_NOLD
; break;
616 case GL_XOR
: rop
= FFB_ROP_NEW_XOR_OLD
; break;
617 case GL_NOOP
: rop
= FFB_ROP_OLD
; break;
618 case GL_COPY_INVERTED
: rop
= FFB_ROP_NNEW
; break;
619 case GL_INVERT
: rop
= FFB_ROP_NOLD
; break;
620 case GL_EQUIV
: rop
= FFB_ROP_NNEW_XOR_NOLD
; break;
621 case GL_AND_REVERSE
: rop
= FFB_ROP_NEW_AND_NOLD
; break;
622 case GL_AND_INVERTED
: rop
= FFB_ROP_NNEW_AND_OLD
; break;
623 case GL_OR_REVERSE
: rop
= FFB_ROP_NEW_OR_NOLD
; break;
624 case GL_OR_INVERTED
: rop
= FFB_ROP_NNEW_OR_OLD
; break;
630 rop
|= fmesa
->rop
& ~0xff;
631 if (rop
!= fmesa
->rop
) {
633 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_ROP
, 1);
636 FALLBACK( ctx
, FFB_BADATTR_BLENDROP
, GL_FALSE
);
641 /* XXX Also need to track near/far just like 3dfx driver.
643 * XXX Actually, that won't work, because the 3dfx chip works by
644 * XXX having 1/w coordinates fed to it for each primitive, and
645 * XXX it uses this to index it's 64 entry fog table.
647 static void ffb_fog_linear(GLcontext
*ctx
, ffbContextPtr fmesa
)
649 GLfloat c
= ctx
->ProjectionMatrix
.m
[10];
650 GLfloat d
= ctx
->ProjectionMatrix
.m
[14];
651 GLfloat tz
= ctx
->Viewport
.WindowMap
.m
[MAT_TZ
];
652 GLfloat szInv
= 1.0F
/ ctx
->Viewport
.WindowMap
.m
[MAT_SZ
];
653 GLfloat fogEnd
= ctx
->Fog
.End
;
654 GLfloat fogScale
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
660 /* Compute the Z at which f reaches 0.0, this is the full
663 * Thus compute Z (as seen by the chip during rendering),
666 * 0.0 = (fogEnd - eyez) * fogScale
668 * fogScale is usually not zero, thus we are looking for:
672 * fogEnd = -d / (c + ((Z - tz) * szInv))
673 * fogEnd * (c + ((Z - tz) * szInv)) = -d
674 * (c + ((Z - tz) * szInv)) = -d / fogEnd
675 * (Z - tz) * szInv = (-d / fogEnd) - c
676 * (Z - tz) = ((-d / fogEnd) - c) / szInv
677 * Z = (((-d / fogEnd) - c) / szInv) + tz
679 Zzero
= (((-d
/ fogEnd
) - c
) / szInv
) + tz
;
681 /* Compute the Z at which f reaches 1.0, this is where
682 * the incoming frag's full intensity is shown. This
685 * 1.0 = (fogEnd - eyez)
687 * We are looking for:
689 * 1.0 + eyez = fogEnd
691 * 1.0 + (-d / (c + ((Z - tz) * szInv))) = fogEnd
692 * -d / (c + ((Z - tz) * szInv)) = fogEnd - 1.0
693 * -d / (FogEnd - 1.0) = (c + ((Z - tz) * szInv))
694 * (-d / (fogEnd - 1.0)) - c = ((Z - tz) * szInv)
695 * ((-d / (fogEnd - 1.0)) - c) / szInv = (Z - tz)
696 * (((-d / (fogEnd - 1.0)) - c) / szInv) + tz = Z
698 Zone
= (((-d
/ (fogEnd
- 1.0)) - c
) / szInv
) + tz
;
700 /* FFB's Zfront must be less than Zback, thus we may have
701 * to invert Sf/Sb to satisfy this constraint.
706 zf
= Z_FROM_MESA(Zzero
);
707 zb
= Z_FROM_MESA(Zone
);
711 zf
= Z_FROM_MESA(Zone
);
712 zb
= Z_FROM_MESA(Zzero
);
717 static void ffbDDFogfv(GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
720 fprintf(stderr
, "ffbDDFogfv: pname(%s)\n", _mesa_lookup_enum_by_nr(pname
));
724 static void ffbDDLineStipple(GLcontext
*ctx
, GLint factor
, GLushort pattern
)
726 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
729 fprintf(stderr
, "ffbDDLineStipple: factor(%d) pattern(%04x)\n",
732 if (ctx
->Line
.StippleFlag
) {
733 factor
= ctx
->Line
.StippleFactor
;
734 pattern
= ctx
->Line
.StipplePattern
;
735 if ((GLuint
) factor
> 15) {
736 fmesa
->lpat
= FFB_LPAT_BAD
;
738 fmesa
->lpat
= ((factor
<< FFB_LPAT_SCALEVAL_SHIFT
) |
739 (0 << FFB_LPAT_PATLEN_SHIFT
) |
740 ((pattern
& 0xffff) << FFB_LPAT_PATTERN_SHIFT
));
747 void ffbXformAreaPattern(ffbContextPtr fmesa
, const GLubyte
*mask
)
749 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
753 i
= (dPriv
->y
+ dPriv
->h
) & (32 - 1);
754 xoff
= dPriv
->x
& (32 - 1);
755 while (lines
++ < 32) {
757 (((GLuint
)mask
[0] << 24) |
758 ((GLuint
)mask
[1] << 16) |
759 ((GLuint
)mask
[2] << 8) |
760 ((GLuint
)mask
[3] << 0));
763 (raw
<< xoff
) | (raw
>> (32 - xoff
));
764 i
= (i
- 1) & (32 - 1);
768 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_APAT
, 32);
771 static void ffbDDPolygonStipple(GLcontext
*ctx
, const GLubyte
*mask
)
773 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
776 fprintf(stderr
, "ffbDDPolygonStipple: state(%d)\n",
777 ctx
->Polygon
.StippleFlag
);
779 ffbXformAreaPattern(fmesa
, mask
);
782 static void ffbDDEnable(GLcontext
*ctx
, GLenum cap
, GLboolean state
)
784 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
788 fprintf(stderr
, "ffbDDEnable: %s state(%d)\n",
789 _mesa_lookup_enum_by_nr(cap
), state
);
794 tmp
= ffbComputeAlphaFunc(ctx
);
796 tmp
= FFB_XCLIP_TEST_ALWAYS
;
798 if (tmp
!= fmesa
->xclip
) {
800 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_XCLIP
, 1);
805 tmp
= (fmesa
->ppc
& ~FFB_PPC_ABE_MASK
);
807 tmp
|= FFB_PPC_ABE_ENABLE
;
809 tmp
|= FFB_PPC_ABE_DISABLE
;
811 if (fmesa
->ppc
!= tmp
) {
813 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_PPC
, 1);
814 ffbDDBlendFuncSeparate(ctx
, 0, 0, 0, 0 );
823 if (tmp
!= fmesa
->magnc
) {
824 unsigned int fbc
= fmesa
->fbc
;
825 fbc
&= ~FFB_FBC_ZE_MASK
;
827 fbc
|= FFB_FBC_ZE_ON
;
829 fbc
|= FFB_FBC_ZE_OFF
;
831 ffbDDDepthFunc(ctx
, ctx
->Depth
.Func
);
833 FFB_MAKE_DIRTY(fmesa
, (FFB_STATE_MAGNC
| FFB_STATE_FBC
), 2);
837 case GL_SCISSOR_TEST
:
838 ffbDDScissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
839 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
842 case GL_STENCIL_TEST
:
843 if (!(fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
)) {
844 FALLBACK( ctx
, FFB_BADATTR_STENCIL
, state
);
847 tmp
= fmesa
->fbc
& ~FFB_FBC_YE_MASK
;
849 ffbDDStencilFunc(ctx
,
850 ctx
->Stencil
.Function
[0],
852 ctx
->Stencil
.ValueMask
[0]);
853 ffbDDStencilMask(ctx
, ctx
->Stencil
.WriteMask
[0]);
855 ctx
->Stencil
.FailFunc
[0],
856 ctx
->Stencil
.ZFailFunc
[0],
857 ctx
->Stencil
.ZPassFunc
[0]);
858 tmp
|= FFB_FBC_YE_MASK
;
860 fmesa
->stencil
= 0xf0000000;
861 fmesa
->stencilctl
= 0x33300000;
862 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_STENCIL
, 6);
863 tmp
|= FFB_FBC_YE_OFF
;
865 if (tmp
!= fmesa
->fbc
) {
867 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
872 /* Until I implement the fog support... */
873 FALLBACK( ctx
, FFB_BADATTR_FOG
, state
);
876 case GL_LINE_STIPPLE
:
880 ffbDDLineStipple(ctx
,
881 ctx
->Line
.StippleFactor
,
882 ctx
->Line
.StipplePattern
);
885 case GL_POLYGON_STIPPLE
:
886 /* Do nothing, we interrogate the state during
887 * reduced primitive changes. Since our caller
888 * will set NEW_POLYGON in the ctx NewState this
889 * will cause the driver rasterization functions
890 * to be reevaluated, which will cause us to force
891 * a reduced primitive change next rendering pass
892 * and it all works out.
901 void ffbSyncHardware(ffbContextPtr fmesa
)
903 ffb_fbcPtr ffb
= fmesa
->regs
;
907 FFBFifo(fmesa
, fmesa
->state_fifo_ents
);
909 dirty
= fmesa
->state_dirty
;
910 if (dirty
& (FFB_STATE_FBC
| FFB_STATE_PPC
| FFB_STATE_DRAWOP
|
911 FFB_STATE_ROP
| FFB_STATE_LPAT
| FFB_STATE_WID
)) {
912 if (dirty
& FFB_STATE_FBC
)
913 ffb
->fbc
= fmesa
->fbc
;
914 if (dirty
& FFB_STATE_PPC
)
915 ffb
->ppc
= fmesa
->ppc
;
916 if (dirty
& FFB_STATE_DRAWOP
)
917 ffb
->drawop
= fmesa
->drawop
;
918 if (dirty
& FFB_STATE_ROP
)
919 ffb
->rop
= fmesa
->rop
;
920 if (dirty
& FFB_STATE_LPAT
)
921 ffb
->rop
= fmesa
->lpat
;
922 if (dirty
& FFB_STATE_WID
)
923 ffb
->wid
= fmesa
->wid
;
925 if (dirty
& (FFB_STATE_PMASK
| FFB_STATE_XPMASK
| FFB_STATE_YPMASK
|
926 FFB_STATE_ZPMASK
| FFB_STATE_XCLIP
| FFB_STATE_CMP
|
927 FFB_STATE_MATCHAB
| FFB_STATE_MAGNAB
| FFB_STATE_MATCHC
|
929 if (dirty
& FFB_STATE_PMASK
)
930 ffb
->pmask
= fmesa
->pmask
;
931 if (dirty
& FFB_STATE_XPMASK
)
932 ffb
->xpmask
= fmesa
->xpmask
;
933 if (dirty
& FFB_STATE_YPMASK
)
934 ffb
->ypmask
= fmesa
->ypmask
;
935 if (dirty
& FFB_STATE_ZPMASK
)
936 ffb
->zpmask
= fmesa
->zpmask
;
937 if (dirty
& FFB_STATE_XCLIP
)
938 ffb
->xclip
= fmesa
->xclip
;
939 if (dirty
& FFB_STATE_CMP
)
940 ffb
->cmp
= fmesa
->cmp
;
941 if (dirty
& FFB_STATE_MATCHAB
)
942 ffb
->matchab
= fmesa
->matchab
;
943 if (dirty
& FFB_STATE_MAGNAB
)
944 ffb
->magnab
= fmesa
->magnab
;
945 if (dirty
& FFB_STATE_MATCHC
)
946 ffb
->matchc
= fmesa
->matchc
;
947 if (dirty
& FFB_STATE_MAGNC
)
948 ffb
->magnc
= fmesa
->magnc
;
951 if (dirty
& FFB_STATE_DCUE
) {
952 ffb
->dcss
= fmesa
->dcss
;
953 ffb
->dcsf
= fmesa
->dcsf
;
954 ffb
->dcsb
= fmesa
->dcsb
;
955 ffb
->dczf
= fmesa
->dczf
;
956 ffb
->dczb
= fmesa
->dczb
;
957 if (fmesa
->ffb_sarea
->flags
& (FFB_DRI_FFB2
| FFB_DRI_FFB2PLUS
)) {
958 ffb
->dcss1
= fmesa
->dcss1
;
959 ffb
->dcss2
= fmesa
->dcss2
;
960 ffb
->dcss3
= fmesa
->dcss3
;
961 ffb
->dcs2
= fmesa
->dcs2
;
962 ffb
->dcs3
= fmesa
->dcs3
;
963 ffb
->dcs4
= fmesa
->dcs4
;
964 ffb
->dcd2
= fmesa
->dcd2
;
965 ffb
->dcd3
= fmesa
->dcd3
;
966 ffb
->dcd4
= fmesa
->dcd4
;
970 if (dirty
& FFB_STATE_BLEND
) {
971 ffb
->blendc
= fmesa
->blendc
;
972 ffb
->blendc1
= fmesa
->blendc1
;
973 ffb
->blendc2
= fmesa
->blendc2
;
976 if (dirty
& FFB_STATE_CLIP
) {
977 ffb
->vclipmin
= fmesa
->vclipmin
;
978 ffb
->vclipmax
= fmesa
->vclipmax
;
979 ffb
->vclipzmin
= fmesa
->vclipzmin
;
980 ffb
->vclipzmax
= fmesa
->vclipzmax
;
981 for (i
= 0; i
< 4; i
++) {
982 ffb
->auxclip
[i
].min
= fmesa
->aux_clips
[i
].min
;
983 ffb
->auxclip
[i
].max
= fmesa
->aux_clips
[i
].max
;
987 if ((dirty
& FFB_STATE_STENCIL
) &&
988 (fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
)) {
989 ffb
->stencil
= fmesa
->stencil
;
990 ffb
->stencilctl
= fmesa
->stencilctl
;
991 ffb
->fbc
= FFB_FBC_WB_C
;
992 ffb
->rawstencilctl
= (fmesa
->stencilctl
| (1 << 19));
993 ffb
->fbc
= fmesa
->fbc
;
994 ffb
->consty
= fmesa
->consty
;
997 if (dirty
& FFB_STATE_APAT
) {
998 for (i
= 0; i
< 32; i
++)
999 ffb
->pattern
[i
] = fmesa
->pattern
[i
];
1002 fmesa
->state_dirty
= 0;
1003 fmesa
->state_fifo_ents
= 0;
1004 fmesa
->ffbScreen
->rp_active
= 1;
1007 static void ffbDDUpdateState(GLcontext
*ctx
, GLuint newstate
)
1009 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1011 /* When we are hw rendering, changing certain kinds of
1012 * state does not require flushing all of our context.
1014 if (fmesa
->bad_fragment_attrs
== 0 &&
1015 (newstate
& ~_NEW_COLOR
) == 0)
1018 _swrast_InvalidateState( ctx
, newstate
);
1019 _swsetup_InvalidateState( ctx
, newstate
);
1020 _ac_InvalidateState( ctx
, newstate
);
1021 _tnl_InvalidateState( ctx
, newstate
);
1023 if (newstate
& _NEW_TEXTURE
)
1024 FALLBACK( ctx
, FFB_BADATTR_TEXTURE
,
1025 (ctx
->Texture
._EnabledUnits
!= 0));
1028 fprintf(stderr
, "ffbDDUpdateState: newstate(%08x)\n", newstate
);
1031 fmesa
->new_gl_state
|= newstate
;
1033 /* Force a reduced primitive change next rendering
1036 fmesa
->raster_primitive
= GL_POLYGON
+ 1;
1039 /* When the modelview matrix changes, this changes what
1040 * the eye coordinates will be so we have to recompute
1041 * the depth cueing parameters.
1043 * XXX DD_HAVE_HARDWARE_FOG.
1045 if (ctx
->Fog
.Enabled
&& (newstate
& _NEW_MODELVIEW
))
1051 void ffbDDInitStateFuncs(GLcontext
*ctx
)
1053 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1055 ctx
->Driver
.UpdateState
= ffbDDUpdateState
;
1057 ctx
->Driver
.Enable
= ffbDDEnable
;
1058 ctx
->Driver
.AlphaFunc
= ffbDDAlphaFunc
;
1059 ctx
->Driver
.BlendEquationSeparate
= ffbDDBlendEquationSeparate
;
1060 ctx
->Driver
.BlendFuncSeparate
= ffbDDBlendFuncSeparate
;
1061 ctx
->Driver
.DepthFunc
= ffbDDDepthFunc
;
1062 ctx
->Driver
.DepthMask
= ffbDDDepthMask
;
1063 ctx
->Driver
.Fogfv
= ffbDDFogfv
;
1064 ctx
->Driver
.LineStipple
= ffbDDLineStipple
;
1065 ctx
->Driver
.PolygonStipple
= ffbDDPolygonStipple
;
1066 ctx
->Driver
.Scissor
= ffbDDScissor
;
1067 ctx
->Driver
.ColorMask
= ffbDDColorMask
;
1068 ctx
->Driver
.LogicOpcode
= ffbDDLogicOp
;
1069 ctx
->Driver
.Viewport
= ffbDDViewport
;
1070 ctx
->Driver
.DepthRange
= ffbDDDepthRange
;
1072 if (fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
) {
1073 ctx
->Driver
.StencilFunc
= ffbDDStencilFunc
;
1074 ctx
->Driver
.StencilMask
= ffbDDStencilMask
;
1075 ctx
->Driver
.StencilOp
= ffbDDStencilOp
;
1078 ctx
->Driver
.DrawBuffer
= ffbDDDrawBuffer
;
1079 ctx
->Driver
.ReadBuffer
= ffbDDReadBuffer
;
1080 ctx
->Driver
.ClearColor
= ffbDDClearColor
;
1081 ctx
->Driver
.ClearDepth
= ffbDDClearDepth
;
1082 ctx
->Driver
.ClearStencil
= ffbDDClearStencil
;
1084 /* We will support color index modes later... -DaveM */
1086 ctx->Driver.ClearIndex = 0;
1087 ctx->Driver.IndexMask = 0;
1091 struct swrast_device_driver
*swdd
=
1092 _swrast_GetDeviceDriverReference(ctx
);
1093 swdd
->SetBuffer
= ffbDDSetBuffer
;
1099 void ffbDDInitContextHwState(GLcontext
*ctx
)
1101 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1105 fmesa
->hw_locked
= 0;
1107 fmesa
->bad_fragment_attrs
= 0;
1108 fmesa
->state_dirty
= FFB_STATE_ALL
;
1109 fmesa
->new_gl_state
= ~0;
1112 fmesa
->fbc
= (FFB_FBC_WE_FORCEON
| FFB_FBC_WM_COMBINED
|
1113 FFB_FBC_SB_BOTH
| FFB_FBC_ZE_MASK
|
1114 FFB_FBC_YE_OFF
| FFB_FBC_XE_OFF
|
1116 if (ctx
->Visual
.doubleBufferMode
) {
1117 /* Buffer B is the initial back buffer. */
1118 fmesa
->back_buffer
= 1;
1119 fmesa
->fbc
|= FFB_FBC_WB_BC
| FFB_FBC_RB_B
;
1121 fmesa
->back_buffer
= 0;
1122 fmesa
->fbc
|= FFB_FBC_WB_A
| FFB_FBC_RB_A
;
1126 fmesa
->ppc
= (FFB_PPC_ACE_DISABLE
| FFB_PPC_DCE_DISABLE
|
1127 FFB_PPC_ABE_DISABLE
| FFB_PPC_VCE_3D
|
1128 FFB_PPC_APE_DISABLE
| FFB_PPC_TBE_OPAQUE
|
1129 FFB_PPC_ZS_CONST
| FFB_PPC_YS_CONST
|
1130 FFB_PPC_XS_WID
| FFB_PPC_CS_VAR
);
1133 fmesa
->drawop
= FFB_DRAWOP_RECTANGLE
;
1135 /* GL_COPY is the default LogicOp. */
1136 fmesa
->rop
= (FFB_ROP_NEW
<< 16) | (FFB_ROP_NEW
<< 8) | FFB_ROP_NEW
;
1138 /* No line patterning enabled. */
1139 fmesa
->lpat
= 0x00000000;
1141 /* We do not know the WID value until the first context switch. */
1147 /* ColorMask, all enabled. */
1148 fmesa
->pmask
= 0xffffffff;
1150 fmesa
->xpmask
= 0x000000ff;
1151 fmesa
->ypmask
= 0x0000000f;
1152 fmesa
->zpmask
= 0x0fffffff;
1154 /* AlphaFunc GL_ALWAYS, AlphaRef 0 */
1155 fmesa
->xclip
= FFB_XCLIP_TEST_ALWAYS
| 0x00;
1157 /* This sets us up to use WID clipping (so the DRI clipping
1158 * rectangle is unneeded by us). All other match and magnitude
1159 * tests are set to pass.
1162 fmesa
->cmp
= ((FFB_CMP_MATCH_ALWAYS
<< 24) | /* MATCH C */
1163 (FFB_CMP_MAGN_ALWAYS
<< 16) | /* MAGN C */
1164 (FFB_CMP_MATCH_EQ
<< 8) | /* MATCH AB */
1165 (FFB_CMP_MAGN_ALWAYS
<< 0)); /* MAGN AB */
1166 fmesa
->matchab
= 0xff000000;
1167 fmesa
->magnab
= 0x00000000;
1168 fmesa
->matchc
= 0x00000000;
1169 fmesa
->magnc
= 0x00000000;
1171 /* Depth cue parameters, all zeros to start. */
1173 fmesa
->dcss
= 0x00000000;
1174 fmesa
->dcsf
= 0x00000000;
1175 fmesa
->dcsb
= 0x00000000;
1176 fmesa
->dczf
= 0x00000000;
1177 fmesa
->dczb
= 0x00000000;
1178 fmesa
->dcss1
= 0x00000000;
1179 fmesa
->dcss2
= 0x00000000;
1180 fmesa
->dcss3
= 0x00000000;
1181 fmesa
->dcs2
= 0x00000000;
1182 fmesa
->dcs3
= 0x00000000;
1183 fmesa
->dcs4
= 0x00000000;
1184 fmesa
->dcd2
= 0x00000000;
1185 fmesa
->dcd3
= 0x00000000;
1186 fmesa
->dcd4
= 0x00000000;
1188 /* Alpha blending unit state. */
1190 fmesa
->blendc
= (1 << 0) | (0 << 2); /* src(GL_ONE) | dst(GL_ZERO) */
1191 fmesa
->blendc1
= 0x00000000;
1192 fmesa
->blendc2
= 0x00000000;
1194 /* ViewPort clip state. */
1195 fifo_count
+= 4 + (4 * 2);
1196 fmesa
->vclipmin
= 0x00000000;
1197 fmesa
->vclipmax
= 0xffffffff;
1198 fmesa
->vclipzmin
= 0x00000000;
1199 fmesa
->vclipzmax
= 0x0fffffff;
1200 for (i
= 0; i
< 4; i
++) {
1201 fmesa
->aux_clips
[0].min
= 0x00000000;
1202 fmesa
->aux_clips
[0].max
= 0x00000000;
1205 /* Stenciling state. */
1207 fmesa
->stencil
= 0xf0000000; /* Stencil MASK, Y plane */
1208 fmesa
->stencilctl
= 0x33300000; /* All stencil tests disabled */
1209 fmesa
->consty
= 0x0;
1211 /* Area pattern, used for polygon stipples. */
1213 for (i
= 0; i
< 32; i
++)
1214 fmesa
->pattern
[i
] = 0x00000000;
1216 fmesa
->state_fifo_ents
= fifo_count
;
1217 fmesa
->state_all_fifo_ents
= fifo_count
;