1 /**************************************************************************
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Keith Whitwell <keith@tungstengraphics.com>
38 #include "api_arrayelt.h"
42 #include "framebuffer.h"
44 #include "swrast/swrast.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_vertprog.h"
58 #include "drirenderbuffer.h"
61 /* =============================================================
65 static void r200AlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
67 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
68 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
71 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
73 R200_STATECHANGE( rmesa
, ctx
);
75 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
76 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
80 pp_misc
|= R200_ALPHA_TEST_FAIL
;
83 pp_misc
|= R200_ALPHA_TEST_LESS
;
86 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
89 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
92 pp_misc
|= R200_ALPHA_TEST_GREATER
;
95 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
98 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
101 pp_misc
|= R200_ALPHA_TEST_PASS
;
105 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
108 static void r200BlendColor( GLcontext
*ctx
, const GLfloat cf
[4] )
111 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
112 R200_STATECHANGE( rmesa
, ctx
);
113 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
114 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
115 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
116 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
117 if (rmesa
->r200Screen
->drmSupportsBlendColor
)
118 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = r200PackColor( 4, color
[0], color
[1], color
[2], color
[3] );
122 * Calculate the hardware blend factor setting. This same function is used
123 * for source and destination of both alpha and RGB.
126 * The hardware register value for the specified blend factor. This value
127 * will need to be shifted into the correct position for either source or
128 * destination factor.
131 * Since the two cases where source and destination are handled differently
132 * are essentially error cases, they should never happen. Determine if these
133 * cases can be removed.
135 static int blend_factor( GLenum factor
, GLboolean is_src
)
141 func
= R200_BLEND_GL_ZERO
;
144 func
= R200_BLEND_GL_ONE
;
147 func
= R200_BLEND_GL_DST_COLOR
;
149 case GL_ONE_MINUS_DST_COLOR
:
150 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
153 func
= R200_BLEND_GL_SRC_COLOR
;
155 case GL_ONE_MINUS_SRC_COLOR
:
156 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
159 func
= R200_BLEND_GL_SRC_ALPHA
;
161 case GL_ONE_MINUS_SRC_ALPHA
:
162 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
165 func
= R200_BLEND_GL_DST_ALPHA
;
167 case GL_ONE_MINUS_DST_ALPHA
:
168 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
170 case GL_SRC_ALPHA_SATURATE
:
171 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
173 case GL_CONSTANT_COLOR
:
174 func
= R200_BLEND_GL_CONST_COLOR
;
176 case GL_ONE_MINUS_CONSTANT_COLOR
:
177 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
179 case GL_CONSTANT_ALPHA
:
180 func
= R200_BLEND_GL_CONST_ALPHA
;
182 case GL_ONE_MINUS_CONSTANT_ALPHA
:
183 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
186 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
192 * Sets both the blend equation and the blend function.
193 * This is done in a single
194 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
195 * change the interpretation of the blend function.
196 * Also, make sure that blend function and blend equation are set to their default
197 * value if color blending is not enabled, since at least blend equations GL_MIN
198 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
201 static void r200_set_blend_state( GLcontext
* ctx
)
203 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
204 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
205 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
207 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
208 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
209 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
210 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
211 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
212 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
214 R200_STATECHANGE( rmesa
, ctx
);
216 if (rmesa
->r200Screen
->drmSupportsBlendColor
) {
217 if (ctx
->Color
.ColorLogicOpEnabled
) {
218 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
219 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
220 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
222 } else if (ctx
->Color
.BlendEnabled
) {
223 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
;
226 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
227 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
228 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
233 if (ctx
->Color
.ColorLogicOpEnabled
) {
234 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
235 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
237 } else if (ctx
->Color
.BlendEnabled
) {
238 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
;
241 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
242 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
247 func
= (blend_factor( ctx
->Color
.BlendSrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
248 (blend_factor( ctx
->Color
.BlendDstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
250 switch(ctx
->Color
.BlendEquationRGB
) {
252 eqn
= R200_COMB_FCN_ADD_CLAMP
;
255 case GL_FUNC_SUBTRACT
:
256 eqn
= R200_COMB_FCN_SUB_CLAMP
;
259 case GL_FUNC_REVERSE_SUBTRACT
:
260 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
264 eqn
= R200_COMB_FCN_MIN
;
265 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
266 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
270 eqn
= R200_COMB_FCN_MAX
;
271 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
272 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
276 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
277 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationRGB
);
281 if (!rmesa
->r200Screen
->drmSupportsBlendColor
) {
282 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
286 funcA
= (blend_factor( ctx
->Color
.BlendSrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
287 (blend_factor( ctx
->Color
.BlendDstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
289 switch(ctx
->Color
.BlendEquationA
) {
291 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
294 case GL_FUNC_SUBTRACT
:
295 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
298 case GL_FUNC_REVERSE_SUBTRACT
:
299 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
303 eqnA
= R200_COMB_FCN_MIN
;
304 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
305 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
309 eqnA
= R200_COMB_FCN_MAX
;
310 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
311 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
315 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
316 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationA
);
320 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
321 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
325 static void r200BlendEquationSeparate( GLcontext
*ctx
,
326 GLenum modeRGB
, GLenum modeA
)
328 r200_set_blend_state( ctx
);
331 static void r200BlendFuncSeparate( GLcontext
*ctx
,
332 GLenum sfactorRGB
, GLenum dfactorRGB
,
333 GLenum sfactorA
, GLenum dfactorA
)
335 r200_set_blend_state( ctx
);
339 /* =============================================================
343 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
345 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
347 R200_STATECHANGE( rmesa
, ctx
);
348 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
350 switch ( ctx
->Depth
.Func
) {
352 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
355 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
358 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
361 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
364 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
367 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
370 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
373 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
378 static void r200ClearDepth( GLcontext
*ctx
, GLclampd d
)
380 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
381 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
382 R200_DEPTH_FORMAT_MASK
);
385 case R200_DEPTH_FORMAT_16BIT_INT_Z
:
386 rmesa
->state
.depth
.clear
= d
* 0x0000ffff;
388 case R200_DEPTH_FORMAT_24BIT_INT_Z
:
389 rmesa
->state
.depth
.clear
= d
* 0x00ffffff;
394 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
396 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
397 R200_STATECHANGE( rmesa
, ctx
);
399 if ( ctx
->Depth
.Mask
) {
400 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
402 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
407 /* =============================================================
412 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
414 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
415 union { int i
; float f
; } c
, d
;
419 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
420 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
424 if (!ctx
->Fog
.Enabled
)
426 R200_STATECHANGE(rmesa
, tcl
);
427 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
428 switch (ctx
->Fog
.Mode
) {
430 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
431 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
436 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
437 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
441 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
443 d
.f
= -ctx
->Fog
.Density
;
446 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
448 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
455 switch (ctx
->Fog
.Mode
) {
458 d
.f
= -ctx
->Fog
.Density
;
462 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
470 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
471 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
475 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
476 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
481 R200_STATECHANGE( rmesa
, ctx
);
482 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
483 i
= r200PackColor( 4, col
[0], col
[1], col
[2], 0 );
484 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
485 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
487 case GL_FOG_COORD_SRC
: {
488 GLuint out_0
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
];
489 GLuint fog
= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
];
491 fog
&= ~R200_FOG_USE_MASK
;
492 if ( ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORD
|| ctx
->VertexProgram
.Enabled
) {
493 fog
|= R200_FOG_USE_VTX_FOG
;
494 out_0
|= R200_VTX_DISCRETE_FOG
;
497 fog
|= R200_FOG_USE_SPEC_ALPHA
;
498 out_0
&= ~R200_VTX_DISCRETE_FOG
;
501 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
502 R200_STATECHANGE( rmesa
, ctx
);
503 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
506 if (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
]) {
507 R200_STATECHANGE( rmesa
, vtx
);
508 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
517 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
518 R200_STATECHANGE( rmesa
, fog
);
519 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
520 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
525 /* =============================================================
530 static GLboolean
intersect_rect( drm_clip_rect_t
*out
,
535 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
536 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
537 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
538 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
539 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
540 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
545 void r200RecalcScissorRects( r200ContextPtr rmesa
)
547 drm_clip_rect_t
*out
;
550 /* Grow cliprect store?
552 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
553 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
554 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
555 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
558 if (rmesa
->state
.scissor
.pClipRects
)
559 FREE(rmesa
->state
.scissor
.pClipRects
);
561 rmesa
->state
.scissor
.pClipRects
=
562 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
563 sizeof(drm_clip_rect_t
) );
565 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
566 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
571 out
= rmesa
->state
.scissor
.pClipRects
;
572 rmesa
->state
.scissor
.numClipRects
= 0;
574 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
575 if ( intersect_rect( out
,
576 &rmesa
->pClipRects
[i
],
577 &rmesa
->state
.scissor
.rect
) ) {
578 rmesa
->state
.scissor
.numClipRects
++;
585 static void r200UpdateScissor( GLcontext
*ctx
)
587 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
589 if ( rmesa
->dri
.drawable
) {
590 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
592 int x
= ctx
->Scissor
.X
;
593 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
594 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
595 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
597 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
598 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
599 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
600 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
602 r200RecalcScissorRects( rmesa
);
607 static void r200Scissor( GLcontext
*ctx
,
608 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
610 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
612 if ( ctx
->Scissor
.Enabled
) {
613 R200_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
614 r200UpdateScissor( ctx
);
620 /* =============================================================
624 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
626 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
627 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
628 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
630 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
631 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
633 if ( ctx
->Polygon
.CullFlag
) {
634 switch ( ctx
->Polygon
.CullFaceMode
) {
636 s
&= ~R200_FFACE_SOLID
;
637 t
|= R200_CULL_FRONT
;
640 s
&= ~R200_BFACE_SOLID
;
643 case GL_FRONT_AND_BACK
:
644 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
645 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
650 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
651 R200_STATECHANGE(rmesa
, set
);
652 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
655 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
656 R200_STATECHANGE(rmesa
, tcl
);
657 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
661 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
663 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
665 R200_STATECHANGE( rmesa
, set
);
666 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
668 R200_STATECHANGE( rmesa
, tcl
);
669 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
673 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
676 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
677 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
682 /* =============================================================
685 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
687 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
688 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
690 R200_STATECHANGE( rmesa
, cst
);
691 R200_STATECHANGE( rmesa
, ptp
);
692 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
693 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
694 /* this is the size param of the point size calculation (point size reg value
695 is not used when calculation is active). */
696 fcmd
[PTP_VPORT_SCALE_PTSIZE
] = ctx
->Point
.Size
;
699 static void r200PointParameter( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
701 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
702 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
705 case GL_POINT_SIZE_MIN
:
706 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
707 R200_STATECHANGE( rmesa
, lin
);
708 R200_STATECHANGE( rmesa
, ptp
);
709 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= 0xffff;
710 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Point
.MinSize
* 16.0) << 16;
711 fcmd
[PTP_CLAMP_MIN
] = ctx
->Point
.MinSize
;
713 case GL_POINT_SIZE_MAX
:
714 R200_STATECHANGE( rmesa
, cst
);
715 R200_STATECHANGE( rmesa
, ptp
);
716 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= 0xffff;
717 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= (GLuint
)(ctx
->Point
.MaxSize
* 16.0) << 16;
718 fcmd
[PTP_CLAMP_MAX
] = ctx
->Point
.MaxSize
;
720 case GL_POINT_DISTANCE_ATTENUATION
:
721 R200_STATECHANGE( rmesa
, vtx
);
722 R200_STATECHANGE( rmesa
, spr
);
723 R200_STATECHANGE( rmesa
, ptp
);
724 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.ptp
.cmd
;
725 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &=
726 ~(R200_PS_MULT_MASK
| R200_PS_LIN_ATT_ZERO
| R200_PS_SE_SEL_STATE
);
727 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
728 r200ValidateState looks like overkill */
729 if (ctx
->Point
.Params
[0] != 1.0 ||
730 ctx
->Point
.Params
[1] != 0.0 ||
731 ctx
->Point
.Params
[2] != 0.0 ||
732 (ctx
->VertexProgram
.Enabled
&& ctx
->VertexProgram
.PointSizeEnabled
)) {
733 /* all we care for vp would be the ps_se_sel_state setting */
734 fcmd
[PTP_ATT_CONST_QUAD
] = ctx
->Point
.Params
[2];
735 fcmd
[PTP_ATT_CONST_LIN
] = ctx
->Point
.Params
[1];
736 fcmd
[PTP_ATT_CONST_CON
] = ctx
->Point
.Params
[0];
737 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_MULT_ATTENCONST
;
738 if (ctx
->Point
.Params
[1] == 0.0)
739 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_LIN_ATT_ZERO
;
740 /* FIXME: setting this here doesn't look quite ok - we only want to do
741 that if we're actually drawing points probably */
742 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_PT_SIZE
;
743 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |= R200_VTX_POINT_SIZE
;
746 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
747 R200_PS_SE_SEL_STATE
| R200_PS_MULT_CONST
;
748 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_PT_SIZE
;
749 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~R200_VTX_POINT_SIZE
;
752 case GL_POINT_FADE_THRESHOLD_SIZE
:
753 /* don't support multisampling, so doesn't matter. */
755 /* can't do these but don't need them.
756 case GL_POINT_SPRITE_R_MODE_NV:
757 case GL_POINT_SPRITE_COORD_ORIGIN: */
759 fprintf(stderr
, "bad pname parameter in r200PointParameter\n");
764 /* =============================================================
767 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
769 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
771 R200_STATECHANGE( rmesa
, lin
);
772 R200_STATECHANGE( rmesa
, set
);
774 /* Line width is stored in U6.4 format.
776 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
777 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Line
._Width
* 16.0);
779 if ( widthf
> 1.0 ) {
780 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
782 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
786 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
788 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
790 R200_STATECHANGE( rmesa
, lin
);
791 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
792 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
796 /* =============================================================
799 static void r200ColorMask( GLcontext
*ctx
,
800 GLboolean r
, GLboolean g
,
801 GLboolean b
, GLboolean a
)
803 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
804 GLuint mask
= r200PackColor( rmesa
->r200Screen
->cpp
,
805 ctx
->Color
.ColorMask
[RCOMP
],
806 ctx
->Color
.ColorMask
[GCOMP
],
807 ctx
->Color
.ColorMask
[BCOMP
],
808 ctx
->Color
.ColorMask
[ACOMP
] );
810 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
812 if (!(r
&& g
&& b
&& a
))
813 flag
|= R200_PLANE_MASK_ENABLE
;
815 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
816 R200_STATECHANGE( rmesa
, ctx
);
817 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
820 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
821 R200_STATECHANGE( rmesa
, msk
);
822 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
827 /* =============================================================
831 static void r200PolygonOffset( GLcontext
*ctx
,
832 GLfloat factor
, GLfloat units
)
834 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
835 float_ui32_type constant
= { units
* rmesa
->state
.depth
.scale
};
836 float_ui32_type factoru
= { factor
};
841 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
843 R200_STATECHANGE( rmesa
, zbs
);
844 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = factoru
.ui32
;
845 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = constant
.ui32
;
848 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
850 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
852 drm_radeon_stipple_t stipple
;
854 /* Must flip pattern upside down.
856 for ( i
= 0 ; i
< 32 ; i
++ ) {
857 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
860 /* TODO: push this into cmd mechanism
862 R200_FIREVERTICES( rmesa
);
863 LOCK_HARDWARE( rmesa
);
865 /* FIXME: Use window x,y offsets into stipple RAM.
867 stipple
.mask
= rmesa
->state
.stipple
.mask
;
868 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
869 &stipple
, sizeof(stipple
) );
870 UNLOCK_HARDWARE( rmesa
);
873 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
875 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
876 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
878 /* Can't generally do unfilled via tcl, but some good special
881 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
882 if (rmesa
->TclFallback
) {
883 r200ChooseRenderState( ctx
);
884 r200ChooseVertexState( ctx
);
889 /* =============================================================
890 * Rendering attributes
892 * We really don't want to recalculate all this every time we bind a
893 * texture. These things shouldn't change all that often, so it makes
894 * sense to break them out of the core texture state update routines.
897 /* Examine lighting and texture state to determine if separate specular
900 static void r200UpdateSpecular( GLcontext
*ctx
)
902 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
903 u_int32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
905 R200_STATECHANGE( rmesa
, tcl
);
906 R200_STATECHANGE( rmesa
, vtx
);
908 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
909 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
910 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
911 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
912 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
914 p
&= ~R200_SPECULAR_ENABLE
;
916 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
919 if (ctx
->Light
.Enabled
&&
920 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
921 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
922 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
923 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
924 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
925 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
926 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
927 p
|= R200_SPECULAR_ENABLE
;
928 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
929 ~R200_DIFFUSE_SPECULAR_COMBINE
;
931 else if (ctx
->Light
.Enabled
) {
932 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
933 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
934 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
935 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
936 } else if (ctx
->Fog
.ColorSumEnabled
) {
937 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
938 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
939 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
940 p
|= R200_SPECULAR_ENABLE
;
942 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
943 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
946 if (ctx
->Fog
.Enabled
) {
947 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
948 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
949 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
952 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
953 R200_STATECHANGE( rmesa
, ctx
);
954 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
957 /* Update vertex/render formats
959 if (rmesa
->TclFallback
) {
960 r200ChooseRenderState( ctx
);
961 r200ChooseVertexState( ctx
);
966 /* =============================================================
971 /* Update on colormaterial, material emmissive/ambient,
972 * lightmodel.globalambient
974 static void update_global_ambient( GLcontext
*ctx
)
976 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
977 float *fcmd
= (float *)R200_DB_STATE( glt
);
979 /* Need to do more if both emmissive & ambient are PREMULT:
980 * I believe this is not nessary when using source_material. This condition thus
981 * will never happen currently, and the function has no dependencies on materials now
983 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
984 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
985 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
987 COPY_3V( &fcmd
[GLT_RED
],
988 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
989 ACC_SCALE_3V( &fcmd
[GLT_RED
],
990 ctx
->Light
.Model
.Ambient
,
991 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
995 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
998 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
1001 /* Update on change to
1003 * - light[p].enabled
1005 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
1007 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1009 /* fprintf(stderr, "%s\n", __FUNCTION__); */
1012 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1013 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
1015 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
1016 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
1017 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
1019 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1023 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
1025 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1026 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
1027 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1028 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1029 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1030 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1031 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1032 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1033 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1034 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
1036 if (ctx
->Light
.ColorMaterialEnabled
) {
1037 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
1039 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1040 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1041 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
1044 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1045 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
1047 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1048 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1049 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
1052 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1053 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
1055 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1056 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1057 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
1060 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1061 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
1063 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1064 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1065 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
1068 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
1069 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
1072 if (mask
& MAT_BIT_BACK_EMISSION
) {
1073 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1074 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1077 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1078 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1080 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1081 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1082 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1084 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1085 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1087 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1088 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1089 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1091 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1092 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1094 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1095 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1096 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1099 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1100 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1104 /* Default to SOURCE_MATERIAL:
1107 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1108 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1109 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1110 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1111 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1112 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1113 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1114 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1117 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1118 R200_STATECHANGE( rmesa
, tcl
);
1119 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1125 void r200UpdateMaterial( GLcontext
*ctx
)
1127 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1128 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1129 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1130 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1133 /* Might be possible and faster to update everything unconditionally? */
1134 if (ctx
->Light
.ColorMaterialEnabled
)
1135 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1137 if (R200_DEBUG
& DEBUG_STATE
)
1138 fprintf(stderr
, "%s\n", __FUNCTION__
);
1140 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1141 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1142 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1143 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1144 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1146 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1147 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1148 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1149 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1150 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1152 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1153 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1154 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1155 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1156 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1158 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1159 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1160 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1161 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1162 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1164 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1165 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1168 if (mask
& MAT_BIT_BACK_EMISSION
) {
1169 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1170 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1171 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1172 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1174 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1175 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1176 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1177 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1178 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1180 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1181 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1182 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1183 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1184 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1186 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1187 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1188 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1189 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1190 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1192 if (mask
& MAT_BIT_BACK_SHININESS
) {
1193 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1196 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1197 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1199 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1200 update_global_ambient( ctx ); */
1205 * _MESA_NEW_NEED_EYE_COORDS
1207 * Uses derived state from mesa:
1212 * _ModelViewInvScale
1216 * which are calculated in light.c and are correct for the current
1217 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1218 * and _MESA_NEW_NEED_EYE_COORDS.
1220 static void update_light( GLcontext
*ctx
)
1222 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1224 /* Have to check these, or have an automatic shortcircuit mechanism
1225 * to remove noop statechanges. (Or just do a better job on the
1229 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1231 if (ctx
->_NeedEyeCoords
)
1232 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1234 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1236 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1238 R200_STATECHANGE( rmesa
, tcl
);
1239 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1244 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1245 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1246 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1247 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1248 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1249 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1254 if (ctx
->Light
.Enabled
) {
1256 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1257 if (ctx
->Light
.Light
[p
].Enabled
) {
1258 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1259 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1261 if (l
->EyePosition
[3] == 0.0) {
1262 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1263 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1264 fcmd
[LIT_POSITION_W
] = 0;
1265 fcmd
[LIT_DIRECTION_W
] = 0;
1267 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1268 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1269 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1270 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1271 fcmd
[LIT_DIRECTION_W
] = 0;
1274 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1280 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1281 GLenum pname
, const GLfloat
*params
)
1283 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1284 GLint p
= light
- GL_LIGHT0
;
1285 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1286 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1293 update_light_colors( ctx
, p
);
1296 case GL_SPOT_DIRECTION
:
1297 /* picked up in update_light */
1301 /* positions picked up in update_light, but can do flag here */
1302 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1303 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1305 R200_STATECHANGE(rmesa
, tcl
);
1306 if (l
->EyePosition
[3] != 0.0F
)
1307 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1309 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1313 case GL_SPOT_EXPONENT
:
1314 R200_STATECHANGE(rmesa
, lit
[p
]);
1315 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1318 case GL_SPOT_CUTOFF
: {
1319 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1320 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1322 R200_STATECHANGE(rmesa
, lit
[p
]);
1323 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1325 R200_STATECHANGE(rmesa
, tcl
);
1326 if (l
->SpotCutoff
!= 180.0F
)
1327 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1329 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1334 case GL_CONSTANT_ATTENUATION
:
1335 R200_STATECHANGE(rmesa
, lit
[p
]);
1336 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1337 if ( params
[0] == 0.0 )
1338 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1340 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1342 case GL_LINEAR_ATTENUATION
:
1343 R200_STATECHANGE(rmesa
, lit
[p
]);
1344 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1346 case GL_QUADRATIC_ATTENUATION
:
1347 R200_STATECHANGE(rmesa
, lit
[p
]);
1348 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1354 /* Set RANGE_ATTEN only when needed */
1357 case GL_CONSTANT_ATTENUATION
:
1358 case GL_LINEAR_ATTENUATION
:
1359 case GL_QUADRATIC_ATTENUATION
: {
1360 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1361 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1362 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1363 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1364 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1365 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1367 if ( l
->EyePosition
[3] == 0.0F
||
1368 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1369 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1370 /* Disable attenuation */
1371 icmd
[idx
] &= ~atten_flag
;
1373 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1374 /* Enable only constant portion of attenuation calculation */
1375 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1377 /* Enable full attenuation calculation */
1378 icmd
[idx
] &= ~atten_const_flag
;
1379 icmd
[idx
] |= atten_flag
;
1383 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1391 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1393 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1394 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1395 for these and only these modes). This means specular highlights may turn out
1396 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1397 is not set, though it seems to happen rarely and the effect seems quite
1398 subtle. May need TCL fallback to fix it completely, though I'm not sure
1399 how you'd identify the cases where the specular highlights indeed will
1400 be wrong. Don't know if fglrx does something special in that case.
1402 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1403 R200_STATECHANGE( rmesa
, tcl
);
1404 if (ctx
->Light
.Model
.LocalViewer
||
1405 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1406 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1408 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1411 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1412 const GLfloat
*param
)
1414 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1417 case GL_LIGHT_MODEL_AMBIENT
:
1418 update_global_ambient( ctx
);
1421 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1422 r200UpdateLocalViewer( ctx
);
1425 case GL_LIGHT_MODEL_TWO_SIDE
:
1426 R200_STATECHANGE( rmesa
, tcl
);
1427 if (ctx
->Light
.Model
.TwoSide
)
1428 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1430 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1431 if (rmesa
->TclFallback
) {
1432 r200ChooseRenderState( ctx
);
1433 r200ChooseVertexState( ctx
);
1437 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1438 r200UpdateSpecular(ctx
);
1446 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1448 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1449 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1451 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1452 R200_ALPHA_SHADE_MASK
|
1453 R200_SPECULAR_SHADE_MASK
|
1454 R200_FOG_SHADE_MASK
|
1455 R200_DISC_FOG_SHADE_MASK
);
1459 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1460 R200_ALPHA_SHADE_FLAT
|
1461 R200_SPECULAR_SHADE_FLAT
|
1462 R200_FOG_SHADE_FLAT
|
1463 R200_DISC_FOG_SHADE_FLAT
);
1466 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1467 R200_ALPHA_SHADE_GOURAUD
|
1468 R200_SPECULAR_SHADE_GOURAUD
|
1469 R200_FOG_SHADE_GOURAUD
|
1470 R200_DISC_FOG_SHADE_GOURAUD
);
1476 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1477 R200_STATECHANGE( rmesa
, set
);
1478 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1483 /* =============================================================
1487 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1489 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1490 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1491 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1493 R200_STATECHANGE( rmesa
, ucp
[p
] );
1494 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1495 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1496 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1497 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1500 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1502 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1505 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1506 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1507 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1509 R200_STATECHANGE( rmesa
, ucp
[p
] );
1510 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1511 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1512 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1513 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1519 /* =============================================================
1524 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1525 GLint ref
, GLuint mask
)
1527 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1528 GLuint refmask
= (((ctx
->Stencil
.Ref
[0] & 0xff) << R200_STENCIL_REF_SHIFT
) |
1529 ((ctx
->Stencil
.ValueMask
[0] & 0xff) << R200_STENCIL_MASK_SHIFT
));
1531 R200_STATECHANGE( rmesa
, ctx
);
1532 R200_STATECHANGE( rmesa
, msk
);
1534 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1535 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1536 R200_STENCIL_VALUE_MASK
);
1538 switch ( ctx
->Stencil
.Function
[0] ) {
1540 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1543 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1546 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1549 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1552 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1555 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1558 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1561 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1565 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1569 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1571 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1573 R200_STATECHANGE( rmesa
, msk
);
1574 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1575 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1576 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
);
1580 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1581 GLenum zfail
, GLenum zpass
)
1583 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1585 R200_STATECHANGE( rmesa
, ctx
);
1586 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1587 R200_STENCIL_ZFAIL_MASK
|
1588 R200_STENCIL_ZPASS_MASK
);
1590 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1592 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1595 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1598 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1601 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1604 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1606 case GL_INCR_WRAP_EXT
:
1607 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1609 case GL_DECR_WRAP_EXT
:
1610 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1613 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1617 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1619 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1622 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1625 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1628 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1631 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1633 case GL_INCR_WRAP_EXT
:
1634 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1636 case GL_DECR_WRAP_EXT
:
1637 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1640 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1644 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1646 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1649 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1652 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1655 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1658 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1660 case GL_INCR_WRAP_EXT
:
1661 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1663 case GL_DECR_WRAP_EXT
:
1664 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1667 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1672 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1674 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1676 rmesa
->state
.stencil
.clear
=
1677 ((GLuint
) (ctx
->Stencil
.Clear
& 0xff) |
1678 (0xff << R200_STENCIL_MASK_SHIFT
) |
1679 ((ctx
->Stencil
.WriteMask
[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT
));
1683 /* =============================================================
1684 * Window position and viewport transformation
1688 * To correctly position primitives:
1690 #define SUBPIXEL_X 0.125
1691 #define SUBPIXEL_Y 0.125
1695 * Called when window size or position changes or viewport or depth range
1696 * state is changed. We update the hardware viewport state here.
1698 void r200UpdateWindow( GLcontext
*ctx
)
1700 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1701 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1702 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1703 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1704 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1706 float_ui32_type sx
= { v
[MAT_SX
] };
1707 float_ui32_type tx
= { v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
};
1708 float_ui32_type sy
= { - v
[MAT_SY
] };
1709 float_ui32_type ty
= { (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
};
1710 float_ui32_type sz
= { v
[MAT_SZ
] * rmesa
->state
.depth
.scale
};
1711 float_ui32_type tz
= { v
[MAT_TZ
] * rmesa
->state
.depth
.scale
};
1713 R200_FIREVERTICES( rmesa
);
1714 R200_STATECHANGE( rmesa
, vpt
);
1716 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = sx
.ui32
;
1717 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1718 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = sy
.ui32
;
1719 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1720 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = sz
.ui32
;
1721 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = tz
.ui32
;
1726 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1727 GLsizei width
, GLsizei height
)
1729 /* Don't pipeline viewport changes, conflict with window offset
1730 * setting below. Could apply deltas to rescue pipelined viewport
1731 * values, or keep the originals hanging around.
1733 r200UpdateWindow( ctx
);
1736 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1739 r200UpdateWindow( ctx
);
1742 void r200UpdateViewportOffset( GLcontext
*ctx
)
1744 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1745 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1746 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1747 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1748 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1753 tx
.f
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1754 ty
.f
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1756 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != tx
.ui32
||
1757 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != ty
.ui32
)
1759 /* Note: this should also modify whatever data the context reset
1762 R200_STATECHANGE( rmesa
, vpt
);
1763 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = tx
.ui32
;
1764 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = ty
.ui32
;
1766 /* update polygon stipple x/y screen offset */
1769 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1771 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1772 R200_STIPPLE_Y_OFFSET_MASK
);
1774 /* add magic offsets, then invert */
1775 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1776 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1777 & R200_STIPPLE_COORD_MASK
);
1779 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1780 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1782 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1783 R200_STATECHANGE( rmesa
, msc
);
1784 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1789 r200UpdateScissor( ctx
);
1794 /* =============================================================
1798 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1800 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1802 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1803 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1804 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1805 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1806 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1808 color
[2], color
[3] );
1812 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1814 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1815 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1819 static GLuint r200_rop_tab
[] = {
1822 R200_ROP_AND_REVERSE
,
1824 R200_ROP_AND_INVERTED
,
1831 R200_ROP_OR_REVERSE
,
1832 R200_ROP_COPY_INVERTED
,
1833 R200_ROP_OR_INVERTED
,
1838 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1840 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1841 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1845 R200_STATECHANGE( rmesa
, msk
);
1846 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1851 * Set up the cliprects for either front or back-buffer drawing.
1853 void r200SetCliprects( r200ContextPtr rmesa
)
1855 __DRIdrawablePrivate
*const drawable
= rmesa
->dri
.drawable
;
1856 __DRIdrawablePrivate
*const readable
= rmesa
->dri
.readable
;
1857 GLframebuffer
*const draw_fb
= (GLframebuffer
*) drawable
->driverPrivate
;
1858 GLframebuffer
*const read_fb
= (GLframebuffer
*) readable
->driverPrivate
;
1860 if (draw_fb
->_ColorDrawBufferMask
[0]
1861 == BUFFER_BIT_BACK_LEFT
) {
1862 /* Can't ignore 2d windows if we are page flipping.
1864 if ( drawable
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1865 rmesa
->numClipRects
= drawable
->numClipRects
;
1866 rmesa
->pClipRects
= drawable
->pClipRects
;
1869 rmesa
->numClipRects
= drawable
->numBackClipRects
;
1870 rmesa
->pClipRects
= drawable
->pBackClipRects
;
1874 /* front buffer (or none, or multiple buffers) */
1875 rmesa
->numClipRects
= drawable
->numClipRects
;
1876 rmesa
->pClipRects
= drawable
->pClipRects
;
1879 if ((draw_fb
->Width
!= drawable
->w
) || (draw_fb
->Height
!= drawable
->h
)) {
1880 _mesa_resize_framebuffer(rmesa
->glCtx
, draw_fb
,
1881 drawable
->w
, drawable
->h
);
1882 draw_fb
->Initialized
= GL_TRUE
;
1885 if (drawable
!= readable
) {
1886 if ((read_fb
->Width
!= readable
->w
) ||
1887 (read_fb
->Height
!= readable
->h
)) {
1888 _mesa_resize_framebuffer(rmesa
->glCtx
, read_fb
,
1889 readable
->w
, readable
->h
);
1890 read_fb
->Initialized
= GL_TRUE
;
1894 if (rmesa
->state
.scissor
.enabled
)
1895 r200RecalcScissorRects( rmesa
);
1897 rmesa
->lastStamp
= drawable
->lastStamp
;
1901 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1903 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1905 if (R200_DEBUG
& DEBUG_DRI
)
1906 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1907 _mesa_lookup_enum_by_nr( mode
));
1909 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1912 * _ColorDrawBufferMask is easier to cope with than <mode>.
1913 * Check for software fallback, update cliprects.
1915 switch ( ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] ) {
1916 case BUFFER_BIT_FRONT_LEFT
:
1917 case BUFFER_BIT_BACK_LEFT
:
1918 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1921 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1922 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1926 r200SetCliprects( rmesa
);
1928 /* We'll set the drawing engine's offset/pitch parameters later
1929 * when we update other state.
1934 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1936 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1939 /* =============================================================
1940 * State enable/disable
1943 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1945 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1948 if ( R200_DEBUG
& DEBUG_STATE
)
1949 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1950 _mesa_lookup_enum_by_nr( cap
),
1951 state
? "GL_TRUE" : "GL_FALSE" );
1954 /* Fast track this one...
1962 R200_STATECHANGE( rmesa
, ctx
);
1964 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1966 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1971 case GL_COLOR_LOGIC_OP
:
1972 r200_set_blend_state( ctx
);
1975 case GL_CLIP_PLANE0
:
1976 case GL_CLIP_PLANE1
:
1977 case GL_CLIP_PLANE2
:
1978 case GL_CLIP_PLANE3
:
1979 case GL_CLIP_PLANE4
:
1980 case GL_CLIP_PLANE5
:
1981 p
= cap
-GL_CLIP_PLANE0
;
1982 R200_STATECHANGE( rmesa
, tcl
);
1984 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1985 r200ClipPlane( ctx
, cap
, NULL
);
1988 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1992 case GL_COLOR_MATERIAL
:
1993 r200ColorMaterial( ctx
, 0, 0 );
1994 r200UpdateMaterial( ctx
);
1998 r200CullFace( ctx
, 0 );
2002 R200_STATECHANGE(rmesa
, ctx
);
2004 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
2006 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
2011 R200_STATECHANGE(rmesa
, ctx
);
2013 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
2014 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
2016 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
2017 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
2022 R200_STATECHANGE(rmesa
, ctx
);
2024 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
2025 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
2027 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
2028 R200_STATECHANGE(rmesa
, tcl
);
2029 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
2031 r200UpdateSpecular( ctx
); /* for PK_SPEC */
2032 if (rmesa
->TclFallback
)
2033 r200ChooseVertexState( ctx
);
2034 _mesa_allow_light_in_model( ctx
, !state
);
2045 R200_STATECHANGE(rmesa
, tcl
);
2046 p
= cap
- GL_LIGHT0
;
2048 flag
= (R200_LIGHT_1_ENABLE
|
2049 R200_LIGHT_1_ENABLE_AMBIENT
|
2050 R200_LIGHT_1_ENABLE_SPECULAR
);
2052 flag
= (R200_LIGHT_0_ENABLE
|
2053 R200_LIGHT_0_ENABLE_AMBIENT
|
2054 R200_LIGHT_0_ENABLE_SPECULAR
);
2057 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
2059 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
2063 update_light_colors( ctx
, p
);
2067 r200UpdateSpecular(ctx
);
2068 /* for reflection map fixup - might set recheck_texgen for all units too */
2069 rmesa
->NewGLState
|= _NEW_TEXTURE
;
2072 case GL_LINE_SMOOTH
:
2073 R200_STATECHANGE( rmesa
, ctx
);
2075 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
2077 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
2081 case GL_LINE_STIPPLE
:
2082 R200_STATECHANGE( rmesa
, set
);
2084 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
2086 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
2091 R200_STATECHANGE( rmesa
, tcl
);
2093 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
2095 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
2099 /* Pointsize registers on r200 only work for point sprites, and point smooth
2100 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
2101 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
2102 * is enough to satisfy conform.
2104 case GL_POINT_SMOOTH
:
2107 /* These don't really do anything, as we don't use the 3vtx
2111 case GL_POLYGON_OFFSET_POINT
:
2112 R200_STATECHANGE( rmesa
, set
);
2114 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
2116 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
2120 case GL_POLYGON_OFFSET_LINE
:
2121 R200_STATECHANGE( rmesa
, set
);
2123 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
2125 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
2130 case GL_POINT_SPRITE_ARB
:
2131 R200_STATECHANGE( rmesa
, spr
);
2134 for (i
= 0; i
< 6; i
++) {
2135 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |=
2136 ctx
->Point
.CoordReplace
[i
] << (R200_PS_GEN_TEX_0_SHIFT
+ i
);
2139 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~R200_PS_GEN_TEX_MASK
;
2143 case GL_POLYGON_OFFSET_FILL
:
2144 R200_STATECHANGE( rmesa
, set
);
2146 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
2148 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
2152 case GL_POLYGON_SMOOTH
:
2153 R200_STATECHANGE( rmesa
, ctx
);
2155 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2157 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2161 case GL_POLYGON_STIPPLE
:
2162 R200_STATECHANGE(rmesa
, set
);
2164 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2166 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2170 case GL_RESCALE_NORMAL_EXT
: {
2171 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2172 R200_STATECHANGE( rmesa
, tcl
);
2174 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2176 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2181 case GL_SCISSOR_TEST
:
2182 R200_FIREVERTICES( rmesa
);
2183 rmesa
->state
.scissor
.enabled
= state
;
2184 r200UpdateScissor( ctx
);
2187 case GL_STENCIL_TEST
:
2188 if ( rmesa
->state
.stencil
.hwBuffer
) {
2189 R200_STATECHANGE( rmesa
, ctx
);
2191 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2193 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2196 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2200 case GL_TEXTURE_GEN_Q
:
2201 case GL_TEXTURE_GEN_R
:
2202 case GL_TEXTURE_GEN_S
:
2203 case GL_TEXTURE_GEN_T
:
2204 /* Picked up in r200UpdateTextureState.
2206 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2209 case GL_COLOR_SUM_EXT
:
2210 r200UpdateSpecular ( ctx
);
2213 case GL_VERTEX_PROGRAM_ARB
:
2216 rmesa
->curr_vp_hw
= NULL
;
2217 R200_STATECHANGE( rmesa
, vap
);
2218 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE
;
2219 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2220 not sure about tcl scalar state - we need at least grd
2221 with vert progs too.
2222 ucp looks like it doesn't get overwritten (may even work
2223 with vp for pos-invariant progs if we're lucky) */
2224 R200_STATECHANGE( rmesa
, mtl
[0] );
2225 R200_STATECHANGE( rmesa
, mtl
[1] );
2226 R200_STATECHANGE( rmesa
, fog
);
2227 R200_STATECHANGE( rmesa
, glt
);
2228 R200_STATECHANGE( rmesa
, eye
);
2229 for (i
= R200_MTX_MV
; i
<= R200_MTX_TEX5
; i
++) {
2230 R200_STATECHANGE( rmesa
, mat
[i
] );
2232 for (i
= 0 ; i
< 8; i
++) {
2233 R200_STATECHANGE( rmesa
, lit
[i
] );
2235 R200_STATECHANGE( rmesa
, tcl
);
2236 for (i
= 0; i
<= ctx
->Const
.MaxClipPlanes
; i
++) {
2237 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << i
)) {
2238 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<< i
);
2241 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2244 /* ugly. Need to call everything which might change compsel. */
2245 r200UpdateSpecular( ctx
);
2247 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2248 but without it doom3 locks up at always the same places. Why? */
2249 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2250 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2251 r200UpdateTextureState( ctx
);
2252 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2253 non-current derived enabled values which may revert the state atoms for frag progs even when
2254 they already got disabled... ugh
2255 Should really figure out why we need to call r200UpdateTextureState in the first place */
2257 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2258 R200_STATECHANGE( rmesa
, pix
[unit
] );
2259 R200_STATECHANGE( rmesa
, tex
[unit
] );
2260 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2261 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2262 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2263 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2264 we don't announce ATI_fs, right? */
2265 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2267 R200_STATECHANGE( rmesa
, cst
);
2268 R200_STATECHANGE( rmesa
, tf
);
2269 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2273 /* picked up later */
2275 /* call functions which change hw state based on ARB_vp enabled or not. */
2276 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2277 r200Fogfv( ctx
, GL_FOG_COORD_SRC
, NULL
);
2280 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB
:
2281 r200PointParameter( ctx
, GL_POINT_DISTANCE_ATTENUATION
, NULL
);
2284 case GL_FRAGMENT_SHADER_ATI
:
2286 /* restore normal tex env colors and make sure tex env combine will get updated
2287 mark env atoms dirty (as their data was overwritten by afs even
2288 if they didn't change) and restore tex coord routing */
2290 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2291 R200_STATECHANGE( rmesa
, pix
[unit
] );
2292 R200_STATECHANGE( rmesa
, tex
[unit
] );
2293 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2294 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2295 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2296 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2297 we don't announce ATI_fs, right? */
2298 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2300 R200_STATECHANGE( rmesa
, cst
);
2301 R200_STATECHANGE( rmesa
, tf
);
2302 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2305 /* need to mark this dirty as pix/tf atoms have overwritten the data
2306 even if the data in the atoms didn't change */
2307 R200_STATECHANGE( rmesa
, atf
);
2308 R200_STATECHANGE( rmesa
, afs
[1] );
2309 /* everything else picked up in r200UpdateTextureState hopefully */
2318 void r200LightingSpaceChange( GLcontext
*ctx
)
2320 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2323 if (R200_DEBUG
& DEBUG_STATE
)
2324 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2325 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2327 if (ctx
->_NeedEyeCoords
)
2328 tmp
= ctx
->Transform
.RescaleNormals
;
2330 tmp
= !ctx
->Transform
.RescaleNormals
;
2332 R200_STATECHANGE( rmesa
, tcl
);
2334 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2336 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2339 if (R200_DEBUG
& DEBUG_STATE
)
2340 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2341 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2344 /* =============================================================
2345 * Deferred state management - matrices, textures, other?
2351 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2353 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2357 for (i
= 0 ; i
< 4 ; i
++) {
2361 *dest
++ = src
[i
+12];
2364 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2367 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2369 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2370 memcpy(dest
, src
, 16*sizeof(float));
2371 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2375 static void update_texturematrix( GLcontext
*ctx
)
2377 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2378 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2379 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2382 if (R200_DEBUG
& DEBUG_STATE
)
2383 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2384 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2386 rmesa
->TexMatEnabled
= 0;
2387 rmesa
->TexMatCompSel
= 0;
2389 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2390 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2393 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2394 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2395 R200_TEXMAT_0_ENABLE
) << unit
;
2397 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2399 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2400 /* Need to preconcatenate any active texgen
2401 * obj/eyeplane matrices:
2403 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2404 ctx
->TextureMatrixStack
[unit
].Top
,
2405 &rmesa
->TexGenMatrix
[unit
] );
2406 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2409 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2410 R200_MTX_TEX0
+unit
);
2413 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2414 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2415 R200_MTX_TEX0
+unit
);
2419 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2420 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2421 R200_STATECHANGE(rmesa
, tcg
);
2422 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2425 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2426 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2427 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2428 R200_STATECHANGE(rmesa
, vtx
);
2429 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2436 * Tell the card where to render (offset, pitch).
2437 * Effected by glDrawBuffer, etc
2440 r200UpdateDrawBuffer(GLcontext
*ctx
)
2442 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2443 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
2444 driRenderbuffer
*drb
;
2446 if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_FRONT_LEFT
) {
2448 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
2450 else if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_BACK_LEFT
) {
2452 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
2455 /* drawing to multiple buffers, or none */
2460 assert(drb
->flippedPitch
);
2462 R200_STATECHANGE( rmesa
, ctx
);
2464 /* Note: we used the (possibly) page-flipped values */
2465 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
]
2466 = ((drb
->flippedOffset
+ rmesa
->r200Screen
->fbLocation
)
2467 & R200_COLOROFFSET_MASK
);
2468 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = drb
->flippedPitch
;
2469 if (rmesa
->sarea
->tiling_enabled
) {
2470 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
2476 void r200ValidateState( GLcontext
*ctx
)
2478 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2479 GLuint new_state
= rmesa
->NewGLState
;
2481 if (new_state
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
2482 r200UpdateDrawBuffer(ctx
);
2485 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
)) {
2486 r200UpdateTextureState( ctx
);
2487 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2488 r200UpdateLocalViewer( ctx
);
2491 /* FIXME: don't really need most of these when vertex progs are enabled */
2493 /* Need an event driven matrix update?
2495 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2496 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2498 /* Need these for lighting (shouldn't upload otherwise)
2500 if (new_state
& (_NEW_MODELVIEW
)) {
2501 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2502 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2505 /* Does this need to be triggered on eg. modelview for
2506 * texgen-derived objplane/eyeplane matrices?
2508 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2509 update_texturematrix( ctx
);
2512 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2513 update_light( ctx
);
2516 /* emit all active clip planes if projection matrix changes.
2518 if (new_state
& (_NEW_PROJECTION
)) {
2519 if (ctx
->Transform
.ClipPlanesEnabled
)
2520 r200UpdateClipPlanes( ctx
);
2523 if (new_state
& (_NEW_PROGRAM
|
2524 /* need to test for pretty much anything due to possible parameter bindings */
2525 _NEW_MODELVIEW
|_NEW_PROJECTION
|_NEW_TRANSFORM
|
2526 _NEW_LIGHT
|_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
|
2527 _NEW_FOG
|_NEW_POINT
|_NEW_TRACK_MATRIX
)) {
2528 if (ctx
->VertexProgram
._Enabled
) {
2529 r200SetupVertexProg( ctx
);
2531 else TCL_FALLBACK(ctx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, 0);
2534 rmesa
->NewGLState
= 0;
2538 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2540 _swrast_InvalidateState( ctx
, new_state
);
2541 _swsetup_InvalidateState( ctx
, new_state
);
2542 _vbo_InvalidateState( ctx
, new_state
);
2543 _tnl_InvalidateState( ctx
, new_state
);
2544 _ae_invalidate_state( ctx
, new_state
);
2545 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2548 /* A hack. The r200 can actually cope just fine with materials
2549 * between begin/ends, so fix this.
2550 * Should map to inputs just like the generic vertex arrays for vertex progs.
2551 * In theory there could still be too many and we'd still need a fallback.
2553 static GLboolean
check_material( GLcontext
*ctx
)
2555 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2558 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2559 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2561 if (tnl
->vb
.AttribPtr
[i
] &&
2562 tnl
->vb
.AttribPtr
[i
]->stride
)
2568 static void r200WrapRunPipeline( GLcontext
*ctx
)
2570 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2571 GLboolean has_material
;
2574 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2578 if (rmesa
->NewGLState
)
2579 r200ValidateState( ctx
);
2581 has_material
= !ctx
->VertexProgram
._Enabled
&& ctx
->Light
.Enabled
&& check_material( ctx
);
2584 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2587 /* Run the pipeline.
2589 _tnl_run_pipeline( ctx
);
2592 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2597 /* Initialize the driver's state functions.
2599 void r200InitStateFuncs( struct dd_function_table
*functions
)
2601 functions
->UpdateState
= r200InvalidateState
;
2602 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2604 functions
->DrawBuffer
= r200DrawBuffer
;
2605 functions
->ReadBuffer
= r200ReadBuffer
;
2607 functions
->AlphaFunc
= r200AlphaFunc
;
2608 functions
->BlendColor
= r200BlendColor
;
2609 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2610 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2611 functions
->ClearColor
= r200ClearColor
;
2612 functions
->ClearDepth
= r200ClearDepth
;
2613 functions
->ClearIndex
= NULL
;
2614 functions
->ClearStencil
= r200ClearStencil
;
2615 functions
->ClipPlane
= r200ClipPlane
;
2616 functions
->ColorMask
= r200ColorMask
;
2617 functions
->CullFace
= r200CullFace
;
2618 functions
->DepthFunc
= r200DepthFunc
;
2619 functions
->DepthMask
= r200DepthMask
;
2620 functions
->DepthRange
= r200DepthRange
;
2621 functions
->Enable
= r200Enable
;
2622 functions
->Fogfv
= r200Fogfv
;
2623 functions
->FrontFace
= r200FrontFace
;
2624 functions
->Hint
= NULL
;
2625 functions
->IndexMask
= NULL
;
2626 functions
->LightModelfv
= r200LightModelfv
;
2627 functions
->Lightfv
= r200Lightfv
;
2628 functions
->LineStipple
= r200LineStipple
;
2629 functions
->LineWidth
= r200LineWidth
;
2630 functions
->LogicOpcode
= r200LogicOpCode
;
2631 functions
->PolygonMode
= r200PolygonMode
;
2632 functions
->PolygonOffset
= r200PolygonOffset
;
2633 functions
->PolygonStipple
= r200PolygonStipple
;
2634 functions
->PointParameterfv
= r200PointParameter
;
2635 functions
->PointSize
= r200PointSize
;
2636 functions
->RenderMode
= r200RenderMode
;
2637 functions
->Scissor
= r200Scissor
;
2638 functions
->ShadeModel
= r200ShadeModel
;
2639 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2640 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2641 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2642 functions
->Viewport
= r200Viewport
;
2646 void r200InitTnlFuncs( GLcontext
*ctx
)
2648 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2649 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;