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"
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
._LogicOpEnabled
) {
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
._LogicOpEnabled
) {
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
) {
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
);
689 R200_STATECHANGE( rmesa
, cst
);
690 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] &= ~0xffff;
691 rmesa
->hw
.cst
.cmd
[CST_RE_POINTSIZE
] |= ((GLuint
)(ctx
->Point
.Size
* 16.0));
694 /* =============================================================
697 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
699 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
701 R200_STATECHANGE( rmesa
, lin
);
702 R200_STATECHANGE( rmesa
, set
);
704 /* Line width is stored in U6.4 format.
706 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
707 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Line
._Width
* 16.0);
709 if ( widthf
> 1.0 ) {
710 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
712 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
716 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
718 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
720 R200_STATECHANGE( rmesa
, lin
);
721 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
722 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
726 /* =============================================================
729 static void r200ColorMask( GLcontext
*ctx
,
730 GLboolean r
, GLboolean g
,
731 GLboolean b
, GLboolean a
)
733 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
734 GLuint mask
= r200PackColor( rmesa
->r200Screen
->cpp
,
735 ctx
->Color
.ColorMask
[RCOMP
],
736 ctx
->Color
.ColorMask
[GCOMP
],
737 ctx
->Color
.ColorMask
[BCOMP
],
738 ctx
->Color
.ColorMask
[ACOMP
] );
740 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
742 if (!(r
&& g
&& b
&& a
))
743 flag
|= R200_PLANE_MASK_ENABLE
;
745 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
746 R200_STATECHANGE( rmesa
, ctx
);
747 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
750 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
751 R200_STATECHANGE( rmesa
, msk
);
752 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
757 /* =============================================================
761 static void r200PolygonOffset( GLcontext
*ctx
,
762 GLfloat factor
, GLfloat units
)
764 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
765 GLfloat constant
= units
* rmesa
->state
.depth
.scale
;
770 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
772 R200_STATECHANGE( rmesa
, zbs
);
773 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = *(GLuint
*)&factor
;
774 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = *(GLuint
*)&constant
;
777 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
779 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
781 drm_radeon_stipple_t stipple
;
783 /* Must flip pattern upside down.
785 for ( i
= 0 ; i
< 32 ; i
++ ) {
786 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
789 /* TODO: push this into cmd mechanism
791 R200_FIREVERTICES( rmesa
);
792 LOCK_HARDWARE( rmesa
);
794 /* FIXME: Use window x,y offsets into stipple RAM.
796 stipple
.mask
= rmesa
->state
.stipple
.mask
;
797 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
798 &stipple
, sizeof(stipple
) );
799 UNLOCK_HARDWARE( rmesa
);
802 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
804 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
805 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
807 /* Can't generally do unfilled via tcl, but some good special
810 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
811 if (rmesa
->TclFallback
) {
812 r200ChooseRenderState( ctx
);
813 r200ChooseVertexState( ctx
);
818 /* =============================================================
819 * Rendering attributes
821 * We really don't want to recalculate all this every time we bind a
822 * texture. These things shouldn't change all that often, so it makes
823 * sense to break them out of the core texture state update routines.
826 /* Examine lighting and texture state to determine if separate specular
829 static void r200UpdateSpecular( GLcontext
*ctx
)
831 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
832 u_int32_t p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
834 R200_STATECHANGE( rmesa
, tcl
);
835 R200_STATECHANGE( rmesa
, vtx
);
837 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
838 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
839 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
840 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
841 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
843 p
&= ~R200_SPECULAR_ENABLE
;
845 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
848 if (ctx
->Light
.Enabled
&&
849 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
850 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
851 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
852 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
853 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
854 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
855 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
856 p
|= R200_SPECULAR_ENABLE
;
857 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
858 ~R200_DIFFUSE_SPECULAR_COMBINE
;
860 else if (ctx
->Light
.Enabled
) {
861 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
862 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
863 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
864 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
865 } else if (ctx
->Fog
.ColorSumEnabled
) {
866 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
867 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
868 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
869 p
|= R200_SPECULAR_ENABLE
;
871 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
872 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
875 if (ctx
->Fog
.Enabled
) {
876 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
877 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
878 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
881 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
882 R200_STATECHANGE( rmesa
, ctx
);
883 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
886 /* Update vertex/render formats
888 if (rmesa
->TclFallback
) {
889 r200ChooseRenderState( ctx
);
890 r200ChooseVertexState( ctx
);
895 /* =============================================================
900 /* Update on colormaterial, material emmissive/ambient,
901 * lightmodel.globalambient
903 static void update_global_ambient( GLcontext
*ctx
)
905 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
906 float *fcmd
= (float *)R200_DB_STATE( glt
);
908 /* Need to do more if both emmissive & ambient are PREMULT:
909 * I believe this is not nessary when using source_material. This condition thus
910 * will never happen currently, and the function has no dependencies on materials now
912 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
913 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
914 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
916 COPY_3V( &fcmd
[GLT_RED
],
917 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
918 ACC_SCALE_3V( &fcmd
[GLT_RED
],
919 ctx
->Light
.Model
.Ambient
,
920 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
924 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
927 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
930 /* Update on change to
934 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
936 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
938 /* fprintf(stderr, "%s\n", __FUNCTION__); */
941 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
942 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
944 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
945 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
946 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
948 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
952 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
954 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
955 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
956 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
957 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
958 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
959 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
960 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
961 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT
) |
962 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
963 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT
));
965 if (ctx
->Light
.ColorMaterialEnabled
) {
966 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
968 if (mask
& MAT_BIT_FRONT_EMISSION
) {
969 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
970 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
973 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
974 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
976 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
977 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
978 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
981 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
982 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
984 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
985 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
986 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
989 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
990 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
992 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
993 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
994 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
997 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_0
<<
998 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
1001 if (mask
& MAT_BIT_BACK_EMISSION
) {
1002 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1003 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1006 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1007 R200_BACK_EMISSIVE_SOURCE_SHIFT
);
1009 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1010 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1011 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1013 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1014 R200_BACK_AMBIENT_SOURCE_SHIFT
);
1016 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1017 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1018 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1020 else light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1021 R200_BACK_DIFFUSE_SOURCE_SHIFT
);
1023 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1024 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
1025 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1028 light_model_ctl1
|= (R200_LM1_SOURCE_MATERIAL_1
<<
1029 R200_BACK_SPECULAR_SOURCE_SHIFT
);
1033 /* Default to SOURCE_MATERIAL:
1036 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
1037 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
1038 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
1039 (R200_LM1_SOURCE_MATERIAL_0
<< R200_FRONT_SPECULAR_SOURCE_SHIFT
) |
1040 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_EMISSIVE_SOURCE_SHIFT
) |
1041 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_AMBIENT_SOURCE_SHIFT
) |
1042 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_DIFFUSE_SOURCE_SHIFT
) |
1043 (R200_LM1_SOURCE_MATERIAL_1
<< R200_BACK_SPECULAR_SOURCE_SHIFT
);
1046 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
1047 R200_STATECHANGE( rmesa
, tcl
);
1048 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
1054 void r200UpdateMaterial( GLcontext
*ctx
)
1056 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1057 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
1058 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
1059 GLfloat
*fcmd2
= (GLfloat
*)R200_DB_STATE( mtl
[1] );
1062 /* Might be possible and faster to update everything unconditionally? */
1063 if (ctx
->Light
.ColorMaterialEnabled
)
1064 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
1066 if (R200_DEBUG
& DEBUG_STATE
)
1067 fprintf(stderr
, "%s\n", __FUNCTION__
);
1069 if (mask
& MAT_BIT_FRONT_EMISSION
) {
1070 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
1071 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
1072 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
1073 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
1075 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
1076 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
1077 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
1078 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
1079 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
1081 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
1082 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
1083 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
1084 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
1085 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
1087 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
1088 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
1089 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
1090 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
1091 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
1093 if (mask
& MAT_BIT_FRONT_SHININESS
) {
1094 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
1097 if (mask
& MAT_BIT_BACK_EMISSION
) {
1098 fcmd2
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_BACK_EMISSION
][0];
1099 fcmd2
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_BACK_EMISSION
][1];
1100 fcmd2
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_BACK_EMISSION
][2];
1101 fcmd2
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_BACK_EMISSION
][3];
1103 if (mask
& MAT_BIT_BACK_AMBIENT
) {
1104 fcmd2
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][0];
1105 fcmd2
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][1];
1106 fcmd2
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][2];
1107 fcmd2
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_BACK_AMBIENT
][3];
1109 if (mask
& MAT_BIT_BACK_DIFFUSE
) {
1110 fcmd2
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][0];
1111 fcmd2
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][1];
1112 fcmd2
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][2];
1113 fcmd2
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_BACK_DIFFUSE
][3];
1115 if (mask
& MAT_BIT_BACK_SPECULAR
) {
1116 fcmd2
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][0];
1117 fcmd2
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][1];
1118 fcmd2
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][2];
1119 fcmd2
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_BACK_SPECULAR
][3];
1121 if (mask
& MAT_BIT_BACK_SHININESS
) {
1122 fcmd2
[MTL_SHININESS
] = mat
[MAT_ATTRIB_BACK_SHININESS
][0];
1125 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
1126 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[1] );
1128 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1129 update_global_ambient( ctx ); */
1134 * _MESA_NEW_NEED_EYE_COORDS
1136 * Uses derived state from mesa:
1141 * _ModelViewInvScale
1145 * which are calculated in light.c and are correct for the current
1146 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1147 * and _MESA_NEW_NEED_EYE_COORDS.
1149 static void update_light( GLcontext
*ctx
)
1151 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1153 /* Have to check these, or have an automatic shortcircuit mechanism
1154 * to remove noop statechanges. (Or just do a better job on the
1158 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1160 if (ctx
->_NeedEyeCoords
)
1161 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1163 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1165 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1167 R200_STATECHANGE( rmesa
, tcl
);
1168 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1173 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1174 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1175 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1176 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1177 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1178 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1183 if (ctx
->Light
.Enabled
) {
1185 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1186 if (ctx
->Light
.Light
[p
].Enabled
) {
1187 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1188 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1190 if (l
->EyePosition
[3] == 0.0) {
1191 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1192 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1193 fcmd
[LIT_POSITION_W
] = 0;
1194 fcmd
[LIT_DIRECTION_W
] = 0;
1196 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1197 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1198 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1199 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1200 fcmd
[LIT_DIRECTION_W
] = 0;
1203 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1209 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1210 GLenum pname
, const GLfloat
*params
)
1212 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1213 GLint p
= light
- GL_LIGHT0
;
1214 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1215 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1222 update_light_colors( ctx
, p
);
1225 case GL_SPOT_DIRECTION
:
1226 /* picked up in update_light */
1230 /* positions picked up in update_light, but can do flag here */
1231 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1232 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1234 R200_STATECHANGE(rmesa
, tcl
);
1235 if (l
->EyePosition
[3] != 0.0F
)
1236 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1238 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1242 case GL_SPOT_EXPONENT
:
1243 R200_STATECHANGE(rmesa
, lit
[p
]);
1244 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1247 case GL_SPOT_CUTOFF
: {
1248 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1249 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1251 R200_STATECHANGE(rmesa
, lit
[p
]);
1252 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1254 R200_STATECHANGE(rmesa
, tcl
);
1255 if (l
->SpotCutoff
!= 180.0F
)
1256 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1258 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1263 case GL_CONSTANT_ATTENUATION
:
1264 R200_STATECHANGE(rmesa
, lit
[p
]);
1265 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1266 if ( params
[0] == 0.0 )
1267 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1269 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1271 case GL_LINEAR_ATTENUATION
:
1272 R200_STATECHANGE(rmesa
, lit
[p
]);
1273 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1275 case GL_QUADRATIC_ATTENUATION
:
1276 R200_STATECHANGE(rmesa
, lit
[p
]);
1277 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1283 /* Set RANGE_ATTEN only when needed */
1286 case GL_CONSTANT_ATTENUATION
:
1287 case GL_LINEAR_ATTENUATION
:
1288 case GL_QUADRATIC_ATTENUATION
: {
1289 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1290 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1291 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1292 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1293 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1294 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1296 if ( l
->EyePosition
[3] == 0.0F
||
1297 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1298 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1299 /* Disable attenuation */
1300 icmd
[idx
] &= ~atten_flag
;
1302 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1303 /* Enable only constant portion of attenuation calculation */
1304 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1306 /* Enable full attenuation calculation */
1307 icmd
[idx
] &= ~atten_const_flag
;
1308 icmd
[idx
] |= atten_flag
;
1312 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1320 static void r200UpdateLocalViewer ( GLcontext
*ctx
)
1322 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1323 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1324 for these and only these modes). This means specular highlights may turn out
1325 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1326 is not set, though it seems to happen rarely and the effect seems quite
1327 subtle. May need TCL fallback to fix it completely, though I'm not sure
1328 how you'd identify the cases where the specular highlights indeed will
1329 be wrong. Don't know if fglrx does something special in that case.
1331 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1332 R200_STATECHANGE( rmesa
, tcl
);
1333 if (ctx
->Light
.Model
.LocalViewer
||
1334 ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
)
1335 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1337 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1340 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1341 const GLfloat
*param
)
1343 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1346 case GL_LIGHT_MODEL_AMBIENT
:
1347 update_global_ambient( ctx
);
1350 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1351 r200UpdateLocalViewer( ctx
);
1354 case GL_LIGHT_MODEL_TWO_SIDE
:
1355 R200_STATECHANGE( rmesa
, tcl
);
1356 if (ctx
->Light
.Model
.TwoSide
)
1357 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1359 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1360 if (rmesa
->TclFallback
) {
1361 r200ChooseRenderState( ctx
);
1362 r200ChooseVertexState( ctx
);
1366 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1367 r200UpdateSpecular(ctx
);
1375 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1377 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1378 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1380 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1381 R200_ALPHA_SHADE_MASK
|
1382 R200_SPECULAR_SHADE_MASK
|
1383 R200_FOG_SHADE_MASK
);
1387 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1388 R200_ALPHA_SHADE_FLAT
|
1389 R200_SPECULAR_SHADE_FLAT
|
1390 R200_FOG_SHADE_FLAT
);
1393 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1394 R200_ALPHA_SHADE_GOURAUD
|
1395 R200_SPECULAR_SHADE_GOURAUD
|
1396 R200_FOG_SHADE_GOURAUD
);
1402 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1403 R200_STATECHANGE( rmesa
, set
);
1404 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1409 /* =============================================================
1413 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1415 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1416 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1417 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1419 R200_STATECHANGE( rmesa
, ucp
[p
] );
1420 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1421 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1422 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1423 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1426 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1428 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1431 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1432 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1433 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1435 R200_STATECHANGE( rmesa
, ucp
[p
] );
1436 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1437 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1438 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1439 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1445 /* =============================================================
1450 r200StencilFuncSeparate( GLcontext
*ctx
, GLenum face
, GLenum func
,
1451 GLint ref
, GLuint mask
)
1453 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1454 GLuint refmask
= ((ctx
->Stencil
.Ref
[0] << R200_STENCIL_REF_SHIFT
) |
1455 (ctx
->Stencil
.ValueMask
[0] << R200_STENCIL_MASK_SHIFT
));
1457 R200_STATECHANGE( rmesa
, ctx
);
1458 R200_STATECHANGE( rmesa
, msk
);
1460 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1461 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1462 R200_STENCIL_VALUE_MASK
);
1464 switch ( ctx
->Stencil
.Function
[0] ) {
1466 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1469 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1472 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1475 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1478 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1481 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1484 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1487 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1491 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1495 r200StencilMaskSeparate( GLcontext
*ctx
, GLenum face
, GLuint mask
)
1497 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1499 R200_STATECHANGE( rmesa
, msk
);
1500 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1501 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1502 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
);
1506 r200StencilOpSeparate( GLcontext
*ctx
, GLenum face
, GLenum fail
,
1507 GLenum zfail
, GLenum zpass
)
1509 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1511 R200_STATECHANGE( rmesa
, ctx
);
1512 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1513 R200_STENCIL_ZFAIL_MASK
|
1514 R200_STENCIL_ZPASS_MASK
);
1516 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1518 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1521 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1524 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1527 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1530 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1532 case GL_INCR_WRAP_EXT
:
1533 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1535 case GL_DECR_WRAP_EXT
:
1536 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1539 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1543 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1545 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1548 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1551 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1554 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1557 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1559 case GL_INCR_WRAP_EXT
:
1560 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1562 case GL_DECR_WRAP_EXT
:
1563 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1566 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1570 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1572 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1575 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1578 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1581 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1584 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1586 case GL_INCR_WRAP_EXT
:
1587 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1589 case GL_DECR_WRAP_EXT
:
1590 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1593 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1598 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1600 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1602 rmesa
->state
.stencil
.clear
=
1603 ((GLuint
) ctx
->Stencil
.Clear
|
1604 (0xff << R200_STENCIL_MASK_SHIFT
) |
1605 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
));
1609 /* =============================================================
1610 * Window position and viewport transformation
1614 * To correctly position primitives:
1616 #define SUBPIXEL_X 0.125
1617 #define SUBPIXEL_Y 0.125
1619 void r200UpdateWindow( GLcontext
*ctx
)
1621 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1622 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1623 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1624 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1625 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1627 GLfloat sx
= v
[MAT_SX
];
1628 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1629 GLfloat sy
= - v
[MAT_SY
];
1630 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1631 GLfloat sz
= v
[MAT_SZ
] * rmesa
->state
.depth
.scale
;
1632 GLfloat tz
= v
[MAT_TZ
] * rmesa
->state
.depth
.scale
;
1634 R200_FIREVERTICES( rmesa
);
1635 R200_STATECHANGE( rmesa
, vpt
);
1637 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = *(GLuint
*)&sx
;
1638 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1639 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = *(GLuint
*)&sy
;
1640 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1641 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = *(GLuint
*)&sz
;
1642 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = *(GLuint
*)&tz
;
1647 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1648 GLsizei width
, GLsizei height
)
1650 /* Don't pipeline viewport changes, conflict with window offset
1651 * setting below. Could apply deltas to rescue pipelined viewport
1652 * values, or keep the originals hanging around.
1654 R200_FIREVERTICES( R200_CONTEXT(ctx
) );
1655 r200UpdateWindow( ctx
);
1658 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1661 r200UpdateWindow( ctx
);
1664 void r200UpdateViewportOffset( GLcontext
*ctx
)
1666 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1667 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1668 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1669 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1670 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1672 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1673 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1675 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != *(GLuint
*)&tx
||
1676 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != *(GLuint
*)&ty
)
1678 /* Note: this should also modify whatever data the context reset
1681 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1682 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1684 /* update polygon stipple x/y screen offset */
1687 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1689 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1690 R200_STIPPLE_Y_OFFSET_MASK
);
1692 /* add magic offsets, then invert */
1693 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1694 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1695 & R200_STIPPLE_COORD_MASK
);
1697 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1698 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1700 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1701 R200_STATECHANGE( rmesa
, msc
);
1702 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1707 r200UpdateScissor( ctx
);
1712 /* =============================================================
1716 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1718 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1720 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1721 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1722 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1723 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1724 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1726 color
[2], color
[3] );
1730 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1732 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1733 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1737 static GLuint r200_rop_tab
[] = {
1740 R200_ROP_AND_REVERSE
,
1742 R200_ROP_AND_INVERTED
,
1749 R200_ROP_OR_REVERSE
,
1750 R200_ROP_COPY_INVERTED
,
1751 R200_ROP_OR_INVERTED
,
1756 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1758 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1759 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1763 R200_STATECHANGE( rmesa
, msk
);
1764 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1768 void r200SetCliprects( r200ContextPtr rmesa
, GLenum mode
)
1770 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1774 rmesa
->numClipRects
= dPriv
->numClipRects
;
1775 rmesa
->pClipRects
= dPriv
->pClipRects
;
1778 /* Can't ignore 2d windows if we are page flipping.
1780 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1781 rmesa
->numClipRects
= dPriv
->numClipRects
;
1782 rmesa
->pClipRects
= dPriv
->pClipRects
;
1785 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1786 rmesa
->pClipRects
= dPriv
->pBackClipRects
;
1790 fprintf(stderr
, "bad mode in r200SetCliprects\n");
1794 if (rmesa
->state
.scissor
.enabled
)
1795 r200RecalcScissorRects( rmesa
);
1799 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1801 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1803 if (R200_DEBUG
& DEBUG_DRI
)
1804 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1805 _mesa_lookup_enum_by_nr( mode
));
1807 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1810 * _ColorDrawBufferMask is easier to cope with than <mode>.
1811 * Check for software fallback, update cliprects.
1813 switch ( ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] ) {
1814 case BUFFER_BIT_FRONT_LEFT
:
1815 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1816 r200SetCliprects( rmesa
, GL_FRONT_LEFT
);
1818 case BUFFER_BIT_BACK_LEFT
:
1819 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1820 r200SetCliprects( rmesa
, GL_BACK_LEFT
);
1823 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1824 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1828 /* We'll set the drawing engine's offset/pitch parameters later
1829 * when we update other state.
1834 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1836 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1839 /* =============================================================
1840 * State enable/disable
1843 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1845 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1848 if ( R200_DEBUG
& DEBUG_STATE
)
1849 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1850 _mesa_lookup_enum_by_nr( cap
),
1851 state
? "GL_TRUE" : "GL_FALSE" );
1854 /* Fast track this one...
1862 R200_STATECHANGE( rmesa
, ctx
);
1864 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1866 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1871 case GL_COLOR_LOGIC_OP
:
1872 r200_set_blend_state( ctx
);
1875 case GL_CLIP_PLANE0
:
1876 case GL_CLIP_PLANE1
:
1877 case GL_CLIP_PLANE2
:
1878 case GL_CLIP_PLANE3
:
1879 case GL_CLIP_PLANE4
:
1880 case GL_CLIP_PLANE5
:
1881 p
= cap
-GL_CLIP_PLANE0
;
1882 R200_STATECHANGE( rmesa
, tcl
);
1884 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1885 r200ClipPlane( ctx
, cap
, NULL
);
1888 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1892 case GL_COLOR_MATERIAL
:
1893 r200ColorMaterial( ctx
, 0, 0 );
1894 r200UpdateMaterial( ctx
);
1898 r200CullFace( ctx
, 0 );
1902 R200_STATECHANGE(rmesa
, ctx
);
1904 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1906 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1911 R200_STATECHANGE(rmesa
, ctx
);
1913 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1914 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1916 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1917 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1922 R200_STATECHANGE(rmesa
, ctx
);
1924 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1925 r200Fogfv( ctx
, GL_FOG_MODE
, NULL
);
1927 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1928 R200_STATECHANGE(rmesa
, tcl
);
1929 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1931 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1932 if (rmesa
->TclFallback
)
1933 r200ChooseVertexState( ctx
);
1934 _mesa_allow_light_in_model( ctx
, !state
);
1945 R200_STATECHANGE(rmesa
, tcl
);
1946 p
= cap
- GL_LIGHT0
;
1948 flag
= (R200_LIGHT_1_ENABLE
|
1949 R200_LIGHT_1_ENABLE_AMBIENT
|
1950 R200_LIGHT_1_ENABLE_SPECULAR
);
1952 flag
= (R200_LIGHT_0_ENABLE
|
1953 R200_LIGHT_0_ENABLE_AMBIENT
|
1954 R200_LIGHT_0_ENABLE_SPECULAR
);
1957 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1959 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1963 update_light_colors( ctx
, p
);
1967 r200UpdateSpecular(ctx
);
1970 case GL_LINE_SMOOTH
:
1971 R200_STATECHANGE( rmesa
, ctx
);
1973 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1975 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1979 case GL_LINE_STIPPLE
:
1980 R200_STATECHANGE( rmesa
, set
);
1982 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1984 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1989 R200_STATECHANGE( rmesa
, tcl
);
1991 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1993 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1997 /* Pointsize registers on r200 only work for point sprites, and point smooth
1998 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1999 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
2000 * is enough to satisfy conform.
2002 case GL_POINT_SMOOTH
:
2005 /* These don't really do anything, as we don't use the 3vtx
2009 case GL_POLYGON_OFFSET_POINT
:
2010 R200_STATECHANGE( rmesa
, set
);
2012 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
2014 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
2018 case GL_POLYGON_OFFSET_LINE
:
2019 R200_STATECHANGE( rmesa
, set
);
2021 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
2023 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
2028 case GL_POLYGON_OFFSET_FILL
:
2029 R200_STATECHANGE( rmesa
, set
);
2031 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
2033 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
2037 case GL_POLYGON_SMOOTH
:
2038 R200_STATECHANGE( rmesa
, ctx
);
2040 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2042 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2046 case GL_POLYGON_STIPPLE
:
2047 R200_STATECHANGE(rmesa
, set
);
2049 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2051 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2055 case GL_RESCALE_NORMAL_EXT
: {
2056 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2057 R200_STATECHANGE( rmesa
, tcl
);
2059 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2061 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2066 case GL_SCISSOR_TEST
:
2067 R200_FIREVERTICES( rmesa
);
2068 rmesa
->state
.scissor
.enabled
= state
;
2069 r200UpdateScissor( ctx
);
2072 case GL_STENCIL_TEST
:
2073 if ( rmesa
->state
.stencil
.hwBuffer
) {
2074 R200_STATECHANGE( rmesa
, ctx
);
2076 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2078 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2081 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2085 case GL_TEXTURE_GEN_Q
:
2086 case GL_TEXTURE_GEN_R
:
2087 case GL_TEXTURE_GEN_S
:
2088 case GL_TEXTURE_GEN_T
:
2089 /* Picked up in r200UpdateTextureState.
2091 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2094 case GL_COLOR_SUM_EXT
:
2095 r200UpdateSpecular ( ctx
);
2098 case GL_VERTEX_PROGRAM_ARB
:
2099 TCL_FALLBACK(rmesa
->glCtx
, R200_TCL_FALLBACK_VERTEX_PROGRAM
, state
);
2102 case GL_FRAGMENT_SHADER_ATI
:
2104 /* restore normal tex env colors and make sure tex env combine will get updated
2105 mark env atoms dirty (as their data was overwritten by afs even
2106 if they didn't change) and restore tex coord routing */
2108 for (unit
= 0; unit
< R200_MAX_TEXTURE_UNITS
; unit
++) {
2109 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &=
2110 ~(R200_TXFORMAT_ST_ROUTE_MASK
| R200_TXFORMAT_LOOKUP_DISABLE
);
2111 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] |= unit
<< R200_TXFORMAT_ST_ROUTE_SHIFT
;
2112 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2113 we don't announce ATI_fs, right? */
2114 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXMULTI_CTL
] = 0;
2115 R200_STATECHANGE( rmesa
, pix
[unit
] );
2116 R200_STATECHANGE( rmesa
, tex
[unit
] );
2118 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] = 0;
2119 R200_STATECHANGE( rmesa
, cst
);
2120 R200_STATECHANGE( rmesa
, tf
);
2123 /* need to mark this dirty as pix/tf atoms have overwritten the data
2124 even if the data in the atoms didn't change */
2125 R200_STATECHANGE( rmesa
, atf
);
2126 R200_STATECHANGE( rmesa
, afs
[1] );
2127 /* everything else picked up in r200UpdateTextureState hopefully */
2136 void r200LightingSpaceChange( GLcontext
*ctx
)
2138 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2141 if (R200_DEBUG
& DEBUG_STATE
)
2142 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2143 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2145 if (ctx
->_NeedEyeCoords
)
2146 tmp
= ctx
->Transform
.RescaleNormals
;
2148 tmp
= !ctx
->Transform
.RescaleNormals
;
2150 R200_STATECHANGE( rmesa
, tcl
);
2152 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2154 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2157 if (R200_DEBUG
& DEBUG_STATE
)
2158 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2159 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2162 /* =============================================================
2163 * Deferred state management - matrices, textures, other?
2169 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2171 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2175 for (i
= 0 ; i
< 4 ; i
++) {
2179 *dest
++ = src
[i
+12];
2182 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2185 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2187 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2188 memcpy(dest
, src
, 16*sizeof(float));
2189 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2193 static void update_texturematrix( GLcontext
*ctx
)
2195 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2196 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2197 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2200 if (R200_DEBUG
& DEBUG_STATE
)
2201 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2202 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2204 rmesa
->TexMatEnabled
= 0;
2205 rmesa
->TexMatCompSel
= 0;
2207 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2208 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2211 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2212 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2213 R200_TEXMAT_0_ENABLE
) << unit
;
2215 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2217 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2218 /* Need to preconcatenate any active texgen
2219 * obj/eyeplane matrices:
2221 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2222 ctx
->TextureMatrixStack
[unit
].Top
,
2223 &rmesa
->TexGenMatrix
[unit
] );
2224 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2227 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2228 R200_MTX_TEX0
+unit
);
2231 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2232 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2233 R200_MTX_TEX0
+unit
);
2237 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2238 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2239 R200_STATECHANGE(rmesa
, tcg
);
2240 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2243 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2244 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2245 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2246 R200_STATECHANGE(rmesa
, vtx
);
2247 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2254 * Tell the card where to render (offset, pitch).
2255 * Effected by glDrawBuffer, etc
2258 r200UpdateDrawBuffer(GLcontext
*ctx
)
2260 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2261 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
2262 driRenderbuffer
*drb
;
2264 if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_FRONT_LEFT
) {
2266 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
2268 else if (fb
->_ColorDrawBufferMask
[0] == BUFFER_BIT_BACK_LEFT
) {
2270 drb
= (driRenderbuffer
*) fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
2273 /* drawing to multiple buffers, or none */
2278 assert(drb
->flippedPitch
);
2280 R200_STATECHANGE( rmesa
, ctx
);
2282 /* Note: we used the (possibly) page-flipped values */
2283 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
]
2284 = ((drb
->flippedOffset
+ rmesa
->r200Screen
->fbLocation
)
2285 & R200_COLOROFFSET_MASK
);
2286 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = drb
->flippedPitch
;
2287 if (rmesa
->sarea
->tiling_enabled
) {
2288 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
2294 void r200ValidateState( GLcontext
*ctx
)
2296 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2297 GLuint new_state
= rmesa
->NewGLState
;
2299 if (new_state
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
2300 r200UpdateDrawBuffer(ctx
);
2303 if (new_state
& (_NEW_TEXTURE
| _NEW_PROGRAM
)) {
2304 r200UpdateTextureState( ctx
);
2305 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2306 r200UpdateLocalViewer( ctx
);
2309 /* Need an event driven matrix update?
2311 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2312 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2314 /* Need these for lighting (shouldn't upload otherwise)
2316 if (new_state
& (_NEW_MODELVIEW
)) {
2317 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2318 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2321 /* Does this need to be triggered on eg. modelview for
2322 * texgen-derived objplane/eyeplane matrices?
2324 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2325 update_texturematrix( ctx
);
2328 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2329 update_light( ctx
);
2332 /* emit all active clip planes if projection matrix changes.
2334 if (new_state
& (_NEW_PROJECTION
)) {
2335 if (ctx
->Transform
.ClipPlanesEnabled
)
2336 r200UpdateClipPlanes( ctx
);
2340 rmesa
->NewGLState
= 0;
2344 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2346 _swrast_InvalidateState( ctx
, new_state
);
2347 _swsetup_InvalidateState( ctx
, new_state
);
2348 _ac_InvalidateState( ctx
, new_state
);
2349 _tnl_InvalidateState( ctx
, new_state
);
2350 _ae_invalidate_state( ctx
, new_state
);
2351 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2352 r200VtxfmtInvalidate( ctx
);
2355 /* A hack. The r200 can actually cope just fine with materials
2356 * between begin/ends, so fix this. But how ?
2358 static GLboolean
check_material( GLcontext
*ctx
)
2360 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2363 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2364 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2366 if (tnl
->vb
.AttribPtr
[i
] &&
2367 tnl
->vb
.AttribPtr
[i
]->stride
)
2373 static void r200WrapRunPipeline( GLcontext
*ctx
)
2375 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2376 GLboolean has_material
;
2379 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2383 if (rmesa
->NewGLState
)
2384 r200ValidateState( ctx
);
2386 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2389 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2392 /* Run the pipeline.
2394 _tnl_run_pipeline( ctx
);
2397 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2402 /* Initialize the driver's state functions.
2404 void r200InitStateFuncs( struct dd_function_table
*functions
)
2406 functions
->UpdateState
= r200InvalidateState
;
2407 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2409 functions
->DrawBuffer
= r200DrawBuffer
;
2410 functions
->ReadBuffer
= r200ReadBuffer
;
2412 functions
->AlphaFunc
= r200AlphaFunc
;
2413 functions
->BlendColor
= r200BlendColor
;
2414 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2415 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2416 functions
->ClearColor
= r200ClearColor
;
2417 functions
->ClearDepth
= r200ClearDepth
;
2418 functions
->ClearIndex
= NULL
;
2419 functions
->ClearStencil
= r200ClearStencil
;
2420 functions
->ClipPlane
= r200ClipPlane
;
2421 functions
->ColorMask
= r200ColorMask
;
2422 functions
->CullFace
= r200CullFace
;
2423 functions
->DepthFunc
= r200DepthFunc
;
2424 functions
->DepthMask
= r200DepthMask
;
2425 functions
->DepthRange
= r200DepthRange
;
2426 functions
->Enable
= r200Enable
;
2427 functions
->Fogfv
= r200Fogfv
;
2428 functions
->FrontFace
= r200FrontFace
;
2429 functions
->Hint
= NULL
;
2430 functions
->IndexMask
= NULL
;
2431 functions
->LightModelfv
= r200LightModelfv
;
2432 functions
->Lightfv
= r200Lightfv
;
2433 functions
->LineStipple
= r200LineStipple
;
2434 functions
->LineWidth
= r200LineWidth
;
2435 functions
->LogicOpcode
= r200LogicOpCode
;
2436 functions
->PolygonMode
= r200PolygonMode
;
2437 functions
->PolygonOffset
= r200PolygonOffset
;
2438 functions
->PolygonStipple
= r200PolygonStipple
;
2439 functions
->PointSize
= r200PointSize
;
2440 functions
->RenderMode
= r200RenderMode
;
2441 functions
->Scissor
= r200Scissor
;
2442 functions
->ShadeModel
= r200ShadeModel
;
2443 functions
->StencilFuncSeparate
= r200StencilFuncSeparate
;
2444 functions
->StencilMaskSeparate
= r200StencilMaskSeparate
;
2445 functions
->StencilOpSeparate
= r200StencilOpSeparate
;
2446 functions
->Viewport
= r200Viewport
;
2448 /* Swrast hooks for imaging extensions:
2450 functions
->CopyColorTable
= _swrast_CopyColorTable
;
2451 functions
->CopyColorSubTable
= _swrast_CopyColorSubTable
;
2452 functions
->CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2453 functions
->CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2457 void r200InitTnlFuncs( GLcontext
*ctx
)
2459 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2460 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;