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 radeonBlendEquation( GLcontext
*ctx
, GLenum mode
)
107 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
108 GLuint b
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] & ~RADEON_COMB_FCN_MASK
;
109 GLboolean fallback
= GL_FALSE
;
114 b
|= RADEON_COMB_FCN_ADD_CLAMP
;
117 case GL_FUNC_SUBTRACT
:
118 b
|= RADEON_COMB_FCN_SUB_CLAMP
;
122 if (ctx
->Color
.BlendEnabled
)
125 b
|= RADEON_COMB_FCN_ADD_CLAMP
;
129 FALLBACK( rmesa
, RADEON_FALLBACK_BLEND_EQ
, fallback
);
131 RADEON_STATECHANGE( rmesa
, ctx
);
132 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = b
;
133 if ( ctx
->Color
.ColorLogicOpEnabled
) {
134 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_ROP_ENABLE
;
136 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_ROP_ENABLE
;
141 static void radeonBlendFuncSeparate( GLcontext
*ctx
,
142 GLenum sfactorRGB
, GLenum dfactorRGB
,
143 GLenum sfactorA
, GLenum dfactorA
)
145 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
146 GLuint b
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] &
147 ~(RADEON_SRC_BLEND_MASK
| RADEON_DST_BLEND_MASK
);
148 GLboolean fallback
= GL_FALSE
;
150 switch ( ctx
->Color
.BlendSrcRGB
) {
152 b
|= RADEON_SRC_BLEND_GL_ZERO
;
155 b
|= RADEON_SRC_BLEND_GL_ONE
;
158 b
|= RADEON_SRC_BLEND_GL_DST_COLOR
;
160 case GL_ONE_MINUS_DST_COLOR
:
161 b
|= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR
;
164 b
|= RADEON_SRC_BLEND_GL_SRC_COLOR
;
166 case GL_ONE_MINUS_SRC_COLOR
:
167 b
|= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR
;
170 b
|= RADEON_SRC_BLEND_GL_SRC_ALPHA
;
172 case GL_ONE_MINUS_SRC_ALPHA
:
173 b
|= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
176 b
|= RADEON_SRC_BLEND_GL_DST_ALPHA
;
178 case GL_ONE_MINUS_DST_ALPHA
:
179 b
|= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA
;
181 case GL_SRC_ALPHA_SATURATE
:
182 b
|= RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE
;
184 case GL_CONSTANT_COLOR
:
185 case GL_ONE_MINUS_CONSTANT_COLOR
:
186 case GL_CONSTANT_ALPHA
:
187 case GL_ONE_MINUS_CONSTANT_ALPHA
:
188 if (ctx
->Color
.BlendEnabled
)
191 b
|= RADEON_SRC_BLEND_GL_ONE
;
197 switch ( ctx
->Color
.BlendDstRGB
) {
199 b
|= RADEON_DST_BLEND_GL_ZERO
;
202 b
|= RADEON_DST_BLEND_GL_ONE
;
205 b
|= RADEON_DST_BLEND_GL_SRC_COLOR
;
207 case GL_ONE_MINUS_SRC_COLOR
:
208 b
|= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR
;
211 b
|= RADEON_DST_BLEND_GL_SRC_ALPHA
;
213 case GL_ONE_MINUS_SRC_ALPHA
:
214 b
|= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
217 b
|= RADEON_DST_BLEND_GL_DST_COLOR
;
219 case GL_ONE_MINUS_DST_COLOR
:
220 b
|= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR
;
223 b
|= RADEON_DST_BLEND_GL_DST_ALPHA
;
225 case GL_ONE_MINUS_DST_ALPHA
:
226 b
|= RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA
;
228 case GL_CONSTANT_COLOR
:
229 case GL_ONE_MINUS_CONSTANT_COLOR
:
230 case GL_CONSTANT_ALPHA
:
231 case GL_ONE_MINUS_CONSTANT_ALPHA
:
232 if (ctx
->Color
.BlendEnabled
)
235 b
|= RADEON_DST_BLEND_GL_ZERO
;
241 FALLBACK( rmesa
, RADEON_FALLBACK_BLEND_FUNC
, fallback
);
243 RADEON_STATECHANGE( rmesa
, ctx
);
244 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = b
;
249 /* =============================================================
253 static void radeonDepthFunc( GLcontext
*ctx
, GLenum func
)
255 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
257 RADEON_STATECHANGE( rmesa
, ctx
);
258 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~RADEON_Z_TEST_MASK
;
260 switch ( ctx
->Depth
.Func
) {
262 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_NEVER
;
265 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_LESS
;
268 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_EQUAL
;
271 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_LEQUAL
;
274 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_GREATER
;
277 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_NEQUAL
;
280 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_GEQUAL
;
283 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_TEST_ALWAYS
;
289 static void radeonDepthMask( GLcontext
*ctx
, GLboolean flag
)
291 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
292 RADEON_STATECHANGE( rmesa
, ctx
);
294 if ( ctx
->Depth
.Mask
) {
295 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_Z_WRITE_ENABLE
;
297 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~RADEON_Z_WRITE_ENABLE
;
301 static void radeonClearDepth( GLcontext
*ctx
, GLclampd d
)
303 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
304 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
305 RADEON_DEPTH_FORMAT_MASK
);
308 case RADEON_DEPTH_FORMAT_16BIT_INT_Z
:
309 rmesa
->state
.depth
.clear
= d
* 0x0000ffff;
311 case RADEON_DEPTH_FORMAT_24BIT_INT_Z
:
312 rmesa
->state
.depth
.clear
= d
* 0x00ffffff;
318 /* =============================================================
323 static void radeonFogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
325 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
326 union { int i
; float f
; } c
, d
;
329 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
330 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
334 if (!ctx
->Fog
.Enabled
)
336 RADEON_STATECHANGE(rmesa
, tcl
);
337 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~RADEON_TCL_FOG_MASK
;
338 switch (ctx
->Fog
.Mode
) {
340 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= RADEON_TCL_FOG_LINEAR
;
341 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
346 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
347 d
.f
= 1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
351 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= RADEON_TCL_FOG_EXP
;
353 d
.f
= ctx
->Fog
.Density
;
356 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= RADEON_TCL_FOG_EXP2
;
358 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
365 switch (ctx
->Fog
.Mode
) {
368 d
.f
= ctx
->Fog
.Density
;
372 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
380 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
381 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
385 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
386 d
.f
= 1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
391 RADEON_STATECHANGE( rmesa
, ctx
);
392 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
393 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] =
394 radeonPackColor( 4, col
[0], col
[1], col
[2], 0 );
396 case GL_FOG_COORDINATE_SOURCE_EXT
:
404 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
405 RADEON_STATECHANGE( rmesa
, fog
);
406 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
407 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
412 /* =============================================================
417 static GLboolean
intersect_rect( XF86DRIClipRectPtr out
,
418 XF86DRIClipRectPtr a
,
419 XF86DRIClipRectPtr b
)
422 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
423 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
424 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
425 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
426 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
427 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
432 void radeonRecalcScissorRects( radeonContextPtr rmesa
)
434 XF86DRIClipRectPtr out
;
437 /* Grow cliprect store?
439 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
440 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
441 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
442 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
445 if (rmesa
->state
.scissor
.pClipRects
)
446 FREE(rmesa
->state
.scissor
.pClipRects
);
448 rmesa
->state
.scissor
.pClipRects
=
449 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
450 sizeof(XF86DRIClipRectRec
) );
452 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
453 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
458 out
= rmesa
->state
.scissor
.pClipRects
;
459 rmesa
->state
.scissor
.numClipRects
= 0;
461 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
462 if ( intersect_rect( out
,
463 &rmesa
->pClipRects
[i
],
464 &rmesa
->state
.scissor
.rect
) ) {
465 rmesa
->state
.scissor
.numClipRects
++;
472 static void radeonUpdateScissor( GLcontext
*ctx
)
474 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
476 if ( rmesa
->dri
.drawable
) {
477 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
479 int x
= ctx
->Scissor
.X
;
480 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
481 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
482 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
484 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
485 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
486 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
487 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
489 radeonRecalcScissorRects( rmesa
);
494 static void radeonScissor( GLcontext
*ctx
,
495 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
497 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
499 if ( ctx
->Scissor
.Enabled
) {
500 RADEON_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
501 radeonUpdateScissor( ctx
);
507 /* =============================================================
511 static void radeonCullFace( GLcontext
*ctx
, GLenum unused
)
513 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
514 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
515 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
517 s
|= RADEON_FFACE_SOLID
| RADEON_BFACE_SOLID
;
518 t
&= ~(RADEON_CULL_FRONT
| RADEON_CULL_BACK
);
520 if ( ctx
->Polygon
.CullFlag
) {
521 switch ( ctx
->Polygon
.CullFaceMode
) {
523 s
&= ~RADEON_FFACE_SOLID
;
524 t
|= RADEON_CULL_FRONT
;
527 s
&= ~RADEON_BFACE_SOLID
;
528 t
|= RADEON_CULL_BACK
;
530 case GL_FRONT_AND_BACK
:
531 s
&= ~(RADEON_FFACE_SOLID
| RADEON_BFACE_SOLID
);
532 t
|= (RADEON_CULL_FRONT
| RADEON_CULL_BACK
);
537 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
538 RADEON_STATECHANGE(rmesa
, set
);
539 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
542 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
543 RADEON_STATECHANGE(rmesa
, tcl
);
544 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
548 static void radeonFrontFace( GLcontext
*ctx
, GLenum mode
)
550 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
552 RADEON_STATECHANGE( rmesa
, set
);
553 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~RADEON_FFACE_CULL_DIR_MASK
;
555 RADEON_STATECHANGE( rmesa
, tcl
);
556 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~RADEON_CULL_FRONT_IS_CCW
;
560 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_FFACE_CULL_CW
;
563 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_FFACE_CULL_CCW
;
564 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= RADEON_CULL_FRONT_IS_CCW
;
570 /* =============================================================
573 static void radeonLineWidth( GLcontext
*ctx
, GLfloat widthf
)
575 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
577 RADEON_STATECHANGE( rmesa
, lin
);
578 RADEON_STATECHANGE( rmesa
, set
);
580 /* Line width is stored in U6.4 format.
582 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] = (GLuint
)(widthf
* 16.0);
583 if ( widthf
> 1.0 ) {
584 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_WIDELINE_ENABLE
;
586 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~RADEON_WIDELINE_ENABLE
;
590 static void radeonLineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
592 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
594 RADEON_STATECHANGE( rmesa
, lin
);
595 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
596 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
600 /* =============================================================
603 static void radeonColorMask( GLcontext
*ctx
,
604 GLboolean r
, GLboolean g
,
605 GLboolean b
, GLboolean a
)
607 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
608 GLuint mask
= radeonPackColor( rmesa
->radeonScreen
->cpp
,
609 ctx
->Color
.ColorMask
[RCOMP
],
610 ctx
->Color
.ColorMask
[GCOMP
],
611 ctx
->Color
.ColorMask
[BCOMP
],
612 ctx
->Color
.ColorMask
[ACOMP
] );
614 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
615 RADEON_STATECHANGE( rmesa
, msk
);
616 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
621 /* =============================================================
625 static void radeonPolygonOffset( GLcontext
*ctx
,
626 GLfloat factor
, GLfloat units
)
628 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
629 GLfloat constant
= units
* rmesa
->state
.depth
.scale
;
631 RADEON_STATECHANGE( rmesa
, zbs
);
632 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = *(GLuint
*)&factor
;
633 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = *(GLuint
*)&constant
;
636 static void radeonPolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
638 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
640 drmRadeonStipple stipple
;
642 /* Must flip pattern upside down.
644 for ( i
= 0 ; i
< 32 ; i
++ ) {
645 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
648 /* TODO: push this into cmd mechanism
650 RADEON_FIREVERTICES( rmesa
);
651 LOCK_HARDWARE( rmesa
);
653 /* FIXME: Use window x,y offsets into stipple RAM.
655 stipple
.mask
= rmesa
->state
.stipple
.mask
;
656 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
657 &stipple
, sizeof(drmRadeonStipple
) );
658 UNLOCK_HARDWARE( rmesa
);
661 static void radeonPolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
663 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
664 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
666 /* Can't generally do unfilled via tcl, but some good special
669 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_UNFILLED
, flag
);
670 if (rmesa
->TclFallback
) {
671 radeonChooseRenderState( ctx
);
672 radeonChooseVertexState( ctx
);
677 /* =============================================================
678 * Rendering attributes
680 * We really don't want to recalculate all this every time we bind a
681 * texture. These things shouldn't change all that often, so it makes
682 * sense to break them out of the core texture state update routines.
685 /* Examine lighting and texture state to determine if separate specular
688 static void radeonUpdateSpecular( GLcontext
*ctx
)
690 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
691 CARD32 p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
693 RADEON_STATECHANGE( rmesa
, tcl
);
695 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] &= ~RADEON_TCL_COMPUTE_SPECULAR
;
696 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] &= ~RADEON_TCL_COMPUTE_DIFFUSE
;
697 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] &= ~RADEON_TCL_VTX_PK_SPEC
;
698 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] &= ~RADEON_TCL_VTX_PK_DIFFUSE
;
699 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &= ~RADEON_LIGHTING_ENABLE
;
701 p
&= ~RADEON_SPECULAR_ENABLE
;
703 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_DIFFUSE_SPECULAR_COMBINE
;
706 if (ctx
->Light
.Enabled
&&
707 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
708 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] |= RADEON_TCL_COMPUTE_SPECULAR
;
709 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] |= RADEON_TCL_COMPUTE_DIFFUSE
;
710 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_SPEC
;
711 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_DIFFUSE
;
712 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_LIGHTING_ENABLE
;
713 p
|= RADEON_SPECULAR_ENABLE
;
714 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &=
715 ~RADEON_DIFFUSE_SPECULAR_COMBINE
;
717 else if (ctx
->Light
.Enabled
) {
718 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] |= RADEON_TCL_COMPUTE_DIFFUSE
;
719 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_DIFFUSE
;
720 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_LIGHTING_ENABLE
;
721 } else if (ctx
->Fog
.ColorSumEnabled
) {
722 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_SPEC
;
723 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_DIFFUSE
;
724 p
|= RADEON_SPECULAR_ENABLE
;
726 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_DIFFUSE
;
729 if (ctx
->Fog
.Enabled
) {
730 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] |= RADEON_TCL_COMPUTE_SPECULAR
;
731 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_PK_SPEC
;
733 /* Bizzare: have to leave lighting enabled to get fog.
735 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_LIGHTING_ENABLE
;
738 if ( ctx
->_TriangleCaps
& DD_SEPARATE_SPECULAR
) {
739 assert( (p
& RADEON_SPECULAR_ENABLE
) != 0 );
741 assert( (p
& RADEON_SPECULAR_ENABLE
) == 0 );
744 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
745 RADEON_STATECHANGE( rmesa
, ctx
);
746 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
749 /* Update vertex/render formats
751 if (rmesa
->TclFallback
) {
752 radeonChooseRenderState( ctx
);
753 radeonChooseVertexState( ctx
);
758 /* =============================================================
763 /* Update on colormaterial, material emmissive/ambient,
764 * lightmodel.globalambient
766 static void update_global_ambient( GLcontext
*ctx
)
768 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
769 float *fcmd
= (float *)RADEON_DB_STATE( glt
);
771 /* Need to do more if both emmissive & ambient are PREMULT:
773 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &
774 ((3 << RADEON_EMISSIVE_SOURCE_SHIFT
) |
775 (3 << RADEON_AMBIENT_SOURCE_SHIFT
))) == 0)
777 COPY_3V( &fcmd
[GLT_RED
],
778 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
779 ACC_SCALE_3V( &fcmd
[GLT_RED
],
780 ctx
->Light
.Model
.Ambient
,
781 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
785 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
788 RADEON_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
791 /* Update on change to
795 * - colormaterial enabled
796 * - colormaterial bitmask
798 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
800 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
802 /* fprintf(stderr, "%s\n", __FUNCTION__); */
805 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
806 float *fcmd
= (float *)RADEON_DB_STATE( lit
[p
] );
807 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
808 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
810 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
811 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
812 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
814 if (!ctx
->Light
.ColorMaterialEnabled
)
817 if ((bitmask
& MAT_BIT_FRONT_AMBIENT
) == 0)
818 SELF_SCALE_3V( &fcmd
[LIT_AMBIENT_RED
], mat
[MAT_ATTRIB_FRONT_AMBIENT
] );
820 if ((bitmask
& MAT_BIT_FRONT_DIFFUSE
) == 0)
821 SELF_SCALE_3V( &fcmd
[LIT_DIFFUSE_RED
], mat
[MAT_ATTRIB_FRONT_DIFFUSE
] );
823 if ((bitmask
& MAT_BIT_FRONT_SPECULAR
) == 0)
824 SELF_SCALE_3V( &fcmd
[LIT_SPECULAR_RED
], mat
[MAT_ATTRIB_FRONT_SPECULAR
] );
826 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
830 /* Also fallback for asym colormaterial mode in twoside lighting...
832 static void check_twoside_fallback( GLcontext
*ctx
)
834 GLboolean fallback
= GL_FALSE
;
837 if (ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
) {
838 if (ctx
->Light
.ColorMaterialEnabled
&&
839 (ctx
->Light
.ColorMaterialBitmask
& BACK_MATERIAL_BITS
) !=
840 ((ctx
->Light
.ColorMaterialBitmask
& FRONT_MATERIAL_BITS
)<<1))
843 for (i
= MAT_ATTRIB_FRONT_AMBIENT
; i
< MAT_ATTRIB_FRONT_INDEXES
; i
+=2)
844 if (memcmp( ctx
->Light
.Material
.Attrib
[i
],
845 ctx
->Light
.Material
.Attrib
[i
+1],
846 sizeof(GLfloat
)*4) != 0) {
853 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE
, fallback
);
857 static void radeonColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
859 if (ctx
->Light
.ColorMaterialEnabled
) {
860 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
861 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
];
862 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
864 /* Default to PREMULT:
866 light_model_ctl1
&= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT
) |
867 (3 << RADEON_AMBIENT_SOURCE_SHIFT
) |
868 (3 << RADEON_DIFFUSE_SOURCE_SHIFT
) |
869 (3 << RADEON_SPECULAR_SOURCE_SHIFT
));
871 if (mask
& MAT_BIT_FRONT_EMISSION
) {
872 light_model_ctl1
|= (RADEON_LM_SOURCE_VERTEX_DIFFUSE
<<
873 RADEON_EMISSIVE_SOURCE_SHIFT
);
876 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
877 light_model_ctl1
|= (RADEON_LM_SOURCE_VERTEX_DIFFUSE
<<
878 RADEON_AMBIENT_SOURCE_SHIFT
);
881 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
882 light_model_ctl1
|= (RADEON_LM_SOURCE_VERTEX_DIFFUSE
<<
883 RADEON_DIFFUSE_SOURCE_SHIFT
);
886 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
887 light_model_ctl1
|= (RADEON_LM_SOURCE_VERTEX_DIFFUSE
<<
888 RADEON_SPECULAR_SOURCE_SHIFT
);
891 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
]) {
894 RADEON_STATECHANGE( rmesa
, tcl
);
895 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] = light_model_ctl1
;
897 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
898 update_light_colors( ctx
, p
);
899 update_global_ambient( ctx
);
903 check_twoside_fallback( ctx
);
906 void radeonUpdateMaterial( GLcontext
*ctx
)
908 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
909 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
910 GLfloat
*fcmd
= (GLfloat
*)RADEON_DB_STATE( mtl
);
914 if (ctx
->Light
.ColorMaterialEnabled
)
915 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
917 if (RADEON_DEBUG
& DEBUG_STATE
)
918 fprintf(stderr
, "%s\n", __FUNCTION__
);
921 if (mask
& MAT_BIT_FRONT_EMISSION
) {
922 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
923 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
924 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
925 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
927 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
928 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
929 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
930 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
931 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
933 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
934 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
935 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
936 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
937 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
939 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
940 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
941 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
942 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
943 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
945 if (mask
& MAT_BIT_FRONT_SHININESS
) {
946 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
949 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
);
951 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
952 update_light_colors( ctx
, p
);
954 check_twoside_fallback( ctx
);
955 update_global_ambient( ctx
);
960 * _MESA_NEW_NEED_EYE_COORDS
962 * Uses derived state from mesa:
971 * which are calculated in light.c and are correct for the current
972 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
973 * and _MESA_NEW_NEED_EYE_COORDS.
975 static void update_light( GLcontext
*ctx
)
977 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
979 /* Have to check these, or have an automatic shortcircuit mechanism
980 * to remove noop statechanges. (Or just do a better job on the
984 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
];
986 if (ctx
->_NeedEyeCoords
)
987 tmp
&= ~RADEON_LIGHT_IN_MODELSPACE
;
989 tmp
|= RADEON_LIGHT_IN_MODELSPACE
;
992 /* Leave this test disabled: (unexplained q3 lockup) (even with
995 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
])
997 RADEON_STATECHANGE( rmesa
, tcl
);
998 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] = tmp
;
1003 GLfloat
*fcmd
= (GLfloat
*)RADEON_DB_STATE( eye
);
1004 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1005 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1006 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1007 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1008 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1013 if (ctx
->Light
.Enabled
) {
1015 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1016 if (ctx
->Light
.Light
[p
].Enabled
) {
1017 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1018 GLfloat
*fcmd
= (GLfloat
*)RADEON_DB_STATE( lit
[p
] );
1020 if (l
->EyePosition
[3] == 0.0) {
1021 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1022 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1023 fcmd
[LIT_POSITION_W
] = 0;
1024 fcmd
[LIT_DIRECTION_W
] = 0;
1026 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1027 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1028 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1029 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1030 fcmd
[LIT_DIRECTION_W
] = 0;
1033 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1039 static void radeonLightfv( GLcontext
*ctx
, GLenum light
,
1040 GLenum pname
, const GLfloat
*params
)
1042 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1043 GLint p
= light
- GL_LIGHT0
;
1044 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1045 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1052 update_light_colors( ctx
, p
);
1055 case GL_SPOT_DIRECTION
:
1056 /* picked up in update_light */
1060 /* positions picked up in update_light, but can do flag here */
1062 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1064 /* FIXME: Set RANGE_ATTEN only when needed */
1066 flag
= RADEON_LIGHT_1_IS_LOCAL
;
1068 flag
= RADEON_LIGHT_0_IS_LOCAL
;
1070 RADEON_STATECHANGE(rmesa
, tcl
);
1071 if (l
->EyePosition
[3] != 0.0F
)
1072 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1074 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1078 case GL_SPOT_EXPONENT
:
1079 RADEON_STATECHANGE(rmesa
, lit
[p
]);
1080 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1083 case GL_SPOT_CUTOFF
: {
1084 GLuint flag
= (p
&1) ? RADEON_LIGHT_1_IS_SPOT
: RADEON_LIGHT_0_IS_SPOT
;
1085 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1087 RADEON_STATECHANGE(rmesa
, lit
[p
]);
1088 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1090 RADEON_STATECHANGE(rmesa
, tcl
);
1091 if (l
->SpotCutoff
!= 180.0F
)
1092 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1094 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1099 case GL_CONSTANT_ATTENUATION
:
1100 RADEON_STATECHANGE(rmesa
, lit
[p
]);
1101 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1102 if ( params
[0] == 0.0 )
1103 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1105 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1107 case GL_LINEAR_ATTENUATION
:
1108 RADEON_STATECHANGE(rmesa
, lit
[p
]);
1109 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1111 case GL_QUADRATIC_ATTENUATION
:
1112 RADEON_STATECHANGE(rmesa
, lit
[p
]);
1113 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1119 /* Set RANGE_ATTEN only when needed */
1122 case GL_CONSTANT_ATTENUATION
:
1123 case GL_LINEAR_ATTENUATION
:
1124 case GL_QUADRATIC_ATTENUATION
:
1126 GLuint
*icmd
= (GLuint
*)RADEON_DB_STATE( tcl
);
1127 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1128 GLuint atten_flag
= ( p
&1 ) ? RADEON_LIGHT_1_ENABLE_RANGE_ATTEN
1129 : RADEON_LIGHT_0_ENABLE_RANGE_ATTEN
;
1130 GLuint atten_const_flag
= ( p
&1 ) ? RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN
1131 : RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1133 if ( l
->EyePosition
[3] == 0.0F
||
1134 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1135 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1136 /* Disable attenuation */
1137 icmd
[idx
] &= ~atten_flag
;
1139 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1140 /* Enable only constant portion of attenuation calculation */
1141 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1143 /* Enable full attenuation calculation */
1144 icmd
[idx
] &= ~atten_const_flag
;
1145 icmd
[idx
] |= atten_flag
;
1149 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1160 static void radeonLightModelfv( GLcontext
*ctx
, GLenum pname
,
1161 const GLfloat
*param
)
1163 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1166 case GL_LIGHT_MODEL_AMBIENT
:
1167 update_global_ambient( ctx
);
1170 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1171 RADEON_STATECHANGE( rmesa
, tcl
);
1172 if (ctx
->Light
.Model
.LocalViewer
)
1173 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_LOCAL_VIEWER
;
1175 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &= ~RADEON_LOCAL_VIEWER
;
1178 case GL_LIGHT_MODEL_TWO_SIDE
:
1179 RADEON_STATECHANGE( rmesa
, tcl
);
1180 if (ctx
->Light
.Model
.TwoSide
)
1181 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= RADEON_LIGHT_TWOSIDE
;
1183 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~RADEON_LIGHT_TWOSIDE
;
1185 check_twoside_fallback( ctx
);
1187 if (rmesa
->TclFallback
) {
1188 radeonChooseRenderState( ctx
);
1189 radeonChooseVertexState( ctx
);
1193 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1194 radeonUpdateSpecular(ctx
);
1202 static void radeonShadeModel( GLcontext
*ctx
, GLenum mode
)
1204 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1205 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1207 s
&= ~(RADEON_DIFFUSE_SHADE_MASK
|
1208 RADEON_ALPHA_SHADE_MASK
|
1209 RADEON_SPECULAR_SHADE_MASK
|
1210 RADEON_FOG_SHADE_MASK
);
1214 s
|= (RADEON_DIFFUSE_SHADE_FLAT
|
1215 RADEON_ALPHA_SHADE_FLAT
|
1216 RADEON_SPECULAR_SHADE_FLAT
|
1217 RADEON_FOG_SHADE_FLAT
);
1220 s
|= (RADEON_DIFFUSE_SHADE_GOURAUD
|
1221 RADEON_ALPHA_SHADE_GOURAUD
|
1222 RADEON_SPECULAR_SHADE_GOURAUD
|
1223 RADEON_FOG_SHADE_GOURAUD
);
1229 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1230 RADEON_STATECHANGE( rmesa
, set
);
1231 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1236 /* =============================================================
1240 static void radeonClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1242 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1243 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1244 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1246 RADEON_STATECHANGE( rmesa
, ucp
[p
] );
1247 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1248 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1249 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1250 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1253 static void radeonUpdateClipPlanes( GLcontext
*ctx
)
1255 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1258 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1259 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1260 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1262 RADEON_STATECHANGE( rmesa
, ucp
[p
] );
1263 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1264 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1265 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1266 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1272 /* =============================================================
1276 static void radeonStencilFunc( GLcontext
*ctx
, GLenum func
,
1277 GLint ref
, GLuint mask
)
1279 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1280 GLuint refmask
= ((ctx
->Stencil
.Ref
[0] << RADEON_STENCIL_REF_SHIFT
) |
1281 (ctx
->Stencil
.ValueMask
[0] << RADEON_STENCIL_MASK_SHIFT
));
1283 RADEON_STATECHANGE( rmesa
, ctx
);
1284 RADEON_STATECHANGE( rmesa
, msk
);
1286 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~RADEON_STENCIL_TEST_MASK
;
1287 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(RADEON_STENCIL_REF_MASK
|
1288 RADEON_STENCIL_VALUE_MASK
);
1290 switch ( ctx
->Stencil
.Function
[0] ) {
1292 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_NEVER
;
1295 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_LESS
;
1298 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_EQUAL
;
1301 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_LEQUAL
;
1304 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_GREATER
;
1307 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_NEQUAL
;
1310 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_GEQUAL
;
1313 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_TEST_ALWAYS
;
1317 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1320 static void radeonStencilMask( GLcontext
*ctx
, GLuint mask
)
1322 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1324 RADEON_STATECHANGE( rmesa
, msk
);
1325 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~RADEON_STENCIL_WRITE_MASK
;
1326 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1327 (ctx
->Stencil
.WriteMask
[0] << RADEON_STENCIL_WRITEMASK_SHIFT
);
1330 static void radeonStencilOp( GLcontext
*ctx
, GLenum fail
,
1331 GLenum zfail
, GLenum zpass
)
1333 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1335 RADEON_STATECHANGE( rmesa
, ctx
);
1336 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(RADEON_STENCIL_FAIL_MASK
|
1337 RADEON_STENCIL_ZFAIL_MASK
|
1338 RADEON_STENCIL_ZPASS_MASK
);
1340 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1342 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_KEEP
;
1345 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_ZERO
;
1348 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_REPLACE
;
1351 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_INC
;
1354 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_DEC
;
1357 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_FAIL_INVERT
;
1361 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1363 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_KEEP
;
1366 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_ZERO
;
1369 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_REPLACE
;
1372 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_INC
;
1375 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_DEC
;
1378 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZFAIL_INVERT
;
1382 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1384 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_KEEP
;
1387 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_ZERO
;
1390 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_REPLACE
;
1393 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_INC
;
1396 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_DEC
;
1399 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= RADEON_STENCIL_ZPASS_INVERT
;
1404 static void radeonClearStencil( GLcontext
*ctx
, GLint s
)
1406 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1408 rmesa
->state
.stencil
.clear
=
1409 ((GLuint
) ctx
->Stencil
.Clear
|
1410 (0xff << RADEON_STENCIL_MASK_SHIFT
) |
1411 (ctx
->Stencil
.WriteMask
[0] << RADEON_STENCIL_WRITEMASK_SHIFT
));
1415 /* =============================================================
1416 * Window position and viewport transformation
1420 * To correctly position primitives:
1422 #define SUBPIXEL_X 0.125
1423 #define SUBPIXEL_Y 0.125
1425 void radeonUpdateWindow( GLcontext
*ctx
)
1427 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1428 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1429 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1430 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1431 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1433 GLfloat sx
= v
[MAT_SX
];
1434 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1435 GLfloat sy
= - v
[MAT_SY
];
1436 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1437 GLfloat sz
= v
[MAT_SZ
] * rmesa
->state
.depth
.scale
;
1438 GLfloat tz
= v
[MAT_TZ
] * rmesa
->state
.depth
.scale
;
1439 RADEON_FIREVERTICES( rmesa
);
1440 RADEON_STATECHANGE( rmesa
, vpt
);
1442 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = *(GLuint
*)&sx
;
1443 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1444 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = *(GLuint
*)&sy
;
1445 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1446 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = *(GLuint
*)&sz
;
1447 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = *(GLuint
*)&tz
;
1452 static void radeonViewport( GLcontext
*ctx
, GLint x
, GLint y
,
1453 GLsizei width
, GLsizei height
)
1455 /* Don't pipeline viewport changes, conflict with window offset
1456 * setting below. Could apply deltas to rescue pipelined viewport
1457 * values, or keep the originals hanging around.
1459 RADEON_FIREVERTICES( RADEON_CONTEXT(ctx
) );
1460 radeonUpdateWindow( ctx
);
1463 static void radeonDepthRange( GLcontext
*ctx
, GLclampd nearval
,
1466 radeonUpdateWindow( ctx
);
1469 void radeonUpdateViewportOffset( GLcontext
*ctx
)
1471 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1472 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1473 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1474 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1475 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1477 GLfloat tx
= v
[MAT_TX
] + xoffset
;
1478 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
;
1480 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != *(GLuint
*)&tx
||
1481 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != *(GLuint
*)&ty
)
1483 /* Note: this should also modify whatever data the context reset
1486 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1487 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1489 /* update polygon stipple x/y screen offset */
1492 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1494 m
&= ~(RADEON_STIPPLE_X_OFFSET_MASK
|
1495 RADEON_STIPPLE_Y_OFFSET_MASK
);
1497 /* add magic offsets, then invert */
1498 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & RADEON_STIPPLE_COORD_MASK
);
1499 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1500 & RADEON_STIPPLE_COORD_MASK
);
1502 m
|= ((stx
<< RADEON_STIPPLE_X_OFFSET_SHIFT
) |
1503 (sty
<< RADEON_STIPPLE_Y_OFFSET_SHIFT
));
1505 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1506 RADEON_STATECHANGE( rmesa
, msc
);
1507 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1512 radeonUpdateScissor( ctx
);
1517 /* =============================================================
1521 static void radeonClearColor( GLcontext
*ctx
, const GLfloat color
[4] )
1523 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1525 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
1526 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
1527 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
1528 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
1529 rmesa
->state
.color
.clear
= radeonPackColor( rmesa
->radeonScreen
->cpp
,
1530 c
[0], c
[1], c
[2], c
[3] );
1534 static void radeonRenderMode( GLcontext
*ctx
, GLenum mode
)
1536 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1537 FALLBACK( rmesa
, RADEON_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1541 static GLuint radeon_rop_tab
[] = {
1544 RADEON_ROP_AND_REVERSE
,
1546 RADEON_ROP_AND_INVERTED
,
1553 RADEON_ROP_OR_REVERSE
,
1554 RADEON_ROP_COPY_INVERTED
,
1555 RADEON_ROP_OR_INVERTED
,
1560 static void radeonLogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1562 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1563 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1567 RADEON_STATECHANGE( rmesa
, msk
);
1568 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = radeon_rop_tab
[rop
];
1572 void radeonSetCliprects( radeonContextPtr rmesa
, GLenum mode
)
1574 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1578 rmesa
->numClipRects
= dPriv
->numClipRects
;
1579 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1582 /* Can't ignore 2d windows if we are page flipping.
1584 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1585 rmesa
->numClipRects
= dPriv
->numClipRects
;
1586 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1589 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1590 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pBackClipRects
;
1594 fprintf(stderr
, "bad mode in radeonSetCliprects\n");
1598 if (rmesa
->state
.scissor
.enabled
)
1599 radeonRecalcScissorRects( rmesa
);
1603 static void radeonDrawBuffer( GLcontext
*ctx
, GLenum mode
)
1605 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1607 if (RADEON_DEBUG
& DEBUG_DRI
)
1608 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1609 _mesa_lookup_enum_by_nr( mode
));
1611 RADEON_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1614 * _DrawDestMask is easier to cope with than <mode>.
1616 switch ( ctx
->Color
._DrawDestMask
) {
1617 case FRONT_LEFT_BIT
:
1618 FALLBACK( rmesa
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1619 radeonSetCliprects( rmesa
, GL_FRONT_LEFT
);
1622 FALLBACK( rmesa
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1623 radeonSetCliprects( rmesa
, GL_BACK_LEFT
);
1626 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1627 FALLBACK( rmesa
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1631 /* We want to update the s/w rast state too so that r200SetBuffer()
1634 _swrast_DrawBuffer(ctx
, mode
);
1636 RADEON_STATECHANGE( rmesa
, ctx
);
1637 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = ((rmesa
->state
.color
.drawOffset
+
1638 rmesa
->radeonScreen
->fbLocation
)
1639 & RADEON_COLOROFFSET_MASK
);
1640 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
1643 static void radeonReadBuffer( GLcontext
*ctx
, GLenum mode
)
1645 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1649 /* =============================================================
1650 * State enable/disable
1653 static void radeonEnable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1655 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1658 if ( RADEON_DEBUG
& DEBUG_STATE
)
1659 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1660 _mesa_lookup_enum_by_nr( cap
),
1661 state
? "GL_TRUE" : "GL_FALSE" );
1664 /* Fast track this one...
1672 RADEON_STATECHANGE( rmesa
, ctx
);
1674 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_ALPHA_TEST_ENABLE
;
1676 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_ALPHA_TEST_ENABLE
;
1681 RADEON_STATECHANGE( rmesa
, ctx
);
1683 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_ALPHA_BLEND_ENABLE
;
1685 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_ALPHA_BLEND_ENABLE
;
1687 if ( ctx
->Color
.ColorLogicOpEnabled
) {
1688 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_ROP_ENABLE
;
1690 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_ROP_ENABLE
;
1693 /* Catch a possible fallback:
1696 ctx
->Driver
.BlendEquation( ctx
, ctx
->Color
.BlendEquation
);
1697 ctx
->Driver
.BlendFuncSeparate( ctx
, ctx
->Color
.BlendSrcRGB
,
1698 ctx
->Color
.BlendDstRGB
,
1699 ctx
->Color
.BlendSrcRGB
,
1700 ctx
->Color
.BlendDstRGB
);
1703 FALLBACK( rmesa
, RADEON_FALLBACK_BLEND_FUNC
, GL_FALSE
);
1704 FALLBACK( rmesa
, RADEON_FALLBACK_BLEND_EQ
, GL_FALSE
);
1708 case GL_CLIP_PLANE0
:
1709 case GL_CLIP_PLANE1
:
1710 case GL_CLIP_PLANE2
:
1711 case GL_CLIP_PLANE3
:
1712 case GL_CLIP_PLANE4
:
1713 case GL_CLIP_PLANE5
:
1714 p
= cap
-GL_CLIP_PLANE0
;
1715 RADEON_STATECHANGE( rmesa
, tcl
);
1717 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (RADEON_UCP_ENABLE_0
<<p
);
1718 radeonClipPlane( ctx
, cap
, NULL
);
1721 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(RADEON_UCP_ENABLE_0
<<p
);
1725 case GL_COLOR_MATERIAL
:
1726 radeonColorMaterial( ctx
, 0, 0 );
1727 radeonUpdateMaterial( ctx
);
1731 radeonCullFace( ctx
, 0 );
1735 RADEON_STATECHANGE(rmesa
, ctx
);
1737 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_Z_ENABLE
;
1739 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_Z_ENABLE
;
1744 RADEON_STATECHANGE(rmesa
, ctx
);
1746 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_DITHER_ENABLE
;
1747 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1749 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_DITHER_ENABLE
;
1750 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1755 RADEON_STATECHANGE(rmesa
, ctx
);
1757 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_FOG_ENABLE
;
1758 radeonFogfv( ctx
, GL_FOG_MODE
, 0 );
1760 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_FOG_ENABLE
;
1761 RADEON_STATECHANGE(rmesa
, tcl
);
1762 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~RADEON_TCL_FOG_MASK
;
1764 radeonUpdateSpecular( ctx
); /* for PK_SPEC */
1765 if (rmesa
->TclFallback
)
1766 radeonChooseVertexState( ctx
);
1767 _mesa_allow_light_in_model( ctx
, !state
);
1778 RADEON_STATECHANGE(rmesa
, tcl
);
1779 p
= cap
- GL_LIGHT0
;
1781 flag
= (RADEON_LIGHT_1_ENABLE
|
1782 RADEON_LIGHT_1_ENABLE_AMBIENT
|
1783 RADEON_LIGHT_1_ENABLE_SPECULAR
);
1785 flag
= (RADEON_LIGHT_0_ENABLE
|
1786 RADEON_LIGHT_0_ENABLE_AMBIENT
|
1787 RADEON_LIGHT_0_ENABLE_SPECULAR
);
1790 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1792 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1796 update_light_colors( ctx
, p
);
1800 RADEON_STATECHANGE(rmesa
, tcl
);
1801 radeonUpdateSpecular(ctx
);
1802 check_twoside_fallback( ctx
);
1805 case GL_LINE_SMOOTH
:
1806 RADEON_STATECHANGE( rmesa
, ctx
);
1808 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_ANTI_ALIAS_LINE
;
1810 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_ANTI_ALIAS_LINE
;
1814 case GL_LINE_STIPPLE
:
1815 RADEON_STATECHANGE( rmesa
, ctx
);
1817 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_PATTERN_ENABLE
;
1819 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_PATTERN_ENABLE
;
1823 case GL_COLOR_LOGIC_OP
:
1824 RADEON_STATECHANGE( rmesa
, ctx
);
1826 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_ROP_ENABLE
;
1828 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_ROP_ENABLE
;
1833 RADEON_STATECHANGE( rmesa
, tcl
);
1835 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_NORMALIZE_NORMALS
;
1837 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &= ~RADEON_NORMALIZE_NORMALS
;
1841 case GL_POLYGON_OFFSET_POINT
:
1842 if (rmesa
->dri
.drmMinor
== 1) {
1843 radeonChooseRenderState( ctx
);
1846 RADEON_STATECHANGE( rmesa
, set
);
1848 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_ZBIAS_ENABLE_POINT
;
1850 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~RADEON_ZBIAS_ENABLE_POINT
;
1855 case GL_POLYGON_OFFSET_LINE
:
1856 if (rmesa
->dri
.drmMinor
== 1) {
1857 radeonChooseRenderState( ctx
);
1860 RADEON_STATECHANGE( rmesa
, set
);
1862 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_ZBIAS_ENABLE_LINE
;
1864 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~RADEON_ZBIAS_ENABLE_LINE
;
1869 case GL_POLYGON_OFFSET_FILL
:
1870 if (rmesa
->dri
.drmMinor
== 1) {
1871 radeonChooseRenderState( ctx
);
1874 RADEON_STATECHANGE( rmesa
, set
);
1876 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= RADEON_ZBIAS_ENABLE_TRI
;
1878 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~RADEON_ZBIAS_ENABLE_TRI
;
1883 case GL_POLYGON_SMOOTH
:
1884 RADEON_STATECHANGE( rmesa
, ctx
);
1886 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_ANTI_ALIAS_POLY
;
1888 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_ANTI_ALIAS_POLY
;
1892 case GL_POLYGON_STIPPLE
:
1893 RADEON_STATECHANGE(rmesa
, ctx
);
1895 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= RADEON_STIPPLE_ENABLE
;
1897 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~RADEON_STIPPLE_ENABLE
;
1901 case GL_RESCALE_NORMAL_EXT
: {
1902 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
1903 RADEON_STATECHANGE( rmesa
, tcl
);
1905 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_RESCALE_NORMALS
;
1907 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &= ~RADEON_RESCALE_NORMALS
;
1912 case GL_SCISSOR_TEST
:
1913 RADEON_FIREVERTICES( rmesa
);
1914 rmesa
->state
.scissor
.enabled
= state
;
1915 radeonUpdateScissor( ctx
);
1918 case GL_STENCIL_TEST
:
1919 if ( rmesa
->state
.stencil
.hwBuffer
) {
1920 RADEON_STATECHANGE( rmesa
, ctx
);
1922 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= RADEON_STENCIL_ENABLE
;
1924 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~RADEON_STENCIL_ENABLE
;
1927 FALLBACK( rmesa
, RADEON_FALLBACK_STENCIL
, state
);
1931 case GL_TEXTURE_GEN_Q
:
1932 case GL_TEXTURE_GEN_R
:
1933 case GL_TEXTURE_GEN_S
:
1934 case GL_TEXTURE_GEN_T
:
1935 /* Picked up in radeonUpdateTextureState.
1937 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
1940 case GL_COLOR_SUM_EXT
:
1941 radeonUpdateSpecular ( ctx
);
1950 static void radeonLightingSpaceChange( GLcontext
*ctx
)
1952 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1954 RADEON_STATECHANGE( rmesa
, tcl
);
1956 if (RADEON_DEBUG
& DEBUG_STATE
)
1957 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1958 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
]);
1960 if (ctx
->_NeedEyeCoords
)
1961 tmp
= ctx
->Transform
.RescaleNormals
;
1963 tmp
= !ctx
->Transform
.RescaleNormals
;
1966 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] |= RADEON_RESCALE_NORMALS
;
1968 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
] &= ~RADEON_RESCALE_NORMALS
;
1971 if (RADEON_DEBUG
& DEBUG_STATE
)
1972 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1973 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL
]);
1976 /* =============================================================
1977 * Deferred state management - matrices, textures, other?
1983 static void upload_matrix( radeonContextPtr rmesa
, GLfloat
*src
, int idx
)
1985 float *dest
= ((float *)RADEON_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
1989 for (i
= 0 ; i
< 4 ; i
++) {
1993 *dest
++ = src
[i
+12];
1996 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
1999 static void upload_matrix_t( radeonContextPtr rmesa
, GLfloat
*src
, int idx
)
2001 float *dest
= ((float *)RADEON_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2002 memcpy(dest
, src
, 16*sizeof(float));
2003 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2007 static void update_texturematrix( GLcontext
*ctx
)
2009 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
2010 GLuint tpc
= rmesa
->hw
.tcl
.cmd
[TCL_TEXTURE_PROC_CTL
];
2011 GLuint vs
= rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
];
2014 rmesa
->TexMatEnabled
= 0;
2016 for (unit
= 0 ; unit
< 2; unit
++) {
2017 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
2019 else if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2020 GLuint inputshift
= RADEON_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
2022 rmesa
->TexMatEnabled
|= (RADEON_TEXGEN_TEXMAT_0_ENABLE
|
2023 RADEON_TEXMAT_0_ENABLE
) << unit
;
2025 if (rmesa
->TexGenEnabled
& (RADEON_TEXMAT_0_ENABLE
<< unit
)) {
2026 /* Need to preconcatenate any active texgen
2027 * obj/eyeplane matrices:
2029 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2030 &rmesa
->TexGenMatrix
[unit
],
2031 ctx
->TextureMatrixStack
[unit
].Top
);
2032 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, TEXMAT_0
+unit
);
2035 rmesa
->TexMatEnabled
|=
2036 (RADEON_TEXGEN_INPUT_TEXCOORD_0
+unit
) << inputshift
;
2037 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2041 else if (rmesa
->TexGenEnabled
& (RADEON_TEXMAT_0_ENABLE
<< unit
)) {
2042 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2048 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2050 vs
&= ~((0xf << RADEON_TCL_TEX_0_OUTPUT_SHIFT
) |
2051 (0xf << RADEON_TCL_TEX_1_OUTPUT_SHIFT
));
2053 if (tpc
& RADEON_TEXGEN_TEXMAT_0_ENABLE
)
2054 vs
|= RADEON_TCL_TEX_COMPUTED_TEX_0
<< RADEON_TCL_TEX_0_OUTPUT_SHIFT
;
2056 vs
|= RADEON_TCL_TEX_INPUT_TEX_0
<< RADEON_TCL_TEX_0_OUTPUT_SHIFT
;
2058 if (tpc
& RADEON_TEXGEN_TEXMAT_1_ENABLE
)
2059 vs
|= RADEON_TCL_TEX_COMPUTED_TEX_1
<< RADEON_TCL_TEX_1_OUTPUT_SHIFT
;
2061 vs
|= RADEON_TCL_TEX_INPUT_TEX_1
<< RADEON_TCL_TEX_1_OUTPUT_SHIFT
;
2063 if (tpc
!= rmesa
->hw
.tcl
.cmd
[TCL_TEXTURE_PROC_CTL
] ||
2064 vs
!= rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
]) {
2066 RADEON_STATECHANGE(rmesa
, tcl
);
2067 rmesa
->hw
.tcl
.cmd
[TCL_TEXTURE_PROC_CTL
] = tpc
;
2068 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXSEL
] = vs
;
2074 void radeonValidateState( GLcontext
*ctx
)
2076 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
2077 GLuint new_state
= rmesa
->NewGLState
;
2079 if (new_state
& _NEW_TEXTURE
) {
2080 radeonUpdateTextureState( ctx
);
2081 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2084 /* Need an event driven matrix update?
2086 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2087 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, MODEL_PROJ
);
2089 /* Need these for lighting (shouldn't upload otherwise)
2091 if (new_state
& (_NEW_MODELVIEW
)) {
2092 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, MODEL
);
2093 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, MODEL_IT
);
2096 /* Does this need to be triggered on eg. modelview for
2097 * texgen-derived objplane/eyeplane matrices?
2099 if (new_state
& _NEW_TEXTURE_MATRIX
) {
2100 update_texturematrix( ctx
);
2103 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2104 update_light( ctx
);
2107 /* emit all active clip planes if projection matrix changes.
2109 if (new_state
& (_NEW_PROJECTION
)) {
2110 if (ctx
->Transform
.ClipPlanesEnabled
)
2111 radeonUpdateClipPlanes( ctx
);
2115 rmesa
->NewGLState
= 0;
2119 static void radeonInvalidateState( GLcontext
*ctx
, GLuint new_state
)
2121 _swrast_InvalidateState( ctx
, new_state
);
2122 _swsetup_InvalidateState( ctx
, new_state
);
2123 _ac_InvalidateState( ctx
, new_state
);
2124 _tnl_InvalidateState( ctx
, new_state
);
2125 _ae_invalidate_state( ctx
, new_state
);
2126 RADEON_CONTEXT(ctx
)->NewGLState
|= new_state
;
2127 radeonVtxfmtInvalidate( ctx
);
2131 /* A hack. Need a faster way to find this out.
2133 static GLboolean
check_material( GLcontext
*ctx
)
2135 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2138 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2139 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2141 if (tnl
->vb
.AttribPtr
[i
] &&
2142 tnl
->vb
.AttribPtr
[i
]->stride
)
2149 static void radeonWrapRunPipeline( GLcontext
*ctx
)
2151 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
2152 GLboolean has_material
;
2155 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2159 if (rmesa
->NewGLState
)
2160 radeonValidateState( ctx
);
2162 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2165 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2168 /* Run the pipeline.
2170 _tnl_run_pipeline( ctx
);
2173 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2178 /* Initialize the driver's state functions.
2180 void radeonInitStateFuncs( GLcontext
*ctx
)
2182 ctx
->Driver
.UpdateState
= radeonInvalidateState
;
2183 ctx
->Driver
.LightingSpaceChange
= radeonLightingSpaceChange
;
2185 ctx
->Driver
.DrawBuffer
= radeonDrawBuffer
;
2186 ctx
->Driver
.ReadBuffer
= radeonReadBuffer
;
2188 ctx
->Driver
.AlphaFunc
= radeonAlphaFunc
;
2189 ctx
->Driver
.BlendEquation
= radeonBlendEquation
;
2190 ctx
->Driver
.BlendFuncSeparate
= radeonBlendFuncSeparate
;
2191 ctx
->Driver
.ClearColor
= radeonClearColor
;
2192 ctx
->Driver
.ClearDepth
= radeonClearDepth
;
2193 ctx
->Driver
.ClearIndex
= NULL
;
2194 ctx
->Driver
.ClearStencil
= radeonClearStencil
;
2195 ctx
->Driver
.ClipPlane
= radeonClipPlane
;
2196 ctx
->Driver
.ColorMask
= radeonColorMask
;
2197 ctx
->Driver
.CullFace
= radeonCullFace
;
2198 ctx
->Driver
.DepthFunc
= radeonDepthFunc
;
2199 ctx
->Driver
.DepthMask
= radeonDepthMask
;
2200 ctx
->Driver
.DepthRange
= radeonDepthRange
;
2201 ctx
->Driver
.Enable
= radeonEnable
;
2202 ctx
->Driver
.Fogfv
= radeonFogfv
;
2203 ctx
->Driver
.FrontFace
= radeonFrontFace
;
2204 ctx
->Driver
.Hint
= NULL
;
2205 ctx
->Driver
.IndexMask
= NULL
;
2206 ctx
->Driver
.LightModelfv
= radeonLightModelfv
;
2207 ctx
->Driver
.Lightfv
= radeonLightfv
;
2208 ctx
->Driver
.LineStipple
= radeonLineStipple
;
2209 ctx
->Driver
.LineWidth
= radeonLineWidth
;
2210 ctx
->Driver
.LogicOpcode
= radeonLogicOpCode
;
2211 ctx
->Driver
.PolygonMode
= radeonPolygonMode
;
2213 if (RADEON_CONTEXT(ctx
)->dri
.drmMinor
> 1)
2214 ctx
->Driver
.PolygonOffset
= radeonPolygonOffset
;
2216 ctx
->Driver
.PolygonStipple
= radeonPolygonStipple
;
2217 ctx
->Driver
.RenderMode
= radeonRenderMode
;
2218 ctx
->Driver
.Scissor
= radeonScissor
;
2219 ctx
->Driver
.ShadeModel
= radeonShadeModel
;
2220 ctx
->Driver
.StencilFunc
= radeonStencilFunc
;
2221 ctx
->Driver
.StencilMask
= radeonStencilMask
;
2222 ctx
->Driver
.StencilOp
= radeonStencilOp
;
2223 ctx
->Driver
.Viewport
= radeonViewport
;
2225 /* Pixel path fallbacks
2227 ctx
->Driver
.Accum
= _swrast_Accum
;
2228 ctx
->Driver
.Bitmap
= _swrast_Bitmap
;
2229 ctx
->Driver
.CopyPixels
= _swrast_CopyPixels
;
2230 ctx
->Driver
.DrawPixels
= _swrast_DrawPixels
;
2231 ctx
->Driver
.ReadPixels
= _swrast_ReadPixels
;
2233 /* Swrast hooks for imaging extensions:
2235 ctx
->Driver
.CopyColorTable
= _swrast_CopyColorTable
;
2236 ctx
->Driver
.CopyColorSubTable
= _swrast_CopyColorSubTable
;
2237 ctx
->Driver
.CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2238 ctx
->Driver
.CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2240 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= radeonUpdateMaterial
;
2241 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= radeonWrapRunPipeline
;