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 <keithw@vmware.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/light.h"
41 #include "main/framebuffer.h"
42 #include "main/fbobject.h"
43 #include "main/stencil.h"
44 #include "main/viewport.h"
46 #include "swrast/swrast.h"
49 #include "tnl/t_pipeline.h"
50 #include "swrast_setup/swrast_setup.h"
51 #include "drivers/common/meta.h"
52 #include "util/bitscan.h"
54 #include "radeon_common.h"
55 #include "radeon_mipmap_tree.h"
56 #include "r200_context.h"
57 #include "r200_ioctl.h"
58 #include "r200_state.h"
61 #include "r200_swtcl.h"
62 #include "r200_vertprog.h"
65 /* =============================================================
69 static void r200AlphaFunc( struct gl_context
*ctx
, GLenum func
, GLfloat ref
)
71 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
72 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
75 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
77 R200_STATECHANGE( rmesa
, ctx
);
79 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
80 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
84 pp_misc
|= R200_ALPHA_TEST_FAIL
;
87 pp_misc
|= R200_ALPHA_TEST_LESS
;
90 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
93 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
96 pp_misc
|= R200_ALPHA_TEST_GREATER
;
99 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
102 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
105 pp_misc
|= R200_ALPHA_TEST_PASS
;
109 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
112 static void r200BlendColor( struct gl_context
*ctx
, const GLfloat cf
[4] )
115 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
116 R200_STATECHANGE( rmesa
, ctx
);
117 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
118 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
119 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
120 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
121 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = radeonPackColor( 4, color
[0], color
[1], color
[2], color
[3] );
125 * Calculate the hardware blend factor setting. This same function is used
126 * for source and destination of both alpha and RGB.
129 * The hardware register value for the specified blend factor. This value
130 * will need to be shifted into the correct position for either source or
131 * destination factor.
134 * Since the two cases where source and destination are handled differently
135 * are essentially error cases, they should never happen. Determine if these
136 * cases can be removed.
138 static int blend_factor( GLenum factor
, GLboolean is_src
)
144 func
= R200_BLEND_GL_ZERO
;
147 func
= R200_BLEND_GL_ONE
;
150 func
= R200_BLEND_GL_DST_COLOR
;
152 case GL_ONE_MINUS_DST_COLOR
:
153 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
156 func
= R200_BLEND_GL_SRC_COLOR
;
158 case GL_ONE_MINUS_SRC_COLOR
:
159 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
162 func
= R200_BLEND_GL_SRC_ALPHA
;
164 case GL_ONE_MINUS_SRC_ALPHA
:
165 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
168 func
= R200_BLEND_GL_DST_ALPHA
;
170 case GL_ONE_MINUS_DST_ALPHA
:
171 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
173 case GL_SRC_ALPHA_SATURATE
:
174 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
176 case GL_CONSTANT_COLOR
:
177 func
= R200_BLEND_GL_CONST_COLOR
;
179 case GL_ONE_MINUS_CONSTANT_COLOR
:
180 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
182 case GL_CONSTANT_ALPHA
:
183 func
= R200_BLEND_GL_CONST_ALPHA
;
185 case GL_ONE_MINUS_CONSTANT_ALPHA
:
186 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
189 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
195 * Sets both the blend equation and the blend function.
196 * This is done in a single
197 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
198 * change the interpretation of the blend function.
199 * Also, make sure that blend function and blend equation are set to their default
200 * value if color blending is not enabled, since at least blend equations GL_MIN
201 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
204 static void r200_set_blend_state( struct gl_context
* ctx
)
206 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
207 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
208 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
210 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
211 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
212 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
213 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
214 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
215 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
217 R200_STATECHANGE( rmesa
, ctx
);
219 if (ctx
->Color
.ColorLogicOpEnabled
) {
220 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
221 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
222 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
224 } else if (ctx
->Color
.BlendEnabled
) {
225 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
;
228 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
229 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
230 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
234 func
= (blend_factor( ctx
->Color
.Blend
[0].SrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
235 (blend_factor( ctx
->Color
.Blend
[0].DstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
237 switch(ctx
->Color
.Blend
[0].EquationRGB
) {
239 eqn
= R200_COMB_FCN_ADD_CLAMP
;
242 case GL_FUNC_SUBTRACT
:
243 eqn
= R200_COMB_FCN_SUB_CLAMP
;
246 case GL_FUNC_REVERSE_SUBTRACT
:
247 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
251 eqn
= R200_COMB_FCN_MIN
;
252 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
253 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
257 eqn
= R200_COMB_FCN_MAX
;
258 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
259 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
263 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
264 __func__
, __LINE__
, ctx
->Color
.Blend
[0].EquationRGB
);
268 funcA
= (blend_factor( ctx
->Color
.Blend
[0].SrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
269 (blend_factor( ctx
->Color
.Blend
[0].DstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
271 switch(ctx
->Color
.Blend
[0].EquationA
) {
273 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
276 case GL_FUNC_SUBTRACT
:
277 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
280 case GL_FUNC_REVERSE_SUBTRACT
:
281 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
285 eqnA
= R200_COMB_FCN_MIN
;
286 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
287 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
291 eqnA
= R200_COMB_FCN_MAX
;
292 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
293 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
297 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
298 __func__
, __LINE__
, ctx
->Color
.Blend
[0].EquationA
);
302 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
303 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
307 static void r200BlendEquationSeparate( struct gl_context
*ctx
,
308 GLenum modeRGB
, GLenum modeA
)
310 r200_set_blend_state( ctx
);
313 static void r200BlendFuncSeparate( struct gl_context
*ctx
,
314 GLenum sfactorRGB
, GLenum dfactorRGB
,
315 GLenum sfactorA
, GLenum dfactorA
)
317 r200_set_blend_state( ctx
);
321 /* =============================================================
325 static void r200DepthFunc( struct gl_context
*ctx
, GLenum func
)
327 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
329 R200_STATECHANGE( rmesa
, ctx
);
330 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
332 switch ( ctx
->Depth
.Func
) {
334 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
337 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
340 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
343 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
346 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
349 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
352 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
355 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
360 static void r200DepthMask( struct gl_context
*ctx
, GLboolean flag
)
362 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
363 R200_STATECHANGE( rmesa
, ctx
);
365 if ( ctx
->Depth
.Mask
) {
366 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
368 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
373 /* =============================================================
378 static void r200Fogfv( struct gl_context
*ctx
, GLenum pname
, const GLfloat
*param
)
380 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
381 union { int i
; float f
; } c
, d
;
385 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
386 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
390 if (!ctx
->Fog
.Enabled
)
392 R200_STATECHANGE(rmesa
, tcl
);
393 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
394 switch (ctx
->Fog
.Mode
) {
396 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
397 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
402 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
403 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
407 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
409 d
.f
= -ctx
->Fog
.Density
;
412 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
414 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
421 switch (ctx
->Fog
.Mode
) {
424 d
.f
= -ctx
->Fog
.Density
;
428 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
436 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
437 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
441 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
442 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
447 R200_STATECHANGE( rmesa
, ctx
);
448 _mesa_unclamped_float_rgba_to_ubyte(col
, ctx
->Fog
.Color
);
449 i
= radeonPackColor( 4, col
[0], col
[1], col
[2], 0 );
450 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
451 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
453 case GL_FOG_COORD_SRC
: {
454 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
455 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
457 fog
&= ~R200_FOG_USE_MASK
;
458 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
|| ctx
->VertexProgram
.Enabled
) {
459 fog
|= R200_FOG_USE_VTX_FOG
;
460 out_0
|= R200_VTX_DISCRETE_FOG
;
463 fog
|= R200_FOG_USE_SPEC_ALPHA
;
464 out_0
&= ~R200_VTX_DISCRETE_FOG
;
467 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
468 R200_STATECHANGE( rmesa
, ctx
);
469 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
472 if (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
]) {
473 R200_STATECHANGE( rmesa
, vtx
);
474 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
483 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
484 R200_STATECHANGE( rmesa
, fog
);
485 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
486 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
490 /* =============================================================
494 static void r200CullFace( struct gl_context
*ctx
, GLenum unused
)
496 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
497 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
498 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
500 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
501 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
503 if ( ctx
->Polygon
.CullFlag
) {
504 switch ( ctx
->Polygon
.CullFaceMode
) {
506 s
&= ~R200_FFACE_SOLID
;
507 t
|= R200_CULL_FRONT
;
510 s
&= ~R200_BFACE_SOLID
;
513 case GL_FRONT_AND_BACK
:
514 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
515 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
520 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
521 R200_STATECHANGE(rmesa
, set
);
522 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
525 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
526 R200_STATECHANGE(rmesa
, tcl
);
527 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
531 static void r200FrontFace( struct gl_context
*ctx
, GLenum mode
)
533 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
534 int cull_face
= (mode
== GL_CW
) ? R200_FFACE_CULL_CW
: R200_FFACE_CULL_CCW
;
536 R200_STATECHANGE( rmesa
, set
);
537 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
539 R200_STATECHANGE( rmesa
, tcl
);
540 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
542 /* Winding is inverted when rendering to FBO */
543 if (ctx
->DrawBuffer
&& _mesa_is_user_fbo(ctx
->DrawBuffer
))
544 cull_face
= (mode
== GL_CCW
) ? R200_FFACE_CULL_CW
: R200_FFACE_CULL_CCW
;
545 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= cull_face
;
547 if ( mode
== GL_CCW
)
548 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
551 /* =============================================================
554 static void r200PointSize( struct gl_context
*ctx
, GLfloat size
)
556 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
557 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
559 radeon_print(RADEON_STATE
, RADEON_TRACE
,
560 "%s(%p) size: %f, fixed point result: %d.%d (%d/16)\n",
562 ((GLuint
)(ctx
->Point
.Size
* 16.0))/16,
563 (((GLuint
)(ctx
->Point
.Size
* 16.0))&15)*100/16,
564 ((GLuint
)(ctx
->Point
.Size
* 16.0))&15);
566 R200_STATECHANGE( rmesa
, cst
);
567 R200_STATECHANGE( rmesa
, ptp
);
568 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
569 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
570 /* this is the size param of the point size calculation (point size reg value
571 is not used when calculation is active). */
572 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
575 static void r200PointParameter( struct gl_context
*ctx
, GLenum pname
, const GLfloat
*params
)
577 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
578 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
581 case GL_POINT_SIZE_MIN
:
582 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
583 R200_STATECHANGE( rmesa
, lin
);
584 R200_STATECHANGE( rmesa
, ptp
);
585 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
586 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
587 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
589 case GL_POINT_SIZE_MAX
:
590 R200_STATECHANGE( rmesa
, cst
);
591 R200_STATECHANGE( rmesa
, ptp
);
592 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
593 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
594 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
596 case GL_POINT_DISTANCE_ATTENUATION
:
597 R200_STATECHANGE( rmesa
, vtx
);
598 R200_STATECHANGE( rmesa
, spr
);
599 R200_STATECHANGE( rmesa
, ptp
);
600 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
601 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
602 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
603 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
604 r200ValidateState looks like overkill */
605 if (ctx
->Point
.Params
[0] != 1.0 ||
606 ctx
->Point
.Params
[1] != 0.0 ||
607 ctx
->Point
.Params
[2] != 0.0 ||
608 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
609 /* all we care for vp would be the ps_se_sel_state setting */
610 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
611 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
612 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
613 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
614 if (ctx
->Point
.Params
[1] == 0.0)
615 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
616 /* FIXME: setting this here doesn't look quite ok - we only want to do
617 that if we're actually drawing points probably */
618 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
619 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
622 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
623 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
624 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
625 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
628 case GL_POINT_FADE_THRESHOLD_SIZE
:
629 /* don't support multisampling, so doesn't matter. */
631 /* can't do these but don't need them.
632 case GL_POINT_SPRITE_R_MODE_NV:
633 case GL_POINT_SPRITE_COORD_ORIGIN: */
635 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
640 /* =============================================================
643 static void r200LineWidth( struct gl_context
*ctx
, GLfloat widthf
)
645 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
647 R200_STATECHANGE( rmesa
, lin
);
648 R200_STATECHANGE( rmesa
, set
);
650 /* Line width is stored in U6.4 format.
651 * Same min/max limits for AA, non-AA lines.
653 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
654 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)
655 (CLAMP(widthf
, ctx
->Const
.MinLineWidth
, ctx
->Const
.MaxLineWidth
) * 16.0);
657 if ( widthf
> 1.0 ) {
658 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
660 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
664 static void r200LineStipple( struct gl_context
*ctx
, GLint factor
, GLushort pattern
)
666 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
668 R200_STATECHANGE( rmesa
, lin
);
669 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
670 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
674 /* =============================================================
677 static void r200ColorMask( struct gl_context
*ctx
,
678 GLboolean r
, GLboolean g
,
679 GLboolean b
, GLboolean a
)
681 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
683 struct radeon_renderbuffer
*rrb
;
684 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
686 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
689 mask
= radeonPackColor( rrb
->cpp
,
690 ctx
->Color
.ColorMask
[0][RCOMP
],
691 ctx
->Color
.ColorMask
[0][GCOMP
],
692 ctx
->Color
.ColorMask
[0][BCOMP
],
693 ctx
->Color
.ColorMask
[0][ACOMP
] );
696 if (!(r
&& g
&& b
&& a
))
697 flag
|= R200_PLANE_MASK_ENABLE
;
699 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
700 R200_STATECHANGE( rmesa
, ctx
);
701 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
704 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
705 R200_STATECHANGE( rmesa
, msk
);
706 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
711 /* =============================================================
715 static void r200PolygonOffset( struct gl_context
*ctx
,
716 GLfloat factor
, GLfloat units
, GLfloat clamp
)
718 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
719 const GLfloat depthScale
= 1.0F
/ ctx
->DrawBuffer
->_DepthMaxF
;
720 float_ui32_type constant
= { units
* depthScale
};
721 float_ui32_type factoru
= { factor
};
726 /* fprintf(stderr, "%s f:%f u:%f\n", __func__, factor, constant); */
728 R200_STATECHANGE( rmesa
, zbs
);
729 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
730 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
733 static void r200PolygonMode( struct gl_context
*ctx
, GLenum face
, GLenum mode
)
735 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
736 GLboolean unfilled
= (ctx
->Polygon
.FrontMode
!= GL_FILL
||
737 ctx
->Polygon
.BackMode
!= GL_FILL
);
739 /* Can't generally do unfilled via tcl, but some good special
742 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, unfilled
);
743 if (rmesa
->radeon
.TclFallback
) {
744 r200ChooseRenderState( ctx
);
745 r200ChooseVertexState( ctx
);
750 /* =============================================================
751 * Rendering attributes
753 * We really don't want to recalculate all this every time we bind a
754 * texture. These things shouldn't change all that often, so it makes
755 * sense to break them out of the core texture state update routines.
758 /* Examine lighting and texture state to determine if separate specular
761 static void r200UpdateSpecular( struct gl_context
*ctx
)
763 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
764 uint32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
766 R200_STATECHANGE( rmesa
, tcl
);
767 R200_STATECHANGE( rmesa
, vtx
);
769 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
770 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
771 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
772 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
773 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
775 p
&= ~R200_SPECULAR_ENABLE
;
777 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
780 if (ctx
->Light
.Enabled
&&
781 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
782 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
783 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
784 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
785 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
786 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
787 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
788 p
|= R200_SPECULAR_ENABLE
;
789 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
790 ~R200_DIFFUSE_SPECULAR_COMBINE
;
792 else if (ctx
->Light
.Enabled
) {
793 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
794 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
795 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
796 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
797 } else if (ctx
->Fog
.ColorSumEnabled
) {
798 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
799 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
800 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
801 p
|= R200_SPECULAR_ENABLE
;
803 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
804 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
807 if (ctx
->Fog
.Enabled
) {
808 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
809 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
810 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
813 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
814 R200_STATECHANGE( rmesa
, ctx
);
815 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
818 /* Update vertex/render formats
820 if (rmesa
->radeon
.TclFallback
) {
821 r200ChooseRenderState( ctx
);
822 r200ChooseVertexState( ctx
);
827 /* =============================================================
832 /* Update on colormaterial, material emmissive/ambient,
833 * lightmodel.globalambient
835 static void update_global_ambient( struct gl_context
*ctx
)
837 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
838 float *fcmd
= (float *)R200_DB_STATE( glt
);
840 /* Need to do more if both emmissive & ambient are PREMULT:
841 * I believe this is not nessary when using source_material. This condition thus
842 * will never happen currently, and the function has no dependencies on materials now
844 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
845 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
846 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
848 COPY_3V( &fcmd
[GLT_RED
],
849 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
850 ACC_SCALE_3V( &fcmd
[GLT_RED
],
851 ctx
->Light
.Model
.Ambient
,
852 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
856 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
859 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
862 /* Update on change to
866 static void update_light_colors( struct gl_context
*ctx
, GLuint p
)
868 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
870 /* fprintf(stderr, "%s\n", __func__); */
873 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
874 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
876 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
877 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
878 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
880 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
884 static void r200ColorMaterial( struct gl_context
*ctx
, GLenum face
, GLenum mode
)
886 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
887 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
888 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
889 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
890 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
891 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
892 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
893 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
894 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
895 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
897 if (ctx
->Light
.ColorMaterialEnabled
) {
898 GLuint mask
= ctx
->Light
._ColorMaterialBitmask
;
900 if (mask
& MAT_BIT_FRONT_EMISSION
) {
901 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
902 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
905 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
906 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
908 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
909 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
910 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
913 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
914 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
916 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
917 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
918 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
921 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
922 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
924 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
925 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
926 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
929 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
930 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
933 if (mask
& MAT_BIT_BACK_EMISSION
) {
934 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
935 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
938 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
939 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
941 if (mask
& MAT_BIT_BACK_AMBIENT
) {
942 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
943 R200_BACK_AMBIENT_SOURCE_SHIFT
);
945 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
946 R200_BACK_AMBIENT_SOURCE_SHIFT
);
948 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
949 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
950 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
952 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
953 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
955 if (mask
& MAT_BIT_BACK_SPECULAR
) {
956 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
957 R200_BACK_SPECULAR_SOURCE_SHIFT
);
960 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
961 R200_BACK_SPECULAR_SOURCE_SHIFT
);
965 /* Default to SOURCE_MATERIAL:
968 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
969 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
970 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
971 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
972 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
973 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
974 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
975 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
978 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
979 R200_STATECHANGE( rmesa
, tcl
);
980 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
986 void r200UpdateMaterial( struct gl_context
*ctx
)
988 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
989 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
990 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
991 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
994 /* Might be possible and faster to update everything unconditionally? */
995 if (ctx
->Light
.ColorMaterialEnabled
)
996 mask
&= ~ctx
->Light
._ColorMaterialBitmask
;
998 if (R200_DEBUG
& RADEON_STATE
)
999 fprintf(stderr
, "%s\n", __func__
);
1001 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1002 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1003 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1004 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1005 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1007 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1008 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1009 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1010 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1011 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1013 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1014 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1015 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1016 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1017 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1019 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1020 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1021 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1022 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1023 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1025 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1026 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1029 if (mask
& MAT_BIT_BACK_EMISSION
) {
1030 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1031 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1032 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1033 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1035 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1036 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1037 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1038 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1039 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1041 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1042 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1043 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1044 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1045 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1047 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1048 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1049 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1050 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1051 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1053 if (mask
& MAT_BIT_BACK_SHININESS
) {
1054 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1057 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1058 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1060 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1061 update_global_ambient( ctx ); */
1066 * _MESA_NEW_NEED_EYE_COORDS
1068 * Uses derived state from mesa:
1072 * _NormSpotDirection
1073 * _ModelViewInvScale
1077 * which are calculated in light.c and are correct for the current
1078 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1079 * and _MESA_NEW_NEED_EYE_COORDS.
1081 static void update_light( struct gl_context
*ctx
)
1083 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1085 /* Have to check these, or have an automatic shortcircuit mechanism
1086 * to remove noop statechanges. (Or just do a better job on the
1090 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1092 if (ctx
->_NeedEyeCoords
)
1093 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1095 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1097 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1099 R200_STATECHANGE( rmesa
, tcl
);
1100 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1105 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1106 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1107 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1108 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1109 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1110 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1115 if (ctx
->Light
.Enabled
) {
1116 GLbitfield mask
= ctx
->Light
._EnabledLights
;
1118 const int p
= u_bit_scan(&mask
);
1119 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1120 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1122 if (l
->EyePosition
[3] == 0.0) {
1123 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1124 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1125 fcmd
[LIT_POSITION_W
] = 0;
1126 fcmd
[LIT_DIRECTION_W
] = 0;
1128 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1129 fcmd
[LIT_DIRECTION_X
] = -l
->_NormSpotDirection
[0];
1130 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormSpotDirection
[1];
1131 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormSpotDirection
[2];
1132 fcmd
[LIT_DIRECTION_W
] = 0;
1135 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1140 static void r200Lightfv( struct gl_context
*ctx
, GLenum light
,
1141 GLenum pname
, const GLfloat
*params
)
1143 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1144 GLint p
= light
- GL_LIGHT0
;
1145 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1146 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1153 update_light_colors( ctx
, p
);
1156 case GL_SPOT_DIRECTION
:
1157 /* picked up in update_light */
1161 /* positions picked up in update_light, but can do flag here */
1162 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1163 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1165 R200_STATECHANGE(rmesa
, tcl
);
1166 if (l
->EyePosition
[3] != 0.0F
)
1167 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1169 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1173 case GL_SPOT_EXPONENT
:
1174 R200_STATECHANGE(rmesa
, lit
[p
]);
1175 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1178 case GL_SPOT_CUTOFF
: {
1179 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1180 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1182 R200_STATECHANGE(rmesa
, lit
[p
]);
1183 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1185 R200_STATECHANGE(rmesa
, tcl
);
1186 if (l
->SpotCutoff
!= 180.0F
)
1187 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1189 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1194 case GL_CONSTANT_ATTENUATION
:
1195 R200_STATECHANGE(rmesa
, lit
[p
]);
1196 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1197 if ( params
[0] == 0.0 )
1198 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1200 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1202 case GL_LINEAR_ATTENUATION
:
1203 R200_STATECHANGE(rmesa
, lit
[p
]);
1204 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1206 case GL_QUADRATIC_ATTENUATION
:
1207 R200_STATECHANGE(rmesa
, lit
[p
]);
1208 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1214 /* Set RANGE_ATTEN only when needed */
1217 case GL_CONSTANT_ATTENUATION
:
1218 case GL_LINEAR_ATTENUATION
:
1219 case GL_QUADRATIC_ATTENUATION
: {
1220 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1221 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1222 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1223 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1224 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1225 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1227 if ( l
->EyePosition
[3] == 0.0F
||
1228 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1229 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1230 /* Disable attenuation */
1231 icmd
[idx
] &= ~atten_flag
;
1233 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1234 /* Enable only constant portion of attenuation calculation */
1235 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1237 /* Enable full attenuation calculation */
1238 icmd
[idx
] &= ~atten_const_flag
;
1239 icmd
[idx
] |= atten_flag
;
1243 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1251 static void r200UpdateLocalViewer ( struct gl_context
*ctx
)
1253 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1254 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1255 for these and only these modes). This means specular highlights may turn out
1256 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1257 is not set, though it seems to happen rarely and the effect seems quite
1258 subtle. May need TCL fallback to fix it completely, though I'm not sure
1259 how you'd identify the cases where the specular highlights indeed will
1260 be wrong. Don't know if fglrx does something special in that case.
1262 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1263 R200_STATECHANGE( rmesa
, tcl
);
1264 if (ctx
->Light
.Model
.LocalViewer
||
1265 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1266 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1268 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1271 static void r200LightModelfv( struct gl_context
*ctx
, GLenum pname
,
1272 const GLfloat
*param
)
1274 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1277 case GL_LIGHT_MODEL_AMBIENT
:
1278 update_global_ambient( ctx
);
1281 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1282 r200UpdateLocalViewer( ctx
);
1285 case GL_LIGHT_MODEL_TWO_SIDE
:
1286 R200_STATECHANGE( rmesa
, tcl
);
1287 if (ctx
->Light
.Model
.TwoSide
)
1288 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1290 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1291 if (rmesa
->radeon
.TclFallback
) {
1292 r200ChooseRenderState( ctx
);
1293 r200ChooseVertexState( ctx
);
1297 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1298 r200UpdateSpecular(ctx
);
1306 static void r200ShadeModel( struct gl_context
*ctx
, GLenum mode
)
1308 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1309 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1311 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1312 R200_ALPHA_SHADE_MASK
|
1313 R200_SPECULAR_SHADE_MASK
|
1314 R200_FOG_SHADE_MASK
|
1315 R200_DISC_FOG_SHADE_MASK
);
1319 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1320 R200_ALPHA_SHADE_FLAT
|
1321 R200_SPECULAR_SHADE_FLAT
|
1322 R200_FOG_SHADE_FLAT
|
1323 R200_DISC_FOG_SHADE_FLAT
);
1326 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1327 R200_ALPHA_SHADE_GOURAUD
|
1328 R200_SPECULAR_SHADE_GOURAUD
|
1329 R200_FOG_SHADE_GOURAUD
|
1330 R200_DISC_FOG_SHADE_GOURAUD
);
1336 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1337 R200_STATECHANGE( rmesa
, set
);
1338 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1343 /* =============================================================
1347 static void r200ClipPlane( struct gl_context
*ctx
, GLenum plane
, const GLfloat
*eq
)
1349 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1350 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1351 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1353 R200_STATECHANGE( rmesa
, ucp
[p
] );
1354 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1355 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1356 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1357 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1360 static void r200UpdateClipPlanes( struct gl_context
*ctx
)
1362 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1363 GLbitfield mask
= ctx
->Transform
.ClipPlanesEnabled
;
1366 const int p
= u_bit_scan(&mask
);
1367 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1369 R200_STATECHANGE( rmesa
, ucp
[p
] );
1370 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1371 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1372 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1373 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1378 /* =============================================================
1383 r200StencilFuncSeparate( struct gl_context
*ctx
, GLenum face
, GLenum func
,
1384 GLint ref
, GLuint mask
)
1386 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1387 GLuint refmask
= ((_mesa_get_stencil_ref(ctx
, 0) << R200_STENCIL_REF_SHIFT
) |
1388 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1390 R200_STATECHANGE( rmesa
, ctx
);
1391 R200_STATECHANGE( rmesa
, msk
);
1393 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1394 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1395 R200_STENCIL_VALUE_MASK
);
1397 switch ( ctx
->Stencil
.Function
[0] ) {
1399 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1402 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1405 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1408 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1411 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1414 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1417 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1420 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1424 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1428 r200StencilMaskSeparate( struct gl_context
*ctx
, GLenum face
, GLuint mask
)
1430 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1432 R200_STATECHANGE( rmesa
, msk
);
1433 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1434 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1435 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1439 r200StencilOpSeparate( struct gl_context
*ctx
, GLenum face
, GLenum fail
,
1440 GLenum zfail
, GLenum zpass
)
1442 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1444 R200_STATECHANGE( rmesa
, ctx
);
1445 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1446 R200_STENCIL_ZFAIL_MASK
|
1447 R200_STENCIL_ZPASS_MASK
);
1449 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1451 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1454 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1457 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1460 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1463 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1465 case GL_INCR_WRAP_EXT
:
1466 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1468 case GL_DECR_WRAP_EXT
:
1469 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1472 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1476 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1478 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1481 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1484 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1487 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1490 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1492 case GL_INCR_WRAP_EXT
:
1493 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1495 case GL_DECR_WRAP_EXT
:
1496 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1499 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1503 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1505 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1508 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1511 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1514 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1517 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1519 case GL_INCR_WRAP_EXT
:
1520 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1522 case GL_DECR_WRAP_EXT
:
1523 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1526 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1532 /* =============================================================
1533 * Window position and viewport transformation
1537 * Called when window size or position changes or viewport or depth range
1538 * state is changed. We update the hardware viewport state here.
1540 void r200UpdateWindow( struct gl_context
*ctx
)
1542 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1543 __DRIdrawable
*dPriv
= radeon_get_drawable(&rmesa
->radeon
);
1544 GLfloat xoffset
= 0;
1545 GLfloat yoffset
= dPriv
? (GLfloat
) dPriv
->h
: 0;
1546 const GLboolean render_to_fbo
= (ctx
->DrawBuffer
? _mesa_is_user_fbo(ctx
->DrawBuffer
) : 0);
1547 float scale
[3], translate
[3];
1548 GLfloat y_scale
, y_bias
;
1550 if (render_to_fbo
) {
1558 _mesa_get_viewport_xform(ctx
, 0, scale
, translate
);
1559 float_ui32_type sx
= { scale
[0] };
1560 float_ui32_type sy
= { scale
[1] * y_scale
};
1561 float_ui32_type sz
= { scale
[2] };
1562 float_ui32_type tx
= { translate
[0] + xoffset
};
1563 float_ui32_type ty
= { (translate
[1] * y_scale
) + y_bias
};
1564 float_ui32_type tz
= { translate
[2] };
1566 R200_STATECHANGE( rmesa
, vpt
);
1568 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1569 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1570 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1571 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1572 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1573 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1576 void r200_vtbl_update_scissor( struct gl_context
*ctx
)
1578 r200ContextPtr r200
= R200_CONTEXT(ctx
);
1579 unsigned x1
, y1
, x2
, y2
;
1580 struct radeon_renderbuffer
*rrb
;
1582 R200_SET_STATE(r200
, set
, SET_RE_CNTL
, R200_SCISSOR_ENABLE
| r200
->hw
.set
.cmd
[SET_RE_CNTL
]);
1584 if (r200
->radeon
.state
.scissor
.enabled
) {
1585 x1
= r200
->radeon
.state
.scissor
.rect
.x1
;
1586 y1
= r200
->radeon
.state
.scissor
.rect
.y1
;
1587 x2
= r200
->radeon
.state
.scissor
.rect
.x2
;
1588 y2
= r200
->radeon
.state
.scissor
.rect
.y2
;
1590 rrb
= radeon_get_colorbuffer(&r200
->radeon
);
1593 x2
= rrb
->base
.Base
.Width
- 1;
1594 y2
= rrb
->base
.Base
.Height
- 1;
1597 R200_SET_STATE(r200
, sci
, SCI_XY_1
, x1
| (y1
<< 16));
1598 R200_SET_STATE(r200
, sci
, SCI_XY_2
, x2
| (y2
<< 16));
1602 static void r200Viewport(struct gl_context
*ctx
)
1604 /* Don't pipeline viewport changes, conflict with window offset
1605 * setting below. Could apply deltas to rescue pipelined viewport
1606 * values, or keep the originals hanging around.
1608 r200UpdateWindow( ctx
);
1610 radeon_viewport(ctx
);
1613 static void r200DepthRange(struct gl_context
*ctx
)
1615 r200UpdateWindow( ctx
);
1618 /* =============================================================
1622 static void r200RenderMode( struct gl_context
*ctx
, GLenum mode
)
1624 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1625 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1629 static GLuint r200_rop_tab
[] = {
1632 R200_ROP_AND_REVERSE
,
1634 R200_ROP_AND_INVERTED
,
1641 R200_ROP_OR_REVERSE
,
1642 R200_ROP_COPY_INVERTED
,
1643 R200_ROP_OR_INVERTED
,
1648 static void r200LogicOpCode( struct gl_context
*ctx
, GLenum opcode
)
1650 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1651 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1655 R200_STATECHANGE( rmesa
, msk
);
1656 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1659 /* =============================================================
1660 * State enable/disable
1663 static void r200Enable( struct gl_context
*ctx
, GLenum cap
, GLboolean state
)
1665 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1668 if ( R200_DEBUG
& RADEON_STATE
)
1669 fprintf( stderr
, "%s( %s = %s )\n", __func__
,
1670 _mesa_enum_to_string( cap
),
1671 state
? "GL_TRUE" : "GL_FALSE" );
1674 /* Fast track this one...
1682 R200_STATECHANGE( rmesa
, ctx
);
1684 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1686 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1691 case GL_COLOR_LOGIC_OP
:
1692 r200_set_blend_state( ctx
);
1695 case GL_CLIP_PLANE0
:
1696 case GL_CLIP_PLANE1
:
1697 case GL_CLIP_PLANE2
:
1698 case GL_CLIP_PLANE3
:
1699 case GL_CLIP_PLANE4
:
1700 case GL_CLIP_PLANE5
:
1701 p
= cap
-GL_CLIP_PLANE0
;
1702 R200_STATECHANGE( rmesa
, tcl
);
1704 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1705 r200ClipPlane( ctx
, cap
, NULL
);
1708 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1712 case GL_COLOR_MATERIAL
:
1713 r200ColorMaterial( ctx
, 0, 0 );
1714 r200UpdateMaterial( ctx
);
1718 r200CullFace( ctx
, 0 );
1722 R200_STATECHANGE(rmesa
, ctx
);
1724 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1726 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1731 R200_STATECHANGE(rmesa
, ctx
);
1733 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1734 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->radeon
.state
.color
.roundEnable
;
1736 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1737 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->radeon
.state
.color
.roundEnable
;
1742 R200_STATECHANGE(rmesa
, ctx
);
1744 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1745 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1747 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1748 R200_STATECHANGE(rmesa
, tcl
);
1749 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1751 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1752 if (rmesa
->radeon
.TclFallback
)
1753 r200ChooseVertexState( ctx
);
1754 _mesa_allow_light_in_model( ctx
, !state
);
1765 R200_STATECHANGE(rmesa
, tcl
);
1766 p
= cap
- GL_LIGHT0
;
1768 flag
= (R200_LIGHT_1_ENABLE
|
1769 R200_LIGHT_1_ENABLE_AMBIENT
|
1770 R200_LIGHT_1_ENABLE_SPECULAR
);
1772 flag
= (R200_LIGHT_0_ENABLE
|
1773 R200_LIGHT_0_ENABLE_AMBIENT
|
1774 R200_LIGHT_0_ENABLE_SPECULAR
);
1777 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1779 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1783 update_light_colors( ctx
, p
);
1787 r200UpdateSpecular(ctx
);
1788 /* for reflection map fixup - might set recheck_texgen for all units too */
1789 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE
;
1792 case GL_LINE_SMOOTH
:
1793 R200_STATECHANGE( rmesa
, ctx
);
1795 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1797 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1801 case GL_LINE_STIPPLE
:
1802 R200_STATECHANGE( rmesa
, set
);
1804 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1806 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1811 R200_STATECHANGE( rmesa
, tcl
);
1813 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1815 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1819 /* Pointsize registers on r200 only work for point sprites, and point smooth
1820 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1821 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1822 * is enough to satisfy conform.
1824 case GL_POINT_SMOOTH
:
1827 /* These don't really do anything, as we don't use the 3vtx
1831 case GL_POLYGON_OFFSET_POINT
:
1832 R200_STATECHANGE( rmesa
, set
);
1834 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1836 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1840 case GL_POLYGON_OFFSET_LINE
:
1841 R200_STATECHANGE( rmesa
, set
);
1843 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1845 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1850 case GL_POINT_SPRITE_ARB
:
1851 R200_STATECHANGE( rmesa
, spr
);
1853 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_GEN_TEX_MASK
&
1854 (ctx
->Point
.CoordReplace
<< R200_PS_GEN_TEX_0_SHIFT
);
1856 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
1860 case GL_POLYGON_OFFSET_FILL
:
1861 R200_STATECHANGE( rmesa
, set
);
1863 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1865 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1869 case GL_POLYGON_SMOOTH
:
1870 R200_STATECHANGE( rmesa
, ctx
);
1872 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
1874 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
1878 case GL_POLYGON_STIPPLE
:
1879 R200_STATECHANGE(rmesa
, set
);
1881 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
1883 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
1887 case GL_RESCALE_NORMAL_EXT
: {
1888 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
1889 R200_STATECHANGE( rmesa
, tcl
);
1891 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1893 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1898 case GL_SCISSOR_TEST
:
1899 radeon_firevertices(&rmesa
->radeon
);
1900 rmesa
->radeon
.state
.scissor
.enabled
= state
;
1901 radeonUpdateScissor( ctx
);
1904 case GL_STENCIL_TEST
:
1906 GLboolean hw_stencil
= GL_FALSE
;
1907 if (ctx
->DrawBuffer
) {
1908 struct radeon_renderbuffer
*rrbStencil
1909 = radeon_get_renderbuffer(ctx
->DrawBuffer
, BUFFER_STENCIL
);
1910 hw_stencil
= (rrbStencil
&& rrbStencil
->bo
);
1914 R200_STATECHANGE( rmesa
, ctx
);
1916 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
1918 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
1921 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
1926 case GL_TEXTURE_GEN_Q
:
1927 case GL_TEXTURE_GEN_R
:
1928 case GL_TEXTURE_GEN_S
:
1929 case GL_TEXTURE_GEN_T
:
1930 /* Picked up in r200UpdateTextureState.
1932 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
1935 case GL_COLOR_SUM_EXT
:
1936 r200UpdateSpecular ( ctx
);
1939 case GL_VERTEX_PROGRAM_ARB
:
1942 rmesa
->curr_vp_hw
= NULL
;
1943 R200_STATECHANGE( rmesa
, vap
);
1944 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
1945 /* mark all tcl atoms (tcl vector state got overwritten) dirty
1946 not sure about tcl scalar state - we need at least grd
1947 with vert progs too.
1948 ucp looks like it doesn't get overwritten (may even work
1949 with vp for pos-invariant progs if we're lucky) */
1950 R200_STATECHANGE( rmesa
, mtl
[0] );
1951 R200_STATECHANGE( rmesa
, mtl
[1] );
1952 R200_STATECHANGE( rmesa
, fog
);
1953 R200_STATECHANGE( rmesa
, glt
);
1954 R200_STATECHANGE( rmesa
, eye
);
1955 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
1956 R200_STATECHANGE( rmesa
, mat
[i
] );
1958 for (i
= 0 ; i
< 8; i
++) {
1959 R200_STATECHANGE( rmesa
, lit
[i
] );
1961 R200_STATECHANGE( rmesa
, tcl
);
1962 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
1963 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
1964 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
1967 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
1970 /* ugly. Need to call everything which might change compsel. */
1971 r200UpdateSpecular( ctx
);
1973 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
1974 but without it doom3 locks up at always the same places. Why? */
1975 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
1976 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
1977 r200UpdateTextureState( ctx
);
1978 /* if we call r200UpdateTextureState we need the code below because we are calling it with
1979 non-current derived enabled values which may revert the state atoms for frag progs even when
1980 they already got disabled... ugh
1981 Should really figure out why we need to call r200UpdateTextureState in the first place */
1983 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
1984 R200_STATECHANGE( rmesa
, pix
[unit
] );
1985 R200_STATECHANGE( rmesa
, tex
[unit
] );
1986 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
1987 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
1988 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
1989 /* need to guard this with drmSupportsFragmentShader? Should never get here if
1990 we don't announce ATI_fs, right? */
1991 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
1993 R200_STATECHANGE( rmesa
, cst
);
1994 R200_STATECHANGE( rmesa
, tf
);
1995 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
1999 /* picked up later */
2001 /* call functions which change hw state based on ARB_vp enabled or not. */
2002 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2003 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2006 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2007 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2010 case GL_FRAGMENT_SHADER_ATI
:
2012 /* restore normal tex env colors and make sure tex env combine will get updated
2013 mark env atoms dirty (as their data was overwritten by afs even
2014 if they didn't change) and restore tex coord routing */
2016 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2017 R200_STATECHANGE( rmesa
, pix
[unit
] );
2018 R200_STATECHANGE( rmesa
, tex
[unit
] );
2019 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2020 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2021 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2022 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2024 R200_STATECHANGE( rmesa
, cst
);
2025 R200_STATECHANGE( rmesa
, tf
);
2026 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2029 /* need to mark this dirty as pix/tf atoms have overwritten the data
2030 even if the data in the atoms didn't change */
2031 R200_STATECHANGE( rmesa
, atf
);
2032 R200_STATECHANGE( rmesa
, afs
[1] );
2033 /* everything else picked up in r200UpdateTextureState hopefully */
2042 void r200LightingSpaceChange( struct gl_context
*ctx
)
2044 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2047 if (R200_DEBUG
& RADEON_STATE
)
2048 fprintf(stderr
, "%s %d BEFORE %x\n", __func__
, ctx
->_NeedEyeCoords
,
2049 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2051 if (ctx
->_NeedEyeCoords
)
2052 tmp
= ctx
->Transform
.RescaleNormals
;
2054 tmp
= !ctx
->Transform
.RescaleNormals
;
2056 R200_STATECHANGE( rmesa
, tcl
);
2058 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2060 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2063 if (R200_DEBUG
& RADEON_STATE
)
2064 fprintf(stderr
, "%s %d AFTER %x\n", __func__
, ctx
->_NeedEyeCoords
,
2065 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2068 /* =============================================================
2069 * Deferred state management - matrices, textures, other?
2075 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2077 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2081 for (i
= 0 ; i
< 4 ; i
++) {
2085 *dest
++ = src
[i
+12];
2088 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2091 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2093 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2094 memcpy(dest
, src
, 16*sizeof(float));
2095 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2099 static void update_texturematrix( struct gl_context
*ctx
)
2101 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2102 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2103 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2106 if (R200_DEBUG
& RADEON_STATE
)
2107 fprintf(stderr
, "%s before COMPSEL: %x\n", __func__
,
2108 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2110 rmesa
->TexMatEnabled
= 0;
2111 rmesa
->TexMatCompSel
= 0;
2113 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2114 if (!ctx
->Texture
.Unit
[unit
]._Current
)
2117 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2118 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2119 R200_TEXMAT_0_ENABLE
) << unit
;
2121 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2123 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2124 /* Need to preconcatenate any active texgen
2125 * obj/eyeplane matrices:
2127 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2128 ctx
->TextureMatrixStack
[unit
].Top
,
2129 &rmesa
->TexGenMatrix
[unit
] );
2130 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2133 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2134 R200_MTX_TEX0
+unit
);
2137 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2138 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2139 R200_MTX_TEX0
+unit
);
2143 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2144 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2145 R200_STATECHANGE(rmesa
, tcg
);
2146 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2149 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2150 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2151 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2152 R200_STATECHANGE(rmesa
, vtx
);
2153 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2157 GLboolean
r200ValidateBuffers(struct gl_context
*ctx
)
2159 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2160 struct radeon_renderbuffer
*rrb
;
2161 struct radeon_dma_bo
*dma_bo
;
2164 if (RADEON_DEBUG
& RADEON_IOCTL
)
2165 fprintf(stderr
, "%s\n", __func__
);
2166 radeon_cs_space_reset_bos(rmesa
->radeon
.cmdbuf
.cs
);
2168 rrb
= radeon_get_colorbuffer(&rmesa
->radeon
);
2170 if (rrb
&& rrb
->bo
) {
2171 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2172 0, RADEON_GEM_DOMAIN_VRAM
);
2176 rrb
= radeon_get_depthbuffer(&rmesa
->radeon
);
2178 if (rrb
&& rrb
->bo
) {
2179 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, rrb
->bo
,
2180 0, RADEON_GEM_DOMAIN_VRAM
);
2183 for (i
= 0; i
< ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxTextureImageUnits
; ++i
) {
2186 if (!ctx
->Texture
.Unit
[i
]._Current
)
2189 t
= radeon_tex_obj(ctx
->Texture
.Unit
[i
]._Current
);
2190 if (t
->image_override
&& t
->bo
)
2191 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->bo
,
2192 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2194 radeon_cs_space_add_persistent_bo(rmesa
->radeon
.cmdbuf
.cs
, t
->mt
->bo
,
2195 RADEON_GEM_DOMAIN_GTT
| RADEON_GEM_DOMAIN_VRAM
, 0);
2198 dma_bo
= first_elem(&rmesa
->radeon
.dma
.reserved
);
2200 ret
= radeon_cs_space_check_with_bo(rmesa
->radeon
.cmdbuf
.cs
, dma_bo
->bo
, RADEON_GEM_DOMAIN_GTT
, 0);
2207 GLboolean
r200ValidateState( struct gl_context
*ctx
)
2209 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2210 GLuint new_state
= rmesa
->radeon
.NewGLState
;
2212 if (new_state
& _NEW_BUFFERS
) {
2213 _mesa_update_framebuffer(ctx
, ctx
->ReadBuffer
, ctx
->DrawBuffer
);
2214 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2215 _mesa_update_draw_buffer_bounds(ctx
, ctx
->DrawBuffer
);
2217 R200_STATECHANGE(rmesa
, ctx
);
2220 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
| _NEW_PROGRAM_CONSTANTS
)) {
2221 r200UpdateTextureState( ctx
);
2222 new_state
|= rmesa
->radeon
.NewGLState
; /* may add TEXTURE_MATRIX */
2223 r200UpdateLocalViewer( ctx
);
2226 /* we need to do a space check here */
2227 if (!r200ValidateBuffers(ctx
))
2230 /* FIXME: don't really need most of these when vertex progs are enabled */
2232 /* Need an event driven matrix update?
2234 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2235 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2237 /* Need these for lighting (shouldn't upload otherwise)
2239 if (new_state
& (_NEW_MODELVIEW
)) {
2240 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2241 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2244 /* Does this need to be triggered on eg. modelview for
2245 * texgen-derived objplane/eyeplane matrices?
2247 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2248 update_texturematrix( ctx
);
2251 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2252 update_light( ctx
);
2255 /* emit all active clip planes if projection matrix changes.
2257 if (new_state
& (_NEW_PROJECTION
)) {
2258 if (ctx
->Transform
.ClipPlanesEnabled
)
2259 r200UpdateClipPlanes( ctx
);
2262 if (new_state
& (_NEW_PROGRAM
|
2263 _NEW_PROGRAM_CONSTANTS
|
2264 /* need to test for pretty much anything due to possible parameter bindings */
2265 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2266 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2267 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2268 if (ctx
->VertexProgram
._Enabled
) {
2269 r200SetupVertexProg( ctx
);
2271 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2274 rmesa
->radeon
.NewGLState
= 0;
2279 static void r200InvalidateState( struct gl_context
*ctx
, GLuint new_state
)
2281 _swrast_InvalidateState( ctx
, new_state
);
2282 _swsetup_InvalidateState( ctx
, new_state
);
2283 _vbo_InvalidateState( ctx
, new_state
);
2284 _tnl_InvalidateState( ctx
, new_state
);
2285 _ae_invalidate_state( ctx
, new_state
);
2286 R200_CONTEXT(ctx
)->radeon
.NewGLState
|= new_state
;
2289 /* A hack. The r200 can actually cope just fine with materials
2290 * between begin/ends, so fix this.
2291 * Should map to inputs just like the generic vertex arrays for vertex progs.
2292 * In theory there could still be too many and we'd still need a fallback.
2294 static GLboolean
check_material( struct gl_context
*ctx
)
2296 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2299 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2300 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2302 if (tnl
->vb
.AttribPtr
[i
] &&
2303 tnl
->vb
.AttribPtr
[i
]->stride
)
2309 static void r200WrapRunPipeline( struct gl_context
*ctx
)
2311 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2312 GLboolean has_material
;
2315 fprintf(stderr
, "%s, newstate: %x\n", __func__
, rmesa
->radeon
.NewGLState
);
2319 if (rmesa
->radeon
.NewGLState
)
2320 if (!r200ValidateState( ctx
))
2321 FALLBACK(rmesa
, RADEON_FALLBACK_TEXTURE
, GL_TRUE
);
2323 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2326 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2329 /* Run the pipeline.
2331 _tnl_run_pipeline( ctx
);
2334 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2339 static void r200PolygonStipple( struct gl_context
*ctx
, const GLubyte
*mask
)
2341 r200ContextPtr r200
= R200_CONTEXT(ctx
);
2344 radeon_firevertices(&r200
->radeon
);
2346 radeon_print(RADEON_STATE
, RADEON_TRACE
,
2347 "%s(%p) first 32 bits are %x.\n",
2352 R200_STATECHANGE(r200
, stp
);
2354 /* Must flip pattern upside down.
2356 for ( i
= 31 ; i
>= 0; i
--) {
2357 r200
->hw
.stp
.cmd
[3 + i
] = ((GLuint
*) mask
)[i
];
2360 /* Initialize the driver's state functions.
2362 void r200InitStateFuncs( radeonContextPtr radeon
, struct dd_function_table
*functions
)
2364 functions
->UpdateState
= r200InvalidateState
;
2365 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2367 functions
->DrawBuffer
= radeonDrawBuffer
;
2368 functions
->ReadBuffer
= radeonReadBuffer
;
2370 functions
->CopyPixels
= _mesa_meta_CopyPixels
;
2371 functions
->DrawPixels
= _mesa_meta_DrawPixels
;
2372 functions
->ReadPixels
= radeonReadPixels
;
2374 functions
->AlphaFunc
= r200AlphaFunc
;
2375 functions
->BlendColor
= r200BlendColor
;
2376 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2377 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2378 functions
->ClipPlane
= r200ClipPlane
;
2379 functions
->ColorMask
= r200ColorMask
;
2380 functions
->CullFace
= r200CullFace
;
2381 functions
->DepthFunc
= r200DepthFunc
;
2382 functions
->DepthMask
= r200DepthMask
;
2383 functions
->DepthRange
= r200DepthRange
;
2384 functions
->Enable
= r200Enable
;
2385 functions
->Fogfv
= r200Fogfv
;
2386 functions
->FrontFace
= r200FrontFace
;
2387 functions
->LightModelfv
= r200LightModelfv
;
2388 functions
->Lightfv
= r200Lightfv
;
2389 functions
->LineStipple
= r200LineStipple
;
2390 functions
->LineWidth
= r200LineWidth
;
2391 functions
->LogicOpcode
= r200LogicOpCode
;
2392 functions
->PolygonMode
= r200PolygonMode
;
2393 functions
->PolygonOffset
= r200PolygonOffset
;
2394 functions
->PolygonStipple
= r200PolygonStipple
;
2395 functions
->PointParameterfv
= r200PointParameter
;
2396 functions
->PointSize
= r200PointSize
;
2397 functions
->RenderMode
= r200RenderMode
;
2398 functions
->Scissor
= radeonScissor
;
2399 functions
->ShadeModel
= r200ShadeModel
;
2400 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2401 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2402 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2403 functions
->Viewport
= r200Viewport
;
2407 void r200InitTnlFuncs( struct gl_context
*ctx
)
2409 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2410 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;