2 /**************************************************************************
4 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
6 The Weather Channel (TM) funded Tungsten Graphics to develop the
7 initial release of the Radeon 8500 driver under the XFree86 license.
8 This notice must be preserved.
10 Permission is hereby granted, free of charge, to any person obtaining
11 a copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sublicense, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial
20 portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
34 * Keith Whitwell <keith@tungstengraphics.com>
39 #include "api_arrayelt.h"
44 #include "swrast/swrast.h"
45 #include "array_cache/acache.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
50 #include "r200_context.h"
51 #include "r200_ioctl.h"
52 #include "r200_state.h"
55 #include "r200_swtcl.h"
56 #include "r200_vtxfmt.h"
57 #include "r200_vertprog.h"
59 #include "drirenderbuffer.h"
62 /* =============================================================
66 static void r200AlphaFunc( GLcontext
*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( GLcontext
*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
->r200Screen
->drmSupportsBlendColor
)
119 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = r200PackColor( 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( GLcontext
* 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
->r200Screen
->drmSupportsBlendColor
) {
218 if (ctx
->Color
._LogicOpEnabled
) {
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
._LogicOpEnabled
) {
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
.BlendSrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
249 (blend_factor( ctx
->Color
.BlendDstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
251 switch(ctx
->Color
.BlendEquationRGB
) {
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
.BlendEquationRGB
);
282 if (!rmesa
->r200Screen
->drmSupportsBlendColor
) {
283 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
287 funcA
= (blend_factor( ctx
->Color
.BlendSrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
288 (blend_factor( ctx
->Color
.BlendDstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
290 switch(ctx
->Color
.BlendEquationA
) {
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
.BlendEquationA
);
321 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
322 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
326 static void r200BlendEquationSeparate( GLcontext
*ctx
,
327 GLenum modeRGB
, GLenum modeA
)
329 r200_set_blend_state( ctx
);
332 static void r200BlendFuncSeparate( GLcontext
*ctx
,
333 GLenum sfactorRGB
, GLenum dfactorRGB
,
334 GLenum sfactorA
, GLenum dfactorA
)
336 r200_set_blend_state( ctx
);
340 /* =============================================================
344 static void r200DepthFunc( GLcontext
*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( GLcontext
*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
->state
.depth
.clear
= d
* 0x0000ffff;
389 case R200_DEPTH_FORMAT_24BIT_INT_Z
:
390 rmesa
->state
.depth
.clear
= d
* 0x00ffffff;
395 static void r200DepthMask( GLcontext
*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( GLcontext
*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 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
484 i
= r200PackColor( 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
) {
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
;
526 /* =============================================================
531 static GLboolean
intersect_rect( drm_clip_rect_t
*out
,
536 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
537 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
538 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
539 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
540 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
541 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
546 void r200RecalcScissorRects( r200ContextPtr rmesa
)
548 drm_clip_rect_t
*out
;
551 /* Grow cliprect store?
553 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
554 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
555 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
556 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
559 if (rmesa
->state
.scissor
.pClipRects
)
560 FREE(rmesa
->state
.scissor
.pClipRects
);
562 rmesa
->state
.scissor
.pClipRects
=
563 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
564 sizeof(drm_clip_rect_t
) );
566 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
567 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
572 out
= rmesa
->state
.scissor
.pClipRects
;
573 rmesa
->state
.scissor
.numClipRects
= 0;
575 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
576 if ( intersect_rect( out
,
577 &rmesa
->pClipRects
[i
],
578 &rmesa
->state
.scissor
.rect
) ) {
579 rmesa
->state
.scissor
.numClipRects
++;
586 static void r200UpdateScissor( GLcontext
*ctx
)
588 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
590 if ( rmesa
->dri
.drawable
) {
591 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
593 int x
= ctx
->Scissor
.X
;
594 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
595 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
596 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
598 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
599 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
600 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
601 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
603 r200RecalcScissorRects( rmesa
);
608 static void r200Scissor( GLcontext
*ctx
,
609 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
611 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
613 if ( ctx
->Scissor
.Enabled
) {
614 R200_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
615 r200UpdateScissor( ctx
);
621 /* =============================================================
625 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
627 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
628 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
629 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
631 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
632 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
634 if ( ctx
->Polygon
.CullFlag
) {
635 switch ( ctx
->Polygon
.CullFaceMode
) {
637 s
&= ~R200_FFACE_SOLID
;
638 t
|= R200_CULL_FRONT
;
641 s
&= ~R200_BFACE_SOLID
;
644 case GL_FRONT_AND_BACK
:
645 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
646 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
651 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
652 R200_STATECHANGE(rmesa
, set
);
653 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
656 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
657 R200_STATECHANGE(rmesa
, tcl
);
658 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
662 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
664 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
666 R200_STATECHANGE( rmesa
, set
);
667 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
669 R200_STATECHANGE( rmesa
, tcl
);
670 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
674 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
677 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
678 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
683 /* =============================================================
686 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
688 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
690 R200_STATECHANGE( rmesa
, cst
);
691 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
692 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
695 /* =============================================================
698 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
700 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
702 R200_STATECHANGE( rmesa
, lin
);
703 R200_STATECHANGE( rmesa
, set
);
705 /* Line width is stored in U6.4 format.
707 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
708 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Line
._Width
* 16.0);
710 if ( widthf
> 1.0 ) {
711 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
713 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
717 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
719 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
721 R200_STATECHANGE( rmesa
, lin
);
722 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
723 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
727 /* =============================================================
730 static void r200ColorMask( GLcontext
*ctx
,
731 GLboolean r
, GLboolean g
,
732 GLboolean b
, GLboolean a
)
734 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
735 GLuint mask
= r200PackColor( rmesa
->r200Screen
->cpp
,
736 ctx
->Color
.ColorMask
[RCOMP
],
737 ctx
->Color
.ColorMask
[GCOMP
],
738 ctx
->Color
.ColorMask
[BCOMP
],
739 ctx
->Color
.ColorMask
[ACOMP
] );
741 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
743 if (!(r
&& g
&& b
&& a
))
744 flag
|= R200_PLANE_MASK_ENABLE
;
746 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
747 R200_STATECHANGE( rmesa
, ctx
);
748 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
751 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
752 R200_STATECHANGE( rmesa
, msk
);
753 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
758 /* =============================================================
762 static void r200PolygonOffset( GLcontext
*ctx
,
763 GLfloat factor
, GLfloat units
)
765 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
766 float_ui32_type constant
= { units
* rmesa
->state
.depth
.scale
};
767 float_ui32_type factoru
= { factor
};
772 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
774 R200_STATECHANGE( rmesa
, zbs
);
775 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
776 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
779 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
781 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
783 drm_radeon_stipple_t stipple
;
785 /* Must flip pattern upside down.
787 for ( i
= 0 ; i
< 32 ; i
++ ) {
788 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
791 /* TODO: push this into cmd mechanism
793 R200_FIREVERTICES( rmesa
);
794 LOCK_HARDWARE( rmesa
);
796 /* FIXME: Use window x,y offsets into stipple RAM.
798 stipple
.mask
= rmesa
->state
.stipple
.mask
;
799 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
800 &stipple
, sizeof(stipple
) );
801 UNLOCK_HARDWARE( rmesa
);
804 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
806 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
807 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
809 /* Can't generally do unfilled via tcl, but some good special
812 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
813 if (rmesa
->TclFallback
) {
814 r200ChooseRenderState( ctx
);
815 r200ChooseVertexState( ctx
);
820 /* =============================================================
821 * Rendering attributes
823 * We really don't want to recalculate all this every time we bind a
824 * texture. These things shouldn't change all that often, so it makes
825 * sense to break them out of the core texture state update routines.
828 /* Examine lighting and texture state to determine if separate specular
831 static void r200UpdateSpecular( GLcontext
*ctx
)
833 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
834 u_int32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
836 R200_STATECHANGE( rmesa
, tcl
);
837 R200_STATECHANGE( rmesa
, vtx
);
839 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
840 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
841 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
842 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
843 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
845 p
&= ~R200_SPECULAR_ENABLE
;
847 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
850 if (ctx
->Light
.Enabled
&&
851 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
852 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
853 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
854 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
855 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
856 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
857 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
858 p
|= R200_SPECULAR_ENABLE
;
859 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
860 ~R200_DIFFUSE_SPECULAR_COMBINE
;
862 else if (ctx
->Light
.Enabled
) {
863 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
864 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
865 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
866 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
867 } else if (ctx
->Fog
.ColorSumEnabled
) {
868 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
869 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
870 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
871 p
|= R200_SPECULAR_ENABLE
;
873 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
874 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
877 if (ctx
->Fog
.Enabled
) {
878 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
879 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
880 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
883 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
884 R200_STATECHANGE( rmesa
, ctx
);
885 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
888 /* Update vertex/render formats
890 if (rmesa
->TclFallback
) {
891 r200ChooseRenderState( ctx
);
892 r200ChooseVertexState( ctx
);
897 /* =============================================================
902 /* Update on colormaterial, material emmissive/ambient,
903 * lightmodel.globalambient
905 static void update_global_ambient( GLcontext
*ctx
)
907 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
908 float *fcmd
= (float *)R200_DB_STATE( glt
);
910 /* Need to do more if both emmissive & ambient are PREMULT:
911 * I believe this is not nessary when using source_material. This condition thus
912 * will never happen currently, and the function has no dependencies on materials now
914 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
915 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
916 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
918 COPY_3V( &fcmd
[GLT_RED
],
919 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
920 ACC_SCALE_3V( &fcmd
[GLT_RED
],
921 ctx
->Light
.Model
.Ambient
,
922 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
926 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
929 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
932 /* Update on change to
936 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
938 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
940 /* fprintf(stderr, "%s\n", __FUNCTION__); */
943 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
944 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
946 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
947 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
948 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
950 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
954 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
956 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
957 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
958 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
959 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
960 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
961 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
962 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
963 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
964 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
965 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
967 if (ctx
->Light
.ColorMaterialEnabled
) {
968 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
970 if (mask
& MAT_BIT_FRONT_EMISSION
) {
971 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
972 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
975 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
976 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
978 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
979 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
980 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
983 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
984 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
986 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
987 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
988 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
991 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
992 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
994 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
995 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
996 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
999 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1000 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
1003 if (mask
& MAT_BIT_BACK_EMISSION
) {
1004 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1005 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1008 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1009 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1011 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1012 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1013 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1015 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1016 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1018 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1019 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1020 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1022 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1023 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1025 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1026 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1027 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1030 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1031 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1035 /* Default to SOURCE_MATERIAL:
1038 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1039 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1040 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1041 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1042 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1043 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1044 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1045 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1048 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1049 R200_STATECHANGE( rmesa
, tcl
);
1050 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1056 void r200UpdateMaterial( GLcontext
*ctx
)
1058 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1059 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1060 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1061 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1064 /* Might be possible and faster to update everything unconditionally? */
1065 if (ctx
->Light
.ColorMaterialEnabled
)
1066 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1068 if (R200_DEBUG
& DEBUG_STATE
)
1069 fprintf(stderr
, "%s\n", __FUNCTION__
);
1071 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1072 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1073 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1074 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1075 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1077 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1078 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1079 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1080 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1081 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1083 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1084 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1085 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1086 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1087 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1089 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1090 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1091 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1092 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1093 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1095 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1096 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1099 if (mask
& MAT_BIT_BACK_EMISSION
) {
1100 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1101 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1102 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1103 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1105 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1106 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1107 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1108 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1109 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1111 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1112 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1113 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1114 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1115 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1117 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1118 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1119 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1120 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1121 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1123 if (mask
& MAT_BIT_BACK_SHININESS
) {
1124 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1127 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1128 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1130 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1131 update_global_ambient( ctx ); */
1136 * _MESA_NEW_NEED_EYE_COORDS
1138 * Uses derived state from mesa:
1143 * _ModelViewInvScale
1147 * which are calculated in light.c and are correct for the current
1148 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1149 * and _MESA_NEW_NEED_EYE_COORDS.
1151 static void update_light( GLcontext
*ctx
)
1153 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1155 /* Have to check these, or have an automatic shortcircuit mechanism
1156 * to remove noop statechanges. (Or just do a better job on the
1160 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1162 if (ctx
->_NeedEyeCoords
)
1163 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1165 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1167 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1169 R200_STATECHANGE( rmesa
, tcl
);
1170 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1175 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1176 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1177 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1178 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1179 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1180 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1185 if (ctx
->Light
.Enabled
) {
1187 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1188 if (ctx
->Light
.Light
[p
].Enabled
) {
1189 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1190 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1192 if (l
->EyePosition
[3] == 0.0) {
1193 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1194 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1195 fcmd
[LIT_POSITION_W
] = 0;
1196 fcmd
[LIT_DIRECTION_W
] = 0;
1198 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1199 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1200 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1201 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1202 fcmd
[LIT_DIRECTION_W
] = 0;
1205 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1211 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1212 GLenum pname
, const GLfloat
*params
)
1214 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1215 GLint p
= light
- GL_LIGHT0
;
1216 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1217 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1224 update_light_colors( ctx
, p
);
1227 case GL_SPOT_DIRECTION
:
1228 /* picked up in update_light */
1232 /* positions picked up in update_light, but can do flag here */
1233 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1234 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1236 R200_STATECHANGE(rmesa
, tcl
);
1237 if (l
->EyePosition
[3] != 0.0F
)
1238 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1240 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1244 case GL_SPOT_EXPONENT
:
1245 R200_STATECHANGE(rmesa
, lit
[p
]);
1246 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1249 case GL_SPOT_CUTOFF
: {
1250 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1251 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1253 R200_STATECHANGE(rmesa
, lit
[p
]);
1254 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1256 R200_STATECHANGE(rmesa
, tcl
);
1257 if (l
->SpotCutoff
!= 180.0F
)
1258 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1260 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1265 case GL_CONSTANT_ATTENUATION
:
1266 R200_STATECHANGE(rmesa
, lit
[p
]);
1267 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1268 if ( params
[0] == 0.0 )
1269 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1271 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1273 case GL_LINEAR_ATTENUATION
:
1274 R200_STATECHANGE(rmesa
, lit
[p
]);
1275 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1277 case GL_QUADRATIC_ATTENUATION
:
1278 R200_STATECHANGE(rmesa
, lit
[p
]);
1279 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1285 /* Set RANGE_ATTEN only when needed */
1288 case GL_CONSTANT_ATTENUATION
:
1289 case GL_LINEAR_ATTENUATION
:
1290 case GL_QUADRATIC_ATTENUATION
: {
1291 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1292 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1293 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1294 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1295 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1296 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1298 if ( l
->EyePosition
[3] == 0.0F
||
1299 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1300 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1301 /* Disable attenuation */
1302 icmd
[idx
] &= ~atten_flag
;
1304 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1305 /* Enable only constant portion of attenuation calculation */
1306 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1308 /* Enable full attenuation calculation */
1309 icmd
[idx
] &= ~atten_const_flag
;
1310 icmd
[idx
] |= atten_flag
;
1314 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1322 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1324 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1325 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1326 for these and only these modes). This means specular highlights may turn out
1327 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1328 is not set, though it seems to happen rarely and the effect seems quite
1329 subtle. May need TCL fallback to fix it completely, though I'm not sure
1330 how you'd identify the cases where the specular highlights indeed will
1331 be wrong. Don't know if fglrx does something special in that case.
1333 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1334 R200_STATECHANGE( rmesa
, tcl
);
1335 if (ctx
->Light
.Model
.LocalViewer
||
1336 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1337 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1339 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1342 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1343 const GLfloat
*param
)
1345 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1348 case GL_LIGHT_MODEL_AMBIENT
:
1349 update_global_ambient( ctx
);
1352 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1353 r200UpdateLocalViewer( ctx
);
1356 case GL_LIGHT_MODEL_TWO_SIDE
:
1357 R200_STATECHANGE( rmesa
, tcl
);
1358 if (ctx
->Light
.Model
.TwoSide
)
1359 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1361 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1362 if (rmesa
->TclFallback
) {
1363 r200ChooseRenderState( ctx
);
1364 r200ChooseVertexState( ctx
);
1368 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1369 r200UpdateSpecular(ctx
);
1377 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1379 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1380 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1382 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1383 R200_ALPHA_SHADE_MASK
|
1384 R200_SPECULAR_SHADE_MASK
|
1385 R200_FOG_SHADE_MASK
);
1389 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1390 R200_ALPHA_SHADE_FLAT
|
1391 R200_SPECULAR_SHADE_FLAT
|
1392 R200_FOG_SHADE_FLAT
);
1395 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1396 R200_ALPHA_SHADE_GOURAUD
|
1397 R200_SPECULAR_SHADE_GOURAUD
|
1398 R200_FOG_SHADE_GOURAUD
);
1404 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1405 R200_STATECHANGE( rmesa
, set
);
1406 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1411 /* =============================================================
1415 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1417 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1418 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1419 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1421 R200_STATECHANGE( rmesa
, ucp
[p
] );
1422 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1423 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1424 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1425 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1428 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1430 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1433 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1434 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1435 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1437 R200_STATECHANGE( rmesa
, ucp
[p
] );
1438 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1439 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1440 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1441 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1447 /* =============================================================
1452 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1453 GLint ref
, GLuint mask
)
1455 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1456 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1457 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1459 R200_STATECHANGE( rmesa
, ctx
);
1460 R200_STATECHANGE( rmesa
, msk
);
1462 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1463 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1464 R200_STENCIL_VALUE_MASK
);
1466 switch ( ctx
->Stencil
.Function
[0] ) {
1468 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1471 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1474 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1477 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1480 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1483 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1486 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1489 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1493 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1497 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1499 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1501 R200_STATECHANGE( rmesa
, msk
);
1502 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1503 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1504 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1508 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1509 GLenum zfail
, GLenum zpass
)
1511 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1513 R200_STATECHANGE( rmesa
, ctx
);
1514 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1515 R200_STENCIL_ZFAIL_MASK
|
1516 R200_STENCIL_ZPASS_MASK
);
1518 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1520 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1523 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1526 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1529 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1532 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1534 case GL_INCR_WRAP_EXT
:
1535 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1537 case GL_DECR_WRAP_EXT
:
1538 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1541 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1545 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1547 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1550 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1553 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1556 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1559 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1561 case GL_INCR_WRAP_EXT
:
1562 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1564 case GL_DECR_WRAP_EXT
:
1565 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1568 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1572 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1574 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1577 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1580 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1583 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1586 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1588 case GL_INCR_WRAP_EXT
:
1589 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1591 case GL_DECR_WRAP_EXT
:
1592 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1595 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1600 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1602 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1604 rmesa
->state
.stencil
.clear
=
1605 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1606 (0xff << R200_STENCIL_MASK_SHIFT
) |
1607 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1611 /* =============================================================
1612 * Window position and viewport transformation
1616 * To correctly position primitives:
1618 #define SUBPIXEL_X 0.125
1619 #define SUBPIXEL_Y 0.125
1621 void r200UpdateWindow( GLcontext
*ctx
)
1623 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1624 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1625 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1626 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1627 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1629 float_ui32_type sx
= { v
[MAT_SX
] };
1630 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
};
1631 float_ui32_type sy
= { - v
[MAT_SY
] };
1632 float_ui32_type ty
= { (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
};
1633 float_ui32_type sz
= { v
[MAT_SZ
] * rmesa
->state
.depth
.scale
};
1634 float_ui32_type tz
= { v
[MAT_TZ
] * rmesa
->state
.depth
.scale
};
1636 R200_FIREVERTICES( rmesa
);
1637 R200_STATECHANGE( rmesa
, vpt
);
1639 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1640 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1641 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1642 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1643 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1644 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1649 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1650 GLsizei width
, GLsizei height
)
1652 /* Don't pipeline viewport changes, conflict with window offset
1653 * setting below. Could apply deltas to rescue pipelined viewport
1654 * values, or keep the originals hanging around.
1656 r200UpdateWindow( ctx
);
1659 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1662 r200UpdateWindow( ctx
);
1665 void r200UpdateViewportOffset( GLcontext
*ctx
)
1667 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1668 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1669 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1670 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1671 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1676 tx
.f
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1677 ty
.f
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1679 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1680 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1682 /* Note: this should also modify whatever data the context reset
1685 R200_STATECHANGE( rmesa
, vpt
);
1686 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1687 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1689 /* update polygon stipple x/y screen offset */
1692 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1694 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1695 R200_STIPPLE_Y_OFFSET_MASK
);
1697 /* add magic offsets, then invert */
1698 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1699 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1700 & R200_STIPPLE_COORD_MASK
);
1702 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1703 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1705 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1706 R200_STATECHANGE( rmesa
, msc
);
1707 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1712 r200UpdateScissor( ctx
);
1717 /* =============================================================
1721 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1723 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1725 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1726 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1727 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1728 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1729 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1731 color
[2], color
[3] );
1735 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1737 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1738 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1742 static GLuint r200_rop_tab
[] = {
1745 R200_ROP_AND_REVERSE
,
1747 R200_ROP_AND_INVERTED
,
1754 R200_ROP_OR_REVERSE
,
1755 R200_ROP_COPY_INVERTED
,
1756 R200_ROP_OR_INVERTED
,
1761 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1763 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1764 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1768 R200_STATECHANGE( rmesa
, msk
);
1769 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1773 void r200SetCliprects( r200ContextPtr rmesa
, GLenum mode
)
1775 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1779 rmesa
->numClipRects
= dPriv
->numClipRects
;
1780 rmesa
->pClipRects
= dPriv
->pClipRects
;
1783 /* Can't ignore 2d windows if we are page flipping.
1785 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1786 rmesa
->numClipRects
= dPriv
->numClipRects
;
1787 rmesa
->pClipRects
= dPriv
->pClipRects
;
1790 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1791 rmesa
->pClipRects
= dPriv
->pBackClipRects
;
1795 fprintf(stderr
, "bad mode in r200SetCliprects\n");
1799 if (rmesa
->state
.scissor
.enabled
)
1800 r200RecalcScissorRects( rmesa
);
1804 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1806 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1808 if (R200_DEBUG
& DEBUG_DRI
)
1809 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1810 _mesa_lookup_enum_by_nr( mode
));
1812 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1815 * _ColorDrawBufferMask is easier to cope with than <mode>.
1816 * Check for software fallback, update cliprects.
1818 switch ( ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] ) {
1819 case BUFFER_BIT_FRONT_LEFT
:
1820 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1821 r200SetCliprects( rmesa
, GL_FRONT_LEFT
);
1823 case BUFFER_BIT_BACK_LEFT
:
1824 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1825 r200SetCliprects( rmesa
, GL_BACK_LEFT
);
1828 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1829 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1833 /* We'll set the drawing engine's offset/pitch parameters later
1834 * when we update other state.
1839 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1841 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1844 /* =============================================================
1845 * State enable/disable
1848 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1850 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1853 if ( R200_DEBUG
& DEBUG_STATE
)
1854 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1855 _mesa_lookup_enum_by_nr( cap
),
1856 state
? "GL_TRUE" : "GL_FALSE" );
1859 /* Fast track this one...
1867 R200_STATECHANGE( rmesa
, ctx
);
1869 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1871 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1876 case GL_COLOR_LOGIC_OP
:
1877 r200_set_blend_state( ctx
);
1880 case GL_CLIP_PLANE0
:
1881 case GL_CLIP_PLANE1
:
1882 case GL_CLIP_PLANE2
:
1883 case GL_CLIP_PLANE3
:
1884 case GL_CLIP_PLANE4
:
1885 case GL_CLIP_PLANE5
:
1886 p
= cap
-GL_CLIP_PLANE0
;
1887 R200_STATECHANGE( rmesa
, tcl
);
1889 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1890 r200ClipPlane( ctx
, cap
, NULL
);
1893 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1897 case GL_COLOR_MATERIAL
:
1898 r200ColorMaterial( ctx
, 0, 0 );
1899 r200UpdateMaterial( ctx
);
1903 r200CullFace( ctx
, 0 );
1907 R200_STATECHANGE(rmesa
, ctx
);
1909 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1911 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1916 R200_STATECHANGE(rmesa
, ctx
);
1918 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1919 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1921 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1922 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1927 R200_STATECHANGE(rmesa
, ctx
);
1929 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1930 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1932 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1933 R200_STATECHANGE(rmesa
, tcl
);
1934 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1936 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1937 if (rmesa
->TclFallback
)
1938 r200ChooseVertexState( ctx
);
1939 _mesa_allow_light_in_model( ctx
, !state
);
1950 R200_STATECHANGE(rmesa
, tcl
);
1951 p
= cap
- GL_LIGHT0
;
1953 flag
= (R200_LIGHT_1_ENABLE
|
1954 R200_LIGHT_1_ENABLE_AMBIENT
|
1955 R200_LIGHT_1_ENABLE_SPECULAR
);
1957 flag
= (R200_LIGHT_0_ENABLE
|
1958 R200_LIGHT_0_ENABLE_AMBIENT
|
1959 R200_LIGHT_0_ENABLE_SPECULAR
);
1962 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1964 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1968 update_light_colors( ctx
, p
);
1972 r200UpdateSpecular(ctx
);
1975 case GL_LINE_SMOOTH
:
1976 R200_STATECHANGE( rmesa
, ctx
);
1978 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1980 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1984 case GL_LINE_STIPPLE
:
1985 R200_STATECHANGE( rmesa
, set
);
1987 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1989 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1994 R200_STATECHANGE( rmesa
, tcl
);
1996 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1998 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
2002 /* Pointsize registers on r200 only work for point sprites, and point smooth
2003 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
2004 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
2005 * is enough to satisfy conform.
2007 case GL_POINT_SMOOTH
:
2010 /* These don't really do anything, as we don't use the 3vtx
2014 case GL_POLYGON_OFFSET_POINT
:
2015 R200_STATECHANGE( rmesa
, set
);
2017 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
2019 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
2023 case GL_POLYGON_OFFSET_LINE
:
2024 R200_STATECHANGE( rmesa
, set
);
2026 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
2028 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
2033 case GL_POLYGON_OFFSET_FILL
:
2034 R200_STATECHANGE( rmesa
, set
);
2036 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
2038 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
2042 case GL_POLYGON_SMOOTH
:
2043 R200_STATECHANGE( rmesa
, ctx
);
2045 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2047 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2051 case GL_POLYGON_STIPPLE
:
2052 R200_STATECHANGE(rmesa
, set
);
2054 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2056 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2060 case GL_RESCALE_NORMAL_EXT
: {
2061 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2062 R200_STATECHANGE( rmesa
, tcl
);
2064 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2066 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2071 case GL_SCISSOR_TEST
:
2072 R200_FIREVERTICES( rmesa
);
2073 rmesa
->state
.scissor
.enabled
= state
;
2074 r200UpdateScissor( ctx
);
2077 case GL_STENCIL_TEST
:
2078 if ( rmesa
->state
.stencil
.hwBuffer
) {
2079 R200_STATECHANGE( rmesa
, ctx
);
2081 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2083 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2086 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2090 case GL_TEXTURE_GEN_Q
:
2091 case GL_TEXTURE_GEN_R
:
2092 case GL_TEXTURE_GEN_S
:
2093 case GL_TEXTURE_GEN_T
:
2094 /* Picked up in r200UpdateTextureState.
2096 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2099 case GL_COLOR_SUM_EXT
:
2100 r200UpdateSpecular ( ctx
);
2103 case GL_VERTEX_PROGRAM_ARB
:
2106 R200_STATECHANGE( rmesa
, vap
);
2107 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2108 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2109 not sure about tcl scalar state - we need at least grd
2110 with vert progs too.
2111 ucp looks like it doesn't get overwritten (may even work
2112 with vp for pos-invariant progs if we're lucky) */
2113 R200_STATECHANGE( rmesa
, mtl
[0] );
2114 R200_STATECHANGE( rmesa
, mtl
[1] );
2115 R200_STATECHANGE( rmesa
, fog
);
2116 R200_STATECHANGE( rmesa
, glt
);
2117 R200_STATECHANGE( rmesa
, eye
);
2118 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2119 R200_STATECHANGE( rmesa
, mat
[i
] );
2121 for (i
= 0 ; i
< 8; i
++) {
2122 R200_STATECHANGE( rmesa
, lit
[i
] );
2124 R200_STATECHANGE( rmesa
, tcl
);
2125 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2126 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2127 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2130 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2133 /* FIXME: ugly as hell. need to call everything which might change tcl_output_vtxfmt0/1 and compsel */
2134 r200UpdateSpecular( ctx
);
2135 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2136 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2137 but without it doom3 locks up at always the same places. Why? */
2138 r200UpdateTextureState( ctx
);
2139 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2140 non-current derived enabled values which may revert the state atoms for frag progs even when
2141 they already got disabled... ugh
2142 Should really figure out why we need to call r200UpdateTextureState in the first place */
2144 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2145 R200_STATECHANGE( rmesa
, pix
[unit
] );
2146 R200_STATECHANGE( rmesa
, tex
[unit
] );
2147 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2148 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2149 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2150 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2151 we don't announce ATI_fs, right? */
2152 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2154 R200_STATECHANGE( rmesa
, cst
);
2155 R200_STATECHANGE( rmesa
, tf
);
2156 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2159 R200_STATECHANGE( rmesa
, vap
);
2160 if (!rmesa
->TclFallback
) {
2161 /* FIXME: fglrx sets R200_VAP_SINGLE_BUF_STATE_ENABLE too. Do we need it? */
2162 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] |= R200_VAP_PROG_VTX_SHADER_ENABLE
/*| R200_VAP_SINGLE_BUF_STATE_ENABLE*/;
2164 R200_STATECHANGE( rmesa
, vpi
[0] );
2165 R200_STATECHANGE( rmesa
, vpi
[1] );
2166 R200_STATECHANGE( rmesa
, vpp
[0] );
2167 R200_STATECHANGE( rmesa
, vpp
[1] );
2171 case GL_FRAGMENT_SHADER_ATI
:
2173 /* restore normal tex env colors and make sure tex env combine will get updated
2174 mark env atoms dirty (as their data was overwritten by afs even
2175 if they didn't change) and restore tex coord routing */
2177 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2178 R200_STATECHANGE( rmesa
, pix
[unit
] );
2179 R200_STATECHANGE( rmesa
, tex
[unit
] );
2180 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2181 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2182 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2183 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2184 we don't announce ATI_fs, right? */
2185 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2187 R200_STATECHANGE( rmesa
, cst
);
2188 R200_STATECHANGE( rmesa
, tf
);
2189 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2192 /* need to mark this dirty as pix/tf atoms have overwritten the data
2193 even if the data in the atoms didn't change */
2194 R200_STATECHANGE( rmesa
, atf
);
2195 R200_STATECHANGE( rmesa
, afs
[1] );
2196 /* everything else picked up in r200UpdateTextureState hopefully */
2205 void r200LightingSpaceChange( GLcontext
*ctx
)
2207 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2210 if (R200_DEBUG
& DEBUG_STATE
)
2211 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2212 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2214 if (ctx
->_NeedEyeCoords
)
2215 tmp
= ctx
->Transform
.RescaleNormals
;
2217 tmp
= !ctx
->Transform
.RescaleNormals
;
2219 R200_STATECHANGE( rmesa
, tcl
);
2221 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2223 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2226 if (R200_DEBUG
& DEBUG_STATE
)
2227 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2228 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2231 /* =============================================================
2232 * Deferred state management - matrices, textures, other?
2238 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2240 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2244 for (i
= 0 ; i
< 4 ; i
++) {
2248 *dest
++ = src
[i
+12];
2251 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2254 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2256 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2257 memcpy(dest
, src
, 16*sizeof(float));
2258 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2262 static void update_texturematrix( GLcontext
*ctx
)
2264 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2265 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2266 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2269 if (R200_DEBUG
& DEBUG_STATE
)
2270 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2271 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2273 rmesa
->TexMatEnabled
= 0;
2274 rmesa
->TexMatCompSel
= 0;
2276 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2277 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2280 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2281 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2282 R200_TEXMAT_0_ENABLE
) << unit
;
2284 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2286 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2287 /* Need to preconcatenate any active texgen
2288 * obj/eyeplane matrices:
2290 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2291 ctx
->TextureMatrixStack
[unit
].Top
,
2292 &rmesa
->TexGenMatrix
[unit
] );
2293 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2296 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2297 R200_MTX_TEX0
+unit
);
2300 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2301 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2302 R200_MTX_TEX0
+unit
);
2306 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2307 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2308 R200_STATECHANGE(rmesa
, tcg
);
2309 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2312 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2313 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2314 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2315 R200_STATECHANGE(rmesa
, vtx
);
2316 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2323 * Tell the card where to render (offset, pitch).
2324 * Effected by glDrawBuffer, etc
2327 r200UpdateDrawBuffer(GLcontext
*ctx
)
2329 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2330 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
2331 driRenderbuffer
*drb
;
2333 if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_FRONT_LEFT
) {
2335 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
2337 else if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_BACK_LEFT
) {
2339 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
2342 /* drawing to multiple buffers, or none */
2347 assert(drb
->flippedPitch
);
2349 R200_STATECHANGE( rmesa
, ctx
);
2351 /* Note: we used the (possibly) page-flipped values */
2352 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
]
2353 = ((drb
->flippedOffset
+ rmesa
->r200Screen
->fbLocation
)
2354 & R200_COLOROFFSET_MASK
);
2355 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = drb
->flippedPitch
;
2356 if (rmesa
->sarea
->tiling_enabled
) {
2357 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
2363 void r200ValidateState( GLcontext
*ctx
)
2365 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2366 GLuint new_state
= rmesa
->NewGLState
;
2368 if (new_state
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
2369 r200UpdateDrawBuffer(ctx
);
2372 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
)) {
2373 r200UpdateTextureState( ctx
);
2374 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2375 r200UpdateLocalViewer( ctx
);
2378 /* FIXME: don't really need most of these when vertex progs are enabled */
2380 /* Need an event driven matrix update?
2382 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2383 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2385 /* Need these for lighting (shouldn't upload otherwise)
2387 if (new_state
& (_NEW_MODELVIEW
)) {
2388 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2389 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2392 /* Does this need to be triggered on eg. modelview for
2393 * texgen-derived objplane/eyeplane matrices?
2395 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2396 update_texturematrix( ctx
);
2399 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2400 update_light( ctx
);
2403 /* emit all active clip planes if projection matrix changes.
2405 if (new_state
& (_NEW_PROJECTION
)) {
2406 if (ctx
->Transform
.ClipPlanesEnabled
)
2407 r200UpdateClipPlanes( ctx
);
2410 if (new_state
& (_NEW_PROGRAM
|
2411 /* need to test for pretty much anything due to possible parameter bindings */
2412 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2413 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2414 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2415 if (ctx
->VertexProgram
._Enabled
) {
2416 r200SetupVertexProg( ctx
);
2418 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2421 rmesa
->NewGLState
= 0;
2425 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2427 _swrast_InvalidateState( ctx
, new_state
);
2428 _swsetup_InvalidateState( ctx
, new_state
);
2429 _ac_InvalidateState( ctx
, new_state
);
2430 _tnl_InvalidateState( ctx
, new_state
);
2431 _ae_invalidate_state( ctx
, new_state
);
2432 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2433 r200VtxfmtInvalidate( ctx
);
2436 /* A hack. The r200 can actually cope just fine with materials
2437 * between begin/ends, so fix this. But how ?
2439 static GLboolean
check_material( GLcontext
*ctx
)
2441 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2444 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2445 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2447 if (tnl
->vb
.AttribPtr
[i
] &&
2448 tnl
->vb
.AttribPtr
[i
]->stride
)
2454 static void r200WrapRunPipeline( GLcontext
*ctx
)
2456 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2457 GLboolean has_material
;
2460 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2464 if (rmesa
->NewGLState
)
2465 r200ValidateState( ctx
);
2467 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2470 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2473 /* Run the pipeline.
2475 _tnl_run_pipeline( ctx
);
2478 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2483 /* Initialize the driver's state functions.
2485 void r200InitStateFuncs( struct dd_function_table
*functions
)
2487 functions
->UpdateState
= r200InvalidateState
;
2488 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2490 functions
->DrawBuffer
= r200DrawBuffer
;
2491 functions
->ReadBuffer
= r200ReadBuffer
;
2493 functions
->AlphaFunc
= r200AlphaFunc
;
2494 functions
->BlendColor
= r200BlendColor
;
2495 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2496 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2497 functions
->ClearColor
= r200ClearColor
;
2498 functions
->ClearDepth
= r200ClearDepth
;
2499 functions
->ClearIndex
= NULL
;
2500 functions
->ClearStencil
= r200ClearStencil
;
2501 functions
->ClipPlane
= r200ClipPlane
;
2502 functions
->ColorMask
= r200ColorMask
;
2503 functions
->CullFace
= r200CullFace
;
2504 functions
->DepthFunc
= r200DepthFunc
;
2505 functions
->DepthMask
= r200DepthMask
;
2506 functions
->DepthRange
= r200DepthRange
;
2507 functions
->Enable
= r200Enable
;
2508 functions
->Fogfv
= r200Fogfv
;
2509 functions
->FrontFace
= r200FrontFace
;
2510 functions
->Hint
= NULL
;
2511 functions
->IndexMask
= NULL
;
2512 functions
->LightModelfv
= r200LightModelfv
;
2513 functions
->Lightfv
= r200Lightfv
;
2514 functions
->LineStipple
= r200LineStipple
;
2515 functions
->LineWidth
= r200LineWidth
;
2516 functions
->LogicOpcode
= r200LogicOpCode
;
2517 functions
->PolygonMode
= r200PolygonMode
;
2518 functions
->PolygonOffset
= r200PolygonOffset
;
2519 functions
->PolygonStipple
= r200PolygonStipple
;
2520 functions
->PointSize
= r200PointSize
;
2521 functions
->RenderMode
= r200RenderMode
;
2522 functions
->Scissor
= r200Scissor
;
2523 functions
->ShadeModel
= r200ShadeModel
;
2524 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2525 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2526 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2527 functions
->Viewport
= r200Viewport
;
2529 /* Swrast hooks for imaging extensions:
2531 functions
->CopyColorTable
= _swrast_CopyColorTable
;
2532 functions
->CopyColorSubTable
= _swrast_CopyColorSubTable
;
2533 functions
->CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2534 functions
->CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2538 void r200InitTnlFuncs( GLcontext
*ctx
)
2540 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2541 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;