1 /**************************************************************************
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Keith Whitwell <keith@tungstengraphics.com>
36 #include "main/glheader.h"
37 #include "main/imports.h"
38 #include "main/api_arrayelt.h"
39 #include "main/enums.h"
40 #include "main/colormac.h"
41 #include "main/light.h"
42 #include "main/framebuffer.h"
44 #include "swrast/swrast.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
49 #include "drivers/common/meta.h"
51 #include "radeon_common.h"
52 #include "radeon_mipmap_tree.h"
53 #include "r200_context.h"
54 #include "r200_ioctl.h"
55 #include "r200_state.h"
58 #include "r200_swtcl.h"
59 #include "r200_vertprog.h"
62 /* =============================================================
66 static void r200AlphaFunc( struct gl_context
*ctx
, GLenum func
, GLfloat ref
)
68 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
69 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
72 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
74 R200_STATECHANGE( rmesa
, ctx
);
76 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
77 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
81 pp_misc
|= R200_ALPHA_TEST_FAIL
;
84 pp_misc
|= R200_ALPHA_TEST_LESS
;
87 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
90 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
93 pp_misc
|= R200_ALPHA_TEST_GREATER
;
96 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
99 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
102 pp_misc
|= R200_ALPHA_TEST_PASS
;
106 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
109 static void r200BlendColor( struct gl_context
*ctx
, const GLfloat cf
[4] )
112 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
113 R200_STATECHANGE( rmesa
, ctx
);
114 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
115 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
116 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
117 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
118 if (rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
)
119 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = radeonPackColor( 4, color
[0], color
[1], color
[2], color
[3] );
123 * Calculate the hardware blend factor setting. This same function is used
124 * for source and destination of both alpha and RGB.
127 * The hardware register value for the specified blend factor. This value
128 * will need to be shifted into the correct position for either source or
129 * destination factor.
132 * Since the two cases where source and destination are handled differently
133 * are essentially error cases, they should never happen. Determine if these
134 * cases can be removed.
136 static int blend_factor( GLenum factor
, GLboolean is_src
)
142 func
= R200_BLEND_GL_ZERO
;
145 func
= R200_BLEND_GL_ONE
;
148 func
= R200_BLEND_GL_DST_COLOR
;
150 case GL_ONE_MINUS_DST_COLOR
:
151 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
154 func
= R200_BLEND_GL_SRC_COLOR
;
156 case GL_ONE_MINUS_SRC_COLOR
:
157 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
160 func
= R200_BLEND_GL_SRC_ALPHA
;
162 case GL_ONE_MINUS_SRC_ALPHA
:
163 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
166 func
= R200_BLEND_GL_DST_ALPHA
;
168 case GL_ONE_MINUS_DST_ALPHA
:
169 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
171 case GL_SRC_ALPHA_SATURATE
:
172 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
174 case GL_CONSTANT_COLOR
:
175 func
= R200_BLEND_GL_CONST_COLOR
;
177 case GL_ONE_MINUS_CONSTANT_COLOR
:
178 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
180 case GL_CONSTANT_ALPHA
:
181 func
= R200_BLEND_GL_CONST_ALPHA
;
183 case GL_ONE_MINUS_CONSTANT_ALPHA
:
184 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
187 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
193 * Sets both the blend equation and the blend function.
194 * This is done in a single
195 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
196 * change the interpretation of the blend function.
197 * Also, make sure that blend function and blend equation are set to their default
198 * value if color blending is not enabled, since at least blend equations GL_MIN
199 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
202 static void r200_set_blend_state( struct gl_context
* ctx
)
204 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
205 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
206 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
208 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
209 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
210 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
211 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
212 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
213 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
215 R200_STATECHANGE( rmesa
, ctx
);
217 if (rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
) {
218 if (ctx
->Color
.ColorLogicOpEnabled
) {
219 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
220 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
221 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
223 } else if (ctx
->Color
.BlendEnabled
) {
224 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
;
227 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
228 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
229 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
234 if (ctx
->Color
.ColorLogicOpEnabled
) {
235 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
236 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
238 } else if (ctx
->Color
.BlendEnabled
) {
239 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
;
242 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
243 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
248 func
= (blend_factor( ctx
->Color
.Blend
[0].SrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
249 (blend_factor( ctx
->Color
.Blend
[0].DstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
251 switch(ctx
->Color
.Blend
[0].EquationRGB
) {
253 eqn
= R200_COMB_FCN_ADD_CLAMP
;
256 case GL_FUNC_SUBTRACT
:
257 eqn
= R200_COMB_FCN_SUB_CLAMP
;
260 case GL_FUNC_REVERSE_SUBTRACT
:
261 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
265 eqn
= R200_COMB_FCN_MIN
;
266 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
267 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
271 eqn
= R200_COMB_FCN_MAX
;
272 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
273 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
277 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
278 __FUNCTION__
, __LINE__
, ctx
->Color
.Blend
[0].EquationRGB
);
282 if (!rmesa
->radeon
.radeonScreen
->drmSupportsBlendColor
) {
283 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
287 funcA
= (blend_factor( ctx
->Color
.Blend
[0].SrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
288 (blend_factor( ctx
->Color
.Blend
[0].DstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
290 switch(ctx
->Color
.Blend
[0].EquationA
) {
292 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
295 case GL_FUNC_SUBTRACT
:
296 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
299 case GL_FUNC_REVERSE_SUBTRACT
:
300 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
304 eqnA
= R200_COMB_FCN_MIN
;
305 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
306 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
310 eqnA
= R200_COMB_FCN_MAX
;
311 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
312 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
316 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
317 __FUNCTION__
, __LINE__
, ctx
->Color
.Blend
[0].EquationA
);
321 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
322 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
326 static void r200BlendEquationSeparate( struct gl_context
*ctx
,
327 GLenum modeRGB
, GLenum modeA
)
329 r200_set_blend_state( ctx
);
332 static void r200BlendFuncSeparate( struct gl_context
*ctx
,
333 GLenum sfactorRGB
, GLenum dfactorRGB
,
334 GLenum sfactorA
, GLenum dfactorA
)
336 r200_set_blend_state( ctx
);
340 /* =============================================================
344 static void r200DepthFunc( struct gl_context
*ctx
, GLenum func
)
346 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
348 R200_STATECHANGE( rmesa
, ctx
);
349 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
351 switch ( ctx
->Depth
.Func
) {
353 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
356 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
359 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
362 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
365 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
368 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
371 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
374 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
379 static void r200ClearDepth( struct gl_context
*ctx
, GLclampd d
)
381 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
382 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
383 R200_DEPTH_FORMAT_MASK
);
386 case R200_DEPTH_FORMAT_16BIT_INT_Z
:
387 rmesa
->radeon
.state
.depth
.clear
= d
* 0x0000ffff;
389 case R200_DEPTH_FORMAT_24BIT_INT_Z
:
390 rmesa
->radeon
.state
.depth
.clear
= d
* 0x00ffffff;
395 static void r200DepthMask( struct gl_context
*ctx
, GLboolean flag
)
397 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
398 R200_STATECHANGE( rmesa
, ctx
);
400 if ( ctx
->Depth
.Mask
) {
401 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
403 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
408 /* =============================================================
413 static void r200Fogfv( struct gl_context
*ctx
, GLenum pname
, const GLfloat
*param
)
415 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
416 union { int i
; float f
; } c
, d
;
420 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
421 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
425 if (!ctx
->Fog
.Enabled
)
427 R200_STATECHANGE(rmesa
, tcl
);
428 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
429 switch (ctx
->Fog
.Mode
) {
431 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
432 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
437 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
438 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
442 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
444 d
.f
= -ctx
->Fog
.Density
;
447 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
449 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
456 switch (ctx
->Fog
.Mode
) {
459 d
.f
= -ctx
->Fog
.Density
;
463 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
471 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
472 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
476 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
477 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
482 R200_STATECHANGE( rmesa
, ctx
);
483 _mesa_unclamped_float_rgba_to_ubyte(col
, ctx
->Fog
.Color
);
484 i
= radeonPackColor( 4, col
[0], col
[1], col
[2], 0 );
485 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
486 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
488 case GL_FOG_COORD_SRC
: {
489 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
490 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
492 fog
&= ~R200_FOG_USE_MASK
;
493 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
|| ctx
->VertexProgram
.Enabled
) {
494 fog
|= R200_FOG_USE_VTX_FOG
;
495 out_0
|= R200_VTX_DISCRETE_FOG
;
498 fog
|= R200_FOG_USE_SPEC_ALPHA
;
499 out_0
&= ~R200_VTX_DISCRETE_FOG
;
502 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
503 R200_STATECHANGE( rmesa
, ctx
);
504 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
507 if (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
]) {
508 R200_STATECHANGE( rmesa
, vtx
);
509 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
518 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
519 R200_STATECHANGE( rmesa
, fog
);
520 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
521 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
525 /* =============================================================
529 static void r200CullFace( struct gl_context
*ctx
, GLenum unused
)
531 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
532 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
533 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
535 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
536 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
538 if ( ctx
->Polygon
.CullFlag
) {
539 switch ( ctx
->Polygon
.CullFaceMode
) {
541 s
&= ~R200_FFACE_SOLID
;
542 t
|= R200_CULL_FRONT
;
545 s
&= ~R200_BFACE_SOLID
;
548 case GL_FRONT_AND_BACK
:
549 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
550 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
555 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
556 R200_STATECHANGE(rmesa
, set
);
557 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
560 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
561 R200_STATECHANGE(rmesa
, tcl
);
562 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
566 static void r200FrontFace( struct gl_context
*ctx
, GLenum mode
)
568 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
570 R200_STATECHANGE( rmesa
, set
);
571 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
573 R200_STATECHANGE( rmesa
, tcl
);
574 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
576 /* Winding is inverted when rendering to FBO */
577 if (ctx
->DrawBuffer
&& ctx
->DrawBuffer
->Name
)
578 mode
= (mode
== GL_CW
) ? GL_CCW
: GL_CW
;
582 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
585 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
586 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
591 /* =============================================================
594 static void r200PointSize( struct gl_context
*ctx
, GLfloat size
)
596 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
597 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
599 radeon_print(RADEON_STATE
, RADEON_TRACE
,
600 "%s(%p) size: %f, fixed point result: %d.%d (%d/16)\n",
602 ((GLuint
)(ctx
->Point
.Size
* 16.0))/16,
603 (((GLuint
)(ctx
->Point
.Size
* 16.0))&15)*100/16,
604 ((GLuint
)(ctx
->Point
.Size
* 16.0))&15);
606 R200_STATECHANGE( rmesa
, cst
);
607 R200_STATECHANGE( rmesa
, ptp
);
608 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
609 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
610 /* this is the size param of the point size calculation (point size reg value
611 is not used when calculation is active). */
612 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
615 static void r200PointParameter( struct gl_context
*ctx
, GLenum pname
, const GLfloat
*params
)
617 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
618 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
621 case GL_POINT_SIZE_MIN
:
622 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
623 R200_STATECHANGE( rmesa
, lin
);
624 R200_STATECHANGE( rmesa
, ptp
);
625 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
626 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
627 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
629 case GL_POINT_SIZE_MAX
:
630 R200_STATECHANGE( rmesa
, cst
);
631 R200_STATECHANGE( rmesa
, ptp
);
632 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
633 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
634 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
636 case GL_POINT_DISTANCE_ATTENUATION
:
637 R200_STATECHANGE( rmesa
, vtx
);
638 R200_STATECHANGE( rmesa
, spr
);
639 R200_STATECHANGE( rmesa
, ptp
);
640 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
641 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
642 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
643 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
644 r200ValidateState looks like overkill */
645 if (ctx
->Point
.Params
[0] != 1.0 ||
646 ctx
->Point
.Params
[1] != 0.0 ||
647 ctx
->Point
.Params
[2] != 0.0 ||
648 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
649 /* all we care for vp would be the ps_se_sel_state setting */
650 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
651 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
652 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
653 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
654 if (ctx
->Point
.Params
[1] == 0.0)
655 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
656 /* FIXME: setting this here doesn't look quite ok - we only want to do
657 that if we're actually drawing points probably */
658 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
659 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
662 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
663 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
664 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
665 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
668 case GL_POINT_FADE_THRESHOLD_SIZE
:
669 /* don't support multisampling, so doesn't matter. */
671 /* can't do these but don't need them.
672 case GL_POINT_SPRITE_R_MODE_NV:
673 case GL_POINT_SPRITE_COORD_ORIGIN: */
675 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
680 /* =============================================================
683 static void r200LineWidth( struct gl_context
*ctx
, GLfloat widthf
)
685 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
687 R200_STATECHANGE( rmesa
, lin
);
688 R200_STATECHANGE( rmesa
, set
);
690 /* Line width is stored in U6.4 format.
691 * Same min/max limits for AA, non-AA lines.
693 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
694 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)
695 (CLAMP(widthf
, ctx
->Const
.MinLineWidth
, ctx
->Const
.MaxLineWidth
) * 16.0);
697 if ( widthf
> 1.0 ) {
698 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
700 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
704 static void r200LineStipple( struct gl_context
*ctx
, GLint factor
, GLushort pattern
)
706 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
708 R200_STATECHANGE( rmesa
, lin
);
709 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
710 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
714 /* =============================================================
717 static void r200ColorMask( struct gl_context
*ctx
,
718 GLboolean r
, GLboolean g
,
719 GLboolean b
, GLboolean a
)
721 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
723 struct radeon_renderbuffer
*rrb
;
724 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
726 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
729 mask
= radeonPackColor( rrb
->cpp
,
730 ctx
->Color
.ColorMask
[0][RCOMP
],
731 ctx
->Color
.ColorMask
[0][GCOMP
],
732 ctx
->Color
.ColorMask
[0][BCOMP
],
733 ctx
->Color
.ColorMask
[0][ACOMP
] );
736 if (!(r
&& g
&& b
&& a
))
737 flag
|= R200_PLANE_MASK_ENABLE
;
739 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
740 R200_STATECHANGE( rmesa
, ctx
);
741 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
744 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
745 R200_STATECHANGE( rmesa
, msk
);
746 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
751 /* =============================================================
755 static void r200PolygonOffset( struct gl_context
*ctx
,
756 GLfloat factor
, GLfloat units
)
758 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
759 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
760 float_ui32_type constant
= { units
* depthScale
};
761 float_ui32_type factoru
= { factor
};
766 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
768 R200_STATECHANGE( rmesa
, zbs
);
769 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
770 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
773 static void r200PolygonMode( struct gl_context
*ctx
, GLenum face
, GLenum mode
)
775 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
776 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
778 /* Can't generally do unfilled via tcl, but some good special
781 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
782 if (rmesa
->radeon
.TclFallback
) {
783 r200ChooseRenderState( ctx
);
784 r200ChooseVertexState( ctx
);
789 /* =============================================================
790 * Rendering attributes
792 * We really don't want to recalculate all this every time we bind a
793 * texture. These things shouldn't change all that often, so it makes
794 * sense to break them out of the core texture state update routines.
797 /* Examine lighting and texture state to determine if separate specular
800 static void r200UpdateSpecular( struct gl_context
*ctx
)
802 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
803 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
805 R200_STATECHANGE( rmesa
, tcl
);
806 R200_STATECHANGE( rmesa
, vtx
);
808 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
809 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
810 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
811 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
812 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
814 p
&= ~R200_SPECULAR_ENABLE
;
816 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
819 if (ctx
->Light
.Enabled
&&
820 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
821 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
822 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
823 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
824 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
825 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
826 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
827 p
|= R200_SPECULAR_ENABLE
;
828 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
829 ~R200_DIFFUSE_SPECULAR_COMBINE
;
831 else if (ctx
->Light
.Enabled
) {
832 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
833 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
834 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
835 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
836 } else if (ctx
->Fog
.ColorSumEnabled
) {
837 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
838 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
839 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
840 p
|= R200_SPECULAR_ENABLE
;
842 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
843 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
846 if (ctx
->Fog
.Enabled
) {
847 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
848 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
849 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
852 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
853 R200_STATECHANGE( rmesa
, ctx
);
854 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
857 /* Update vertex/render formats
859 if (rmesa
->radeon
.TclFallback
) {
860 r200ChooseRenderState( ctx
);
861 r200ChooseVertexState( ctx
);
866 /* =============================================================
871 /* Update on colormaterial, material emmissive/ambient,
872 * lightmodel.globalambient
874 static void update_global_ambient( struct gl_context
*ctx
)
876 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
877 float *fcmd
= (float *)R200_DB_STATE( glt
);
879 /* Need to do more if both emmissive & ambient are PREMULT:
880 * I believe this is not nessary when using source_material. This condition thus
881 * will never happen currently, and the function has no dependencies on materials now
883 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
884 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
885 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
887 COPY_3V( &fcmd
[GLT_RED
],
888 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
889 ACC_SCALE_3V( &fcmd
[GLT_RED
],
890 ctx
->Light
.Model
.Ambient
,
891 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
895 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
898 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
901 /* Update on change to
905 static void update_light_colors( struct gl_context
*ctx
, GLuint p
)
907 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
909 /* fprintf(stderr, "%s\n", __FUNCTION__); */
912 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
913 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
915 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
916 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
917 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
919 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
923 static void r200ColorMaterial( struct gl_context
*ctx
, GLenum face
, GLenum mode
)
925 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
926 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
927 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
928 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
929 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
930 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
931 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
932 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
933 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
934 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
936 if (ctx
->Light
.ColorMaterialEnabled
) {
937 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
939 if (mask
& MAT_BIT_FRONT_EMISSION
) {
940 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
941 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
944 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
945 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
947 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
948 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
949 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
952 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
953 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
955 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
956 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
957 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
960 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
961 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
963 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
964 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
965 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
968 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
969 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
972 if (mask
& MAT_BIT_BACK_EMISSION
) {
973 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
974 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
977 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
978 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
980 if (mask
& MAT_BIT_BACK_AMBIENT
) {
981 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
982 R200_BACK_AMBIENT_SOURCE_SHIFT
);
984 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
985 R200_BACK_AMBIENT_SOURCE_SHIFT
);
987 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
988 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
989 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
991 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
992 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
994 if (mask
& MAT_BIT_BACK_SPECULAR
) {
995 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
996 R200_BACK_SPECULAR_SOURCE_SHIFT
);
999 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1000 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1004 /* Default to SOURCE_MATERIAL:
1007 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1008 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1009 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1010 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1011 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1012 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1013 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1014 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1017 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1018 R200_STATECHANGE( rmesa
, tcl
);
1019 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1025 void r200UpdateMaterial( struct gl_context
*ctx
)
1027 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1028 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1029 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1030 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1033 /* Might be possible and faster to update everything unconditionally? */
1034 if (ctx
->Light
.ColorMaterialEnabled
)
1035 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1037 if (R200_DEBUG
& RADEON_STATE
)
1038 fprintf(stderr
, "%s\n", __FUNCTION__
);
1040 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1041 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1042 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1043 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1044 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1046 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1047 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1048 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1049 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1050 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1052 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1053 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1054 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1055 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1056 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1058 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1059 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1060 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1061 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1062 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1064 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1065 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1068 if (mask
& MAT_BIT_BACK_EMISSION
) {
1069 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1070 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1071 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1072 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1074 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1075 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1076 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1077 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1078 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1080 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1081 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1082 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1083 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1084 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1086 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1087 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1088 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1089 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1090 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1092 if (mask
& MAT_BIT_BACK_SHININESS
) {
1093 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1096 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1097 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1099 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1100 update_global_ambient( ctx ); */
1105 * _MESA_NEW_NEED_EYE_COORDS
1107 * Uses derived state from mesa:
1111 * _NormSpotDirection
1112 * _ModelViewInvScale
1116 * which are calculated in light.c and are correct for the current
1117 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1118 * and _MESA_NEW_NEED_EYE_COORDS.
1120 static void update_light( struct gl_context
*ctx
)
1122 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1124 /* Have to check these, or have an automatic shortcircuit mechanism
1125 * to remove noop statechanges. (Or just do a better job on the
1129 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1131 if (ctx
->_NeedEyeCoords
)
1132 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1134 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1136 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1138 R200_STATECHANGE( rmesa
, tcl
);
1139 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1144 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1145 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1146 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1147 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1148 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1149 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1154 if (ctx
->Light
.Enabled
) {
1156 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1157 if (ctx
->Light
.Light
[p
].Enabled
) {
1158 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1159 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1161 if (l
->EyePosition
[3] == 0.0) {
1162 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1163 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1164 fcmd
[LIT_POSITION_W
] = 0;
1165 fcmd
[LIT_DIRECTION_W
] = 0;
1167 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1168 fcmd
[LIT_DIRECTION_X
] = -l
->_NormSpotDirection
[0];
1169 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormSpotDirection
[1];
1170 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormSpotDirection
[2];
1171 fcmd
[LIT_DIRECTION_W
] = 0;
1174 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1180 static void r200Lightfv( struct gl_context
*ctx
, GLenum light
,
1181 GLenum pname
, const GLfloat
*params
)
1183 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1184 GLint p
= light
- GL_LIGHT0
;
1185 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1186 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1193 update_light_colors( ctx
, p
);
1196 case GL_SPOT_DIRECTION
:
1197 /* picked up in update_light */
1201 /* positions picked up in update_light, but can do flag here */
1202 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1203 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1205 R200_STATECHANGE(rmesa
, tcl
);
1206 if (l
->EyePosition
[3] != 0.0F
)
1207 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1209 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1213 case GL_SPOT_EXPONENT
:
1214 R200_STATECHANGE(rmesa
, lit
[p
]);
1215 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1218 case GL_SPOT_CUTOFF
: {
1219 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1220 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1222 R200_STATECHANGE(rmesa
, lit
[p
]);
1223 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1225 R200_STATECHANGE(rmesa
, tcl
);
1226 if (l
->SpotCutoff
!= 180.0F
)
1227 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1229 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1234 case GL_CONSTANT_ATTENUATION
:
1235 R200_STATECHANGE(rmesa
, lit
[p
]);
1236 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1237 if ( params
[0] == 0.0 )
1238 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1240 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1242 case GL_LINEAR_ATTENUATION
:
1243 R200_STATECHANGE(rmesa
, lit
[p
]);
1244 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1246 case GL_QUADRATIC_ATTENUATION
:
1247 R200_STATECHANGE(rmesa
, lit
[p
]);
1248 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1254 /* Set RANGE_ATTEN only when needed */
1257 case GL_CONSTANT_ATTENUATION
:
1258 case GL_LINEAR_ATTENUATION
:
1259 case GL_QUADRATIC_ATTENUATION
: {
1260 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1261 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1262 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1263 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1264 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1265 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1267 if ( l
->EyePosition
[3] == 0.0F
||
1268 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1269 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1270 /* Disable attenuation */
1271 icmd
[idx
] &= ~atten_flag
;
1273 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1274 /* Enable only constant portion of attenuation calculation */
1275 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1277 /* Enable full attenuation calculation */
1278 icmd
[idx
] &= ~atten_const_flag
;
1279 icmd
[idx
] |= atten_flag
;
1283 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1291 static void r200UpdateLocalViewer ( struct gl_context
*ctx
)
1293 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1294 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1295 for these and only these modes). This means specular highlights may turn out
1296 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1297 is not set, though it seems to happen rarely and the effect seems quite
1298 subtle. May need TCL fallback to fix it completely, though I'm not sure
1299 how you'd identify the cases where the specular highlights indeed will
1300 be wrong. Don't know if fglrx does something special in that case.
1302 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1303 R200_STATECHANGE( rmesa
, tcl
);
1304 if (ctx
->Light
.Model
.LocalViewer
||
1305 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1306 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1308 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1311 static void r200LightModelfv( struct gl_context
*ctx
, GLenum pname
,
1312 const GLfloat
*param
)
1314 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1317 case GL_LIGHT_MODEL_AMBIENT
:
1318 update_global_ambient( ctx
);
1321 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1322 r200UpdateLocalViewer( ctx
);
1325 case GL_LIGHT_MODEL_TWO_SIDE
:
1326 R200_STATECHANGE( rmesa
, tcl
);
1327 if (ctx
->Light
.Model
.TwoSide
)
1328 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1330 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1331 if (rmesa
->radeon
.TclFallback
) {
1332 r200ChooseRenderState( ctx
);
1333 r200ChooseVertexState( ctx
);
1337 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1338 r200UpdateSpecular(ctx
);
1346 static void r200ShadeModel( struct gl_context
*ctx
, GLenum mode
)
1348 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1349 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1351 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1352 R200_ALPHA_SHADE_MASK
|
1353 R200_SPECULAR_SHADE_MASK
|
1354 R200_FOG_SHADE_MASK
|
1355 R200_DISC_FOG_SHADE_MASK
);
1359 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1360 R200_ALPHA_SHADE_FLAT
|
1361 R200_SPECULAR_SHADE_FLAT
|
1362 R200_FOG_SHADE_FLAT
|
1363 R200_DISC_FOG_SHADE_FLAT
);
1366 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1367 R200_ALPHA_SHADE_GOURAUD
|
1368 R200_SPECULAR_SHADE_GOURAUD
|
1369 R200_FOG_SHADE_GOURAUD
|
1370 R200_DISC_FOG_SHADE_GOURAUD
);
1376 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1377 R200_STATECHANGE( rmesa
, set
);
1378 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1383 /* =============================================================
1387 static void r200ClipPlane( struct gl_context
*ctx
, GLenum plane
, const GLfloat
*eq
)
1389 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1390 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1391 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1393 R200_STATECHANGE( rmesa
, ucp
[p
] );
1394 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1395 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1396 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1397 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1400 static void r200UpdateClipPlanes( struct gl_context
*ctx
)
1402 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1405 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1406 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1407 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1409 R200_STATECHANGE( rmesa
, ucp
[p
] );
1410 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1411 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1412 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1413 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1419 /* =============================================================
1424 r200StencilFuncSeparate( struct gl_context
*ctx
, GLenum face
, GLenum func
,
1425 GLint ref
, GLuint mask
)
1427 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1428 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1429 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1431 R200_STATECHANGE( rmesa
, ctx
);
1432 R200_STATECHANGE( rmesa
, msk
);
1434 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1435 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1436 R200_STENCIL_VALUE_MASK
);
1438 switch ( ctx
->Stencil
.Function
[0] ) {
1440 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1443 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1446 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1449 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1452 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1455 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1458 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1461 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1465 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1469 r200StencilMaskSeparate( struct gl_context
*ctx
, GLenum face
, GLuint mask
)
1471 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1473 R200_STATECHANGE( rmesa
, msk
);
1474 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1475 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1476 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1480 r200StencilOpSeparate( struct gl_context
*ctx
, GLenum face
, GLenum fail
,
1481 GLenum zfail
, GLenum zpass
)
1483 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1485 R200_STATECHANGE( rmesa
, ctx
);
1486 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1487 R200_STENCIL_ZFAIL_MASK
|
1488 R200_STENCIL_ZPASS_MASK
);
1490 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1492 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1495 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1498 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1501 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1504 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1506 case GL_INCR_WRAP_EXT
:
1507 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1509 case GL_DECR_WRAP_EXT
:
1510 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1513 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1517 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1519 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1522 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1525 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1528 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1531 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1533 case GL_INCR_WRAP_EXT
:
1534 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1536 case GL_DECR_WRAP_EXT
:
1537 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1540 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1544 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1546 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1549 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1552 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1555 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1558 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1560 case GL_INCR_WRAP_EXT
:
1561 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1563 case GL_DECR_WRAP_EXT
:
1564 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1567 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1572 static void r200ClearStencil( struct gl_context
*ctx
, GLint s
)
1574 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1576 rmesa
->radeon
.state
.stencil
.clear
=
1577 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1578 (0xff << R200_STENCIL_MASK_SHIFT
) |
1579 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1583 /* =============================================================
1584 * Window position and viewport transformation
1588 * Called when window size or position changes or viewport or depth range
1589 * state is changed. We update the hardware viewport state here.
1591 void r200UpdateWindow( struct gl_context
*ctx
)
1593 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1594 __DRIdrawable
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1595 GLfloat xoffset
= dPriv
? (GLfloat
) dPriv
->x
: 0;
1596 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->y
+ dPriv
->h
: 0;
1597 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1598 const GLboolean render_to_fbo
= (ctx
->DrawBuffer
? (ctx
->DrawBuffer
->Name
!= 0) : 0);
1599 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
1600 GLfloat y_scale
, y_bias
;
1602 if (render_to_fbo
) {
1610 float_ui32_type sx
= { v
[MAT_SX
] };
1611 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
};
1612 float_ui32_type sy
= { v
[MAT_SY
] * y_scale
};
1613 float_ui32_type ty
= { (v
[MAT_TY
] * y_scale
) + y_bias
};
1614 float_ui32_type sz
= { v
[MAT_SZ
] * depthScale
};
1615 float_ui32_type tz
= { v
[MAT_TZ
] * depthScale
};
1617 R200_STATECHANGE( rmesa
, vpt
);
1619 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1620 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1621 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1622 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1623 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1624 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1627 void r200_vtbl_update_scissor( struct gl_context
*ctx
)
1629 r200ContextPtr r200
= R200_CONTEXT(ctx
);
1630 unsigned x1
, y1
, x2
, y2
;
1631 struct radeon_renderbuffer
*rrb
;
1633 R200_SET_STATE(r200
, set
, SET_RE_CNTL
, R200_SCISSOR_ENABLE
| r200
->hw
.set
.cmd
[SET_RE_CNTL
]);
1635 if (r200
->radeon
.state
.scissor
.enabled
) {
1636 x1
= r200
->radeon
.state
.scissor
.rect
.x1
;
1637 y1
= r200
->radeon
.state
.scissor
.rect
.y1
;
1638 x2
= r200
->radeon
.state
.scissor
.rect
.x2
;
1639 y2
= r200
->radeon
.state
.scissor
.rect
.y2
;
1641 rrb
= radeon_get_colorbuffer(&r200
->radeon
);
1644 x2
= rrb
->base
.Width
- 1;
1645 y2
= rrb
->base
.Height
- 1;
1648 R200_SET_STATE(r200
, sci
, SCI_XY_1
, x1
| (y1
<< 16));
1649 R200_SET_STATE(r200
, sci
, SCI_XY_2
, x2
| (y2
<< 16));
1653 static void r200Viewport( struct gl_context
*ctx
, GLint x
, GLint y
,
1654 GLsizei width
, GLsizei height
)
1656 /* Don't pipeline viewport changes, conflict with window offset
1657 * setting below. Could apply deltas to rescue pipelined viewport
1658 * values, or keep the originals hanging around.
1660 r200UpdateWindow( ctx
);
1662 radeon_viewport(ctx
, x
, y
, width
, height
);
1665 static void r200DepthRange( struct gl_context
*ctx
, GLclampd nearval
,
1668 r200UpdateWindow( ctx
);
1671 void r200UpdateViewportOffset( struct gl_context
*ctx
)
1673 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1674 __DRIdrawable
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1675 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1676 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1677 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1682 tx
.f
= v
[MAT_TX
] + xoffset
;
1683 ty
.f
= (- v
[MAT_TY
]) + yoffset
;
1685 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1686 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1688 /* Note: this should also modify whatever data the context reset
1691 R200_STATECHANGE( rmesa
, vpt
);
1692 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1693 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1695 /* update polygon stipple x/y screen offset */
1698 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1700 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1701 R200_STIPPLE_Y_OFFSET_MASK
);
1703 /* add magic offsets, then invert */
1704 stx
= 31 - ((dPriv
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1705 sty
= 31 - ((dPriv
->y
+ dPriv
->h
- 1)
1706 & R200_STIPPLE_COORD_MASK
);
1708 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1709 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1711 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1712 R200_STATECHANGE( rmesa
, msc
);
1713 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1718 radeonUpdateScissor( ctx
);
1723 /* =============================================================
1727 static void r200ClearColor( struct gl_context
*ctx
,
1728 const union gl_color_union c
)
1730 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1732 struct radeon_renderbuffer
*rrb
;
1734 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
1737 _mesa_unclamped_float_rgba_to_ubyte(color
, c
.f
);
1738 rmesa
->radeon
.state
.color
.clear
= radeonPackColor( rrb
->cpp
,
1740 color
[2], color
[3] );
1744 static void r200RenderMode( struct gl_context
*ctx
, GLenum mode
)
1746 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1747 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1751 static GLuint r200_rop_tab
[] = {
1754 R200_ROP_AND_REVERSE
,
1756 R200_ROP_AND_INVERTED
,
1763 R200_ROP_OR_REVERSE
,
1764 R200_ROP_COPY_INVERTED
,
1765 R200_ROP_OR_INVERTED
,
1770 static void r200LogicOpCode( struct gl_context
*ctx
, GLenum opcode
)
1772 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1773 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1777 R200_STATECHANGE( rmesa
, msk
);
1778 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1781 /* =============================================================
1782 * State enable/disable
1785 static void r200Enable( struct gl_context
*ctx
, GLenum cap
, GLboolean state
)
1787 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1790 if ( R200_DEBUG
& RADEON_STATE
)
1791 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1792 _mesa_lookup_enum_by_nr( cap
),
1793 state
? "GL_TRUE" : "GL_FALSE" );
1796 /* Fast track this one...
1804 R200_STATECHANGE( rmesa
, ctx
);
1806 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1808 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1813 case GL_COLOR_LOGIC_OP
:
1814 r200_set_blend_state( ctx
);
1817 case GL_CLIP_PLANE0
:
1818 case GL_CLIP_PLANE1
:
1819 case GL_CLIP_PLANE2
:
1820 case GL_CLIP_PLANE3
:
1821 case GL_CLIP_PLANE4
:
1822 case GL_CLIP_PLANE5
:
1823 p
= cap
-GL_CLIP_PLANE0
;
1824 R200_STATECHANGE( rmesa
, tcl
);
1826 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1827 r200ClipPlane( ctx
, cap
, NULL
);
1830 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1834 case GL_COLOR_MATERIAL
:
1835 r200ColorMaterial( ctx
, 0, 0 );
1836 r200UpdateMaterial( ctx
);
1840 r200CullFace( ctx
, 0 );
1844 R200_STATECHANGE(rmesa
, ctx
);
1846 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1848 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1853 R200_STATECHANGE(rmesa
, ctx
);
1855 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1856 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1858 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1859 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1864 R200_STATECHANGE(rmesa
, ctx
);
1866 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1867 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1869 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1870 R200_STATECHANGE(rmesa
, tcl
);
1871 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1873 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1874 if (rmesa
->radeon
.TclFallback
)
1875 r200ChooseVertexState( ctx
);
1876 _mesa_allow_light_in_model( ctx
, !state
);
1887 R200_STATECHANGE(rmesa
, tcl
);
1888 p
= cap
- GL_LIGHT0
;
1890 flag
= (R200_LIGHT_1_ENABLE
|
1891 R200_LIGHT_1_ENABLE_AMBIENT
|
1892 R200_LIGHT_1_ENABLE_SPECULAR
);
1894 flag
= (R200_LIGHT_0_ENABLE
|
1895 R200_LIGHT_0_ENABLE_AMBIENT
|
1896 R200_LIGHT_0_ENABLE_SPECULAR
);
1899 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1901 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1905 update_light_colors( ctx
, p
);
1909 r200UpdateSpecular(ctx
);
1910 /* for reflection map fixup - might set recheck_texgen for all units too */
1911 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1914 case GL_LINE_SMOOTH
:
1915 R200_STATECHANGE( rmesa
, ctx
);
1917 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1919 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1923 case GL_LINE_STIPPLE
:
1924 R200_STATECHANGE( rmesa
, set
);
1926 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1928 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1933 R200_STATECHANGE( rmesa
, tcl
);
1935 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1937 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1941 /* Pointsize registers on r200 only work for point sprites, and point smooth
1942 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1943 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1944 * is enough to satisfy conform.
1946 case GL_POINT_SMOOTH
:
1949 /* These don't really do anything, as we don't use the 3vtx
1953 case GL_POLYGON_OFFSET_POINT
:
1954 R200_STATECHANGE( rmesa
, set
);
1956 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1958 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1962 case GL_POLYGON_OFFSET_LINE
:
1963 R200_STATECHANGE( rmesa
, set
);
1965 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1967 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1972 case GL_POINT_SPRITE_ARB
:
1973 R200_STATECHANGE( rmesa
, spr
);
1976 for (i
= 0; i
< 6; i
++) {
1977 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
1978 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
1981 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
1985 case GL_POLYGON_OFFSET_FILL
:
1986 R200_STATECHANGE( rmesa
, set
);
1988 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1990 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1994 case GL_POLYGON_SMOOTH
:
1995 R200_STATECHANGE( rmesa
, ctx
);
1997 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
1999 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2003 case GL_POLYGON_STIPPLE
:
2004 R200_STATECHANGE(rmesa
, set
);
2006 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2008 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2012 case GL_RESCALE_NORMAL_EXT
: {
2013 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2014 R200_STATECHANGE( rmesa
, tcl
);
2016 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2018 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2023 case GL_SCISSOR_TEST
:
2024 radeon_firevertices(&rmesa
->radeon
);
2025 rmesa
->radeon
.state
.scissor
.enabled
= state
;
2026 radeonUpdateScissor( ctx
);
2029 case GL_STENCIL_TEST
:
2031 GLboolean hw_stencil
= GL_FALSE
;
2032 if (ctx
->DrawBuffer
) {
2033 struct radeon_renderbuffer
*rrbStencil
2034 = radeon_get_renderbuffer(ctx
->DrawBuffer
, BUFFER_STENCIL
);
2035 hw_stencil
= (rrbStencil
&& rrbStencil
->bo
);
2039 R200_STATECHANGE( rmesa
, ctx
);
2041 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2043 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2046 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2051 case GL_TEXTURE_GEN_Q
:
2052 case GL_TEXTURE_GEN_R
:
2053 case GL_TEXTURE_GEN_S
:
2054 case GL_TEXTURE_GEN_T
:
2055 /* Picked up in r200UpdateTextureState.
2057 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2060 case GL_COLOR_SUM_EXT
:
2061 r200UpdateSpecular ( ctx
);
2064 case GL_VERTEX_PROGRAM_ARB
:
2067 rmesa
->curr_vp_hw
= NULL
;
2068 R200_STATECHANGE( rmesa
, vap
);
2069 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2070 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2071 not sure about tcl scalar state - we need at least grd
2072 with vert progs too.
2073 ucp looks like it doesn't get overwritten (may even work
2074 with vp for pos-invariant progs if we're lucky) */
2075 R200_STATECHANGE( rmesa
, mtl
[0] );
2076 R200_STATECHANGE( rmesa
, mtl
[1] );
2077 R200_STATECHANGE( rmesa
, fog
);
2078 R200_STATECHANGE( rmesa
, glt
);
2079 R200_STATECHANGE( rmesa
, eye
);
2080 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2081 R200_STATECHANGE( rmesa
, mat
[i
] );
2083 for (i
= 0 ; i
< 8; i
++) {
2084 R200_STATECHANGE( rmesa
, lit
[i
] );
2086 R200_STATECHANGE( rmesa
, tcl
);
2087 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2088 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2089 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2092 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2095 /* ugly. Need to call everything which might change compsel. */
2096 r200UpdateSpecular( ctx
);
2098 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2099 but without it doom3 locks up at always the same places. Why? */
2100 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2101 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2102 r200UpdateTextureState( ctx
);
2103 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2104 non-current derived enabled values which may revert the state atoms for frag progs even when
2105 they already got disabled... ugh
2106 Should really figure out why we need to call r200UpdateTextureState in the first place */
2108 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2109 R200_STATECHANGE( rmesa
, pix
[unit
] );
2110 R200_STATECHANGE( rmesa
, tex
[unit
] );
2111 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2112 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2113 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2114 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2115 we don't announce ATI_fs, right? */
2116 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2118 R200_STATECHANGE( rmesa
, cst
);
2119 R200_STATECHANGE( rmesa
, tf
);
2120 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2124 /* picked up later */
2126 /* call functions which change hw state based on ARB_vp enabled or not. */
2127 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2128 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2131 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2132 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2135 case GL_FRAGMENT_SHADER_ATI
:
2137 /* restore normal tex env colors and make sure tex env combine will get updated
2138 mark env atoms dirty (as their data was overwritten by afs even
2139 if they didn't change) and restore tex coord routing */
2141 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2142 R200_STATECHANGE( rmesa
, pix
[unit
] );
2143 R200_STATECHANGE( rmesa
, tex
[unit
] );
2144 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2145 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2146 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2147 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2148 we don't announce ATI_fs, right? */
2149 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2151 R200_STATECHANGE( rmesa
, cst
);
2152 R200_STATECHANGE( rmesa
, tf
);
2153 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2156 /* need to mark this dirty as pix/tf atoms have overwritten the data
2157 even if the data in the atoms didn't change */
2158 R200_STATECHANGE( rmesa
, atf
);
2159 R200_STATECHANGE( rmesa
, afs
[1] );
2160 /* everything else picked up in r200UpdateTextureState hopefully */
2169 void r200LightingSpaceChange( struct gl_context
*ctx
)
2171 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2174 if (R200_DEBUG
& RADEON_STATE
)
2175 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2176 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2178 if (ctx
->_NeedEyeCoords
)
2179 tmp
= ctx
->Transform
.RescaleNormals
;
2181 tmp
= !ctx
->Transform
.RescaleNormals
;
2183 R200_STATECHANGE( rmesa
, tcl
);
2185 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2187 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2190 if (R200_DEBUG
& RADEON_STATE
)
2191 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2192 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2195 /* =============================================================
2196 * Deferred state management - matrices, textures, other?
2202 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2204 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2208 for (i
= 0 ; i
< 4 ; i
++) {
2212 *dest
++ = src
[i
+12];
2215 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2218 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2220 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2221 memcpy(dest
, src
, 16*sizeof(float));
2222 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2226 static void update_texturematrix( struct gl_context
*ctx
)
2228 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2229 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2230 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2233 if (R200_DEBUG
& RADEON_STATE
)
2234 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2235 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2237 rmesa
->TexMatEnabled
= 0;
2238 rmesa
->TexMatCompSel
= 0;
2240 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2241 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2244 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2245 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2246 R200_TEXMAT_0_ENABLE
) << unit
;
2248 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2250 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2251 /* Need to preconcatenate any active texgen
2252 * obj/eyeplane matrices:
2254 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2255 ctx
->TextureMatrixStack
[unit
].Top
,
2256 &rmesa
->TexGenMatrix
[unit
] );
2257 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2260 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2261 R200_MTX_TEX0
+unit
);
2264 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2265 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2266 R200_MTX_TEX0
+unit
);
2270 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2271 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2272 R200_STATECHANGE(rmesa
, tcg
);
2273 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2276 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2277 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2278 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2279 R200_STATECHANGE(rmesa
, vtx
);
2280 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2284 static GLboolean
r200ValidateBuffers(struct gl_context
*ctx
)
2286 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2287 struct radeon_renderbuffer
*rrb
;
2288 struct radeon_dma_bo
*dma_bo
;
2291 if (RADEON_DEBUG
& RADEON_IOCTL
)
2292 fprintf(stderr
, "%s\n", __FUNCTION__
);
2293 radeon_cs_space_reset_bos(rmesa
->radeon
.cmdbuf
.cs
);
2295 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
2297 if (rrb
&& rrb
->bo
) {
2298 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2299 0, RADEON_GEM_DOMAIN_VRAM
);
2303 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2305 if (rrb
&& rrb
->bo
) {
2306 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2307 0, RADEON_GEM_DOMAIN_VRAM
);
2310 for (i
= 0; i
< ctx
->Const
.MaxTextureImageUnits
; ++i
) {
2313 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
2316 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2317 if (t
->image_override
&& t
->bo
)
2318 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->bo
,
2319 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2321 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->mt
->bo
,
2322 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2325 dma_bo
= first_elem(&rmesa
->radeon
.dma
.reserved
);
2327 ret
= radeon_cs_space_check_with_bo(rmesa
->radeon
.cmdbuf
.cs
, dma_bo
->bo
, RADEON_GEM_DOMAIN_GTT
, 0);
2334 GLboolean
r200ValidateState( struct gl_context
*ctx
)
2336 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2337 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2339 if (new_state
& _NEW_BUFFERS
) {
2340 _mesa_update_framebuffer(ctx
);
2341 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2342 _mesa_update_draw_buffer_bounds(ctx
);
2344 R200_STATECHANGE(rmesa
, ctx
);
2347 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
)) {
2348 r200UpdateTextureState( ctx
);
2349 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2350 r200UpdateLocalViewer( ctx
);
2353 /* we need to do a space check here */
2354 if (!r200ValidateBuffers(ctx
))
2357 /* FIXME: don't really need most of these when vertex progs are enabled */
2359 /* Need an event driven matrix update?
2361 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2362 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2364 /* Need these for lighting (shouldn't upload otherwise)
2366 if (new_state
& (_NEW_MODELVIEW
)) {
2367 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2368 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2371 /* Does this need to be triggered on eg. modelview for
2372 * texgen-derived objplane/eyeplane matrices?
2374 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2375 update_texturematrix( ctx
);
2378 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2379 update_light( ctx
);
2382 /* emit all active clip planes if projection matrix changes.
2384 if (new_state
& (_NEW_PROJECTION
)) {
2385 if (ctx
->Transform
.ClipPlanesEnabled
)
2386 r200UpdateClipPlanes( ctx
);
2389 if (new_state
& (_NEW_PROGRAM
|
2390 _NEW_PROGRAM_CONSTANTS
|
2391 /* need to test for pretty much anything due to possible parameter bindings */
2392 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2393 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2394 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2395 if (ctx
->VertexProgram
._Enabled
) {
2396 r200SetupVertexProg( ctx
);
2398 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2401 rmesa
->radeon
.NewGLState
= 0;
2406 static void r200InvalidateState( struct gl_context
*ctx
, GLuint new_state
)
2408 _swrast_InvalidateState( ctx
, new_state
);
2409 _swsetup_InvalidateState( ctx
, new_state
);
2410 _vbo_InvalidateState( ctx
, new_state
);
2411 _tnl_InvalidateState( ctx
, new_state
);
2412 _ae_invalidate_state( ctx
, new_state
);
2413 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2416 /* A hack. The r200 can actually cope just fine with materials
2417 * between begin/ends, so fix this.
2418 * Should map to inputs just like the generic vertex arrays for vertex progs.
2419 * In theory there could still be too many and we'd still need a fallback.
2421 static GLboolean
check_material( struct gl_context
*ctx
)
2423 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2426 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2427 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2429 if (tnl
->vb
.AttribPtr
[i
] &&
2430 tnl
->vb
.AttribPtr
[i
]->stride
)
2436 static void r200WrapRunPipeline( struct gl_context
*ctx
)
2438 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2439 GLboolean has_material
;
2442 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->radeon
.NewGLState
);
2446 if (rmesa
->radeon
.NewGLState
)
2447 if (!r200ValidateState( ctx
))
2448 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2450 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2453 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2456 /* Run the pipeline.
2458 _tnl_run_pipeline( ctx
);
2461 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2466 static void r200PolygonStipple( struct gl_context
*ctx
, const GLubyte
*mask
)
2468 r200ContextPtr r200
= R200_CONTEXT(ctx
);
2471 radeon_firevertices(&r200
->radeon
);
2473 radeon_print(RADEON_STATE
, RADEON_TRACE
,
2474 "%s(%p) first 32 bits are %x.\n",
2479 R200_STATECHANGE(r200
, stp
);
2481 /* Must flip pattern upside down.
2483 for ( i
= 31 ; i
>= 0; i
--) {
2484 r200
->hw
.stp
.cmd
[3 + i
] = ((GLuint
*) mask
)[i
];
2487 /* Initialize the driver's state functions.
2489 void r200InitStateFuncs( radeonContextPtr radeon
, struct dd_function_table
*functions
)
2491 functions
->UpdateState
= r200InvalidateState
;
2492 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2494 functions
->DrawBuffer
= radeonDrawBuffer
;
2495 functions
->ReadBuffer
= radeonReadBuffer
;
2497 functions
->CopyPixels
= _mesa_meta_CopyPixels
;
2498 functions
->DrawPixels
= _mesa_meta_DrawPixels
;
2499 functions
->ReadPixels
= radeonReadPixels
;
2501 functions
->AlphaFunc
= r200AlphaFunc
;
2502 functions
->BlendColor
= r200BlendColor
;
2503 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2504 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2505 functions
->ClearColor
= r200ClearColor
;
2506 functions
->ClearDepth
= r200ClearDepth
;
2507 functions
->ClearStencil
= r200ClearStencil
;
2508 functions
->ClipPlane
= r200ClipPlane
;
2509 functions
->ColorMask
= r200ColorMask
;
2510 functions
->CullFace
= r200CullFace
;
2511 functions
->DepthFunc
= r200DepthFunc
;
2512 functions
->DepthMask
= r200DepthMask
;
2513 functions
->DepthRange
= r200DepthRange
;
2514 functions
->Enable
= r200Enable
;
2515 functions
->Fogfv
= r200Fogfv
;
2516 functions
->FrontFace
= r200FrontFace
;
2517 functions
->Hint
= NULL
;
2518 functions
->LightModelfv
= r200LightModelfv
;
2519 functions
->Lightfv
= r200Lightfv
;
2520 functions
->LineStipple
= r200LineStipple
;
2521 functions
->LineWidth
= r200LineWidth
;
2522 functions
->LogicOpcode
= r200LogicOpCode
;
2523 functions
->PolygonMode
= r200PolygonMode
;
2524 functions
->PolygonOffset
= r200PolygonOffset
;
2525 functions
->PolygonStipple
= r200PolygonStipple
;
2526 functions
->PointParameterfv
= r200PointParameter
;
2527 functions
->PointSize
= r200PointSize
;
2528 functions
->RenderMode
= r200RenderMode
;
2529 functions
->Scissor
= radeonScissor
;
2530 functions
->ShadeModel
= r200ShadeModel
;
2531 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2532 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2533 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2534 functions
->Viewport
= r200Viewport
;
2538 void r200InitTnlFuncs( struct gl_context
*ctx
)
2540 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2541 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;