1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.8 2002/12/16 16:18:58 dawes Exp $ */
2 /**************************************************************************
4 Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Gareth Hughes <gareth@valinux.com>
33 * Keith Whitwell <keith@tungstengraphics.com>
38 #include "api_arrayelt.h"
43 #include "swrast/swrast.h"
44 #include "array_cache/acache.h"
46 #include "tnl/t_pipeline.h"
47 #include "main/light.h"
48 #include "swrast_setup/swrast_setup.h"
50 #include "radeon_context.h"
51 #include "radeon_ioctl.h"
52 #include "radeon_state.h"
53 #include "radeon_tcl.h"
54 #include "radeon_tex.h"
55 #include "radeon_swtcl.h"
56 #include "radeon_vtxfmt.h"
58 /* =============================================================
62 static void radeonAlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
64 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
65 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
68 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
70 RADEON_STATECHANGE( rmesa
, ctx
);
72 pp_misc
&= ~(RADEON_ALPHA_TEST_OP_MASK
| RADEON_REF_ALPHA_MASK
);
73 pp_misc
|= (refByte
& RADEON_REF_ALPHA_MASK
);
77 pp_misc
|= RADEON_ALPHA_TEST_FAIL
;
80 pp_misc
|= RADEON_ALPHA_TEST_LESS
;
83 pp_misc
|= RADEON_ALPHA_TEST_EQUAL
;
86 pp_misc
|= RADEON_ALPHA_TEST_LEQUAL
;
89 pp_misc
|= RADEON_ALPHA_TEST_GREATER
;
92 pp_misc
|= RADEON_ALPHA_TEST_NEQUAL
;
95 pp_misc
|= RADEON_ALPHA_TEST_GEQUAL
;
98 pp_misc
|= RADEON_ALPHA_TEST_PASS
;
102 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
105 static void radeonBlendEquationSeparate( GLcontext
*ctx
,
106 GLenum modeRGB
, GLenum modeA
)
108 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
109 GLuint b
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] & ~RADEON_COMB_FCN_MASK
;
110 GLboolean fallback
= GL_FALSE
;
112 assert( modeRGB
== modeA
);
117 b
|= RADEON_COMB_FCN_ADD_CLAMP
;
120 case GL_FUNC_SUBTRACT
:
121 b
|= RADEON_COMB_FCN_SUB_CLAMP
;
125 if (ctx
->Color
.BlendEnabled
)
128 b
|= RADEON_COMB_FCN_ADD_CLAMP
;
132 FALLBACK( rmesa
, RADEON_FALLBACK_BLEND_EQ
, fallback
);
134 RADEON_STATECHANGE( rmesa
, ctx
);
135 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = b
;
136 if ( ctx
->Color
._LogicOpEnabled
) {
137 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_ROP_ENABLE
;
139 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_ROP_ENABLE
;
144 static void radeonBlendFuncSeparate( GLcontext
*ctx
,
145 GLenum sfactorRGB
, GLenum dfactorRGB
,
146 GLenum sfactorA
, GLenum dfactorA
)
148 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
149 GLuint b
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] &
150 ~(RADEON_SRC_BLEND_MASK
| RADEON_DST_BLEND_MASK
);
151 GLboolean fallback
= GL_FALSE
;
153 switch ( ctx
->Color
.BlendSrcRGB
) {
155 b
|= RADEON_SRC_BLEND_GL_ZERO
;
158 b
|= RADEON_SRC_BLEND_GL_ONE
;
161 b
|= RADEON_SRC_BLEND_GL_DST_COLOR
;
163 case GL_ONE_MINUS_DST_COLOR
:
164 b
|= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR
;
167 b
|= RADEON_SRC_BLEND_GL_SRC_COLOR
;
169 case GL_ONE_MINUS_SRC_COLOR
:
170 b
|= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR
;
173 b
|= RADEON_SRC_BLEND_GL_SRC_ALPHA
;
175 case GL_ONE_MINUS_SRC_ALPHA
:
176 b
|= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
179 b
|= RADEON_SRC_BLEND_GL_DST_ALPHA
;
181 case GL_ONE_MINUS_DST_ALPHA
:
182 b
|= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA
;
184 case GL_SRC_ALPHA_SATURATE
:
185 b
|= RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE
;
187 case GL_CONSTANT_COLOR
:
188 case GL_ONE_MINUS_CONSTANT_COLOR
:
189 case GL_CONSTANT_ALPHA
:
190 case GL_ONE_MINUS_CONSTANT_ALPHA
:
191 if (ctx
->Color
.BlendEnabled
)
194 b
|= RADEON_SRC_BLEND_GL_ONE
;
200 switch ( ctx
->Color
.BlendDstRGB
) {
202 b
|= RADEON_DST_BLEND_GL_ZERO
;
205 b
|= RADEON_DST_BLEND_GL_ONE
;
208 b
|= RADEON_DST_BLEND_GL_SRC_COLOR
;
210 case GL_ONE_MINUS_SRC_COLOR
:
211 b
|= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR
;
214 b
|= RADEON_DST_BLEND_GL_SRC_ALPHA
;
216 case GL_ONE_MINUS_SRC_ALPHA
:
217 b
|= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
220 b
|= RADEON_DST_BLEND_GL_DST_COLOR
;
222 case GL_ONE_MINUS_DST_COLOR
:
223 b
|= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR
;
226 b
|= RADEON_DST_BLEND_GL_DST_ALPHA
;
228 case GL_ONE_MINUS_DST_ALPHA
:
229 b
|= RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA
;
231 case GL_CONSTANT_COLOR
:
232 case GL_ONE_MINUS_CONSTANT_COLOR
:
233 case GL_CONSTANT_ALPHA
:
234 case GL_ONE_MINUS_CONSTANT_ALPHA
:
235 if (ctx
->Color
.BlendEnabled
)
238 b
|= RADEON_DST_BLEND_GL_ZERO
;
244 FALLBACK( rmesa
, RADEON_FALLBACK_BLEND_FUNC
, fallback
);
246 RADEON_STATECHANGE( rmesa
, ctx
);
247 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = b
;
252 /* =============================================================
256 static void radeonDepthFunc( GLcontext
*ctx
, GLenum func
)
258 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
260 RADEON_STATECHANGE( rmesa
, ctx
);
261 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~RADEON_Z_TEST_MASK
;
263 switch ( ctx
->Depth
.Func
) {
265 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_NEVER
;
268 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_LESS
;
271 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_EQUAL
;
274 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_LEQUAL
;
277 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_GREATER
;
280 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_NEQUAL
;
283 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_GEQUAL
;
286 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_ALWAYS
;
292 static void radeonDepthMask( GLcontext
*ctx
, GLboolean flag
)
294 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
295 RADEON_STATECHANGE( rmesa
, ctx
);
297 if ( ctx
->Depth
.Mask
) {
298 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_WRITE_ENABLE
;
300 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~RADEON_Z_WRITE_ENABLE
;
304 static void radeonClearDepth( GLcontext
*ctx
, GLclampd d
)
306 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
307 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
308 RADEON_DEPTH_FORMAT_MASK
);
311 case RADEON_DEPTH_FORMAT_16BIT_INT_Z
:
312 rmesa
->state
.depth
.clear
= d
* 0x0000ffff;
314 case RADEON_DEPTH_FORMAT_24BIT_INT_Z
:
315 rmesa
->state
.depth
.clear
= d
* 0x00ffffff;
321 /* =============================================================
326 static void radeonFogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
328 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
329 union { int i
; float f
; } c
, d
;
332 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
333 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
337 if (!ctx
->Fog
.Enabled
)
339 RADEON_STATECHANGE(rmesa
, tcl
);
340 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~RADEON_TCL_FOG_MASK
;
341 switch (ctx
->Fog
.Mode
) {
343 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= RADEON_TCL_FOG_LINEAR
;
344 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
349 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
350 d
.f
= 1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
354 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= RADEON_TCL_FOG_EXP
;
356 d
.f
= ctx
->Fog
.Density
;
359 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= RADEON_TCL_FOG_EXP2
;
361 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
368 switch (ctx
->Fog
.Mode
) {
371 d
.f
= ctx
->Fog
.Density
;
375 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
383 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
384 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
388 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
389 d
.f
= 1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
394 RADEON_STATECHANGE( rmesa
, ctx
);
395 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
396 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] =
397 radeonPackColor( 4, col
[0], col
[1], col
[2], 0 );
399 case GL_FOG_COORDINATE_SOURCE_EXT
:
407 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
408 RADEON_STATECHANGE( rmesa
, fog
);
409 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
410 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
415 /* =============================================================
420 static GLboolean
intersect_rect( XF86DRIClipRectPtr out
,
421 XF86DRIClipRectPtr a
,
422 XF86DRIClipRectPtr b
)
425 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
426 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
427 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
428 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
429 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
430 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
435 void radeonRecalcScissorRects( radeonContextPtr rmesa
)
437 XF86DRIClipRectPtr out
;
440 /* Grow cliprect store?
442 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
443 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
444 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
445 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
448 if (rmesa
->state
.scissor
.pClipRects
)
449 FREE(rmesa
->state
.scissor
.pClipRects
);
451 rmesa
->state
.scissor
.pClipRects
=
452 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
453 sizeof(XF86DRIClipRectRec
) );
455 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
456 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
461 out
= rmesa
->state
.scissor
.pClipRects
;
462 rmesa
->state
.scissor
.numClipRects
= 0;
464 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
465 if ( intersect_rect( out
,
466 &rmesa
->pClipRects
[i
],
467 &rmesa
->state
.scissor
.rect
) ) {
468 rmesa
->state
.scissor
.numClipRects
++;
475 static void radeonUpdateScissor( GLcontext
*ctx
)
477 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
479 if ( rmesa
->dri
.drawable
) {
480 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
482 int x
= ctx
->Scissor
.X
;
483 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
484 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
485 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
487 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
488 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
489 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
490 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
492 radeonRecalcScissorRects( rmesa
);
497 static void radeonScissor( GLcontext
*ctx
,
498 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
500 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
502 if ( ctx
->Scissor
.Enabled
) {
503 RADEON_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
504 radeonUpdateScissor( ctx
);
510 /* =============================================================
514 static void radeonCullFace( GLcontext
*ctx
, GLenum unused
)
516 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
517 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
518 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
520 s
|= RADEON_FFACE_SOLID
| RADEON_BFACE_SOLID
;
521 t
&= ~(RADEON_CULL_FRONT
| RADEON_CULL_BACK
);
523 if ( ctx
->Polygon
.CullFlag
) {
524 switch ( ctx
->Polygon
.CullFaceMode
) {
526 s
&= ~RADEON_FFACE_SOLID
;
527 t
|= RADEON_CULL_FRONT
;
530 s
&= ~RADEON_BFACE_SOLID
;
531 t
|= RADEON_CULL_BACK
;
533 case GL_FRONT_AND_BACK
:
534 s
&= ~(RADEON_FFACE_SOLID
| RADEON_BFACE_SOLID
);
535 t
|= (RADEON_CULL_FRONT
| RADEON_CULL_BACK
);
540 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
541 RADEON_STATECHANGE(rmesa
, set
);
542 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
545 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
546 RADEON_STATECHANGE(rmesa
, tcl
);
547 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
551 static void radeonFrontFace( GLcontext
*ctx
, GLenum mode
)
553 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
555 RADEON_STATECHANGE( rmesa
, set
);
556 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~RADEON_FFACE_CULL_DIR_MASK
;
558 RADEON_STATECHANGE( rmesa
, tcl
);
559 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~RADEON_CULL_FRONT_IS_CCW
;
563 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_FFACE_CULL_CW
;
566 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_FFACE_CULL_CCW
;
567 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= RADEON_CULL_FRONT_IS_CCW
;
573 /* =============================================================
576 static void radeonLineWidth( GLcontext
*ctx
, GLfloat widthf
)
578 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
580 RADEON_STATECHANGE( rmesa
, lin
);
581 RADEON_STATECHANGE( rmesa
, set
);
583 /* Line width is stored in U6.4 format.
585 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] = (GLuint
)(widthf
* 16.0);
586 if ( widthf
> 1.0 ) {
587 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_WIDELINE_ENABLE
;
589 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~RADEON_WIDELINE_ENABLE
;
593 static void radeonLineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
595 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
597 RADEON_STATECHANGE( rmesa
, lin
);
598 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
599 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
603 /* =============================================================
606 static void radeonColorMask( GLcontext
*ctx
,
607 GLboolean r
, GLboolean g
,
608 GLboolean b
, GLboolean a
)
610 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
611 GLuint mask
= radeonPackColor( rmesa
->radeonScreen
->cpp
,
612 ctx
->Color
.ColorMask
[RCOMP
],
613 ctx
->Color
.ColorMask
[GCOMP
],
614 ctx
->Color
.ColorMask
[BCOMP
],
615 ctx
->Color
.ColorMask
[ACOMP
] );
617 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
618 RADEON_STATECHANGE( rmesa
, msk
);
619 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
624 /* =============================================================
628 static void radeonPolygonOffset( GLcontext
*ctx
,
629 GLfloat factor
, GLfloat units
)
631 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
632 GLfloat constant
= units
* rmesa
->state
.depth
.scale
;
634 RADEON_STATECHANGE( rmesa
, zbs
);
635 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = *(GLuint
*)&factor
;
636 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = *(GLuint
*)&constant
;
639 static void radeonPolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
641 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
643 drmRadeonStipple stipple
;
645 /* Must flip pattern upside down.
647 for ( i
= 0 ; i
< 32 ; i
++ ) {
648 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
651 /* TODO: push this into cmd mechanism
653 RADEON_FIREVERTICES( rmesa
);
654 LOCK_HARDWARE( rmesa
);
656 /* FIXME: Use window x,y offsets into stipple RAM.
658 stipple
.mask
= rmesa
->state
.stipple
.mask
;
659 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
660 &stipple
, sizeof(drmRadeonStipple
) );
661 UNLOCK_HARDWARE( rmesa
);
664 static void radeonPolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
666 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
667 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
669 /* Can't generally do unfilled via tcl, but some good special
672 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_UNFILLED
, flag
);
673 if (rmesa
->TclFallback
) {
674 radeonChooseRenderState( ctx
);
675 radeonChooseVertexState( ctx
);
680 /* =============================================================
681 * Rendering attributes
683 * We really don't want to recalculate all this every time we bind a
684 * texture. These things shouldn't change all that often, so it makes
685 * sense to break them out of the core texture state update routines.
688 /* Examine lighting and texture state to determine if separate specular
691 static void radeonUpdateSpecular( GLcontext
*ctx
)
693 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
694 CARD32 p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
696 RADEON_STATECHANGE( rmesa
, tcl
);
698 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] &= ~RADEON_TCL_COMPUTE_SPECULAR
;
699 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] &= ~RADEON_TCL_COMPUTE_DIFFUSE
;
700 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] &= ~RADEON_TCL_VTX_PK_SPEC
;
701 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] &= ~RADEON_TCL_VTX_PK_DIFFUSE
;
702 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &= ~RADEON_LIGHTING_ENABLE
;
704 p
&= ~RADEON_SPECULAR_ENABLE
;
706 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_DIFFUSE_SPECULAR_COMBINE
;
709 if (ctx
->Light
.Enabled
&&
710 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
711 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] |= RADEON_TCL_COMPUTE_SPECULAR
;
712 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] |= RADEON_TCL_COMPUTE_DIFFUSE
;
713 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_SPEC
;
714 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_DIFFUSE
;
715 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_LIGHTING_ENABLE
;
716 p
|= RADEON_SPECULAR_ENABLE
;
717 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &=
718 ~RADEON_DIFFUSE_SPECULAR_COMBINE
;
720 else if (ctx
->Light
.Enabled
) {
721 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] |= RADEON_TCL_COMPUTE_DIFFUSE
;
722 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_DIFFUSE
;
723 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_LIGHTING_ENABLE
;
724 } else if (ctx
->Fog
.ColorSumEnabled
) {
725 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_SPEC
;
726 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_DIFFUSE
;
727 p
|= RADEON_SPECULAR_ENABLE
;
729 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_DIFFUSE
;
732 if (ctx
->Fog
.Enabled
) {
733 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] |= RADEON_TCL_COMPUTE_SPECULAR
;
734 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_SPEC
;
736 /* Bizzare: have to leave lighting enabled to get fog.
738 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_LIGHTING_ENABLE
;
741 if (NEED_SECONDARY_COLOR(ctx
)) {
742 assert( (p
& RADEON_SPECULAR_ENABLE
) != 0 );
744 assert( (p
& RADEON_SPECULAR_ENABLE
) == 0 );
747 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
748 RADEON_STATECHANGE( rmesa
, ctx
);
749 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
752 /* Update vertex/render formats
754 if (rmesa
->TclFallback
) {
755 radeonChooseRenderState( ctx
);
756 radeonChooseVertexState( ctx
);
761 /* =============================================================
766 /* Update on colormaterial, material emmissive/ambient,
767 * lightmodel.globalambient
769 static void update_global_ambient( GLcontext
*ctx
)
771 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
772 float *fcmd
= (float *)RADEON_DB_STATE( glt
);
774 /* Need to do more if both emmissive & ambient are PREMULT:
776 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &
777 ((3 << RADEON_EMISSIVE_SOURCE_SHIFT
) |
778 (3 << RADEON_AMBIENT_SOURCE_SHIFT
))) == 0)
780 COPY_3V( &fcmd
[GLT_RED
],
781 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
782 ACC_SCALE_3V( &fcmd
[GLT_RED
],
783 ctx
->Light
.Model
.Ambient
,
784 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
788 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
791 RADEON_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
794 /* Update on change to
798 * - colormaterial enabled
799 * - colormaterial bitmask
801 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
803 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
805 /* fprintf(stderr, "%s\n", __FUNCTION__); */
808 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
809 float *fcmd
= (float *)RADEON_DB_STATE( lit
[p
] );
810 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
811 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
813 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
814 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
815 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
817 if (!ctx
->Light
.ColorMaterialEnabled
)
820 if ((bitmask
& MAT_BIT_FRONT_AMBIENT
) == 0)
821 SELF_SCALE_3V( &fcmd
[LIT_AMBIENT_RED
], mat
[MAT_ATTRIB_FRONT_AMBIENT
] );
823 if ((bitmask
& MAT_BIT_FRONT_DIFFUSE
) == 0)
824 SELF_SCALE_3V( &fcmd
[LIT_DIFFUSE_RED
], mat
[MAT_ATTRIB_FRONT_DIFFUSE
] );
826 if ((bitmask
& MAT_BIT_FRONT_SPECULAR
) == 0)
827 SELF_SCALE_3V( &fcmd
[LIT_SPECULAR_RED
], mat
[MAT_ATTRIB_FRONT_SPECULAR
] );
829 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
833 /* Also fallback for asym colormaterial mode in twoside lighting...
835 static void check_twoside_fallback( GLcontext
*ctx
)
837 GLboolean fallback
= GL_FALSE
;
840 if (ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
) {
841 if (ctx
->Light
.ColorMaterialEnabled
&&
842 (ctx
->Light
.ColorMaterialBitmask
& BACK_MATERIAL_BITS
) !=
843 ((ctx
->Light
.ColorMaterialBitmask
& FRONT_MATERIAL_BITS
)<<1))
846 for (i
= MAT_ATTRIB_FRONT_AMBIENT
; i
< MAT_ATTRIB_FRONT_INDEXES
; i
+=2)
847 if (memcmp( ctx
->Light
.Material
.Attrib
[i
],
848 ctx
->Light
.Material
.Attrib
[i
+1],
849 sizeof(GLfloat
)*4) != 0) {
856 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE
, fallback
);
860 static void radeonColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
862 if (ctx
->Light
.ColorMaterialEnabled
) {
863 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
864 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
];
865 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
867 /* Default to PREMULT:
869 light_model_ctl1
&= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT
) |
870 (3 << RADEON_AMBIENT_SOURCE_SHIFT
) |
871 (3 << RADEON_DIFFUSE_SOURCE_SHIFT
) |
872 (3 << RADEON_SPECULAR_SOURCE_SHIFT
));
874 if (mask
& MAT_BIT_FRONT_EMISSION
) {
875 light_model_ctl1
|= (RADEON_LM_SOURCE_VERTEX_DIFFUSE
<<
876 RADEON_EMISSIVE_SOURCE_SHIFT
);
879 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
880 light_model_ctl1
|= (RADEON_LM_SOURCE_VERTEX_DIFFUSE
<<
881 RADEON_AMBIENT_SOURCE_SHIFT
);
884 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
885 light_model_ctl1
|= (RADEON_LM_SOURCE_VERTEX_DIFFUSE
<<
886 RADEON_DIFFUSE_SOURCE_SHIFT
);
889 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
890 light_model_ctl1
|= (RADEON_LM_SOURCE_VERTEX_DIFFUSE
<<
891 RADEON_SPECULAR_SOURCE_SHIFT
);
894 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
]) {
897 RADEON_STATECHANGE( rmesa
, tcl
);
898 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] = light_model_ctl1
;
900 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
901 update_light_colors( ctx
, p
);
902 update_global_ambient( ctx
);
906 check_twoside_fallback( ctx
);
909 void radeonUpdateMaterial( GLcontext
*ctx
)
911 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
912 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
913 GLfloat
*fcmd
= (GLfloat
*)RADEON_DB_STATE( mtl
);
917 if (ctx
->Light
.ColorMaterialEnabled
)
918 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
920 if (RADEON_DEBUG
& DEBUG_STATE
)
921 fprintf(stderr
, "%s\n", __FUNCTION__
);
924 if (mask
& MAT_BIT_FRONT_EMISSION
) {
925 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
926 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
927 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
928 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
930 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
931 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
932 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
933 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
934 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
936 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
937 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
938 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
939 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
940 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
942 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
943 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
944 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
945 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
946 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
948 if (mask
& MAT_BIT_FRONT_SHININESS
) {
949 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
952 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
);
954 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
955 update_light_colors( ctx
, p
);
957 check_twoside_fallback( ctx
);
958 update_global_ambient( ctx
);
963 * _MESA_NEW_NEED_EYE_COORDS
965 * Uses derived state from mesa:
974 * which are calculated in light.c and are correct for the current
975 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
976 * and _MESA_NEW_NEED_EYE_COORDS.
978 static void update_light( GLcontext
*ctx
)
980 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
982 /* Have to check these, or have an automatic shortcircuit mechanism
983 * to remove noop statechanges. (Or just do a better job on the
987 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
];
989 if (ctx
->_NeedEyeCoords
)
990 tmp
&= ~RADEON_LIGHT_IN_MODELSPACE
;
992 tmp
|= RADEON_LIGHT_IN_MODELSPACE
;
995 /* Leave this test disabled: (unexplained q3 lockup) (even with
998 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
])
1000 RADEON_STATECHANGE( rmesa
, tcl
);
1001 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] = tmp
;
1006 GLfloat
*fcmd
= (GLfloat
*)RADEON_DB_STATE( eye
);
1007 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1008 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1009 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1010 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1011 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1016 if (ctx
->Light
.Enabled
) {
1018 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1019 if (ctx
->Light
.Light
[p
].Enabled
) {
1020 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1021 GLfloat
*fcmd
= (GLfloat
*)RADEON_DB_STATE( lit
[p
] );
1023 if (l
->EyePosition
[3] == 0.0) {
1024 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1025 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1026 fcmd
[LIT_POSITION_W
] = 0;
1027 fcmd
[LIT_DIRECTION_W
] = 0;
1029 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1030 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1031 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1032 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1033 fcmd
[LIT_DIRECTION_W
] = 0;
1036 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1042 static void radeonLightfv( GLcontext
*ctx
, GLenum light
,
1043 GLenum pname
, const GLfloat
*params
)
1045 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1046 GLint p
= light
- GL_LIGHT0
;
1047 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1048 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1055 update_light_colors( ctx
, p
);
1058 case GL_SPOT_DIRECTION
:
1059 /* picked up in update_light */
1063 /* positions picked up in update_light, but can do flag here */
1065 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1067 /* FIXME: Set RANGE_ATTEN only when needed */
1069 flag
= RADEON_LIGHT_1_IS_LOCAL
;
1071 flag
= RADEON_LIGHT_0_IS_LOCAL
;
1073 RADEON_STATECHANGE(rmesa
, tcl
);
1074 if (l
->EyePosition
[3] != 0.0F
)
1075 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1077 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1081 case GL_SPOT_EXPONENT
:
1082 RADEON_STATECHANGE(rmesa
, lit
[p
]);
1083 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1086 case GL_SPOT_CUTOFF
: {
1087 GLuint flag
= (p
&1) ? RADEON_LIGHT_1_IS_SPOT
: RADEON_LIGHT_0_IS_SPOT
;
1088 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1090 RADEON_STATECHANGE(rmesa
, lit
[p
]);
1091 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1093 RADEON_STATECHANGE(rmesa
, tcl
);
1094 if (l
->SpotCutoff
!= 180.0F
)
1095 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1097 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1102 case GL_CONSTANT_ATTENUATION
:
1103 RADEON_STATECHANGE(rmesa
, lit
[p
]);
1104 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1105 if ( params
[0] == 0.0 )
1106 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1108 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1110 case GL_LINEAR_ATTENUATION
:
1111 RADEON_STATECHANGE(rmesa
, lit
[p
]);
1112 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1114 case GL_QUADRATIC_ATTENUATION
:
1115 RADEON_STATECHANGE(rmesa
, lit
[p
]);
1116 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1122 /* Set RANGE_ATTEN only when needed */
1125 case GL_CONSTANT_ATTENUATION
:
1126 case GL_LINEAR_ATTENUATION
:
1127 case GL_QUADRATIC_ATTENUATION
:
1129 GLuint
*icmd
= (GLuint
*)RADEON_DB_STATE( tcl
);
1130 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1131 GLuint atten_flag
= ( p
&1 ) ? RADEON_LIGHT_1_ENABLE_RANGE_ATTEN
1132 : RADEON_LIGHT_0_ENABLE_RANGE_ATTEN
;
1133 GLuint atten_const_flag
= ( p
&1 ) ? RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN
1134 : RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1136 if ( l
->EyePosition
[3] == 0.0F
||
1137 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1138 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1139 /* Disable attenuation */
1140 icmd
[idx
] &= ~atten_flag
;
1142 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1143 /* Enable only constant portion of attenuation calculation */
1144 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1146 /* Enable full attenuation calculation */
1147 icmd
[idx
] &= ~atten_const_flag
;
1148 icmd
[idx
] |= atten_flag
;
1152 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1163 static void radeonLightModelfv( GLcontext
*ctx
, GLenum pname
,
1164 const GLfloat
*param
)
1166 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1169 case GL_LIGHT_MODEL_AMBIENT
:
1170 update_global_ambient( ctx
);
1173 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1174 RADEON_STATECHANGE( rmesa
, tcl
);
1175 if (ctx
->Light
.Model
.LocalViewer
)
1176 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_LOCAL_VIEWER
;
1178 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &= ~RADEON_LOCAL_VIEWER
;
1181 case GL_LIGHT_MODEL_TWO_SIDE
:
1182 RADEON_STATECHANGE( rmesa
, tcl
);
1183 if (ctx
->Light
.Model
.TwoSide
)
1184 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= RADEON_LIGHT_TWOSIDE
;
1186 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~RADEON_LIGHT_TWOSIDE
;
1188 check_twoside_fallback( ctx
);
1190 if (rmesa
->TclFallback
) {
1191 radeonChooseRenderState( ctx
);
1192 radeonChooseVertexState( ctx
);
1196 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1197 radeonUpdateSpecular(ctx
);
1205 static void radeonShadeModel( GLcontext
*ctx
, GLenum mode
)
1207 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1208 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1210 s
&= ~(RADEON_DIFFUSE_SHADE_MASK
|
1211 RADEON_ALPHA_SHADE_MASK
|
1212 RADEON_SPECULAR_SHADE_MASK
|
1213 RADEON_FOG_SHADE_MASK
);
1217 s
|= (RADEON_DIFFUSE_SHADE_FLAT
|
1218 RADEON_ALPHA_SHADE_FLAT
|
1219 RADEON_SPECULAR_SHADE_FLAT
|
1220 RADEON_FOG_SHADE_FLAT
);
1223 s
|= (RADEON_DIFFUSE_SHADE_GOURAUD
|
1224 RADEON_ALPHA_SHADE_GOURAUD
|
1225 RADEON_SPECULAR_SHADE_GOURAUD
|
1226 RADEON_FOG_SHADE_GOURAUD
);
1232 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1233 RADEON_STATECHANGE( rmesa
, set
);
1234 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1239 /* =============================================================
1243 static void radeonClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1245 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1246 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1247 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1249 RADEON_STATECHANGE( rmesa
, ucp
[p
] );
1250 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1251 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1252 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1253 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1256 static void radeonUpdateClipPlanes( GLcontext
*ctx
)
1258 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1261 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1262 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1263 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1265 RADEON_STATECHANGE( rmesa
, ucp
[p
] );
1266 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1267 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1268 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1269 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1275 /* =============================================================
1279 static void radeonStencilFunc( GLcontext
*ctx
, GLenum func
,
1280 GLint ref
, GLuint mask
)
1282 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1283 GLuint refmask
= ((ctx
->Stencil
.Ref
[0] << RADEON_STENCIL_REF_SHIFT
) |
1284 (ctx
->Stencil
.ValueMask
[0] << RADEON_STENCIL_MASK_SHIFT
));
1286 RADEON_STATECHANGE( rmesa
, ctx
);
1287 RADEON_STATECHANGE( rmesa
, msk
);
1289 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~RADEON_STENCIL_TEST_MASK
;
1290 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(RADEON_STENCIL_REF_MASK
|
1291 RADEON_STENCIL_VALUE_MASK
);
1293 switch ( ctx
->Stencil
.Function
[0] ) {
1295 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_NEVER
;
1298 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_LESS
;
1301 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_EQUAL
;
1304 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_LEQUAL
;
1307 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_GREATER
;
1310 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_NEQUAL
;
1313 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_GEQUAL
;
1316 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_ALWAYS
;
1320 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1323 static void radeonStencilMask( GLcontext
*ctx
, GLuint mask
)
1325 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1327 RADEON_STATECHANGE( rmesa
, msk
);
1328 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~RADEON_STENCIL_WRITE_MASK
;
1329 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1330 (ctx
->Stencil
.WriteMask
[0] << RADEON_STENCIL_WRITEMASK_SHIFT
);
1333 static void radeonStencilOp( GLcontext
*ctx
, GLenum fail
,
1334 GLenum zfail
, GLenum zpass
)
1336 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1338 RADEON_STATECHANGE( rmesa
, ctx
);
1339 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(RADEON_STENCIL_FAIL_MASK
|
1340 RADEON_STENCIL_ZFAIL_MASK
|
1341 RADEON_STENCIL_ZPASS_MASK
);
1343 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1345 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_KEEP
;
1348 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_ZERO
;
1351 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_REPLACE
;
1354 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_INC
;
1357 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_DEC
;
1360 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_INVERT
;
1364 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1366 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_KEEP
;
1369 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_ZERO
;
1372 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_REPLACE
;
1375 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_INC
;
1378 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_DEC
;
1381 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_INVERT
;
1385 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1387 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_KEEP
;
1390 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_ZERO
;
1393 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_REPLACE
;
1396 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_INC
;
1399 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_DEC
;
1402 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_INVERT
;
1407 static void radeonClearStencil( GLcontext
*ctx
, GLint s
)
1409 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1411 rmesa
->state
.stencil
.clear
=
1412 ((GLuint
) ctx
->Stencil
.Clear
|
1413 (0xff << RADEON_STENCIL_MASK_SHIFT
) |
1414 (ctx
->Stencil
.WriteMask
[0] << RADEON_STENCIL_WRITEMASK_SHIFT
));
1418 /* =============================================================
1419 * Window position and viewport transformation
1423 * To correctly position primitives:
1425 #define SUBPIXEL_X 0.125
1426 #define SUBPIXEL_Y 0.125
1428 void radeonUpdateWindow( GLcontext
*ctx
)
1430 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1431 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1432 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1433 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1434 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1436 GLfloat sx
= v
[MAT_SX
];
1437 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1438 GLfloat sy
= - v
[MAT_SY
];
1439 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1440 GLfloat sz
= v
[MAT_SZ
] * rmesa
->state
.depth
.scale
;
1441 GLfloat tz
= v
[MAT_TZ
] * rmesa
->state
.depth
.scale
;
1442 RADEON_FIREVERTICES( rmesa
);
1443 RADEON_STATECHANGE( rmesa
, vpt
);
1445 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = *(GLuint
*)&sx
;
1446 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1447 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = *(GLuint
*)&sy
;
1448 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1449 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = *(GLuint
*)&sz
;
1450 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = *(GLuint
*)&tz
;
1455 static void radeonViewport( GLcontext
*ctx
, GLint x
, GLint y
,
1456 GLsizei width
, GLsizei height
)
1458 /* Don't pipeline viewport changes, conflict with window offset
1459 * setting below. Could apply deltas to rescue pipelined viewport
1460 * values, or keep the originals hanging around.
1462 RADEON_FIREVERTICES( RADEON_CONTEXT(ctx
) );
1463 radeonUpdateWindow( ctx
);
1466 static void radeonDepthRange( GLcontext
*ctx
, GLclampd nearval
,
1469 radeonUpdateWindow( ctx
);
1472 void radeonUpdateViewportOffset( GLcontext
*ctx
)
1474 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1475 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1476 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1477 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1478 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1480 GLfloat tx
= v
[MAT_TX
] + xoffset
;
1481 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
;
1483 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != *(GLuint
*)&tx
||
1484 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != *(GLuint
*)&ty
)
1486 /* Note: this should also modify whatever data the context reset
1489 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1490 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1492 /* update polygon stipple x/y screen offset */
1495 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1497 m
&= ~(RADEON_STIPPLE_X_OFFSET_MASK
|
1498 RADEON_STIPPLE_Y_OFFSET_MASK
);
1500 /* add magic offsets, then invert */
1501 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & RADEON_STIPPLE_COORD_MASK
);
1502 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1503 & RADEON_STIPPLE_COORD_MASK
);
1505 m
|= ((stx
<< RADEON_STIPPLE_X_OFFSET_SHIFT
) |
1506 (sty
<< RADEON_STIPPLE_Y_OFFSET_SHIFT
));
1508 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1509 RADEON_STATECHANGE( rmesa
, msc
);
1510 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1515 radeonUpdateScissor( ctx
);
1520 /* =============================================================
1524 static void radeonClearColor( GLcontext
*ctx
, const GLfloat color
[4] )
1526 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1528 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
1529 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
1530 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
1531 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
1532 rmesa
->state
.color
.clear
= radeonPackColor( rmesa
->radeonScreen
->cpp
,
1533 c
[0], c
[1], c
[2], c
[3] );
1537 static void radeonRenderMode( GLcontext
*ctx
, GLenum mode
)
1539 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1540 FALLBACK( rmesa
, RADEON_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1544 static GLuint radeon_rop_tab
[] = {
1547 RADEON_ROP_AND_REVERSE
,
1549 RADEON_ROP_AND_INVERTED
,
1556 RADEON_ROP_OR_REVERSE
,
1557 RADEON_ROP_COPY_INVERTED
,
1558 RADEON_ROP_OR_INVERTED
,
1563 static void radeonLogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1565 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1566 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1570 RADEON_STATECHANGE( rmesa
, msk
);
1571 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = radeon_rop_tab
[rop
];
1575 void radeonSetCliprects( radeonContextPtr rmesa
, GLenum mode
)
1577 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1581 rmesa
->numClipRects
= dPriv
->numClipRects
;
1582 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1585 /* Can't ignore 2d windows if we are page flipping.
1587 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1588 rmesa
->numClipRects
= dPriv
->numClipRects
;
1589 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1592 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1593 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pBackClipRects
;
1597 fprintf(stderr
, "bad mode in radeonSetCliprects\n");
1601 if (rmesa
->state
.scissor
.enabled
)
1602 radeonRecalcScissorRects( rmesa
);
1606 static void radeonDrawBuffer( GLcontext
*ctx
, GLenum mode
)
1608 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1610 if (RADEON_DEBUG
& DEBUG_DRI
)
1611 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1612 _mesa_lookup_enum_by_nr( mode
));
1614 RADEON_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1617 * _DrawDestMask is easier to cope with than <mode>.
1619 switch ( ctx
->Color
._DrawDestMask
) {
1620 case FRONT_LEFT_BIT
:
1621 FALLBACK( rmesa
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1622 radeonSetCliprects( rmesa
, GL_FRONT_LEFT
);
1625 FALLBACK( rmesa
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1626 radeonSetCliprects( rmesa
, GL_BACK_LEFT
);
1629 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1630 FALLBACK( rmesa
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1634 /* We want to update the s/w rast state too so that r200SetBuffer()
1637 _swrast_DrawBuffer(ctx
, mode
);
1639 RADEON_STATECHANGE( rmesa
, ctx
);
1640 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = ((rmesa
->state
.color
.drawOffset
+
1641 rmesa
->radeonScreen
->fbLocation
)
1642 & RADEON_COLOROFFSET_MASK
);
1643 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
1646 static void radeonReadBuffer( GLcontext
*ctx
, GLenum mode
)
1648 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1652 /* =============================================================
1653 * State enable/disable
1656 static void radeonEnable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1658 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1661 if ( RADEON_DEBUG
& DEBUG_STATE
)
1662 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1663 _mesa_lookup_enum_by_nr( cap
),
1664 state
? "GL_TRUE" : "GL_FALSE" );
1667 /* Fast track this one...
1675 RADEON_STATECHANGE( rmesa
, ctx
);
1677 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_ALPHA_TEST_ENABLE
;
1679 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_ALPHA_TEST_ENABLE
;
1684 RADEON_STATECHANGE( rmesa
, ctx
);
1686 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_ALPHA_BLEND_ENABLE
;
1688 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_ALPHA_BLEND_ENABLE
;
1690 if ( ctx
->Color
._LogicOpEnabled
) {
1691 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_ROP_ENABLE
;
1693 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_ROP_ENABLE
;
1696 /* Catch a possible fallback:
1699 ctx
->Driver
.BlendEquationSeparate( ctx
,
1700 ctx
->Color
.BlendEquationRGB
,
1701 ctx
->Color
.BlendEquationA
);
1702 ctx
->Driver
.BlendFuncSeparate( ctx
, ctx
->Color
.BlendSrcRGB
,
1703 ctx
->Color
.BlendDstRGB
,
1704 ctx
->Color
.BlendSrcA
,
1705 ctx
->Color
.BlendDstA
);
1708 FALLBACK( rmesa
, RADEON_FALLBACK_BLEND_FUNC
, GL_FALSE
);
1709 FALLBACK( rmesa
, RADEON_FALLBACK_BLEND_EQ
, GL_FALSE
);
1713 case GL_CLIP_PLANE0
:
1714 case GL_CLIP_PLANE1
:
1715 case GL_CLIP_PLANE2
:
1716 case GL_CLIP_PLANE3
:
1717 case GL_CLIP_PLANE4
:
1718 case GL_CLIP_PLANE5
:
1719 p
= cap
-GL_CLIP_PLANE0
;
1720 RADEON_STATECHANGE( rmesa
, tcl
);
1722 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (RADEON_UCP_ENABLE_0
<<p
);
1723 radeonClipPlane( ctx
, cap
, NULL
);
1726 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(RADEON_UCP_ENABLE_0
<<p
);
1730 case GL_COLOR_MATERIAL
:
1731 radeonColorMaterial( ctx
, 0, 0 );
1732 radeonUpdateMaterial( ctx
);
1736 radeonCullFace( ctx
, 0 );
1740 RADEON_STATECHANGE(rmesa
, ctx
);
1742 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_Z_ENABLE
;
1744 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_Z_ENABLE
;
1749 RADEON_STATECHANGE(rmesa
, ctx
);
1751 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_DITHER_ENABLE
;
1752 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1754 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_DITHER_ENABLE
;
1755 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1760 RADEON_STATECHANGE(rmesa
, ctx
);
1762 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_FOG_ENABLE
;
1763 radeonFogfv( ctx
, GL_FOG_MODE
, 0 );
1765 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_FOG_ENABLE
;
1766 RADEON_STATECHANGE(rmesa
, tcl
);
1767 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~RADEON_TCL_FOG_MASK
;
1769 radeonUpdateSpecular( ctx
); /* for PK_SPEC */
1770 if (rmesa
->TclFallback
)
1771 radeonChooseVertexState( ctx
);
1772 _mesa_allow_light_in_model( ctx
, !state
);
1783 RADEON_STATECHANGE(rmesa
, tcl
);
1784 p
= cap
- GL_LIGHT0
;
1786 flag
= (RADEON_LIGHT_1_ENABLE
|
1787 RADEON_LIGHT_1_ENABLE_AMBIENT
|
1788 RADEON_LIGHT_1_ENABLE_SPECULAR
);
1790 flag
= (RADEON_LIGHT_0_ENABLE
|
1791 RADEON_LIGHT_0_ENABLE_AMBIENT
|
1792 RADEON_LIGHT_0_ENABLE_SPECULAR
);
1795 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1797 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1801 update_light_colors( ctx
, p
);
1805 RADEON_STATECHANGE(rmesa
, tcl
);
1806 radeonUpdateSpecular(ctx
);
1807 check_twoside_fallback( ctx
);
1810 case GL_LINE_SMOOTH
:
1811 RADEON_STATECHANGE( rmesa
, ctx
);
1813 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_ANTI_ALIAS_LINE
;
1815 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_ANTI_ALIAS_LINE
;
1819 case GL_LINE_STIPPLE
:
1820 RADEON_STATECHANGE( rmesa
, ctx
);
1822 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_PATTERN_ENABLE
;
1824 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_PATTERN_ENABLE
;
1828 case GL_COLOR_LOGIC_OP
:
1829 RADEON_STATECHANGE( rmesa
, ctx
);
1830 if ( ctx
->Color
._LogicOpEnabled
) {
1831 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_ROP_ENABLE
;
1833 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_ROP_ENABLE
;
1838 RADEON_STATECHANGE( rmesa
, tcl
);
1840 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_NORMALIZE_NORMALS
;
1842 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &= ~RADEON_NORMALIZE_NORMALS
;
1846 case GL_POLYGON_OFFSET_POINT
:
1847 if (rmesa
->dri
.drmMinor
== 1) {
1848 radeonChooseRenderState( ctx
);
1851 RADEON_STATECHANGE( rmesa
, set
);
1853 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_ZBIAS_ENABLE_POINT
;
1855 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~RADEON_ZBIAS_ENABLE_POINT
;
1860 case GL_POLYGON_OFFSET_LINE
:
1861 if (rmesa
->dri
.drmMinor
== 1) {
1862 radeonChooseRenderState( ctx
);
1865 RADEON_STATECHANGE( rmesa
, set
);
1867 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_ZBIAS_ENABLE_LINE
;
1869 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~RADEON_ZBIAS_ENABLE_LINE
;
1874 case GL_POLYGON_OFFSET_FILL
:
1875 if (rmesa
->dri
.drmMinor
== 1) {
1876 radeonChooseRenderState( ctx
);
1879 RADEON_STATECHANGE( rmesa
, set
);
1881 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_ZBIAS_ENABLE_TRI
;
1883 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~RADEON_ZBIAS_ENABLE_TRI
;
1888 case GL_POLYGON_SMOOTH
:
1889 RADEON_STATECHANGE( rmesa
, ctx
);
1891 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_ANTI_ALIAS_POLY
;
1893 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_ANTI_ALIAS_POLY
;
1897 case GL_POLYGON_STIPPLE
:
1898 RADEON_STATECHANGE(rmesa
, ctx
);
1900 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_STIPPLE_ENABLE
;
1902 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_STIPPLE_ENABLE
;
1906 case GL_RESCALE_NORMAL_EXT
: {
1907 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
1908 RADEON_STATECHANGE( rmesa
, tcl
);
1910 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_RESCALE_NORMALS
;
1912 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &= ~RADEON_RESCALE_NORMALS
;
1917 case GL_SCISSOR_TEST
:
1918 RADEON_FIREVERTICES( rmesa
);
1919 rmesa
->state
.scissor
.enabled
= state
;
1920 radeonUpdateScissor( ctx
);
1923 case GL_STENCIL_TEST
:
1924 if ( rmesa
->state
.stencil
.hwBuffer
) {
1925 RADEON_STATECHANGE( rmesa
, ctx
);
1927 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_STENCIL_ENABLE
;
1929 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_STENCIL_ENABLE
;
1932 FALLBACK( rmesa
, RADEON_FALLBACK_STENCIL
, state
);
1936 case GL_TEXTURE_GEN_Q
:
1937 case GL_TEXTURE_GEN_R
:
1938 case GL_TEXTURE_GEN_S
:
1939 case GL_TEXTURE_GEN_T
:
1940 /* Picked up in radeonUpdateTextureState.
1942 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
1945 case GL_COLOR_SUM_EXT
:
1946 radeonUpdateSpecular ( ctx
);
1955 static void radeonLightingSpaceChange( GLcontext
*ctx
)
1957 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1959 RADEON_STATECHANGE( rmesa
, tcl
);
1961 if (RADEON_DEBUG
& DEBUG_STATE
)
1962 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1963 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
]);
1965 if (ctx
->_NeedEyeCoords
)
1966 tmp
= ctx
->Transform
.RescaleNormals
;
1968 tmp
= !ctx
->Transform
.RescaleNormals
;
1971 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_RESCALE_NORMALS
;
1973 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &= ~RADEON_RESCALE_NORMALS
;
1976 if (RADEON_DEBUG
& DEBUG_STATE
)
1977 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1978 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
]);
1981 /* =============================================================
1982 * Deferred state management - matrices, textures, other?
1988 static void upload_matrix( radeonContextPtr rmesa
, GLfloat
*src
, int idx
)
1990 float *dest
= ((float *)RADEON_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
1994 for (i
= 0 ; i
< 4 ; i
++) {
1998 *dest
++ = src
[i
+12];
2001 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2004 static void upload_matrix_t( radeonContextPtr rmesa
, GLfloat
*src
, int idx
)
2006 float *dest
= ((float *)RADEON_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2007 memcpy(dest
, src
, 16*sizeof(float));
2008 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2012 static void update_texturematrix( GLcontext
*ctx
)
2014 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
2015 GLuint tpc
= rmesa
->hw
.tcl
.cmd
[TCL_TEXTURE_PROC_CTL
];
2016 GLuint vs
= rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
];
2019 rmesa
->TexMatEnabled
= 0;
2021 for (unit
= 0 ; unit
< 2; unit
++) {
2022 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
2024 else if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2025 GLuint inputshift
= RADEON_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
2027 rmesa
->TexMatEnabled
|= (RADEON_TEXGEN_TEXMAT_0_ENABLE
|
2028 RADEON_TEXMAT_0_ENABLE
) << unit
;
2030 if (rmesa
->TexGenEnabled
& (RADEON_TEXMAT_0_ENABLE
<< unit
)) {
2031 /* Need to preconcatenate any active texgen
2032 * obj/eyeplane matrices:
2034 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2035 &rmesa
->TexGenMatrix
[unit
],
2036 ctx
->TextureMatrixStack
[unit
].Top
);
2037 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, TEXMAT_0
+unit
);
2040 rmesa
->TexMatEnabled
|=
2041 (RADEON_TEXGEN_INPUT_TEXCOORD_0
+unit
) << inputshift
;
2042 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2046 else if (rmesa
->TexGenEnabled
& (RADEON_TEXMAT_0_ENABLE
<< unit
)) {
2047 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2053 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2055 vs
&= ~((0xf << RADEON_TCL_TEX_0_OUTPUT_SHIFT
) |
2056 (0xf << RADEON_TCL_TEX_1_OUTPUT_SHIFT
));
2058 if (tpc
& RADEON_TEXGEN_TEXMAT_0_ENABLE
)
2059 vs
|= RADEON_TCL_TEX_COMPUTED_TEX_0
<< RADEON_TCL_TEX_0_OUTPUT_SHIFT
;
2061 vs
|= RADEON_TCL_TEX_INPUT_TEX_0
<< RADEON_TCL_TEX_0_OUTPUT_SHIFT
;
2063 if (tpc
& RADEON_TEXGEN_TEXMAT_1_ENABLE
)
2064 vs
|= RADEON_TCL_TEX_COMPUTED_TEX_1
<< RADEON_TCL_TEX_1_OUTPUT_SHIFT
;
2066 vs
|= RADEON_TCL_TEX_INPUT_TEX_1
<< RADEON_TCL_TEX_1_OUTPUT_SHIFT
;
2068 if (tpc
!= rmesa
->hw
.tcl
.cmd
[TCL_TEXTURE_PROC_CTL
] ||
2069 vs
!= rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
]) {
2071 RADEON_STATECHANGE(rmesa
, tcl
);
2072 rmesa
->hw
.tcl
.cmd
[TCL_TEXTURE_PROC_CTL
] = tpc
;
2073 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] = vs
;
2079 void radeonValidateState( GLcontext
*ctx
)
2081 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
2082 GLuint new_state
= rmesa
->NewGLState
;
2084 if (new_state
& _NEW_TEXTURE
) {
2085 radeonUpdateTextureState( ctx
);
2086 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2089 /* Need an event driven matrix update?
2091 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2092 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, MODEL_PROJ
);
2094 /* Need these for lighting (shouldn't upload otherwise)
2096 if (new_state
& (_NEW_MODELVIEW
)) {
2097 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, MODEL
);
2098 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, MODEL_IT
);
2101 /* Does this need to be triggered on eg. modelview for
2102 * texgen-derived objplane/eyeplane matrices?
2104 if (new_state
& _NEW_TEXTURE_MATRIX
) {
2105 update_texturematrix( ctx
);
2108 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2109 update_light( ctx
);
2112 /* emit all active clip planes if projection matrix changes.
2114 if (new_state
& (_NEW_PROJECTION
)) {
2115 if (ctx
->Transform
.ClipPlanesEnabled
)
2116 radeonUpdateClipPlanes( ctx
);
2120 rmesa
->NewGLState
= 0;
2124 static void radeonInvalidateState( GLcontext
*ctx
, GLuint new_state
)
2126 _swrast_InvalidateState( ctx
, new_state
);
2127 _swsetup_InvalidateState( ctx
, new_state
);
2128 _ac_InvalidateState( ctx
, new_state
);
2129 _tnl_InvalidateState( ctx
, new_state
);
2130 _ae_invalidate_state( ctx
, new_state
);
2131 RADEON_CONTEXT(ctx
)->NewGLState
|= new_state
;
2132 radeonVtxfmtInvalidate( ctx
);
2136 /* A hack. Need a faster way to find this out.
2138 static GLboolean
check_material( GLcontext
*ctx
)
2140 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2143 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2144 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2146 if (tnl
->vb
.AttribPtr
[i
] &&
2147 tnl
->vb
.AttribPtr
[i
]->stride
)
2154 static void radeonWrapRunPipeline( GLcontext
*ctx
)
2156 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
2157 GLboolean has_material
;
2160 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2164 if (rmesa
->NewGLState
)
2165 radeonValidateState( ctx
);
2167 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2170 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2173 /* Run the pipeline.
2175 _tnl_run_pipeline( ctx
);
2178 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2183 /* Initialize the driver's state functions.
2185 void radeonInitStateFuncs( GLcontext
*ctx
)
2187 ctx
->Driver
.UpdateState
= radeonInvalidateState
;
2188 ctx
->Driver
.LightingSpaceChange
= radeonLightingSpaceChange
;
2190 ctx
->Driver
.DrawBuffer
= radeonDrawBuffer
;
2191 ctx
->Driver
.ReadBuffer
= radeonReadBuffer
;
2193 ctx
->Driver
.AlphaFunc
= radeonAlphaFunc
;
2194 ctx
->Driver
.BlendEquationSeparate
= radeonBlendEquationSeparate
;
2195 ctx
->Driver
.BlendFuncSeparate
= radeonBlendFuncSeparate
;
2196 ctx
->Driver
.ClearColor
= radeonClearColor
;
2197 ctx
->Driver
.ClearDepth
= radeonClearDepth
;
2198 ctx
->Driver
.ClearIndex
= NULL
;
2199 ctx
->Driver
.ClearStencil
= radeonClearStencil
;
2200 ctx
->Driver
.ClipPlane
= radeonClipPlane
;
2201 ctx
->Driver
.ColorMask
= radeonColorMask
;
2202 ctx
->Driver
.CullFace
= radeonCullFace
;
2203 ctx
->Driver
.DepthFunc
= radeonDepthFunc
;
2204 ctx
->Driver
.DepthMask
= radeonDepthMask
;
2205 ctx
->Driver
.DepthRange
= radeonDepthRange
;
2206 ctx
->Driver
.Enable
= radeonEnable
;
2207 ctx
->Driver
.Fogfv
= radeonFogfv
;
2208 ctx
->Driver
.FrontFace
= radeonFrontFace
;
2209 ctx
->Driver
.Hint
= NULL
;
2210 ctx
->Driver
.IndexMask
= NULL
;
2211 ctx
->Driver
.LightModelfv
= radeonLightModelfv
;
2212 ctx
->Driver
.Lightfv
= radeonLightfv
;
2213 ctx
->Driver
.LineStipple
= radeonLineStipple
;
2214 ctx
->Driver
.LineWidth
= radeonLineWidth
;
2215 ctx
->Driver
.LogicOpcode
= radeonLogicOpCode
;
2216 ctx
->Driver
.PolygonMode
= radeonPolygonMode
;
2218 if (RADEON_CONTEXT(ctx
)->dri
.drmMinor
> 1)
2219 ctx
->Driver
.PolygonOffset
= radeonPolygonOffset
;
2221 ctx
->Driver
.PolygonStipple
= radeonPolygonStipple
;
2222 ctx
->Driver
.RenderMode
= radeonRenderMode
;
2223 ctx
->Driver
.Scissor
= radeonScissor
;
2224 ctx
->Driver
.ShadeModel
= radeonShadeModel
;
2225 ctx
->Driver
.StencilFunc
= radeonStencilFunc
;
2226 ctx
->Driver
.StencilMask
= radeonStencilMask
;
2227 ctx
->Driver
.StencilOp
= radeonStencilOp
;
2228 ctx
->Driver
.Viewport
= radeonViewport
;
2230 /* Pixel path fallbacks
2232 ctx
->Driver
.Accum
= _swrast_Accum
;
2233 ctx
->Driver
.Bitmap
= _swrast_Bitmap
;
2234 ctx
->Driver
.CopyPixels
= _swrast_CopyPixels
;
2235 ctx
->Driver
.DrawPixels
= _swrast_DrawPixels
;
2236 ctx
->Driver
.ReadPixels
= _swrast_ReadPixels
;
2238 /* Swrast hooks for imaging extensions:
2240 ctx
->Driver
.CopyColorTable
= _swrast_CopyColorTable
;
2241 ctx
->Driver
.CopyColorSubTable
= _swrast_CopyColorSubTable
;
2242 ctx
->Driver
.CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2243 ctx
->Driver
.CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2245 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= radeonUpdateMaterial
;
2246 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= radeonWrapRunPipeline
;