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"
51 #include "r200_context.h"
52 #include "r200_ioctl.h"
53 #include "r200_state.h"
56 #include "r200_swtcl.h"
57 #include "r200_vtxfmt.h"
60 /* =============================================================
64 static void r200AlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
66 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
67 int pp_misc
= rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
];
70 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
72 R200_STATECHANGE( rmesa
, ctx
);
74 pp_misc
&= ~(R200_ALPHA_TEST_OP_MASK
| R200_REF_ALPHA_MASK
);
75 pp_misc
|= (refByte
& R200_REF_ALPHA_MASK
);
79 pp_misc
|= R200_ALPHA_TEST_FAIL
;
82 pp_misc
|= R200_ALPHA_TEST_LESS
;
85 pp_misc
|= R200_ALPHA_TEST_EQUAL
;
88 pp_misc
|= R200_ALPHA_TEST_LEQUAL
;
91 pp_misc
|= R200_ALPHA_TEST_GREATER
;
94 pp_misc
|= R200_ALPHA_TEST_NEQUAL
;
97 pp_misc
|= R200_ALPHA_TEST_GEQUAL
;
100 pp_misc
|= R200_ALPHA_TEST_PASS
;
104 rmesa
->hw
.ctx
.cmd
[CTX_PP_MISC
] = pp_misc
;
107 static void r200BlendColor( GLcontext
*ctx
, const GLfloat cf
[4] )
110 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
111 R200_STATECHANGE( rmesa
, ctx
);
112 CLAMPED_FLOAT_TO_UBYTE(color
[0], cf
[0]);
113 CLAMPED_FLOAT_TO_UBYTE(color
[1], cf
[1]);
114 CLAMPED_FLOAT_TO_UBYTE(color
[2], cf
[2]);
115 CLAMPED_FLOAT_TO_UBYTE(color
[3], cf
[3]);
116 if (rmesa
->r200Screen
->drmSupportsBlendColor
)
117 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCOLOR
] = r200PackColor( 4, color
[0], color
[1], color
[2], color
[3] );
121 * Calculate the hardware blend factor setting. This same function is used
122 * for source and destination of both alpha and RGB.
125 * The hardware register value for the specified blend factor. This value
126 * will need to be shifted into the correct position for either source or
127 * destination factor.
130 * Since the two cases where source and destination are handled differently
131 * are essentially error cases, they should never happen. Determine if these
132 * cases can be removed.
134 static int blend_factor( GLenum factor
, GLboolean is_src
)
140 func
= R200_BLEND_GL_ZERO
;
143 func
= R200_BLEND_GL_ONE
;
146 func
= R200_BLEND_GL_DST_COLOR
;
148 case GL_ONE_MINUS_DST_COLOR
:
149 func
= R200_BLEND_GL_ONE_MINUS_DST_COLOR
;
152 func
= R200_BLEND_GL_SRC_COLOR
;
154 case GL_ONE_MINUS_SRC_COLOR
:
155 func
= R200_BLEND_GL_ONE_MINUS_SRC_COLOR
;
158 func
= R200_BLEND_GL_SRC_ALPHA
;
160 case GL_ONE_MINUS_SRC_ALPHA
:
161 func
= R200_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
164 func
= R200_BLEND_GL_DST_ALPHA
;
166 case GL_ONE_MINUS_DST_ALPHA
:
167 func
= R200_BLEND_GL_ONE_MINUS_DST_ALPHA
;
169 case GL_SRC_ALPHA_SATURATE
:
170 func
= (is_src
) ? R200_BLEND_GL_SRC_ALPHA_SATURATE
: R200_BLEND_GL_ZERO
;
172 case GL_CONSTANT_COLOR
:
173 func
= R200_BLEND_GL_CONST_COLOR
;
175 case GL_ONE_MINUS_CONSTANT_COLOR
:
176 func
= R200_BLEND_GL_ONE_MINUS_CONST_COLOR
;
178 case GL_CONSTANT_ALPHA
:
179 func
= R200_BLEND_GL_CONST_ALPHA
;
181 case GL_ONE_MINUS_CONSTANT_ALPHA
:
182 func
= R200_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
185 func
= (is_src
) ? R200_BLEND_GL_ONE
: R200_BLEND_GL_ZERO
;
191 * Sets both the blend equation and the blend function.
192 * This is done in a single
193 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
194 * change the interpretation of the blend function.
195 * Also, make sure that blend function and blend equation are set to their default
196 * value if color blending is not enabled, since at least blend equations GL_MIN
197 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
200 static void r200_set_blend_state( GLcontext
* ctx
)
202 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
203 GLuint cntl
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &
204 ~(R200_ROP_ENABLE
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
);
206 int func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
207 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
208 int eqn
= R200_COMB_FCN_ADD_CLAMP
;
209 int funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
210 (R200_BLEND_GL_ZERO
<< R200_DST_BLEND_SHIFT
);
211 int eqnA
= R200_COMB_FCN_ADD_CLAMP
;
213 R200_STATECHANGE( rmesa
, ctx
);
215 if (rmesa
->r200Screen
->drmSupportsBlendColor
) {
216 if (ctx
->Color
._LogicOpEnabled
) {
217 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
218 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
219 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
221 } else if (ctx
->Color
.BlendEnabled
) {
222 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
| R200_SEPARATE_ALPHA_ENABLE
;
225 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
226 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqn
| func
;
227 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
232 if (ctx
->Color
._LogicOpEnabled
) {
233 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ROP_ENABLE
;
234 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
236 } else if (ctx
->Color
.BlendEnabled
) {
237 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
| R200_ALPHA_BLEND_ENABLE
;
240 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = cntl
;
241 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
246 func
= (blend_factor( ctx
->Color
.BlendSrcRGB
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
247 (blend_factor( ctx
->Color
.BlendDstRGB
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
249 switch(ctx
->Color
.BlendEquationRGB
) {
251 eqn
= R200_COMB_FCN_ADD_CLAMP
;
254 case GL_FUNC_SUBTRACT
:
255 eqn
= R200_COMB_FCN_SUB_CLAMP
;
258 case GL_FUNC_REVERSE_SUBTRACT
:
259 eqn
= R200_COMB_FCN_RSUB_CLAMP
;
263 eqn
= R200_COMB_FCN_MIN
;
264 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
265 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
269 eqn
= R200_COMB_FCN_MAX
;
270 func
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
271 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
275 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
276 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationRGB
);
280 if (!rmesa
->r200Screen
->drmSupportsBlendColor
) {
281 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = eqn
| func
;
285 funcA
= (blend_factor( ctx
->Color
.BlendSrcA
, GL_TRUE
) << R200_SRC_BLEND_SHIFT
) |
286 (blend_factor( ctx
->Color
.BlendDstA
, GL_FALSE
) << R200_DST_BLEND_SHIFT
);
288 switch(ctx
->Color
.BlendEquationA
) {
290 eqnA
= R200_COMB_FCN_ADD_CLAMP
;
293 case GL_FUNC_SUBTRACT
:
294 eqnA
= R200_COMB_FCN_SUB_CLAMP
;
297 case GL_FUNC_REVERSE_SUBTRACT
:
298 eqnA
= R200_COMB_FCN_RSUB_CLAMP
;
302 eqnA
= R200_COMB_FCN_MIN
;
303 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
304 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
308 eqnA
= R200_COMB_FCN_MAX
;
309 funcA
= (R200_BLEND_GL_ONE
<< R200_SRC_BLEND_SHIFT
) |
310 (R200_BLEND_GL_ONE
<< R200_DST_BLEND_SHIFT
);
314 fprintf( stderr
, "[%s:%u] Invalid A blend equation (0x%04x).\n",
315 __FUNCTION__
, __LINE__
, ctx
->Color
.BlendEquationA
);
319 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ABLENDCNTL
] = eqnA
| funcA
;
320 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CBLENDCNTL
] = eqn
| func
;
324 static void r200BlendEquationSeparate( GLcontext
*ctx
,
325 GLenum modeRGB
, GLenum modeA
)
327 r200_set_blend_state( ctx
);
330 static void r200BlendFuncSeparate( GLcontext
*ctx
,
331 GLenum sfactorRGB
, GLenum dfactorRGB
,
332 GLenum sfactorA
, GLenum dfactorA
)
334 r200_set_blend_state( ctx
);
338 /* =============================================================
342 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
344 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
346 R200_STATECHANGE( rmesa
, ctx
);
347 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
349 switch ( ctx
->Depth
.Func
) {
351 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
354 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
357 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
360 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
363 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
366 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
369 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
372 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
377 static void r200ClearDepth( GLcontext
*ctx
, GLclampd d
)
379 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
380 GLuint format
= (rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &
381 R200_DEPTH_FORMAT_MASK
);
384 case R200_DEPTH_FORMAT_16BIT_INT_Z
:
385 rmesa
->state
.depth
.clear
= d
* 0x0000ffff;
387 case R200_DEPTH_FORMAT_24BIT_INT_Z
:
388 rmesa
->state
.depth
.clear
= d
* 0x00ffffff;
393 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
395 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
396 R200_STATECHANGE( rmesa
, ctx
);
398 if ( ctx
->Depth
.Mask
) {
399 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
401 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
406 /* =============================================================
411 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
413 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
414 union { int i
; float f
; } c
, d
;
418 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
419 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
423 if (!ctx
->Fog
.Enabled
)
425 R200_STATECHANGE(rmesa
, tcl
);
426 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
427 switch (ctx
->Fog
.Mode
) {
429 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
430 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
435 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
436 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
440 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
442 d
.f
= -ctx
->Fog
.Density
;
445 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
447 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
454 switch (ctx
->Fog
.Mode
) {
457 d
.f
= -ctx
->Fog
.Density
;
461 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
469 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
470 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
474 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
475 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
480 R200_STATECHANGE( rmesa
, ctx
);
481 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
482 i
= r200PackColor( 4, col
[0], col
[1], col
[2], 0 );
483 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
484 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
486 case GL_FOG_COORD_SRC
: {
487 GLuint fmt_0
= rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
];
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 fmt_0
|= R200_VTX_DISCRETE_FOG
;
495 out_0
|= R200_VTX_DISCRETE_FOG
;
498 fog
|= R200_FOG_USE_SPEC_ALPHA
;
499 fmt_0
&= ~R200_VTX_DISCRETE_FOG
;
500 out_0
&= ~R200_VTX_DISCRETE_FOG
;
503 if ( fog
!= rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] ) {
504 R200_STATECHANGE( rmesa
, ctx
);
505 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] = fog
;
508 if ( (fmt_0
!= rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
])
509 || (out_0
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
])) {
510 R200_STATECHANGE( rmesa
, vtx
);
511 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
512 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] = out_0
;
521 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
522 R200_STATECHANGE( rmesa
, fog
);
523 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
524 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
529 /* =============================================================
534 static GLboolean
intersect_rect( drm_clip_rect_t
*out
,
539 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
540 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
541 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
542 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
543 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
544 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
549 void r200RecalcScissorRects( r200ContextPtr rmesa
)
551 drm_clip_rect_t
*out
;
554 /* Grow cliprect store?
556 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
557 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
558 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
559 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
562 if (rmesa
->state
.scissor
.pClipRects
)
563 FREE(rmesa
->state
.scissor
.pClipRects
);
565 rmesa
->state
.scissor
.pClipRects
=
566 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
567 sizeof(drm_clip_rect_t
) );
569 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
570 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
575 out
= rmesa
->state
.scissor
.pClipRects
;
576 rmesa
->state
.scissor
.numClipRects
= 0;
578 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
579 if ( intersect_rect( out
,
580 &rmesa
->pClipRects
[i
],
581 &rmesa
->state
.scissor
.rect
) ) {
582 rmesa
->state
.scissor
.numClipRects
++;
589 static void r200UpdateScissor( GLcontext
*ctx
)
591 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
593 if ( rmesa
->dri
.drawable
) {
594 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
596 int x
= ctx
->Scissor
.X
;
597 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
598 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
599 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
601 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
602 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
603 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
604 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
606 r200RecalcScissorRects( rmesa
);
611 static void r200Scissor( GLcontext
*ctx
,
612 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
614 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
616 if ( ctx
->Scissor
.Enabled
) {
617 R200_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
618 r200UpdateScissor( ctx
);
624 /* =============================================================
628 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
630 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
631 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
632 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
634 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
635 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
637 if ( ctx
->Polygon
.CullFlag
) {
638 switch ( ctx
->Polygon
.CullFaceMode
) {
640 s
&= ~R200_FFACE_SOLID
;
641 t
|= R200_CULL_FRONT
;
644 s
&= ~R200_BFACE_SOLID
;
647 case GL_FRONT_AND_BACK
:
648 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
649 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
654 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
655 R200_STATECHANGE(rmesa
, set
);
656 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
659 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
660 R200_STATECHANGE(rmesa
, tcl
);
661 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
665 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
667 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
669 R200_STATECHANGE( rmesa
, set
);
670 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
672 R200_STATECHANGE( rmesa
, tcl
);
673 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
677 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
680 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
681 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
686 /* =============================================================
689 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
691 if (0) fprintf(stderr
, "%s: %f\n", __FUNCTION__
, size
);
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
);
1323 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1324 const GLfloat
*param
)
1326 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1329 case GL_LIGHT_MODEL_AMBIENT
:
1330 update_global_ambient( ctx
);
1333 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1334 R200_STATECHANGE( rmesa
, tcl
);
1335 if (ctx
->Light
.Model
.LocalViewer
)
1336 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1338 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1341 case GL_LIGHT_MODEL_TWO_SIDE
:
1342 R200_STATECHANGE( rmesa
, tcl
);
1343 if (ctx
->Light
.Model
.TwoSide
)
1344 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1346 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~(R200_LIGHT_TWOSIDE
);
1347 if (rmesa
->TclFallback
) {
1348 r200ChooseRenderState( ctx
);
1349 r200ChooseVertexState( ctx
);
1353 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1354 r200UpdateSpecular(ctx
);
1362 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1364 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1365 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1367 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1368 R200_ALPHA_SHADE_MASK
|
1369 R200_SPECULAR_SHADE_MASK
|
1370 R200_FOG_SHADE_MASK
);
1374 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1375 R200_ALPHA_SHADE_FLAT
|
1376 R200_SPECULAR_SHADE_FLAT
|
1377 R200_FOG_SHADE_FLAT
);
1380 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1381 R200_ALPHA_SHADE_GOURAUD
|
1382 R200_SPECULAR_SHADE_GOURAUD
|
1383 R200_FOG_SHADE_GOURAUD
);
1389 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1390 R200_STATECHANGE( rmesa
, set
);
1391 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1396 /* =============================================================
1400 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1402 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1403 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1404 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1406 R200_STATECHANGE( rmesa
, ucp
[p
] );
1407 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1408 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1409 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1410 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1413 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1415 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1418 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1419 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1420 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1422 R200_STATECHANGE( rmesa
, ucp
[p
] );
1423 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1424 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1425 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1426 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1432 /* =============================================================
1436 static void r200StencilFunc( GLcontext
*ctx
, GLenum func
,
1437 GLint ref
, GLuint mask
)
1439 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1440 GLuint refmask
= ((ctx
->Stencil
.Ref
[0] << R200_STENCIL_REF_SHIFT
) |
1441 (ctx
->Stencil
.ValueMask
[0] << R200_STENCIL_MASK_SHIFT
));
1443 R200_STATECHANGE( rmesa
, ctx
);
1444 R200_STATECHANGE( rmesa
, msk
);
1446 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1447 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1448 R200_STENCIL_VALUE_MASK
);
1450 switch ( ctx
->Stencil
.Function
[0] ) {
1452 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1455 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1458 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1461 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1464 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1467 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1470 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1473 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1477 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1480 static void r200StencilMask( GLcontext
*ctx
, GLuint mask
)
1482 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1484 R200_STATECHANGE( rmesa
, msk
);
1485 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1486 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1487 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
);
1490 static void r200StencilOp( GLcontext
*ctx
, GLenum fail
,
1491 GLenum zfail
, GLenum zpass
)
1493 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1495 R200_STATECHANGE( rmesa
, ctx
);
1496 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1497 R200_STENCIL_ZFAIL_MASK
|
1498 R200_STENCIL_ZPASS_MASK
);
1500 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1502 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1505 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1508 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1511 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1514 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1516 case GL_INCR_WRAP_EXT
:
1517 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1519 case GL_DECR_WRAP_EXT
:
1520 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1523 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1527 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1529 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1532 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1535 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1538 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1541 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1543 case GL_INCR_WRAP_EXT
:
1544 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1546 case GL_DECR_WRAP_EXT
:
1547 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1550 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1554 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1556 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1559 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1562 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1565 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1568 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1570 case GL_INCR_WRAP_EXT
:
1571 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1573 case GL_DECR_WRAP_EXT
:
1574 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1577 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1582 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1584 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1586 rmesa
->state
.stencil
.clear
=
1587 ((GLuint
) ctx
->Stencil
.Clear
|
1588 (0xff << R200_STENCIL_MASK_SHIFT
) |
1589 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
));
1593 /* =============================================================
1594 * Window position and viewport transformation
1598 * To correctly position primitives:
1600 #define SUBPIXEL_X 0.125
1601 #define SUBPIXEL_Y 0.125
1603 void r200UpdateWindow( GLcontext
*ctx
)
1605 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1606 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1607 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1608 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1609 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1611 GLfloat sx
= v
[MAT_SX
];
1612 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1613 GLfloat sy
= - v
[MAT_SY
];
1614 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1615 GLfloat sz
= v
[MAT_SZ
] * rmesa
->state
.depth
.scale
;
1616 GLfloat tz
= v
[MAT_TZ
] * rmesa
->state
.depth
.scale
;
1618 R200_FIREVERTICES( rmesa
);
1619 R200_STATECHANGE( rmesa
, vpt
);
1621 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = *(GLuint
*)&sx
;
1622 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1623 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = *(GLuint
*)&sy
;
1624 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1625 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = *(GLuint
*)&sz
;
1626 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = *(GLuint
*)&tz
;
1631 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1632 GLsizei width
, GLsizei height
)
1634 /* Don't pipeline viewport changes, conflict with window offset
1635 * setting below. Could apply deltas to rescue pipelined viewport
1636 * values, or keep the originals hanging around.
1638 R200_FIREVERTICES( R200_CONTEXT(ctx
) );
1639 r200UpdateWindow( ctx
);
1642 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1645 r200UpdateWindow( ctx
);
1648 void r200UpdateViewportOffset( GLcontext
*ctx
)
1650 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1651 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1652 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1653 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1654 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1656 GLfloat tx
= v
[MAT_TX
] + xoffset
;
1657 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
;
1659 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != *(GLuint
*)&tx
||
1660 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != *(GLuint
*)&ty
)
1662 /* Note: this should also modify whatever data the context reset
1665 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1666 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1668 /* update polygon stipple x/y screen offset */
1671 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1673 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1674 R200_STIPPLE_Y_OFFSET_MASK
);
1676 /* add magic offsets, then invert */
1677 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1678 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1679 & R200_STIPPLE_COORD_MASK
);
1681 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1682 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1684 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1685 R200_STATECHANGE( rmesa
, msc
);
1686 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1691 r200UpdateScissor( ctx
);
1696 /* =============================================================
1700 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1702 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1704 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1705 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1706 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1707 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1708 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1710 color
[2], color
[3] );
1714 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1716 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1717 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1721 static GLuint r200_rop_tab
[] = {
1724 R200_ROP_AND_REVERSE
,
1726 R200_ROP_AND_INVERTED
,
1733 R200_ROP_OR_REVERSE
,
1734 R200_ROP_COPY_INVERTED
,
1735 R200_ROP_OR_INVERTED
,
1740 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1742 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1743 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1747 R200_STATECHANGE( rmesa
, msk
);
1748 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1752 void r200SetCliprects( r200ContextPtr rmesa
, GLenum mode
)
1754 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1758 rmesa
->numClipRects
= dPriv
->numClipRects
;
1759 rmesa
->pClipRects
= dPriv
->pClipRects
;
1762 /* Can't ignore 2d windows if we are page flipping.
1764 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1765 rmesa
->numClipRects
= dPriv
->numClipRects
;
1766 rmesa
->pClipRects
= dPriv
->pClipRects
;
1769 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1770 rmesa
->pClipRects
= dPriv
->pBackClipRects
;
1774 fprintf(stderr
, "bad mode in r200SetCliprects\n");
1778 if (rmesa
->state
.scissor
.enabled
)
1779 r200RecalcScissorRects( rmesa
);
1783 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1785 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1787 if (R200_DEBUG
& DEBUG_DRI
)
1788 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1789 _mesa_lookup_enum_by_nr( mode
));
1791 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1794 * _DrawDestMask is easier to cope with than <mode>.
1796 switch ( ctx
->Color
._DrawDestMask
[0] ) {
1797 case DD_FRONT_LEFT_BIT
:
1798 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1799 r200SetCliprects( rmesa
, GL_FRONT_LEFT
);
1801 case DD_BACK_LEFT_BIT
:
1802 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1803 r200SetCliprects( rmesa
, GL_BACK_LEFT
);
1806 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1807 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1811 /* We want to update the s/w rast state too so that r200SetBuffer()
1814 _swrast_DrawBuffer(ctx
, mode
);
1816 R200_STATECHANGE( rmesa
, ctx
);
1817 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = ((rmesa
->state
.color
.drawOffset
+
1818 rmesa
->r200Screen
->fbLocation
)
1819 & R200_COLOROFFSET_MASK
);
1820 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
1824 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1826 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1829 /* =============================================================
1830 * State enable/disable
1833 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1835 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1838 if ( R200_DEBUG
& DEBUG_STATE
)
1839 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1840 _mesa_lookup_enum_by_nr( cap
),
1841 state
? "GL_TRUE" : "GL_FALSE" );
1844 /* Fast track this one...
1852 R200_STATECHANGE( rmesa
, ctx
);
1854 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1856 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1861 case GL_COLOR_LOGIC_OP
:
1862 r200_set_blend_state( ctx
);
1865 case GL_CLIP_PLANE0
:
1866 case GL_CLIP_PLANE1
:
1867 case GL_CLIP_PLANE2
:
1868 case GL_CLIP_PLANE3
:
1869 case GL_CLIP_PLANE4
:
1870 case GL_CLIP_PLANE5
:
1871 p
= cap
-GL_CLIP_PLANE0
;
1872 R200_STATECHANGE( rmesa
, tcl
);
1874 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1875 r200ClipPlane( ctx
, cap
, NULL
);
1878 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1882 case GL_COLOR_MATERIAL
:
1883 r200ColorMaterial( ctx
, 0, 0 );
1884 r200UpdateMaterial( ctx
);
1888 r200CullFace( ctx
, 0 );
1892 R200_STATECHANGE(rmesa
, ctx
);
1894 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1896 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1901 R200_STATECHANGE(rmesa
, ctx
);
1903 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1904 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1906 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1907 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1912 R200_STATECHANGE(rmesa
, ctx
);
1914 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1915 r200Fogfv( ctx
, GL_FOG_MODE
, 0 );
1917 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1918 R200_STATECHANGE(rmesa
, tcl
);
1919 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1921 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1922 if (rmesa
->TclFallback
)
1923 r200ChooseVertexState( ctx
);
1924 _mesa_allow_light_in_model( ctx
, !state
);
1935 R200_STATECHANGE(rmesa
, tcl
);
1936 p
= cap
- GL_LIGHT0
;
1938 flag
= (R200_LIGHT_1_ENABLE
|
1939 R200_LIGHT_1_ENABLE_AMBIENT
|
1940 R200_LIGHT_1_ENABLE_SPECULAR
);
1942 flag
= (R200_LIGHT_0_ENABLE
|
1943 R200_LIGHT_0_ENABLE_AMBIENT
|
1944 R200_LIGHT_0_ENABLE_SPECULAR
);
1947 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1949 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1953 update_light_colors( ctx
, p
);
1957 r200UpdateSpecular(ctx
);
1960 case GL_LINE_SMOOTH
:
1961 R200_STATECHANGE( rmesa
, ctx
);
1963 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1965 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1969 case GL_LINE_STIPPLE
:
1970 R200_STATECHANGE( rmesa
, set
);
1972 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1974 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1979 R200_STATECHANGE( rmesa
, tcl
);
1981 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1983 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1987 /* Pointsize registers on r200 don't seem to do anything. Maybe
1988 * have to pass pointsizes as vertex parameters? In any case,
1989 * setting pointmin == pointsizemax == 1.0, and doing nothing
1990 * for aa is enough to satisfy conform.
1992 case GL_POINT_SMOOTH
:
1995 /* These don't really do anything, as we don't use the 3vtx
1999 case GL_POLYGON_OFFSET_POINT
:
2000 R200_STATECHANGE( rmesa
, set
);
2002 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
2004 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
2008 case GL_POLYGON_OFFSET_LINE
:
2009 R200_STATECHANGE( rmesa
, set
);
2011 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
2013 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
2018 case GL_POLYGON_OFFSET_FILL
:
2019 R200_STATECHANGE( rmesa
, set
);
2021 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
2023 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
2027 case GL_POLYGON_SMOOTH
:
2028 R200_STATECHANGE( rmesa
, ctx
);
2030 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
2032 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
2036 case GL_POLYGON_STIPPLE
:
2037 R200_STATECHANGE(rmesa
, set
);
2039 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
2041 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
2045 case GL_RESCALE_NORMAL_EXT
: {
2046 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
2047 R200_STATECHANGE( rmesa
, tcl
);
2049 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2051 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2056 case GL_SCISSOR_TEST
:
2057 R200_FIREVERTICES( rmesa
);
2058 rmesa
->state
.scissor
.enabled
= state
;
2059 r200UpdateScissor( ctx
);
2062 case GL_STENCIL_TEST
:
2063 if ( rmesa
->state
.stencil
.hwBuffer
) {
2064 R200_STATECHANGE( rmesa
, ctx
);
2066 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
2068 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
2071 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
2075 case GL_TEXTURE_GEN_Q
:
2076 case GL_TEXTURE_GEN_R
:
2077 case GL_TEXTURE_GEN_S
:
2078 case GL_TEXTURE_GEN_T
:
2079 /* Picked up in r200UpdateTextureState.
2081 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
2084 case GL_COLOR_SUM_EXT
:
2085 r200UpdateSpecular ( ctx
);
2088 case GL_VERTEX_PROGRAM_ARB
:
2089 TCL_FALLBACK(rmesa
->glCtx
, R200_TCL_FALLBACK_TCL_DISABLE
, state
);
2098 void r200LightingSpaceChange( GLcontext
*ctx
)
2100 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2103 if (R200_DEBUG
& DEBUG_STATE
)
2104 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2105 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2107 if (ctx
->_NeedEyeCoords
)
2108 tmp
= ctx
->Transform
.RescaleNormals
;
2110 tmp
= !ctx
->Transform
.RescaleNormals
;
2112 R200_STATECHANGE( rmesa
, tcl
);
2114 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
2116 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
2119 if (R200_DEBUG
& DEBUG_STATE
)
2120 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
2121 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
2124 /* =============================================================
2125 * Deferred state management - matrices, textures, other?
2131 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
2133 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2137 for (i
= 0 ; i
< 4 ; i
++) {
2141 *dest
++ = src
[i
+12];
2144 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2147 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2149 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2150 memcpy(dest
, src
, 16*sizeof(float));
2151 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2155 static void update_texturematrix( GLcontext
*ctx
)
2157 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2158 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2159 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2162 if (R200_DEBUG
& DEBUG_STATE
)
2163 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2164 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2166 rmesa
->TexMatEnabled
= 0;
2167 rmesa
->TexMatCompSel
= 0;
2169 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
2170 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2173 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2174 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2175 R200_TEXMAT_0_ENABLE
) << unit
;
2177 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2179 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2180 /* Need to preconcatenate any active texgen
2181 * obj/eyeplane matrices:
2183 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2184 ctx
->TextureMatrixStack
[unit
].Top
,
2185 &rmesa
->TexGenMatrix
[unit
] );
2186 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2189 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2190 R200_MTX_TEX0
+unit
);
2193 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2194 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2195 R200_MTX_TEX0
+unit
);
2199 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2200 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
]) {
2201 R200_STATECHANGE(rmesa
, tcg
);
2202 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2205 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2206 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2207 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2208 R200_STATECHANGE(rmesa
, vtx
);
2209 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2215 void r200ValidateState( GLcontext
*ctx
)
2217 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2218 GLuint new_state
= rmesa
->NewGLState
;
2220 if (new_state
& _NEW_TEXTURE
) {
2221 r200UpdateTextureState( ctx
);
2222 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2225 /* Need an event driven matrix update?
2227 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2228 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2230 /* Need these for lighting (shouldn't upload otherwise)
2232 if (new_state
& (_NEW_MODELVIEW
)) {
2233 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2234 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2237 /* Does this need to be triggered on eg. modelview for
2238 * texgen-derived objplane/eyeplane matrices?
2240 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2241 update_texturematrix( ctx
);
2244 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2245 update_light( ctx
);
2248 /* emit all active clip planes if projection matrix changes.
2250 if (new_state
& (_NEW_PROJECTION
)) {
2251 if (ctx
->Transform
.ClipPlanesEnabled
)
2252 r200UpdateClipPlanes( ctx
);
2256 rmesa
->NewGLState
= 0;
2260 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2262 _swrast_InvalidateState( ctx
, new_state
);
2263 _swsetup_InvalidateState( ctx
, new_state
);
2264 _ac_InvalidateState( ctx
, new_state
);
2265 _tnl_InvalidateState( ctx
, new_state
);
2266 _ae_invalidate_state( ctx
, new_state
);
2267 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2268 r200VtxfmtInvalidate( ctx
);
2271 /* A hack. The r200 can actually cope just fine with materials
2272 * between begin/ends, so fix this. But how ?
2274 static GLboolean
check_material( GLcontext
*ctx
)
2276 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2279 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2280 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2282 if (tnl
->vb
.AttribPtr
[i
] &&
2283 tnl
->vb
.AttribPtr
[i
]->stride
)
2289 static void r200WrapRunPipeline( GLcontext
*ctx
)
2291 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2292 GLboolean has_material
;
2295 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2299 if (rmesa
->NewGLState
)
2300 r200ValidateState( ctx
);
2302 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2305 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2308 /* Run the pipeline.
2310 _tnl_run_pipeline( ctx
);
2313 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2318 /* Initialize the driver's state functions.
2320 void r200InitStateFuncs( struct dd_function_table
*functions
)
2322 functions
->UpdateState
= r200InvalidateState
;
2323 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2325 functions
->DrawBuffer
= r200DrawBuffer
;
2326 functions
->ReadBuffer
= r200ReadBuffer
;
2328 functions
->AlphaFunc
= r200AlphaFunc
;
2329 functions
->BlendColor
= r200BlendColor
;
2330 functions
->BlendEquationSeparate
= r200BlendEquationSeparate
;
2331 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2332 functions
->ClearColor
= r200ClearColor
;
2333 functions
->ClearDepth
= r200ClearDepth
;
2334 functions
->ClearIndex
= NULL
;
2335 functions
->ClearStencil
= r200ClearStencil
;
2336 functions
->ClipPlane
= r200ClipPlane
;
2337 functions
->ColorMask
= r200ColorMask
;
2338 functions
->CullFace
= r200CullFace
;
2339 functions
->DepthFunc
= r200DepthFunc
;
2340 functions
->DepthMask
= r200DepthMask
;
2341 functions
->DepthRange
= r200DepthRange
;
2342 functions
->Enable
= r200Enable
;
2343 functions
->Fogfv
= r200Fogfv
;
2344 functions
->FrontFace
= r200FrontFace
;
2345 functions
->Hint
= NULL
;
2346 functions
->IndexMask
= NULL
;
2347 functions
->LightModelfv
= r200LightModelfv
;
2348 functions
->Lightfv
= r200Lightfv
;
2349 functions
->LineStipple
= r200LineStipple
;
2350 functions
->LineWidth
= r200LineWidth
;
2351 functions
->LogicOpcode
= r200LogicOpCode
;
2352 functions
->PolygonMode
= r200PolygonMode
;
2353 functions
->PolygonOffset
= r200PolygonOffset
;
2354 functions
->PolygonStipple
= r200PolygonStipple
;
2355 functions
->PointSize
= r200PointSize
;
2356 functions
->RenderMode
= r200RenderMode
;
2357 functions
->Scissor
= r200Scissor
;
2358 functions
->ShadeModel
= r200ShadeModel
;
2359 functions
->StencilFunc
= r200StencilFunc
;
2360 functions
->StencilMask
= r200StencilMask
;
2361 functions
->StencilOp
= r200StencilOp
;
2362 functions
->Viewport
= r200Viewport
;
2364 /* Swrast hooks for imaging extensions:
2366 functions
->CopyColorTable
= _swrast_CopyColorTable
;
2367 functions
->CopyColorSubTable
= _swrast_CopyColorSubTable
;
2368 functions
->CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2369 functions
->CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2373 void r200InitTnlFuncs( GLcontext
*ctx
)
2375 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2376 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;