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>
28 #include "main/mtypes.h"
29 #include "main/colormac.h"
30 #include "main/enums.h"
34 #include "tnl/t_pipeline.h"
35 #include "swrast/swrast.h"
36 #include "swrast_setup/swrast_setup.h"
40 #include "ffb_context.h"
42 #include "ffb_state.h"
46 static unsigned int ffbComputeAlphaFunc(GLcontext
*ctx
)
52 fprintf(stderr
, "ffbDDAlphaFunc: func(%s) ref(%02x)\n",
53 _mesa_lookup_enum_by_nr(ctx
->Color
.AlphaFunc
),
54 ctx
->Color
.AlphaRef
& 0xff);
57 switch (ctx
->Color
.AlphaFunc
) {
58 case GL_NEVER
: xclip
= FFB_XCLIP_TEST_NEVER
; break;
59 case GL_LESS
: xclip
= FFB_XCLIP_TEST_LT
; break;
60 case GL_EQUAL
: xclip
= FFB_XCLIP_TEST_EQ
; break;
61 case GL_LEQUAL
: xclip
= FFB_XCLIP_TEST_LE
; break;
62 case GL_GREATER
: xclip
= FFB_XCLIP_TEST_GT
; break;
63 case GL_NOTEQUAL
: xclip
= FFB_XCLIP_TEST_NE
; break;
64 case GL_GEQUAL
: xclip
= FFB_XCLIP_TEST_GE
; break;
65 case GL_ALWAYS
: xclip
= FFB_XCLIP_TEST_ALWAYS
; break;
68 return FFB_XCLIP_TEST_ALWAYS
| 0x00;
71 CLAMPED_FLOAT_TO_UBYTE(alphaRef
, ctx
->Color
.AlphaRef
);
72 xclip
|= (alphaRef
& 0xff);
77 static void ffbDDAlphaFunc(GLcontext
*ctx
, GLenum func
, GLfloat ref
)
79 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
81 if (ctx
->Color
.AlphaEnabled
) {
82 unsigned int xclip
= ffbComputeAlphaFunc(ctx
);
84 if (fmesa
->xclip
!= xclip
) {
86 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_XCLIP
, 1);
91 static void ffbDDBlendEquationSeparate(GLcontext
*ctx
,
92 GLenum modeRGB
, GLenum modeA
)
96 fprintf(stderr
, "ffbDDBlendEquation: mode(%s)\n",
97 _mesa_lookup_enum_by_nr(modeRGB
));
99 assert( modeRGB
== modeA
);
100 FALLBACK( ctx
, (modeRGB
!= GL_FUNC_ADD
), FFB_BADATTR_BLENDEQN
);
103 static void ffbDDBlendFuncSeparate(GLcontext
*ctx
, GLenum sfactorRGB
,
104 GLenum dfactorRGB
, GLenum sfactorA
,
107 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
108 unsigned int blendc
= 1 << 4;
111 fprintf(stderr
, "ffbDDBlendFuncSeparate: sRGB(%s) dRGB(%s) sA(%s) dA(%s)\n",
112 _mesa_lookup_enum_by_nr(sfactorRGB
),
113 _mesa_lookup_enum_by_nr(dfactorRGB
),
114 _mesa_lookup_enum_by_nr(sfactorA
),
115 _mesa_lookup_enum_by_nr(dfactorA
));
117 switch (ctx
->Color
.BlendSrcRGB
) {
126 case GL_ONE_MINUS_SRC_ALPHA
:
135 if (ctx
->Color
.BlendEnabled
)
136 FALLBACK( ctx
, FFB_BADATTR_BLENDFUNC
, GL_TRUE
);
140 switch (ctx
->Color
.BlendDstRGB
) {
149 case GL_ONE_MINUS_SRC_ALPHA
:
158 if (ctx
->Color
.BlendEnabled
)
159 FALLBACK( ctx
, FFB_BADATTR_BLENDFUNC
, GL_TRUE
);
163 if (ctx
->Color
.BlendEnabled
&&
164 ctx
->Color
.ColorLogicOpEnabled
&&
165 ctx
->Color
.LogicOp
!= GL_COPY
) {
166 /* We could avoid this if sfactor is GL_ONE and
167 * dfactor is GL_ZERO. I do not think that is even
168 * worthwhile to check because if someone is using
169 * blending they use more interesting settings and
170 * also it would add more state tracking to a lot
171 * of the code in this file.
173 FALLBACK(ctx
, FFB_BADATTR_BLENDROP
, GL_TRUE
);
177 FALLBACK( ctx
, (FFB_BADATTR_BLENDFUNC
|FFB_BADATTR_BLENDROP
), GL_FALSE
);
179 if (blendc
!= fmesa
->blendc
) {
180 fmesa
->blendc
= blendc
;
181 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_BLEND
, 1);
185 static void ffbDDDepthFunc(GLcontext
*ctx
, GLenum func
)
187 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
191 fprintf(stderr
, "ffbDDDepthFunc: func(%s)\n",
192 _mesa_lookup_enum_by_nr(func
));
197 cmp
= FFB_CMP_MAGN_NEVER
;
200 cmp
= FFB_CMP_MAGN_ALWAYS
;
203 cmp
= FFB_CMP_MAGN_LT
;
206 cmp
= FFB_CMP_MAGN_LE
;
209 cmp
= FFB_CMP_MAGN_EQ
;
212 cmp
= FFB_CMP_MAGN_GT
;
215 cmp
= FFB_CMP_MAGN_GE
;
218 cmp
= FFB_CMP_MAGN_NE
;
224 if (! ctx
->Depth
.Test
)
225 cmp
= FFB_CMP_MAGN_ALWAYS
;
228 cmp
= (fmesa
->cmp
& ~(0xff<<16)) | cmp
;
229 if (cmp
!= fmesa
->cmp
) {
231 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_CMP
, 1);
235 static void ffbDDDepthMask(GLcontext
*ctx
, GLboolean flag
)
237 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
238 GLuint fbc
= fmesa
->fbc
;
239 GLboolean enabled_now
;
242 fprintf(stderr
, "ffbDDDepthMask: flag(%d)\n", flag
);
245 if ((fbc
& FFB_FBC_ZE_MASK
) == FFB_FBC_ZE_OFF
)
246 enabled_now
= GL_FALSE
;
248 enabled_now
= GL_TRUE
;
250 if (flag
!= enabled_now
) {
251 fbc
&= ~FFB_FBC_ZE_MASK
;
253 fbc
|= FFB_FBC_WB_C
| FFB_FBC_ZE_ON
;
255 fbc
|= FFB_FBC_ZE_OFF
;
256 fbc
&= ~FFB_FBC_WB_C
;
259 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
264 ffbDDStencilFuncSeparate(GLcontext
*ctx
, GLenum face
, GLenum func
,
265 GLint ref
, GLuint mask
)
267 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
268 unsigned int stencil
, stencilctl
, consty
;
270 /* We will properly update sw/hw state when stenciling is
273 if (! ctx
->Stencil
._Enabled
)
276 stencilctl
= fmesa
->stencilctl
;
277 stencilctl
&= ~(7 << 16);
280 case GL_ALWAYS
: stencilctl
|= (0 << 16); break;
281 case GL_GREATER
: stencilctl
|= (1 << 16); break;
282 case GL_EQUAL
: stencilctl
|= (2 << 16); break;
283 case GL_GEQUAL
: stencilctl
|= (3 << 16); break;
284 case GL_NEVER
: stencilctl
|= (4 << 16); break;
285 case GL_LEQUAL
: stencilctl
|= (5 << 16); break;
286 case GL_NOTEQUAL
: stencilctl
|= (6 << 16); break;
287 case GL_LESS
: stencilctl
|= (7 << 16); break;
295 stencil
= fmesa
->stencil
;
296 stencil
&= ~(0xf << 20);
297 stencil
|= (mask
& 0xf) << 20;
299 if (fmesa
->stencil
!= stencil
||
300 fmesa
->stencilctl
!= stencilctl
||
301 fmesa
->consty
!= consty
) {
302 fmesa
->stencil
= stencil
;
303 fmesa
->stencilctl
= stencilctl
;
304 fmesa
->consty
= consty
;
305 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_STENCIL
, 6);
310 ffbDDStencilMaskSeparate(GLcontext
*ctx
, GLenum face
, GLuint mask
)
312 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
315 if (fmesa
->ypmask
!= mask
) {
316 fmesa
->ypmask
= mask
;
317 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_YPMASK
, 1);
322 ffbDDStencilOpSeparate(GLcontext
*ctx
, GLenum face
, GLenum fail
,
323 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 __DRIdrawable
*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 __DRIdrawable
*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)
512 * This function is obsolete. It's not clear how this really effected
513 * span reading/writing above. The span functions should use the
514 * incoming driRenderbuffer (gl_renderbuffer) pointer to determine how
515 * to read from the specified bufer.
517 static void ffbDDSetBuffer(GLcontext
*ctx
, GLframebuffer
*colorBuffer
,
520 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
521 unsigned int fbc
= fmesa
->fbc
;
524 fprintf(stderr
, "ffbDDSetReadBuffer: mode(%s)\n",
525 _mesa_lookup_enum_by_nr(buffer
));
527 fbc
&= ~(FFB_FBC_RB_MASK
);
529 case BUFFER_BIT_FRONT_LEFT
:
530 if (fmesa
->back_buffer
== 0)
536 case BUFFER_BIT_BACK_LEFT
:
537 if (fmesa
->back_buffer
== 0)
544 _mesa_problem(ctx
, "Unexpected buffer in ffbDDSetBuffer()");
548 if (fbc
!= fmesa
->fbc
) {
550 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
556 static void ffbDDClearColor(GLcontext
*ctx
, const GLfloat color
[4])
558 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
560 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
561 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
562 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
564 fmesa
->clear_pixel
= ((c
[0] << 0) |
569 static void ffbDDClearDepth(GLcontext
*ctx
, GLclampd depth
)
571 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
573 fmesa
->clear_depth
= Z_FROM_MESA(depth
* 4294967295.0f
);
576 static void ffbDDClearStencil(GLcontext
*ctx
, GLint stencil
)
578 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
580 fmesa
->clear_stencil
= stencil
& 0xf;
583 /* XXX Actually, should I be using FBC controls for this? -DaveM */
584 static void ffbDDColorMask(GLcontext
*ctx
,
585 GLboolean r
, GLboolean g
,
586 GLboolean b
, GLboolean a
)
588 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
589 unsigned int new_pmask
= 0x0;
592 fprintf(stderr
, "ffbDDColorMask: r(%d) g(%d) b(%d) a(%d)\n",
596 new_pmask
|= 0x000000ff;
598 new_pmask
|= 0x0000ff00;
600 new_pmask
|= 0x00ff0000;
602 new_pmask
|= 0xff000000;
604 if (fmesa
->pmask
!= new_pmask
) {
605 fmesa
->pmask
= new_pmask
;
606 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_PMASK
, 1);
610 static void ffbDDLogicOp(GLcontext
*ctx
, GLenum op
)
612 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
616 fprintf(stderr
, "ffbDDLogicOp: op(%s)\n",
617 _mesa_lookup_enum_by_nr(op
));
620 case GL_CLEAR
: rop
= FFB_ROP_ZERO
; break;
621 case GL_SET
: rop
= FFB_ROP_ONES
; break;
622 case GL_COPY
: rop
= FFB_ROP_NEW
; break;
623 case GL_AND
: rop
= FFB_ROP_NEW_AND_OLD
; break;
624 case GL_NAND
: rop
= FFB_ROP_NEW_AND_NOLD
; break;
625 case GL_OR
: rop
= FFB_ROP_NEW_OR_OLD
; break;
626 case GL_NOR
: rop
= FFB_ROP_NEW_OR_NOLD
; break;
627 case GL_XOR
: rop
= FFB_ROP_NEW_XOR_OLD
; break;
628 case GL_NOOP
: rop
= FFB_ROP_OLD
; break;
629 case GL_COPY_INVERTED
: rop
= FFB_ROP_NNEW
; break;
630 case GL_INVERT
: rop
= FFB_ROP_NOLD
; break;
631 case GL_EQUIV
: rop
= FFB_ROP_NNEW_XOR_NOLD
; break;
632 case GL_AND_REVERSE
: rop
= FFB_ROP_NEW_AND_NOLD
; break;
633 case GL_AND_INVERTED
: rop
= FFB_ROP_NNEW_AND_OLD
; break;
634 case GL_OR_REVERSE
: rop
= FFB_ROP_NEW_OR_NOLD
; break;
635 case GL_OR_INVERTED
: rop
= FFB_ROP_NNEW_OR_OLD
; break;
641 rop
|= fmesa
->rop
& ~0xff;
642 if (rop
!= fmesa
->rop
) {
644 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_ROP
, 1);
647 FALLBACK( ctx
, FFB_BADATTR_BLENDROP
, GL_FALSE
);
652 /* XXX Also need to track near/far just like 3dfx driver.
654 * XXX Actually, that won't work, because the 3dfx chip works by
655 * XXX having 1/w coordinates fed to it for each primitive, and
656 * XXX it uses this to index it's 64 entry fog table.
658 static void ffb_fog_linear(GLcontext
*ctx
, ffbContextPtr fmesa
)
660 GLfloat c
= ctx
->ProjectionMatrix
.m
[10];
661 GLfloat d
= ctx
->ProjectionMatrix
.m
[14];
662 GLfloat tz
= ctx
->Viewport
.WindowMap
.m
[MAT_TZ
];
663 GLfloat szInv
= 1.0F
/ ctx
->Viewport
.WindowMap
.m
[MAT_SZ
];
664 GLfloat fogEnd
= ctx
->Fog
.End
;
665 GLfloat fogScale
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
671 /* Compute the Z at which f reaches 0.0, this is the full
674 * Thus compute Z (as seen by the chip during rendering),
677 * 0.0 = (fogEnd - eyez) * fogScale
679 * fogScale is usually not zero, thus we are looking for:
683 * fogEnd = -d / (c + ((Z - tz) * szInv))
684 * fogEnd * (c + ((Z - tz) * szInv)) = -d
685 * (c + ((Z - tz) * szInv)) = -d / fogEnd
686 * (Z - tz) * szInv = (-d / fogEnd) - c
687 * (Z - tz) = ((-d / fogEnd) - c) / szInv
688 * Z = (((-d / fogEnd) - c) / szInv) + tz
690 Zzero
= (((-d
/ fogEnd
) - c
) / szInv
) + tz
;
692 /* Compute the Z at which f reaches 1.0, this is where
693 * the incoming frag's full intensity is shown. This
696 * 1.0 = (fogEnd - eyez)
698 * We are looking for:
700 * 1.0 + eyez = fogEnd
702 * 1.0 + (-d / (c + ((Z - tz) * szInv))) = fogEnd
703 * -d / (c + ((Z - tz) * szInv)) = fogEnd - 1.0
704 * -d / (FogEnd - 1.0) = (c + ((Z - tz) * szInv))
705 * (-d / (fogEnd - 1.0)) - c = ((Z - tz) * szInv)
706 * ((-d / (fogEnd - 1.0)) - c) / szInv = (Z - tz)
707 * (((-d / (fogEnd - 1.0)) - c) / szInv) + tz = Z
709 Zone
= (((-d
/ (fogEnd
- 1.0)) - c
) / szInv
) + tz
;
711 /* FFB's Zfront must be less than Zback, thus we may have
712 * to invert Sf/Sb to satisfy this constraint.
717 zf
= Z_FROM_MESA(Zzero
);
718 zb
= Z_FROM_MESA(Zone
);
722 zf
= Z_FROM_MESA(Zone
);
723 zb
= Z_FROM_MESA(Zzero
);
728 static void ffbDDFogfv(GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
731 fprintf(stderr
, "ffbDDFogfv: pname(%s)\n", _mesa_lookup_enum_by_nr(pname
));
735 static void ffbDDLineStipple(GLcontext
*ctx
, GLint factor
, GLushort pattern
)
737 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
740 fprintf(stderr
, "ffbDDLineStipple: factor(%d) pattern(%04x)\n",
743 if (ctx
->Line
.StippleFlag
) {
744 factor
= ctx
->Line
.StippleFactor
;
745 pattern
= ctx
->Line
.StipplePattern
;
746 if ((GLuint
) factor
> 15) {
747 fmesa
->lpat
= FFB_LPAT_BAD
;
749 fmesa
->lpat
= ((factor
<< FFB_LPAT_SCALEVAL_SHIFT
) |
750 (0 << FFB_LPAT_PATLEN_SHIFT
) |
751 ((pattern
& 0xffff) << FFB_LPAT_PATTERN_SHIFT
));
758 void ffbXformAreaPattern(ffbContextPtr fmesa
, const GLubyte
*mask
)
760 __DRIdrawable
*dPriv
= fmesa
->driDrawable
;
764 i
= (dPriv
->y
+ dPriv
->h
) & (32 - 1);
765 xoff
= dPriv
->x
& (32 - 1);
766 while (lines
++ < 32) {
768 (((GLuint
)mask
[0] << 24) |
769 ((GLuint
)mask
[1] << 16) |
770 ((GLuint
)mask
[2] << 8) |
771 ((GLuint
)mask
[3] << 0));
774 (raw
<< xoff
) | (raw
>> (32 - xoff
));
775 i
= (i
- 1) & (32 - 1);
779 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_APAT
, 32);
782 static void ffbDDPolygonStipple(GLcontext
*ctx
, const GLubyte
*mask
)
784 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
787 fprintf(stderr
, "ffbDDPolygonStipple: state(%d)\n",
788 ctx
->Polygon
.StippleFlag
);
790 ffbXformAreaPattern(fmesa
, mask
);
793 static void ffbDDEnable(GLcontext
*ctx
, GLenum cap
, GLboolean state
)
795 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
799 fprintf(stderr
, "ffbDDEnable: %s state(%d)\n",
800 _mesa_lookup_enum_by_nr(cap
), state
);
805 tmp
= ffbComputeAlphaFunc(ctx
);
807 tmp
= FFB_XCLIP_TEST_ALWAYS
;
809 if (tmp
!= fmesa
->xclip
) {
811 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_XCLIP
, 1);
816 tmp
= (fmesa
->ppc
& ~FFB_PPC_ABE_MASK
);
818 tmp
|= FFB_PPC_ABE_ENABLE
;
820 tmp
|= FFB_PPC_ABE_DISABLE
;
822 if (fmesa
->ppc
!= tmp
) {
824 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_PPC
, 1);
825 ffbDDBlendFuncSeparate(ctx
, 0, 0, 0, 0 );
834 if (tmp
!= fmesa
->magnc
) {
835 unsigned int fbc
= fmesa
->fbc
;
836 fbc
&= ~FFB_FBC_ZE_MASK
;
838 fbc
|= FFB_FBC_ZE_ON
;
840 fbc
|= FFB_FBC_ZE_OFF
;
842 ffbDDDepthFunc(ctx
, ctx
->Depth
.Func
);
844 FFB_MAKE_DIRTY(fmesa
, (FFB_STATE_MAGNC
| FFB_STATE_FBC
), 2);
848 case GL_SCISSOR_TEST
:
849 ffbDDScissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
850 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
853 case GL_STENCIL_TEST
:
854 if (!(fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
)) {
855 FALLBACK( ctx
, FFB_BADATTR_STENCIL
, state
);
858 tmp
= fmesa
->fbc
& ~FFB_FBC_YE_MASK
;
860 ffbDDStencilFuncSeparate(ctx
, GL_FRONT
,
861 ctx
->Stencil
.Function
[0],
863 ctx
->Stencil
.ValueMask
[0]);
864 ffbDDStencilMaskSeparate(ctx
, GL_FRONT
,
865 ctx
->Stencil
.WriteMask
[0]);
866 ffbDDStencilOpSeparate(ctx
, GL_FRONT
,
867 ctx
->Stencil
.FailFunc
[0],
868 ctx
->Stencil
.ZFailFunc
[0],
869 ctx
->Stencil
.ZPassFunc
[0]);
870 tmp
|= FFB_FBC_YE_MASK
;
872 fmesa
->stencil
= 0xf0000000;
873 fmesa
->stencilctl
= 0x33300000;
874 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_STENCIL
, 6);
875 tmp
|= FFB_FBC_YE_OFF
;
877 if (tmp
!= fmesa
->fbc
) {
879 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
884 /* Until I implement the fog support... */
885 FALLBACK( ctx
, FFB_BADATTR_FOG
, state
);
888 case GL_LINE_STIPPLE
:
892 ffbDDLineStipple(ctx
,
893 ctx
->Line
.StippleFactor
,
894 ctx
->Line
.StipplePattern
);
897 case GL_POLYGON_STIPPLE
:
898 /* Do nothing, we interrogate the state during
899 * reduced primitive changes. Since our caller
900 * will set NEW_POLYGON in the ctx NewState this
901 * will cause the driver rasterization functions
902 * to be reevaluated, which will cause us to force
903 * a reduced primitive change next rendering pass
904 * and it all works out.
913 void ffbSyncHardware(ffbContextPtr fmesa
)
915 ffb_fbcPtr ffb
= fmesa
->regs
;
919 FFBFifo(fmesa
, fmesa
->state_fifo_ents
);
921 dirty
= fmesa
->state_dirty
;
922 if (dirty
& (FFB_STATE_FBC
| FFB_STATE_PPC
| FFB_STATE_DRAWOP
|
923 FFB_STATE_ROP
| FFB_STATE_LPAT
| FFB_STATE_WID
)) {
924 if (dirty
& FFB_STATE_FBC
)
925 ffb
->fbc
= fmesa
->fbc
;
926 if (dirty
& FFB_STATE_PPC
)
927 ffb
->ppc
= fmesa
->ppc
;
928 if (dirty
& FFB_STATE_DRAWOP
)
929 ffb
->drawop
= fmesa
->drawop
;
930 if (dirty
& FFB_STATE_ROP
)
931 ffb
->rop
= fmesa
->rop
;
932 if (dirty
& FFB_STATE_LPAT
)
933 ffb
->rop
= fmesa
->lpat
;
934 if (dirty
& FFB_STATE_WID
)
935 ffb
->wid
= fmesa
->wid
;
937 if (dirty
& (FFB_STATE_PMASK
| FFB_STATE_XPMASK
| FFB_STATE_YPMASK
|
938 FFB_STATE_ZPMASK
| FFB_STATE_XCLIP
| FFB_STATE_CMP
|
939 FFB_STATE_MATCHAB
| FFB_STATE_MAGNAB
| FFB_STATE_MATCHC
|
941 if (dirty
& FFB_STATE_PMASK
)
942 ffb
->pmask
= fmesa
->pmask
;
943 if (dirty
& FFB_STATE_XPMASK
)
944 ffb
->xpmask
= fmesa
->xpmask
;
945 if (dirty
& FFB_STATE_YPMASK
)
946 ffb
->ypmask
= fmesa
->ypmask
;
947 if (dirty
& FFB_STATE_ZPMASK
)
948 ffb
->zpmask
= fmesa
->zpmask
;
949 if (dirty
& FFB_STATE_XCLIP
)
950 ffb
->xclip
= fmesa
->xclip
;
951 if (dirty
& FFB_STATE_CMP
)
952 ffb
->cmp
= fmesa
->cmp
;
953 if (dirty
& FFB_STATE_MATCHAB
)
954 ffb
->matchab
= fmesa
->matchab
;
955 if (dirty
& FFB_STATE_MAGNAB
)
956 ffb
->magnab
= fmesa
->magnab
;
957 if (dirty
& FFB_STATE_MATCHC
)
958 ffb
->matchc
= fmesa
->matchc
;
959 if (dirty
& FFB_STATE_MAGNC
)
960 ffb
->magnc
= fmesa
->magnc
;
963 if (dirty
& FFB_STATE_DCUE
) {
964 ffb
->dcss
= fmesa
->dcss
;
965 ffb
->dcsf
= fmesa
->dcsf
;
966 ffb
->dcsb
= fmesa
->dcsb
;
967 ffb
->dczf
= fmesa
->dczf
;
968 ffb
->dczb
= fmesa
->dczb
;
969 if (fmesa
->ffb_sarea
->flags
& (FFB_DRI_FFB2
| FFB_DRI_FFB2PLUS
)) {
970 ffb
->dcss1
= fmesa
->dcss1
;
971 ffb
->dcss2
= fmesa
->dcss2
;
972 ffb
->dcss3
= fmesa
->dcss3
;
973 ffb
->dcs2
= fmesa
->dcs2
;
974 ffb
->dcs3
= fmesa
->dcs3
;
975 ffb
->dcs4
= fmesa
->dcs4
;
976 ffb
->dcd2
= fmesa
->dcd2
;
977 ffb
->dcd3
= fmesa
->dcd3
;
978 ffb
->dcd4
= fmesa
->dcd4
;
982 if (dirty
& FFB_STATE_BLEND
) {
983 ffb
->blendc
= fmesa
->blendc
;
984 ffb
->blendc1
= fmesa
->blendc1
;
985 ffb
->blendc2
= fmesa
->blendc2
;
988 if (dirty
& FFB_STATE_CLIP
) {
989 ffb
->vclipmin
= fmesa
->vclipmin
;
990 ffb
->vclipmax
= fmesa
->vclipmax
;
991 ffb
->vclipzmin
= fmesa
->vclipzmin
;
992 ffb
->vclipzmax
= fmesa
->vclipzmax
;
993 for (i
= 0; i
< 4; i
++) {
994 ffb
->auxclip
[i
].min
= fmesa
->aux_clips
[i
].min
;
995 ffb
->auxclip
[i
].max
= fmesa
->aux_clips
[i
].max
;
999 if ((dirty
& FFB_STATE_STENCIL
) &&
1000 (fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
)) {
1001 ffb
->stencil
= fmesa
->stencil
;
1002 ffb
->stencilctl
= fmesa
->stencilctl
;
1003 ffb
->fbc
= FFB_FBC_WB_C
;
1004 ffb
->rawstencilctl
= (fmesa
->stencilctl
| (1 << 19));
1005 ffb
->fbc
= fmesa
->fbc
;
1006 ffb
->consty
= fmesa
->consty
;
1009 if (dirty
& FFB_STATE_APAT
) {
1010 for (i
= 0; i
< 32; i
++)
1011 ffb
->pattern
[i
] = fmesa
->pattern
[i
];
1014 fmesa
->state_dirty
= 0;
1015 fmesa
->state_fifo_ents
= 0;
1016 fmesa
->ffbScreen
->rp_active
= 1;
1019 static void ffbDDUpdateState(GLcontext
*ctx
, GLuint newstate
)
1021 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1023 /* When we are hw rendering, changing certain kinds of
1024 * state does not require flushing all of our context.
1026 if (fmesa
->bad_fragment_attrs
== 0 &&
1027 (newstate
& ~_NEW_COLOR
) == 0)
1030 _swrast_InvalidateState( ctx
, newstate
);
1031 _swsetup_InvalidateState( ctx
, newstate
);
1032 _vbo_InvalidateState( ctx
, newstate
);
1033 _tnl_InvalidateState( ctx
, newstate
);
1035 if (newstate
& _NEW_TEXTURE
)
1036 FALLBACK( ctx
, FFB_BADATTR_TEXTURE
,
1037 (ctx
->Texture
._EnabledUnits
!= 0));
1040 fprintf(stderr
, "ffbDDUpdateState: newstate(%08x)\n", newstate
);
1043 fmesa
->new_gl_state
|= newstate
;
1045 /* Force a reduced primitive change next rendering
1048 fmesa
->raster_primitive
= GL_POLYGON
+ 1;
1051 /* When the modelview matrix changes, this changes what
1052 * the eye coordinates will be so we have to recompute
1053 * the depth cueing parameters.
1055 * XXX DD_HAVE_HARDWARE_FOG.
1057 if (ctx
->Fog
.Enabled
&& (newstate
& _NEW_MODELVIEW
))
1063 void ffbDDInitStateFuncs(GLcontext
*ctx
)
1065 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1067 ctx
->Driver
.UpdateState
= ffbDDUpdateState
;
1069 ctx
->Driver
.Enable
= ffbDDEnable
;
1070 ctx
->Driver
.AlphaFunc
= ffbDDAlphaFunc
;
1071 ctx
->Driver
.BlendEquationSeparate
= ffbDDBlendEquationSeparate
;
1072 ctx
->Driver
.BlendFuncSeparate
= ffbDDBlendFuncSeparate
;
1073 ctx
->Driver
.DepthFunc
= ffbDDDepthFunc
;
1074 ctx
->Driver
.DepthMask
= ffbDDDepthMask
;
1075 ctx
->Driver
.Fogfv
= ffbDDFogfv
;
1076 ctx
->Driver
.LineStipple
= ffbDDLineStipple
;
1077 ctx
->Driver
.PolygonStipple
= ffbDDPolygonStipple
;
1078 ctx
->Driver
.Scissor
= ffbDDScissor
;
1079 ctx
->Driver
.ColorMask
= ffbDDColorMask
;
1080 ctx
->Driver
.LogicOpcode
= ffbDDLogicOp
;
1081 ctx
->Driver
.Viewport
= ffbDDViewport
;
1082 ctx
->Driver
.DepthRange
= ffbDDDepthRange
;
1084 if (fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
) {
1085 ctx
->Driver
.StencilFuncSeparate
= ffbDDStencilFuncSeparate
;
1086 ctx
->Driver
.StencilMaskSeparate
= ffbDDStencilMaskSeparate
;
1087 ctx
->Driver
.StencilOpSeparate
= ffbDDStencilOpSeparate
;
1090 ctx
->Driver
.DrawBuffer
= ffbDDDrawBuffer
;
1091 ctx
->Driver
.ReadBuffer
= ffbDDReadBuffer
;
1092 ctx
->Driver
.ClearColor
= ffbDDClearColor
;
1093 ctx
->Driver
.ClearDepth
= ffbDDClearDepth
;
1094 ctx
->Driver
.ClearStencil
= ffbDDClearStencil
;
1096 /* We will support color index modes later... -DaveM */
1098 ctx->Driver.ClearIndex = 0;
1099 ctx->Driver.IndexMask = 0;
1103 void ffbDDInitContextHwState(GLcontext
*ctx
)
1105 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1109 fmesa
->hw_locked
= 0;
1111 fmesa
->bad_fragment_attrs
= 0;
1112 fmesa
->state_dirty
= FFB_STATE_ALL
;
1113 fmesa
->new_gl_state
= ~0;
1116 fmesa
->fbc
= (FFB_FBC_WE_FORCEON
| FFB_FBC_WM_COMBINED
|
1117 FFB_FBC_SB_BOTH
| FFB_FBC_ZE_MASK
|
1118 FFB_FBC_YE_OFF
| FFB_FBC_XE_OFF
|
1120 if (ctx
->Visual
.doubleBufferMode
) {
1121 /* Buffer B is the initial back buffer. */
1122 fmesa
->back_buffer
= 1;
1123 fmesa
->fbc
|= FFB_FBC_WB_BC
| FFB_FBC_RB_B
;
1125 fmesa
->back_buffer
= 0;
1126 fmesa
->fbc
|= FFB_FBC_WB_A
| FFB_FBC_RB_A
;
1130 fmesa
->ppc
= (FFB_PPC_ACE_DISABLE
| FFB_PPC_DCE_DISABLE
|
1131 FFB_PPC_ABE_DISABLE
| FFB_PPC_VCE_3D
|
1132 FFB_PPC_APE_DISABLE
| FFB_PPC_TBE_OPAQUE
|
1133 FFB_PPC_ZS_CONST
| FFB_PPC_YS_CONST
|
1134 FFB_PPC_XS_WID
| FFB_PPC_CS_VAR
);
1137 fmesa
->drawop
= FFB_DRAWOP_RECTANGLE
;
1139 /* GL_COPY is the default LogicOp. */
1140 fmesa
->rop
= (FFB_ROP_NEW
<< 16) | (FFB_ROP_NEW
<< 8) | FFB_ROP_NEW
;
1142 /* No line patterning enabled. */
1143 fmesa
->lpat
= 0x00000000;
1145 /* We do not know the WID value until the first context switch. */
1151 /* ColorMask, all enabled. */
1152 fmesa
->pmask
= 0xffffffff;
1154 fmesa
->xpmask
= 0x000000ff;
1155 fmesa
->ypmask
= 0x0000000f;
1156 fmesa
->zpmask
= 0x0fffffff;
1158 /* AlphaFunc GL_ALWAYS, AlphaRef 0 */
1159 fmesa
->xclip
= FFB_XCLIP_TEST_ALWAYS
| 0x00;
1161 /* This sets us up to use WID clipping (so the DRI clipping
1162 * rectangle is unneeded by us). All other match and magnitude
1163 * tests are set to pass.
1166 fmesa
->cmp
= ((FFB_CMP_MATCH_ALWAYS
<< 24) | /* MATCH C */
1167 (FFB_CMP_MAGN_ALWAYS
<< 16) | /* MAGN C */
1168 (FFB_CMP_MATCH_EQ
<< 8) | /* MATCH AB */
1169 (FFB_CMP_MAGN_ALWAYS
<< 0)); /* MAGN AB */
1170 fmesa
->matchab
= 0xff000000;
1171 fmesa
->magnab
= 0x00000000;
1172 fmesa
->matchc
= 0x00000000;
1173 fmesa
->magnc
= 0x00000000;
1175 /* Depth cue parameters, all zeros to start. */
1177 fmesa
->dcss
= 0x00000000;
1178 fmesa
->dcsf
= 0x00000000;
1179 fmesa
->dcsb
= 0x00000000;
1180 fmesa
->dczf
= 0x00000000;
1181 fmesa
->dczb
= 0x00000000;
1182 fmesa
->dcss1
= 0x00000000;
1183 fmesa
->dcss2
= 0x00000000;
1184 fmesa
->dcss3
= 0x00000000;
1185 fmesa
->dcs2
= 0x00000000;
1186 fmesa
->dcs3
= 0x00000000;
1187 fmesa
->dcs4
= 0x00000000;
1188 fmesa
->dcd2
= 0x00000000;
1189 fmesa
->dcd3
= 0x00000000;
1190 fmesa
->dcd4
= 0x00000000;
1192 /* Alpha blending unit state. */
1194 fmesa
->blendc
= (1 << 0) | (0 << 2); /* src(GL_ONE) | dst(GL_ZERO) */
1195 fmesa
->blendc1
= 0x00000000;
1196 fmesa
->blendc2
= 0x00000000;
1198 /* ViewPort clip state. */
1199 fifo_count
+= 4 + (4 * 2);
1200 fmesa
->vclipmin
= 0x00000000;
1201 fmesa
->vclipmax
= 0xffffffff;
1202 fmesa
->vclipzmin
= 0x00000000;
1203 fmesa
->vclipzmax
= 0x0fffffff;
1204 for (i
= 0; i
< 4; i
++) {
1205 fmesa
->aux_clips
[0].min
= 0x00000000;
1206 fmesa
->aux_clips
[0].max
= 0x00000000;
1209 /* Stenciling state. */
1211 fmesa
->stencil
= 0xf0000000; /* Stencil MASK, Y plane */
1212 fmesa
->stencilctl
= 0x33300000; /* All stencil tests disabled */
1213 fmesa
->consty
= 0x0;
1215 /* Area pattern, used for polygon stipples. */
1217 for (i
= 0; i
< 32; i
++)
1218 fmesa
->pattern
[i
] = 0x00000000;
1220 fmesa
->state_fifo_ents
= fifo_count
;
1221 fmesa
->state_all_fifo_ents
= fifo_count
;