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>
34 #include "ffb_depth.h"
35 #include "ffb_context.h"
38 #include "ffb_state.h"
40 #include "extensions.h"
43 #include "swrast/swrast.h"
44 #include "array_cache/acache.h"
46 #include "swrast_setup/swrast_setup.h"
48 #include "tnl/t_pipeline.h"
52 static unsigned int ffbComputeAlphaFunc(GLcontext
*ctx
)
58 fprintf(stderr
, "ffbDDAlphaFunc: func(%s) ref(%02x)\n",
59 _mesa_lookup_enum_by_nr(ctx
->Color
.AlphaFunc
),
60 ctx
->Color
.AlphaRef
& 0xff);
63 switch (ctx
->Color
.AlphaFunc
) {
64 case GL_NEVER
: xclip
= FFB_XCLIP_TEST_NEVER
; break;
65 case GL_LESS
: xclip
= FFB_XCLIP_TEST_LT
; break;
66 case GL_EQUAL
: xclip
= FFB_XCLIP_TEST_EQ
; break;
67 case GL_LEQUAL
: xclip
= FFB_XCLIP_TEST_LE
; break;
68 case GL_GREATER
: xclip
= FFB_XCLIP_TEST_GT
; break;
69 case GL_NOTEQUAL
: xclip
= FFB_XCLIP_TEST_NE
; break;
70 case GL_GEQUAL
: xclip
= FFB_XCLIP_TEST_GE
; break;
71 case GL_ALWAYS
: xclip
= FFB_XCLIP_TEST_ALWAYS
; break;
74 return FFB_XCLIP_TEST_ALWAYS
| 0x00;
77 CLAMPED_FLOAT_TO_UBYTE(alphaRef
, ctx
->Color
.AlphaRef
);
78 xclip
|= (alphaRef
& 0xff);
83 static void ffbDDAlphaFunc(GLcontext
*ctx
, GLenum func
, GLfloat ref
)
85 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
87 if (ctx
->Color
.AlphaEnabled
) {
88 unsigned int xclip
= ffbComputeAlphaFunc(ctx
);
90 if (fmesa
->xclip
!= xclip
) {
92 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_XCLIP
, 1);
97 static void ffbDDBlendEquationSeparate(GLcontext
*ctx
,
98 GLenum modeRGB
, GLenum modeA
)
102 fprintf(stderr
, "ffbDDBlendEquation: mode(%s)\n",
103 _mesa_lookup_enum_by_nr(modeRGB
));
105 assert( modeRGB
== modeA
);
106 FALLBACK( ctx
, (modeRGB
!= GL_FUNC_ADD
), FFB_BADATTR_BLENDEQN
);
109 static void ffbDDBlendFuncSeparate(GLcontext
*ctx
, GLenum sfactorRGB
,
110 GLenum dfactorRGB
, GLenum sfactorA
,
113 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
114 unsigned int blendc
= 1 << 4;
117 fprintf(stderr
, "ffbDDBlendFuncSeparate: sRGB(%s) dRGB(%s) sA(%s) dA(%s)\n",
118 _mesa_lookup_enum_by_nr(sfactorRGB
),
119 _mesa_lookup_enum_by_nr(dfactorRGB
),
120 _mesa_lookup_enum_by_nr(sfactorA
),
121 _mesa_lookup_enum_by_nr(dfactorA
));
123 switch (ctx
->Color
.BlendSrcRGB
) {
132 case GL_ONE_MINUS_SRC_ALPHA
:
141 if (ctx
->Color
.BlendEnabled
)
142 FALLBACK( ctx
, FFB_BADATTR_BLENDFUNC
, GL_TRUE
);
146 switch (ctx
->Color
.BlendDstRGB
) {
155 case GL_ONE_MINUS_SRC_ALPHA
:
164 if (ctx
->Color
.BlendEnabled
)
165 FALLBACK( ctx
, FFB_BADATTR_BLENDFUNC
, GL_TRUE
);
169 if (ctx
->Color
.BlendEnabled
&&
170 ctx
->Color
.ColorLogicOpEnabled
&&
171 ctx
->Color
.LogicOp
!= GL_COPY
) {
172 /* We could avoid this if sfactor is GL_ONE and
173 * dfactor is GL_ZERO. I do not think that is even
174 * worthwhile to check because if someone is using
175 * blending they use more interesting settings and
176 * also it would add more state tracking to a lot
177 * of the code in this file.
179 FALLBACK(ctx
, FFB_BADATTR_BLENDROP
, GL_TRUE
);
183 FALLBACK( ctx
, (FFB_BADATTR_BLENDFUNC
|FFB_BADATTR_BLENDROP
), GL_FALSE
);
185 if (blendc
!= fmesa
->blendc
) {
186 fmesa
->blendc
= blendc
;
187 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_BLEND
, 1);
191 static void ffbDDDepthFunc(GLcontext
*ctx
, GLenum func
)
193 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
197 fprintf(stderr
, "ffbDDDepthFunc: func(%s)\n",
198 _mesa_lookup_enum_by_nr(func
));
203 cmp
= FFB_CMP_MAGN_NEVER
;
206 cmp
= FFB_CMP_MAGN_ALWAYS
;
209 cmp
= FFB_CMP_MAGN_LT
;
212 cmp
= FFB_CMP_MAGN_LE
;
215 cmp
= FFB_CMP_MAGN_EQ
;
218 cmp
= FFB_CMP_MAGN_GT
;
221 cmp
= FFB_CMP_MAGN_GE
;
224 cmp
= FFB_CMP_MAGN_NE
;
230 if (! ctx
->Depth
.Test
)
231 cmp
= FFB_CMP_MAGN_ALWAYS
;
234 cmp
= (fmesa
->cmp
& ~(0xff<<16)) | cmp
;
235 if (cmp
!= fmesa
->cmp
) {
237 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_CMP
, 1);
241 static void ffbDDDepthMask(GLcontext
*ctx
, GLboolean flag
)
243 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
244 GLuint fbc
= fmesa
->fbc
;
245 GLboolean enabled_now
;
248 fprintf(stderr
, "ffbDDDepthMask: flag(%d)\n", flag
);
251 if ((fbc
& FFB_FBC_ZE_MASK
) == FFB_FBC_ZE_OFF
)
252 enabled_now
= GL_FALSE
;
254 enabled_now
= GL_TRUE
;
256 if (flag
!= enabled_now
) {
257 fbc
&= ~FFB_FBC_ZE_MASK
;
259 fbc
|= FFB_FBC_WB_C
| FFB_FBC_ZE_ON
;
261 fbc
|= FFB_FBC_ZE_OFF
;
262 fbc
&= ~FFB_FBC_WB_C
;
265 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
269 static void ffbDDStencilFunc(GLcontext
*ctx
, GLenum func
, GLint ref
, GLuint mask
)
271 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
272 unsigned int stencil
, stencilctl
, consty
;
274 /* We will properly update sw/hw state when stenciling is
277 if (! ctx
->Stencil
.Enabled
)
280 stencilctl
= fmesa
->stencilctl
;
281 stencilctl
&= ~(7 << 16);
284 case GL_ALWAYS
: stencilctl
|= (0 << 16); break;
285 case GL_GREATER
: stencilctl
|= (1 << 16); break;
286 case GL_EQUAL
: stencilctl
|= (2 << 16); break;
287 case GL_GEQUAL
: stencilctl
|= (3 << 16); break;
288 case GL_NEVER
: stencilctl
|= (4 << 16); break;
289 case GL_LEQUAL
: stencilctl
|= (5 << 16); break;
290 case GL_NOTEQUAL
: stencilctl
|= (6 << 16); break;
291 case GL_LESS
: stencilctl
|= (7 << 16); break;
299 stencil
= fmesa
->stencil
;
300 stencil
&= ~(0xf << 20);
301 stencil
|= (mask
& 0xf) << 20;
303 if (fmesa
->stencil
!= stencil
||
304 fmesa
->stencilctl
!= stencilctl
||
305 fmesa
->consty
!= consty
) {
306 fmesa
->stencil
= stencil
;
307 fmesa
->stencilctl
= stencilctl
;
308 fmesa
->consty
= consty
;
309 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_STENCIL
, 6);
313 static void ffbDDStencilMask(GLcontext
*ctx
, GLuint mask
)
315 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
318 if (fmesa
->ypmask
!= mask
) {
319 fmesa
->ypmask
= mask
;
320 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_YPMASK
, 1);
324 static void ffbDDStencilOp(GLcontext
*ctx
, GLenum fail
, GLenum zfail
, GLenum zpass
)
326 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
327 unsigned int stencilctl
;
329 /* We will properly update sw/hw state when stenciling is
332 if (! ctx
->Stencil
.Enabled
)
335 stencilctl
= fmesa
->stencilctl
;
336 stencilctl
&= ~(0xfff00000);
339 case GL_ZERO
: stencilctl
|= (0 << 28); break;
340 case GL_KEEP
: stencilctl
|= (1 << 28); break;
341 case GL_INVERT
: stencilctl
|= (2 << 28); break;
342 case GL_REPLACE
: stencilctl
|= (3 << 28); break;
343 case GL_INCR
: stencilctl
|= (4 << 28); break;
344 case GL_DECR
: stencilctl
|= (5 << 28); break;
351 case GL_ZERO
: stencilctl
|= (0 << 24); break;
352 case GL_KEEP
: stencilctl
|= (1 << 24); break;
353 case GL_INVERT
: stencilctl
|= (2 << 24); break;
354 case GL_REPLACE
: stencilctl
|= (3 << 24); break;
355 case GL_INCR
: stencilctl
|= (4 << 24); break;
356 case GL_DECR
: stencilctl
|= (5 << 24); break;
363 case GL_ZERO
: stencilctl
|= (0 << 20); break;
364 case GL_KEEP
: stencilctl
|= (1 << 20); break;
365 case GL_INVERT
: stencilctl
|= (2 << 20); break;
366 case GL_REPLACE
: stencilctl
|= (3 << 20); break;
367 case GL_INCR
: stencilctl
|= (4 << 20); break;
368 case GL_DECR
: stencilctl
|= (5 << 20); break;
374 if (fmesa
->stencilctl
!= stencilctl
) {
375 fmesa
->stencilctl
= stencilctl
;
376 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_STENCIL
, 6);
380 static void ffbCalcViewportRegs(GLcontext
*ctx
)
382 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
383 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
384 GLuint xmin
, xmax
, ymin
, ymax
, zmin
, zmax
;
385 unsigned int vcmin
, vcmax
;
387 xmin
= ctx
->Viewport
.X
+ dPriv
->x
;
388 xmax
= xmin
+ ctx
->Viewport
.Width
;
389 ymax
= dPriv
->y
+ dPriv
->h
- ctx
->Viewport
.Y
;
390 ymin
= ymax
- ctx
->Viewport
.Height
;
391 if (ctx
->Scissor
.Enabled
) {
392 GLuint sc_xmin
, sc_xmax
, sc_ymin
, sc_ymax
;
394 sc_xmin
= ctx
->Viewport
.X
+ dPriv
->x
;
395 sc_xmax
= sc_xmin
+ ctx
->Viewport
.Width
;
396 sc_ymax
= dPriv
->y
+ dPriv
->h
- ctx
->Viewport
.Y
;
397 sc_ymin
= sc_ymax
- ctx
->Viewport
.Height
;
407 zmin
= ((GLdouble
)ctx
->Viewport
.Near
* 0x0fffffff);
408 zmax
= ((GLdouble
)ctx
->Viewport
.Far
* 0x0fffffff);
410 vcmin
= ((ymin
& 0xffff) << 16) | (xmin
& 0xffff);
411 vcmax
= ((ymax
& 0xffff) << 16) | (xmax
& 0xffff);
412 if (fmesa
->vclipmin
!= vcmin
||
413 fmesa
->vclipmax
!= vcmax
||
414 fmesa
->vclipzmin
!= zmin
||
415 fmesa
->vclipzmax
!= zmax
) {
416 fmesa
->vclipmin
= vcmin
;
417 fmesa
->vclipmax
= vcmax
;
418 fmesa
->vclipzmin
= zmin
;
419 fmesa
->vclipzmax
= zmax
;
420 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_CLIP
, (4 + (4 * 2)));
424 void ffbCalcViewport(GLcontext
*ctx
)
426 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
427 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
428 GLfloat
*m
= fmesa
->hw_viewport
;
429 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
431 m
[MAT_SX
] = v
[MAT_SX
];
432 m
[MAT_TX
] = v
[MAT_TX
] + dPriv
->x
+ SUBPIXEL_X
;
433 m
[MAT_SY
] = - v
[MAT_SY
];
434 m
[MAT_TY
] = - v
[MAT_TY
] + dPriv
->h
+ dPriv
->y
+ SUBPIXEL_Y
;
435 m
[MAT_SZ
] = v
[MAT_SZ
] * ((GLdouble
)1.0 / (GLdouble
)0x0fffffff);
436 m
[MAT_TZ
] = v
[MAT_TZ
] * ((GLdouble
)1.0 / (GLdouble
)0x0fffffff);
438 fmesa
->depth_scale
= ((GLdouble
)1.0 / (GLdouble
)0x0fffffff);
440 ffbCalcViewportRegs(ctx
);
442 fmesa
->setupnewinputs
|= VERT_BIT_POS
;
445 static void ffbDDViewport(GLcontext
*ctx
, GLint x
, GLint y
,
446 GLsizei width
, GLsizei height
)
448 /* update size of Mesa/software ancillary buffers */
449 _mesa_ResizeBuffersMESA();
450 ffbCalcViewport(ctx
);
453 static void ffbDDDepthRange(GLcontext
*ctx
, GLclampd nearval
, GLclampd farval
)
455 ffbCalcViewport(ctx
);
458 static void ffbDDScissor(GLcontext
*ctx
, GLint cx
, GLint cy
,
459 GLsizei cw
, GLsizei ch
)
461 ffbCalcViewport(ctx
);
464 static void ffbDDDrawBuffer(GLcontext
*ctx
, GLenum buffer
)
466 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
467 unsigned int fbc
= fmesa
->fbc
;
470 fprintf(stderr
, "ffbDDDrawBuffer: mode(%s)\n",
471 _mesa_lookup_enum_by_nr(buffer
));
473 fbc
&= ~(FFB_FBC_WB_AB
| FFB_FBC_RB_MASK
);
476 if (fmesa
->back_buffer
== 0)
477 fbc
|= FFB_FBC_WB_B
| FFB_FBC_RB_B
;
479 fbc
|= FFB_FBC_WB_A
| FFB_FBC_RB_A
;
483 if (fmesa
->back_buffer
== 0)
484 fbc
|= FFB_FBC_WB_A
| FFB_FBC_RB_A
;
486 fbc
|= FFB_FBC_WB_B
| FFB_FBC_RB_B
;
489 case GL_FRONT_AND_BACK
:
490 fbc
|= FFB_FBC_WB_AB
;
497 if (fbc
!= fmesa
->fbc
) {
499 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
504 static void ffbDDReadBuffer(GLcontext
*ctx
, GLenum buffer
)
506 /* no-op, unless you implement h/w glRead/CopyPixels */
511 * Specifies buffer for sw fallbacks (spans)
513 static void ffbDDSetBuffer(GLcontext
*ctx
, GLframebuffer
*colorBuffer
,
516 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
517 unsigned int fbc
= fmesa
->fbc
;
520 fprintf(stderr
, "ffbDDSetReadBuffer: mode(%s)\n",
521 _mesa_lookup_enum_by_nr(buffer
));
523 fbc
&= ~(FFB_FBC_RB_MASK
);
525 case DD_FRONT_LEFT_BIT
:
526 if (fmesa
->back_buffer
== 0)
532 case DD_BACK_LEFT_BIT
:
533 if (fmesa
->back_buffer
== 0)
540 _mesa_problem(ctx
, "Unexpected buffer in ffbDDSetBuffer()");
544 if (fbc
!= fmesa
->fbc
) {
546 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
550 static void ffbDDClearColor(GLcontext
*ctx
, const GLfloat color
[4])
552 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
554 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
555 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
556 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
558 fmesa
->clear_pixel
= ((c
[0] << 0) |
563 static void ffbDDClearDepth(GLcontext
*ctx
, GLclampd depth
)
565 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
567 fmesa
->clear_depth
= Z_FROM_MESA(depth
* 4294967295.0f
);
570 static void ffbDDClearStencil(GLcontext
*ctx
, GLint stencil
)
572 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
574 fmesa
->clear_stencil
= stencil
& 0xf;
577 /* XXX Actually, should I be using FBC controls for this? -DaveM */
578 static void ffbDDColorMask(GLcontext
*ctx
,
579 GLboolean r
, GLboolean g
,
580 GLboolean b
, GLboolean a
)
582 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
583 unsigned int new_pmask
= 0x0;
586 fprintf(stderr
, "ffbDDColorMask: r(%d) g(%d) b(%d) a(%d)\n",
590 new_pmask
|= 0x000000ff;
592 new_pmask
|= 0x0000ff00;
594 new_pmask
|= 0x00ff0000;
596 if (fmesa
->pmask
!= new_pmask
) {
597 fmesa
->pmask
= new_pmask
;
598 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_PMASK
, 1);
602 static void ffbDDLogicOp(GLcontext
*ctx
, GLenum op
)
604 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
608 fprintf(stderr
, "ffbDDLogicOp: op(%s)\n",
609 _mesa_lookup_enum_by_nr(op
));
612 case GL_CLEAR
: rop
= FFB_ROP_ZERO
; break;
613 case GL_SET
: rop
= FFB_ROP_ONES
; break;
614 case GL_COPY
: rop
= FFB_ROP_NEW
; break;
615 case GL_AND
: rop
= FFB_ROP_NEW_AND_OLD
; break;
616 case GL_NAND
: rop
= FFB_ROP_NEW_AND_NOLD
; break;
617 case GL_OR
: rop
= FFB_ROP_NEW_OR_OLD
; break;
618 case GL_NOR
: rop
= FFB_ROP_NEW_OR_NOLD
; break;
619 case GL_XOR
: rop
= FFB_ROP_NEW_XOR_OLD
; break;
620 case GL_NOOP
: rop
= FFB_ROP_OLD
; break;
621 case GL_COPY_INVERTED
: rop
= FFB_ROP_NNEW
; break;
622 case GL_INVERT
: rop
= FFB_ROP_NOLD
; break;
623 case GL_EQUIV
: rop
= FFB_ROP_NNEW_XOR_NOLD
; break;
624 case GL_AND_REVERSE
: rop
= FFB_ROP_NEW_AND_NOLD
; break;
625 case GL_AND_INVERTED
: rop
= FFB_ROP_NNEW_AND_OLD
; break;
626 case GL_OR_REVERSE
: rop
= FFB_ROP_NEW_OR_NOLD
; break;
627 case GL_OR_INVERTED
: rop
= FFB_ROP_NNEW_OR_OLD
; break;
633 rop
|= fmesa
->rop
& ~0xff;
634 if (rop
!= fmesa
->rop
) {
636 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_ROP
, 1);
639 FALLBACK( ctx
, FFB_BADATTR_BLENDROP
, GL_FALSE
);
644 /* XXX Also need to track near/far just like 3dfx driver.
646 * XXX Actually, that won't work, because the 3dfx chip works by
647 * XXX having 1/w coordinates fed to it for each primitive, and
648 * XXX it uses this to index it's 64 entry fog table.
650 static void ffb_fog_linear(GLcontext
*ctx
, ffbContextPtr fmesa
)
652 GLfloat c
= ctx
->ProjectionMatrix
.m
[10];
653 GLfloat d
= ctx
->ProjectionMatrix
.m
[14];
654 GLfloat tz
= ctx
->Viewport
.WindowMap
.m
[MAT_TZ
];
655 GLfloat szInv
= 1.0F
/ ctx
->Viewport
.WindowMap
.m
[MAT_SZ
];
656 GLfloat fogEnd
= ctx
->Fog
.End
;
657 GLfloat fogScale
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
663 /* Compute the Z at which f reaches 0.0, this is the full
666 * Thus compute Z (as seen by the chip during rendering),
669 * 0.0 = (fogEnd - eyez) * fogScale
671 * fogScale is usually not zero, thus we are looking for:
675 * fogEnd = -d / (c + ((Z - tz) * szInv))
676 * fogEnd * (c + ((Z - tz) * szInv)) = -d
677 * (c + ((Z - tz) * szInv)) = -d / fogEnd
678 * (Z - tz) * szInv = (-d / fogEnd) - c
679 * (Z - tz) = ((-d / fogEnd) - c) / szInv
680 * Z = (((-d / fogEnd) - c) / szInv) + tz
682 Zzero
= (((-d
/ fogEnd
) - c
) / szInv
) + tz
;
684 /* Compute the Z at which f reaches 1.0, this is where
685 * the incoming frag's full intensity is shown. This
688 * 1.0 = (fogEnd - eyez)
690 * We are looking for:
692 * 1.0 + eyez = fogEnd
694 * 1.0 + (-d / (c + ((Z - tz) * szInv))) = fogEnd
695 * -d / (c + ((Z - tz) * szInv)) = fogEnd - 1.0
696 * -d / (FogEnd - 1.0) = (c + ((Z - tz) * szInv))
697 * (-d / (fogEnd - 1.0)) - c = ((Z - tz) * szInv)
698 * ((-d / (fogEnd - 1.0)) - c) / szInv = (Z - tz)
699 * (((-d / (fogEnd - 1.0)) - c) / szInv) + tz = Z
701 Zone
= (((-d
/ (fogEnd
- 1.0)) - c
) / szInv
) + tz
;
703 /* FFB's Zfront must be less than Zback, thus we may have
704 * to invert Sf/Sb to satisfy this constraint.
709 zf
= Z_FROM_MESA(Zzero
);
710 zb
= Z_FROM_MESA(Zone
);
714 zf
= Z_FROM_MESA(Zone
);
715 zb
= Z_FROM_MESA(Zzero
);
720 static void ffbDDFogfv(GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
723 fprintf(stderr
, "ffbDDFogfv: pname(%s)\n", _mesa_lookup_enum_by_nr(pname
));
727 static void ffbDDLineStipple(GLcontext
*ctx
, GLint factor
, GLushort pattern
)
729 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
732 fprintf(stderr
, "ffbDDLineStipple: factor(%d) pattern(%04x)\n",
735 if (ctx
->Line
.StippleFlag
) {
736 factor
= ctx
->Line
.StippleFactor
;
737 pattern
= ctx
->Line
.StipplePattern
;
738 if ((GLuint
) factor
> 15) {
739 fmesa
->lpat
= FFB_LPAT_BAD
;
741 fmesa
->lpat
= ((factor
<< FFB_LPAT_SCALEVAL_SHIFT
) |
742 (0 << FFB_LPAT_PATLEN_SHIFT
) |
743 ((pattern
& 0xffff) << FFB_LPAT_PATTERN_SHIFT
));
750 void ffbXformAreaPattern(ffbContextPtr fmesa
, const GLubyte
*mask
)
752 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
756 i
= (dPriv
->y
+ dPriv
->h
) & (32 - 1);
757 xoff
= dPriv
->x
& (32 - 1);
758 while (lines
++ < 32) {
760 (((GLuint
)mask
[0] << 24) |
761 ((GLuint
)mask
[1] << 16) |
762 ((GLuint
)mask
[2] << 8) |
763 ((GLuint
)mask
[3] << 0));
766 (raw
<< xoff
) | (raw
>> (32 - xoff
));
767 i
= (i
- 1) & (32 - 1);
771 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_APAT
, 32);
774 static void ffbDDPolygonStipple(GLcontext
*ctx
, const GLubyte
*mask
)
776 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
779 fprintf(stderr
, "ffbDDPolygonStipple: state(%d)\n",
780 ctx
->Polygon
.StippleFlag
);
782 ffbXformAreaPattern(fmesa
, mask
);
785 static void ffbDDEnable(GLcontext
*ctx
, GLenum cap
, GLboolean state
)
787 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
791 fprintf(stderr
, "ffbDDEnable: %s state(%d)\n",
792 _mesa_lookup_enum_by_nr(cap
), state
);
797 tmp
= ffbComputeAlphaFunc(ctx
);
799 tmp
= FFB_XCLIP_TEST_ALWAYS
;
801 if (tmp
!= fmesa
->xclip
) {
803 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_XCLIP
, 1);
808 tmp
= (fmesa
->ppc
& ~FFB_PPC_ABE_MASK
);
810 tmp
|= FFB_PPC_ABE_ENABLE
;
812 tmp
|= FFB_PPC_ABE_DISABLE
;
814 if (fmesa
->ppc
!= tmp
) {
816 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_PPC
, 1);
817 ffbDDBlendFuncSeparate(ctx
, 0, 0, 0, 0 );
826 if (tmp
!= fmesa
->magnc
) {
827 unsigned int fbc
= fmesa
->fbc
;
828 fbc
&= ~FFB_FBC_ZE_MASK
;
830 fbc
|= FFB_FBC_ZE_ON
;
832 fbc
|= FFB_FBC_ZE_OFF
;
834 ffbDDDepthFunc(ctx
, ctx
->Depth
.Func
);
836 FFB_MAKE_DIRTY(fmesa
, (FFB_STATE_MAGNC
| FFB_STATE_FBC
), 2);
840 case GL_SCISSOR_TEST
:
841 ffbDDScissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
842 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
845 case GL_STENCIL_TEST
:
846 if (!(fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
)) {
847 FALLBACK( ctx
, FFB_BADATTR_STENCIL
, state
);
850 tmp
= fmesa
->fbc
& ~FFB_FBC_YE_MASK
;
852 ffbDDStencilFunc(ctx
,
853 ctx
->Stencil
.Function
[0],
855 ctx
->Stencil
.ValueMask
[0]);
856 ffbDDStencilMask(ctx
, ctx
->Stencil
.WriteMask
[0]);
858 ctx
->Stencil
.FailFunc
[0],
859 ctx
->Stencil
.ZFailFunc
[0],
860 ctx
->Stencil
.ZPassFunc
[0]);
861 tmp
|= FFB_FBC_YE_MASK
;
863 fmesa
->stencil
= 0xf0000000;
864 fmesa
->stencilctl
= 0x33300000;
865 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_STENCIL
, 6);
866 tmp
|= FFB_FBC_YE_OFF
;
868 if (tmp
!= fmesa
->fbc
) {
870 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
875 /* Until I implement the fog support... */
876 FALLBACK( ctx
, FFB_BADATTR_FOG
, state
);
879 case GL_LINE_STIPPLE
:
883 ffbDDLineStipple(ctx
,
884 ctx
->Line
.StippleFactor
,
885 ctx
->Line
.StipplePattern
);
888 case GL_POLYGON_STIPPLE
:
889 /* Do nothing, we interrogate the state during
890 * reduced primitive changes. Since our caller
891 * will set NEW_POLYGON in the ctx NewState this
892 * will cause the driver rasterization functions
893 * to be reevaluated, which will cause us to force
894 * a reduced primitive change next rendering pass
895 * and it all works out.
904 void ffbSyncHardware(ffbContextPtr fmesa
)
906 ffb_fbcPtr ffb
= fmesa
->regs
;
910 FFBFifo(fmesa
, fmesa
->state_fifo_ents
);
912 dirty
= fmesa
->state_dirty
;
913 if (dirty
& (FFB_STATE_FBC
| FFB_STATE_PPC
| FFB_STATE_DRAWOP
|
914 FFB_STATE_ROP
| FFB_STATE_LPAT
| FFB_STATE_WID
)) {
915 if (dirty
& FFB_STATE_FBC
)
916 ffb
->fbc
= fmesa
->fbc
;
917 if (dirty
& FFB_STATE_PPC
)
918 ffb
->ppc
= fmesa
->ppc
;
919 if (dirty
& FFB_STATE_DRAWOP
)
920 ffb
->drawop
= fmesa
->drawop
;
921 if (dirty
& FFB_STATE_ROP
)
922 ffb
->rop
= fmesa
->rop
;
923 if (dirty
& FFB_STATE_LPAT
)
924 ffb
->rop
= fmesa
->lpat
;
925 if (dirty
& FFB_STATE_WID
)
926 ffb
->wid
= fmesa
->wid
;
928 if (dirty
& (FFB_STATE_PMASK
| FFB_STATE_XPMASK
| FFB_STATE_YPMASK
|
929 FFB_STATE_ZPMASK
| FFB_STATE_XCLIP
| FFB_STATE_CMP
|
930 FFB_STATE_MATCHAB
| FFB_STATE_MAGNAB
| FFB_STATE_MATCHC
|
932 if (dirty
& FFB_STATE_PMASK
)
933 ffb
->pmask
= fmesa
->pmask
;
934 if (dirty
& FFB_STATE_XPMASK
)
935 ffb
->xpmask
= fmesa
->xpmask
;
936 if (dirty
& FFB_STATE_YPMASK
)
937 ffb
->ypmask
= fmesa
->ypmask
;
938 if (dirty
& FFB_STATE_ZPMASK
)
939 ffb
->zpmask
= fmesa
->zpmask
;
940 if (dirty
& FFB_STATE_XCLIP
)
941 ffb
->xclip
= fmesa
->xclip
;
942 if (dirty
& FFB_STATE_CMP
)
943 ffb
->cmp
= fmesa
->cmp
;
944 if (dirty
& FFB_STATE_MATCHAB
)
945 ffb
->matchab
= fmesa
->matchab
;
946 if (dirty
& FFB_STATE_MAGNAB
)
947 ffb
->magnab
= fmesa
->magnab
;
948 if (dirty
& FFB_STATE_MATCHC
)
949 ffb
->matchc
= fmesa
->matchc
;
950 if (dirty
& FFB_STATE_MAGNC
)
951 ffb
->magnc
= fmesa
->magnc
;
954 if (dirty
& FFB_STATE_DCUE
) {
955 ffb
->dcss
= fmesa
->dcss
;
956 ffb
->dcsf
= fmesa
->dcsf
;
957 ffb
->dcsb
= fmesa
->dcsb
;
958 ffb
->dczf
= fmesa
->dczf
;
959 ffb
->dczb
= fmesa
->dczb
;
960 if (fmesa
->ffb_sarea
->flags
& (FFB_DRI_FFB2
| FFB_DRI_FFB2PLUS
)) {
961 ffb
->dcss1
= fmesa
->dcss1
;
962 ffb
->dcss2
= fmesa
->dcss2
;
963 ffb
->dcss3
= fmesa
->dcss3
;
964 ffb
->dcs2
= fmesa
->dcs2
;
965 ffb
->dcs3
= fmesa
->dcs3
;
966 ffb
->dcs4
= fmesa
->dcs4
;
967 ffb
->dcd2
= fmesa
->dcd2
;
968 ffb
->dcd3
= fmesa
->dcd3
;
969 ffb
->dcd4
= fmesa
->dcd4
;
973 if (dirty
& FFB_STATE_BLEND
) {
974 ffb
->blendc
= fmesa
->blendc
;
975 ffb
->blendc1
= fmesa
->blendc1
;
976 ffb
->blendc2
= fmesa
->blendc2
;
979 if (dirty
& FFB_STATE_CLIP
) {
980 ffb
->vclipmin
= fmesa
->vclipmin
;
981 ffb
->vclipmax
= fmesa
->vclipmax
;
982 ffb
->vclipzmin
= fmesa
->vclipzmin
;
983 ffb
->vclipzmax
= fmesa
->vclipzmax
;
984 for (i
= 0; i
< 4; i
++) {
985 ffb
->auxclip
[i
].min
= fmesa
->aux_clips
[i
].min
;
986 ffb
->auxclip
[i
].max
= fmesa
->aux_clips
[i
].max
;
990 if ((dirty
& FFB_STATE_STENCIL
) &&
991 (fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
)) {
992 ffb
->stencil
= fmesa
->stencil
;
993 ffb
->stencilctl
= fmesa
->stencilctl
;
994 ffb
->fbc
= FFB_FBC_WB_C
;
995 ffb
->rawstencilctl
= (fmesa
->stencilctl
| (1 << 19));
996 ffb
->fbc
= fmesa
->fbc
;
997 ffb
->consty
= fmesa
->consty
;
1000 if (dirty
& FFB_STATE_APAT
) {
1001 for (i
= 0; i
< 32; i
++)
1002 ffb
->pattern
[i
] = fmesa
->pattern
[i
];
1005 fmesa
->state_dirty
= 0;
1006 fmesa
->state_fifo_ents
= 0;
1007 fmesa
->ffbScreen
->rp_active
= 1;
1010 static void ffbDDUpdateState(GLcontext
*ctx
, GLuint newstate
)
1012 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1014 /* When we are hw rendering, changing certain kinds of
1015 * state does not require flushing all of our context.
1017 if (fmesa
->bad_fragment_attrs
== 0 &&
1018 (newstate
& ~_NEW_COLOR
) == 0)
1021 _swrast_InvalidateState( ctx
, newstate
);
1022 _swsetup_InvalidateState( ctx
, newstate
);
1023 _ac_InvalidateState( ctx
, newstate
);
1024 _tnl_InvalidateState( ctx
, newstate
);
1026 if (newstate
& _NEW_TEXTURE
)
1027 FALLBACK( ctx
, FFB_BADATTR_TEXTURE
,
1028 (ctx
->Texture
._EnabledUnits
!= 0));
1031 fprintf(stderr
, "ffbDDUpdateState: newstate(%08x)\n", newstate
);
1034 fmesa
->new_gl_state
|= newstate
;
1036 /* Force a reduced primitive change next rendering
1039 fmesa
->raster_primitive
= GL_POLYGON
+ 1;
1042 /* When the modelview matrix changes, this changes what
1043 * the eye coordinates will be so we have to recompute
1044 * the depth cueing parameters.
1046 * XXX DD_HAVE_HARDWARE_FOG.
1048 if (ctx
->Fog
.Enabled
&& (newstate
& _NEW_MODELVIEW
))
1054 void ffbDDInitStateFuncs(GLcontext
*ctx
)
1056 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1058 ctx
->Driver
.UpdateState
= ffbDDUpdateState
;
1060 ctx
->Driver
.Enable
= ffbDDEnable
;
1061 ctx
->Driver
.AlphaFunc
= ffbDDAlphaFunc
;
1062 ctx
->Driver
.BlendEquationSeparate
= ffbDDBlendEquationSeparate
;
1063 ctx
->Driver
.BlendFuncSeparate
= ffbDDBlendFuncSeparate
;
1064 ctx
->Driver
.DepthFunc
= ffbDDDepthFunc
;
1065 ctx
->Driver
.DepthMask
= ffbDDDepthMask
;
1066 ctx
->Driver
.Fogfv
= ffbDDFogfv
;
1067 ctx
->Driver
.LineStipple
= ffbDDLineStipple
;
1068 ctx
->Driver
.PolygonStipple
= ffbDDPolygonStipple
;
1069 ctx
->Driver
.Scissor
= ffbDDScissor
;
1070 ctx
->Driver
.ColorMask
= ffbDDColorMask
;
1071 ctx
->Driver
.LogicOpcode
= ffbDDLogicOp
;
1072 ctx
->Driver
.Viewport
= ffbDDViewport
;
1073 ctx
->Driver
.DepthRange
= ffbDDDepthRange
;
1075 if (fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
) {
1076 ctx
->Driver
.StencilFunc
= ffbDDStencilFunc
;
1077 ctx
->Driver
.StencilMask
= ffbDDStencilMask
;
1078 ctx
->Driver
.StencilOp
= ffbDDStencilOp
;
1081 ctx
->Driver
.DrawBuffer
= ffbDDDrawBuffer
;
1082 ctx
->Driver
.ReadBuffer
= ffbDDReadBuffer
;
1083 ctx
->Driver
.ClearColor
= ffbDDClearColor
;
1084 ctx
->Driver
.ClearDepth
= ffbDDClearDepth
;
1085 ctx
->Driver
.ClearStencil
= ffbDDClearStencil
;
1087 /* We will support color index modes later... -DaveM */
1089 ctx->Driver.ClearIndex = 0;
1090 ctx->Driver.IndexMask = 0;
1094 struct swrast_device_driver
*swdd
=
1095 _swrast_GetDeviceDriverReference(ctx
);
1096 swdd
->SetBuffer
= ffbDDSetBuffer
;
1102 void ffbDDInitContextHwState(GLcontext
*ctx
)
1104 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1108 fmesa
->hw_locked
= 0;
1110 fmesa
->bad_fragment_attrs
= 0;
1111 fmesa
->state_dirty
= FFB_STATE_ALL
;
1112 fmesa
->new_gl_state
= ~0;
1115 fmesa
->fbc
= (FFB_FBC_WE_FORCEON
| FFB_FBC_WM_COMBINED
|
1116 FFB_FBC_SB_BOTH
| FFB_FBC_ZE_MASK
|
1117 FFB_FBC_YE_OFF
| FFB_FBC_XE_OFF
|
1119 if (ctx
->Visual
.doubleBufferMode
) {
1120 /* Buffer B is the initial back buffer. */
1121 fmesa
->back_buffer
= 1;
1122 fmesa
->fbc
|= FFB_FBC_WB_BC
| FFB_FBC_RB_B
;
1124 fmesa
->back_buffer
= 0;
1125 fmesa
->fbc
|= FFB_FBC_WB_A
| FFB_FBC_RB_A
;
1129 fmesa
->ppc
= (FFB_PPC_ACE_DISABLE
| FFB_PPC_DCE_DISABLE
|
1130 FFB_PPC_ABE_DISABLE
| FFB_PPC_VCE_3D
|
1131 FFB_PPC_APE_DISABLE
| FFB_PPC_TBE_OPAQUE
|
1132 FFB_PPC_ZS_CONST
| FFB_PPC_YS_CONST
|
1133 FFB_PPC_XS_WID
| FFB_PPC_CS_VAR
);
1136 fmesa
->drawop
= FFB_DRAWOP_RECTANGLE
;
1138 /* GL_COPY is the default LogicOp. */
1139 fmesa
->rop
= (FFB_ROP_NEW
<< 16) | (FFB_ROP_NEW
<< 8) | FFB_ROP_NEW
;
1141 /* No line patterning enabled. */
1142 fmesa
->lpat
= 0x00000000;
1144 /* We do not know the WID value until the first context switch. */
1150 /* ColorMask, all enabled. */
1151 fmesa
->pmask
= 0xffffffff;
1153 fmesa
->xpmask
= 0x000000ff;
1154 fmesa
->ypmask
= 0x0000000f;
1155 fmesa
->zpmask
= 0x0fffffff;
1157 /* AlphaFunc GL_ALWAYS, AlphaRef 0 */
1158 fmesa
->xclip
= FFB_XCLIP_TEST_ALWAYS
| 0x00;
1160 /* This sets us up to use WID clipping (so the DRI clipping
1161 * rectangle is unneeded by us). All other match and magnitude
1162 * tests are set to pass.
1165 fmesa
->cmp
= ((FFB_CMP_MATCH_ALWAYS
<< 24) | /* MATCH C */
1166 (FFB_CMP_MAGN_ALWAYS
<< 16) | /* MAGN C */
1167 (FFB_CMP_MATCH_EQ
<< 8) | /* MATCH AB */
1168 (FFB_CMP_MAGN_ALWAYS
<< 0)); /* MAGN AB */
1169 fmesa
->matchab
= 0xff000000;
1170 fmesa
->magnab
= 0x00000000;
1171 fmesa
->matchc
= 0x00000000;
1172 fmesa
->magnc
= 0x00000000;
1174 /* Depth cue parameters, all zeros to start. */
1176 fmesa
->dcss
= 0x00000000;
1177 fmesa
->dcsf
= 0x00000000;
1178 fmesa
->dcsb
= 0x00000000;
1179 fmesa
->dczf
= 0x00000000;
1180 fmesa
->dczb
= 0x00000000;
1181 fmesa
->dcss1
= 0x00000000;
1182 fmesa
->dcss2
= 0x00000000;
1183 fmesa
->dcss3
= 0x00000000;
1184 fmesa
->dcs2
= 0x00000000;
1185 fmesa
->dcs3
= 0x00000000;
1186 fmesa
->dcs4
= 0x00000000;
1187 fmesa
->dcd2
= 0x00000000;
1188 fmesa
->dcd3
= 0x00000000;
1189 fmesa
->dcd4
= 0x00000000;
1191 /* Alpha blending unit state. */
1193 fmesa
->blendc
= (1 << 0) | (0 << 2); /* src(GL_ONE) | dst(GL_ZERO) */
1194 fmesa
->blendc1
= 0x00000000;
1195 fmesa
->blendc2
= 0x00000000;
1197 /* ViewPort clip state. */
1198 fifo_count
+= 4 + (4 * 2);
1199 fmesa
->vclipmin
= 0x00000000;
1200 fmesa
->vclipmax
= 0xffffffff;
1201 fmesa
->vclipzmin
= 0x00000000;
1202 fmesa
->vclipzmax
= 0x0fffffff;
1203 for (i
= 0; i
< 4; i
++) {
1204 fmesa
->aux_clips
[0].min
= 0x00000000;
1205 fmesa
->aux_clips
[0].max
= 0x00000000;
1208 /* Stenciling state. */
1210 fmesa
->stencil
= 0xf0000000; /* Stencil MASK, Y plane */
1211 fmesa
->stencilctl
= 0x33300000; /* All stencil tests disabled */
1212 fmesa
->consty
= 0x0;
1214 /* Area pattern, used for polygon stipples. */
1216 for (i
= 0; i
< 32; i
++)
1217 fmesa
->pattern
[i
] = 0x00000000;
1219 fmesa
->state_fifo_ents
= fifo_count
;
1220 fmesa
->state_all_fifo_ents
= fifo_count
;