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"
31 #include "main/extensions.h"
32 #include "main/enums.h"
36 #include "tnl/t_pipeline.h"
37 #include "swrast/swrast.h"
38 #include "swrast_setup/swrast_setup.h"
42 #include "ffb_depth.h"
43 #include "ffb_context.h"
46 #include "ffb_state.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);
269 ffbDDStencilFuncSeparate(GLcontext
*ctx
, GLenum face
, GLenum func
,
270 GLint ref
, GLuint mask
)
272 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
273 unsigned int stencil
, stencilctl
, consty
;
275 /* We will properly update sw/hw state when stenciling is
278 if (! ctx
->Stencil
.Enabled
)
281 stencilctl
= fmesa
->stencilctl
;
282 stencilctl
&= ~(7 << 16);
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;
300 stencil
= fmesa
->stencil
;
301 stencil
&= ~(0xf << 20);
302 stencil
|= (mask
& 0xf) << 20;
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);
315 ffbDDStencilMaskSeparate(GLcontext
*ctx
, GLenum face
, GLuint mask
)
317 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
320 if (fmesa
->ypmask
!= mask
) {
321 fmesa
->ypmask
= mask
;
322 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_YPMASK
, 1);
327 ffbDDStencilOpSeparate(GLcontext
*ctx
, GLenum face
, GLenum fail
,
328 GLenum zfail
, GLenum zpass
)
330 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
331 unsigned int stencilctl
;
333 /* We will properly update sw/hw state when stenciling is
336 if (! ctx
->Stencil
.Enabled
)
339 stencilctl
= fmesa
->stencilctl
;
340 stencilctl
&= ~(0xfff00000);
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;
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;
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;
378 if (fmesa
->stencilctl
!= stencilctl
) {
379 fmesa
->stencilctl
= stencilctl
;
380 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_STENCIL
, 6);
384 static void ffbCalcViewportRegs(GLcontext
*ctx
)
386 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
387 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
388 GLuint xmin
, xmax
, ymin
, ymax
, zmin
, zmax
;
389 unsigned int vcmin
, vcmax
;
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
;
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
;
411 zmin
= ((GLdouble
)ctx
->Viewport
.Near
* 0x0fffffff);
412 zmax
= ((GLdouble
)ctx
->Viewport
.Far
* 0x0fffffff);
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)));
428 void ffbCalcViewport(GLcontext
*ctx
)
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
;
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);
442 fmesa
->depth_scale
= ((GLdouble
)1.0 / (GLdouble
)0x0fffffff);
444 ffbCalcViewportRegs(ctx
);
446 fmesa
->setupnewinputs
|= VERT_BIT_POS
;
449 static void ffbDDViewport(GLcontext
*ctx
, GLint x
, GLint y
,
450 GLsizei width
, GLsizei height
)
452 ffbCalcViewport(ctx
);
455 static void ffbDDDepthRange(GLcontext
*ctx
, GLclampd nearval
, GLclampd farval
)
457 ffbCalcViewport(ctx
);
460 static void ffbDDScissor(GLcontext
*ctx
, GLint cx
, GLint cy
,
461 GLsizei cw
, GLsizei ch
)
463 ffbCalcViewport(ctx
);
466 static void ffbDDDrawBuffer(GLcontext
*ctx
, GLenum buffer
)
468 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
469 unsigned int fbc
= fmesa
->fbc
;
472 fprintf(stderr
, "ffbDDDrawBuffer: mode(%s)\n",
473 _mesa_lookup_enum_by_nr(buffer
));
475 fbc
&= ~(FFB_FBC_WB_AB
| FFB_FBC_RB_MASK
);
478 if (fmesa
->back_buffer
== 0)
479 fbc
|= FFB_FBC_WB_B
| FFB_FBC_RB_B
;
481 fbc
|= FFB_FBC_WB_A
| FFB_FBC_RB_A
;
485 if (fmesa
->back_buffer
== 0)
486 fbc
|= FFB_FBC_WB_A
| FFB_FBC_RB_A
;
488 fbc
|= FFB_FBC_WB_B
| FFB_FBC_RB_B
;
491 case GL_FRONT_AND_BACK
:
492 fbc
|= FFB_FBC_WB_AB
;
499 if (fbc
!= fmesa
->fbc
) {
501 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
506 static void ffbDDReadBuffer(GLcontext
*ctx
, GLenum buffer
)
508 /* no-op, unless you implement h/w glRead/CopyPixels */
513 * Specifies buffer for sw fallbacks (spans)
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.
522 static void ffbDDSetBuffer(GLcontext
*ctx
, GLframebuffer
*colorBuffer
,
525 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
526 unsigned int fbc
= fmesa
->fbc
;
529 fprintf(stderr
, "ffbDDSetReadBuffer: mode(%s)\n",
530 _mesa_lookup_enum_by_nr(buffer
));
532 fbc
&= ~(FFB_FBC_RB_MASK
);
534 case BUFFER_BIT_FRONT_LEFT
:
535 if (fmesa
->back_buffer
== 0)
541 case BUFFER_BIT_BACK_LEFT
:
542 if (fmesa
->back_buffer
== 0)
549 _mesa_problem(ctx
, "Unexpected buffer in ffbDDSetBuffer()");
553 if (fbc
!= fmesa
->fbc
) {
555 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
561 static void ffbDDClearColor(GLcontext
*ctx
, const GLfloat color
[4])
563 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
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]);
569 fmesa
->clear_pixel
= ((c
[0] << 0) |
574 static void ffbDDClearDepth(GLcontext
*ctx
, GLclampd depth
)
576 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
578 fmesa
->clear_depth
= Z_FROM_MESA(depth
* 4294967295.0f
);
581 static void ffbDDClearStencil(GLcontext
*ctx
, GLint stencil
)
583 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
585 fmesa
->clear_stencil
= stencil
& 0xf;
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
)
593 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
594 unsigned int new_pmask
= 0x0;
597 fprintf(stderr
, "ffbDDColorMask: r(%d) g(%d) b(%d) a(%d)\n",
601 new_pmask
|= 0x000000ff;
603 new_pmask
|= 0x0000ff00;
605 new_pmask
|= 0x00ff0000;
607 new_pmask
|= 0xff000000;
609 if (fmesa
->pmask
!= new_pmask
) {
610 fmesa
->pmask
= new_pmask
;
611 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_PMASK
, 1);
615 static void ffbDDLogicOp(GLcontext
*ctx
, GLenum op
)
617 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
621 fprintf(stderr
, "ffbDDLogicOp: op(%s)\n",
622 _mesa_lookup_enum_by_nr(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;
646 rop
|= fmesa
->rop
& ~0xff;
647 if (rop
!= fmesa
->rop
) {
649 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_ROP
, 1);
652 FALLBACK( ctx
, FFB_BADATTR_BLENDROP
, GL_FALSE
);
657 /* XXX Also need to track near/far just like 3dfx driver.
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.
663 static void ffb_fog_linear(GLcontext
*ctx
, ffbContextPtr fmesa
)
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
);
676 /* Compute the Z at which f reaches 0.0, this is the full
679 * Thus compute Z (as seen by the chip during rendering),
682 * 0.0 = (fogEnd - eyez) * fogScale
684 * fogScale is usually not zero, thus we are looking for:
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
695 Zzero
= (((-d
/ fogEnd
) - c
) / szInv
) + tz
;
697 /* Compute the Z at which f reaches 1.0, this is where
698 * the incoming frag's full intensity is shown. This
701 * 1.0 = (fogEnd - eyez)
703 * We are looking for:
705 * 1.0 + eyez = fogEnd
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
714 Zone
= (((-d
/ (fogEnd
- 1.0)) - c
) / szInv
) + tz
;
716 /* FFB's Zfront must be less than Zback, thus we may have
717 * to invert Sf/Sb to satisfy this constraint.
722 zf
= Z_FROM_MESA(Zzero
);
723 zb
= Z_FROM_MESA(Zone
);
727 zf
= Z_FROM_MESA(Zone
);
728 zb
= Z_FROM_MESA(Zzero
);
733 static void ffbDDFogfv(GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
736 fprintf(stderr
, "ffbDDFogfv: pname(%s)\n", _mesa_lookup_enum_by_nr(pname
));
740 static void ffbDDLineStipple(GLcontext
*ctx
, GLint factor
, GLushort pattern
)
742 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
745 fprintf(stderr
, "ffbDDLineStipple: factor(%d) pattern(%04x)\n",
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
;
754 fmesa
->lpat
= ((factor
<< FFB_LPAT_SCALEVAL_SHIFT
) |
755 (0 << FFB_LPAT_PATLEN_SHIFT
) |
756 ((pattern
& 0xffff) << FFB_LPAT_PATTERN_SHIFT
));
763 void ffbXformAreaPattern(ffbContextPtr fmesa
, const GLubyte
*mask
)
765 __DRIdrawablePrivate
*dPriv
= fmesa
->driDrawable
;
769 i
= (dPriv
->y
+ dPriv
->h
) & (32 - 1);
770 xoff
= dPriv
->x
& (32 - 1);
771 while (lines
++ < 32) {
773 (((GLuint
)mask
[0] << 24) |
774 ((GLuint
)mask
[1] << 16) |
775 ((GLuint
)mask
[2] << 8) |
776 ((GLuint
)mask
[3] << 0));
779 (raw
<< xoff
) | (raw
>> (32 - xoff
));
780 i
= (i
- 1) & (32 - 1);
784 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_APAT
, 32);
787 static void ffbDDPolygonStipple(GLcontext
*ctx
, const GLubyte
*mask
)
789 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
792 fprintf(stderr
, "ffbDDPolygonStipple: state(%d)\n",
793 ctx
->Polygon
.StippleFlag
);
795 ffbXformAreaPattern(fmesa
, mask
);
798 static void ffbDDEnable(GLcontext
*ctx
, GLenum cap
, GLboolean state
)
800 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
804 fprintf(stderr
, "ffbDDEnable: %s state(%d)\n",
805 _mesa_lookup_enum_by_nr(cap
), state
);
810 tmp
= ffbComputeAlphaFunc(ctx
);
812 tmp
= FFB_XCLIP_TEST_ALWAYS
;
814 if (tmp
!= fmesa
->xclip
) {
816 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_XCLIP
, 1);
821 tmp
= (fmesa
->ppc
& ~FFB_PPC_ABE_MASK
);
823 tmp
|= FFB_PPC_ABE_ENABLE
;
825 tmp
|= FFB_PPC_ABE_DISABLE
;
827 if (fmesa
->ppc
!= tmp
) {
829 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_PPC
, 1);
830 ffbDDBlendFuncSeparate(ctx
, 0, 0, 0, 0 );
839 if (tmp
!= fmesa
->magnc
) {
840 unsigned int fbc
= fmesa
->fbc
;
841 fbc
&= ~FFB_FBC_ZE_MASK
;
843 fbc
|= FFB_FBC_ZE_ON
;
845 fbc
|= FFB_FBC_ZE_OFF
;
847 ffbDDDepthFunc(ctx
, ctx
->Depth
.Func
);
849 FFB_MAKE_DIRTY(fmesa
, (FFB_STATE_MAGNC
| FFB_STATE_FBC
), 2);
853 case GL_SCISSOR_TEST
:
854 ffbDDScissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
855 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
858 case GL_STENCIL_TEST
:
859 if (!(fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
)) {
860 FALLBACK( ctx
, FFB_BADATTR_STENCIL
, state
);
863 tmp
= fmesa
->fbc
& ~FFB_FBC_YE_MASK
;
865 ffbDDStencilFuncSeparate(ctx
, GL_FRONT
,
866 ctx
->Stencil
.Function
[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
;
877 fmesa
->stencil
= 0xf0000000;
878 fmesa
->stencilctl
= 0x33300000;
879 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_STENCIL
, 6);
880 tmp
|= FFB_FBC_YE_OFF
;
882 if (tmp
!= fmesa
->fbc
) {
884 FFB_MAKE_DIRTY(fmesa
, FFB_STATE_FBC
, 1);
889 /* Until I implement the fog support... */
890 FALLBACK( ctx
, FFB_BADATTR_FOG
, state
);
893 case GL_LINE_STIPPLE
:
897 ffbDDLineStipple(ctx
,
898 ctx
->Line
.StippleFactor
,
899 ctx
->Line
.StipplePattern
);
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.
918 void ffbSyncHardware(ffbContextPtr fmesa
)
920 ffb_fbcPtr ffb
= fmesa
->regs
;
924 FFBFifo(fmesa
, fmesa
->state_fifo_ents
);
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
;
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
|
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
;
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
;
987 if (dirty
& FFB_STATE_BLEND
) {
988 ffb
->blendc
= fmesa
->blendc
;
989 ffb
->blendc1
= fmesa
->blendc1
;
990 ffb
->blendc2
= fmesa
->blendc2
;
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
;
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
;
1014 if (dirty
& FFB_STATE_APAT
) {
1015 for (i
= 0; i
< 32; i
++)
1016 ffb
->pattern
[i
] = fmesa
->pattern
[i
];
1019 fmesa
->state_dirty
= 0;
1020 fmesa
->state_fifo_ents
= 0;
1021 fmesa
->ffbScreen
->rp_active
= 1;
1024 static void ffbDDUpdateState(GLcontext
*ctx
, GLuint newstate
)
1026 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1028 /* When we are hw rendering, changing certain kinds of
1029 * state does not require flushing all of our context.
1031 if (fmesa
->bad_fragment_attrs
== 0 &&
1032 (newstate
& ~_NEW_COLOR
) == 0)
1035 _swrast_InvalidateState( ctx
, newstate
);
1036 _swsetup_InvalidateState( ctx
, newstate
);
1037 _vbo_InvalidateState( ctx
, newstate
);
1038 _tnl_InvalidateState( ctx
, newstate
);
1040 if (newstate
& _NEW_TEXTURE
)
1041 FALLBACK( ctx
, FFB_BADATTR_TEXTURE
,
1042 (ctx
->Texture
._EnabledUnits
!= 0));
1045 fprintf(stderr
, "ffbDDUpdateState: newstate(%08x)\n", newstate
);
1048 fmesa
->new_gl_state
|= newstate
;
1050 /* Force a reduced primitive change next rendering
1053 fmesa
->raster_primitive
= GL_POLYGON
+ 1;
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.
1060 * XXX DD_HAVE_HARDWARE_FOG.
1062 if (ctx
->Fog
.Enabled
&& (newstate
& _NEW_MODELVIEW
))
1068 void ffbDDInitStateFuncs(GLcontext
*ctx
)
1070 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1072 ctx
->Driver
.UpdateState
= ffbDDUpdateState
;
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
;
1089 if (fmesa
->ffb_sarea
->flags
& FFB_DRI_FFB2PLUS
) {
1090 ctx
->Driver
.StencilFuncSeparate
= ffbDDStencilFuncSeparate
;
1091 ctx
->Driver
.StencilMaskSeparate
= ffbDDStencilMaskSeparate
;
1092 ctx
->Driver
.StencilOpSeparate
= ffbDDStencilOpSeparate
;
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
;
1101 /* We will support color index modes later... -DaveM */
1103 ctx->Driver.ClearIndex = 0;
1104 ctx->Driver.IndexMask = 0;
1108 void ffbDDInitContextHwState(GLcontext
*ctx
)
1110 ffbContextPtr fmesa
= FFB_CONTEXT(ctx
);
1114 fmesa
->hw_locked
= 0;
1116 fmesa
->bad_fragment_attrs
= 0;
1117 fmesa
->state_dirty
= FFB_STATE_ALL
;
1118 fmesa
->new_gl_state
= ~0;
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
|
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
;
1130 fmesa
->back_buffer
= 0;
1131 fmesa
->fbc
|= FFB_FBC_WB_A
| FFB_FBC_RB_A
;
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
);
1142 fmesa
->drawop
= FFB_DRAWOP_RECTANGLE
;
1144 /* GL_COPY is the default LogicOp. */
1145 fmesa
->rop
= (FFB_ROP_NEW
<< 16) | (FFB_ROP_NEW
<< 8) | FFB_ROP_NEW
;
1147 /* No line patterning enabled. */
1148 fmesa
->lpat
= 0x00000000;
1150 /* We do not know the WID value until the first context switch. */
1156 /* ColorMask, all enabled. */
1157 fmesa
->pmask
= 0xffffffff;
1159 fmesa
->xpmask
= 0x000000ff;
1160 fmesa
->ypmask
= 0x0000000f;
1161 fmesa
->zpmask
= 0x0fffffff;
1163 /* AlphaFunc GL_ALWAYS, AlphaRef 0 */
1164 fmesa
->xclip
= FFB_XCLIP_TEST_ALWAYS
| 0x00;
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.
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;
1180 /* Depth cue parameters, all zeros to start. */
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;
1197 /* Alpha blending unit state. */
1199 fmesa
->blendc
= (1 << 0) | (0 << 2); /* src(GL_ONE) | dst(GL_ZERO) */
1200 fmesa
->blendc1
= 0x00000000;
1201 fmesa
->blendc2
= 0x00000000;
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;
1214 /* Stenciling state. */
1216 fmesa
->stencil
= 0xf0000000; /* Stencil MASK, Y plane */
1217 fmesa
->stencilctl
= 0x33300000; /* All stencil tests disabled */
1218 fmesa
->consty
= 0x0;
1220 /* Area pattern, used for polygon stipples. */
1222 for (i
= 0; i
< 32; i
++)
1223 fmesa
->pattern
[i
] = 0x00000000;
1225 fmesa
->state_fifo_ents
= fifo_count
;
1226 fmesa
->state_all_fifo_ents
= fifo_count
;