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 r200BlendEquation( GLcontext
*ctx
, GLenum mode
)
109 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
110 GLuint b
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] & ~R200_COMB_FCN_MASK
;
115 b
|= R200_COMB_FCN_ADD_CLAMP
;
118 case GL_FUNC_SUBTRACT
:
119 b
|= R200_COMB_FCN_SUB_CLAMP
;
122 case GL_FUNC_REVERSE_SUBTRACT
:
123 b
|= R200_COMB_FCN_RSUB_CLAMP
;
127 b
|= R200_COMB_FCN_MIN
;
131 b
|= R200_COMB_FCN_MAX
;
138 R200_STATECHANGE( rmesa
, ctx
);
139 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = b
;
140 if ( ctx
->Color
.ColorLogicOpEnabled
) {
141 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
143 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
147 static void r200BlendFuncSeparate( GLcontext
*ctx
,
148 GLenum sfactorRGB
, GLenum dfactorRGB
,
149 GLenum sfactorA
, GLenum dfactorA
)
151 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
152 GLuint b
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] &
153 ~(R200_SRC_BLEND_MASK
| R200_DST_BLEND_MASK
);
155 switch ( ctx
->Color
.BlendSrcRGB
) {
157 b
|= R200_SRC_BLEND_GL_ZERO
;
160 b
|= R200_SRC_BLEND_GL_ONE
;
163 b
|= R200_SRC_BLEND_GL_DST_COLOR
;
165 case GL_ONE_MINUS_DST_COLOR
:
166 b
|= R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR
;
169 b
|= R200_SRC_BLEND_GL_SRC_COLOR
;
171 case GL_ONE_MINUS_SRC_COLOR
:
172 b
|= R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR
;
175 b
|= R200_SRC_BLEND_GL_SRC_ALPHA
;
177 case GL_ONE_MINUS_SRC_ALPHA
:
178 b
|= R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
181 b
|= R200_SRC_BLEND_GL_DST_ALPHA
;
183 case GL_ONE_MINUS_DST_ALPHA
:
184 b
|= R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA
;
186 case GL_SRC_ALPHA_SATURATE
:
187 b
|= R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE
;
189 case GL_CONSTANT_COLOR
:
190 b
|= R200_SRC_BLEND_GL_CONST_COLOR
;
192 case GL_ONE_MINUS_CONSTANT_COLOR
:
193 b
|= R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR
;
195 case GL_CONSTANT_ALPHA
:
196 b
|= R200_SRC_BLEND_GL_CONST_ALPHA
;
198 case GL_ONE_MINUS_CONSTANT_ALPHA
:
199 b
|= R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
205 switch ( ctx
->Color
.BlendDstRGB
) {
207 b
|= R200_DST_BLEND_GL_ZERO
;
210 b
|= R200_DST_BLEND_GL_ONE
;
213 b
|= R200_DST_BLEND_GL_SRC_COLOR
;
215 case GL_ONE_MINUS_SRC_COLOR
:
216 b
|= R200_DST_BLEND_GL_ONE_MINUS_SRC_COLOR
;
219 b
|= R200_DST_BLEND_GL_SRC_ALPHA
;
221 case GL_ONE_MINUS_SRC_ALPHA
:
222 b
|= R200_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA
;
225 b
|= R200_DST_BLEND_GL_DST_COLOR
;
227 case GL_ONE_MINUS_DST_COLOR
:
228 b
|= R200_DST_BLEND_GL_ONE_MINUS_DST_COLOR
;
231 b
|= R200_DST_BLEND_GL_DST_ALPHA
;
233 case GL_ONE_MINUS_DST_ALPHA
:
234 b
|= R200_DST_BLEND_GL_ONE_MINUS_DST_ALPHA
;
236 case GL_CONSTANT_COLOR
:
237 b
|= R200_DST_BLEND_GL_CONST_COLOR
;
239 case GL_ONE_MINUS_CONSTANT_COLOR
:
240 b
|= R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR
;
242 case GL_CONSTANT_ALPHA
:
243 b
|= R200_DST_BLEND_GL_CONST_ALPHA
;
245 case GL_ONE_MINUS_CONSTANT_ALPHA
:
246 b
|= R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA
;
252 R200_STATECHANGE( rmesa
, ctx
);
253 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_BLENDCNTL
] = b
;
257 /* =============================================================
261 static void r200DepthFunc( GLcontext
*ctx
, GLenum func
)
263 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
265 R200_STATECHANGE( rmesa
, ctx
);
266 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_TEST_MASK
;
268 switch ( ctx
->Depth
.Func
) {
270 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEVER
;
273 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LESS
;
276 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_EQUAL
;
279 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_LEQUAL
;
282 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GREATER
;
285 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_NEQUAL
;
288 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_GEQUAL
;
291 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_TEST_ALWAYS
;
297 static void r200DepthMask( GLcontext
*ctx
, GLboolean flag
)
299 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
300 R200_STATECHANGE( rmesa
, ctx
);
302 if ( ctx
->Depth
.Mask
) {
303 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_Z_WRITE_ENABLE
;
305 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_Z_WRITE_ENABLE
;
310 /* =============================================================
315 static void r200Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
317 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
318 union { int i
; float f
; } c
, d
;
322 c
.i
= rmesa
->hw
.fog
.cmd
[FOG_C
];
323 d
.i
= rmesa
->hw
.fog
.cmd
[FOG_D
];
327 if (!ctx
->Fog
.Enabled
)
329 R200_STATECHANGE(rmesa
, tcl
);
330 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
331 switch (ctx
->Fog
.Mode
) {
333 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_LINEAR
;
334 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
339 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
340 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
344 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP
;
346 d
.f
= -ctx
->Fog
.Density
;
349 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_TCL_FOG_EXP2
;
351 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
358 switch (ctx
->Fog
.Mode
) {
361 d
.f
= -ctx
->Fog
.Density
;
365 d
.f
= -(ctx
->Fog
.Density
* ctx
->Fog
.Density
);
373 if (ctx
->Fog
.Mode
== GL_LINEAR
) {
374 if (ctx
->Fog
.Start
== ctx
->Fog
.End
) {
378 c
.f
= ctx
->Fog
.End
/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
379 d
.f
= -1.0/(ctx
->Fog
.End
-ctx
->Fog
.Start
);
384 R200_STATECHANGE( rmesa
, ctx
);
385 UNCLAMPED_FLOAT_TO_RGB_CHAN( col
, ctx
->Fog
.Color
);
386 i
= r200PackColor( 4, col
[0], col
[1], col
[2], 0 );
387 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_COLOR_MASK
;
388 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= i
;
390 case GL_FOG_COORDINATE_SOURCE_EXT
:
398 if (c
.i
!= rmesa
->hw
.fog
.cmd
[FOG_C
] || d
.i
!= rmesa
->hw
.fog
.cmd
[FOG_D
]) {
399 R200_STATECHANGE( rmesa
, fog
);
400 rmesa
->hw
.fog
.cmd
[FOG_C
] = c
.i
;
401 rmesa
->hw
.fog
.cmd
[FOG_D
] = d
.i
;
406 /* =============================================================
411 static GLboolean
intersect_rect( XF86DRIClipRectPtr out
,
412 XF86DRIClipRectPtr a
,
413 XF86DRIClipRectPtr b
)
416 if ( b
->x1
> out
->x1
) out
->x1
= b
->x1
;
417 if ( b
->y1
> out
->y1
) out
->y1
= b
->y1
;
418 if ( b
->x2
< out
->x2
) out
->x2
= b
->x2
;
419 if ( b
->y2
< out
->y2
) out
->y2
= b
->y2
;
420 if ( out
->x1
>= out
->x2
) return GL_FALSE
;
421 if ( out
->y1
>= out
->y2
) return GL_FALSE
;
426 void r200RecalcScissorRects( r200ContextPtr rmesa
)
428 XF86DRIClipRectPtr out
;
431 /* Grow cliprect store?
433 if (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
434 while (rmesa
->state
.scissor
.numAllocedClipRects
< rmesa
->numClipRects
) {
435 rmesa
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
436 rmesa
->state
.scissor
.numAllocedClipRects
*= 2;
439 if (rmesa
->state
.scissor
.pClipRects
)
440 FREE(rmesa
->state
.scissor
.pClipRects
);
442 rmesa
->state
.scissor
.pClipRects
=
443 MALLOC( rmesa
->state
.scissor
.numAllocedClipRects
*
444 sizeof(XF86DRIClipRectRec
) );
446 if ( rmesa
->state
.scissor
.pClipRects
== NULL
) {
447 rmesa
->state
.scissor
.numAllocedClipRects
= 0;
452 out
= rmesa
->state
.scissor
.pClipRects
;
453 rmesa
->state
.scissor
.numClipRects
= 0;
455 for ( i
= 0 ; i
< rmesa
->numClipRects
; i
++ ) {
456 if ( intersect_rect( out
,
457 &rmesa
->pClipRects
[i
],
458 &rmesa
->state
.scissor
.rect
) ) {
459 rmesa
->state
.scissor
.numClipRects
++;
466 static void r200UpdateScissor( GLcontext
*ctx
)
468 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
470 if ( rmesa
->dri
.drawable
) {
471 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
473 int x
= ctx
->Scissor
.X
;
474 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
475 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
476 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
478 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
479 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
480 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
481 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
483 r200RecalcScissorRects( rmesa
);
488 static void r200Scissor( GLcontext
*ctx
,
489 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
491 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
493 if ( ctx
->Scissor
.Enabled
) {
494 R200_FIREVERTICES( rmesa
); /* don't pipeline cliprect changes */
495 r200UpdateScissor( ctx
);
501 /* =============================================================
505 static void r200CullFace( GLcontext
*ctx
, GLenum unused
)
507 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
508 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
509 GLuint t
= rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
];
511 s
|= R200_FFACE_SOLID
| R200_BFACE_SOLID
;
512 t
&= ~(R200_CULL_FRONT
| R200_CULL_BACK
);
514 if ( ctx
->Polygon
.CullFlag
) {
515 switch ( ctx
->Polygon
.CullFaceMode
) {
517 s
&= ~R200_FFACE_SOLID
;
518 t
|= R200_CULL_FRONT
;
521 s
&= ~R200_BFACE_SOLID
;
524 case GL_FRONT_AND_BACK
:
525 s
&= ~(R200_FFACE_SOLID
| R200_BFACE_SOLID
);
526 t
|= (R200_CULL_FRONT
| R200_CULL_BACK
);
531 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
532 R200_STATECHANGE(rmesa
, set
);
533 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
536 if ( rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] != t
) {
537 R200_STATECHANGE(rmesa
, tcl
);
538 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] = t
;
542 static void r200FrontFace( GLcontext
*ctx
, GLenum mode
)
544 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
546 R200_STATECHANGE( rmesa
, set
);
547 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_FFACE_CULL_DIR_MASK
;
549 R200_STATECHANGE( rmesa
, tcl
);
550 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_CULL_FRONT_IS_CCW
;
554 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CW
;
557 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_FFACE_CULL_CCW
;
558 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= R200_CULL_FRONT_IS_CCW
;
563 /* =============================================================
566 static void r200PointSize( GLcontext
*ctx
, GLfloat size
)
568 if (0) fprintf(stderr
, "%s: %f\n", __FUNCTION__
, size
);
571 /* =============================================================
574 static void r200LineWidth( GLcontext
*ctx
, GLfloat widthf
)
576 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
578 R200_STATECHANGE( rmesa
, lin
);
579 R200_STATECHANGE( rmesa
, set
);
581 /* Line width is stored in U6.4 format.
583 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] &= ~0xffff;
584 rmesa
->hw
.lin
.cmd
[LIN_SE_LINE_WIDTH
] |= (GLuint
)(ctx
->Line
._Width
* 16.0);
586 if ( widthf
> 1.0 ) {
587 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_WIDELINE_ENABLE
;
589 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_WIDELINE_ENABLE
;
593 static void r200LineStipple( GLcontext
*ctx
, GLint factor
, GLushort pattern
)
595 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
597 R200_STATECHANGE( rmesa
, lin
);
598 rmesa
->hw
.lin
.cmd
[LIN_RE_LINE_PATTERN
] =
599 ((((GLuint
)factor
& 0xff) << 16) | ((GLuint
)pattern
));
603 /* =============================================================
606 static void r200ColorMask( GLcontext
*ctx
,
607 GLboolean r
, GLboolean g
,
608 GLboolean b
, GLboolean a
)
610 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
611 GLuint mask
= r200PackColor( rmesa
->r200Screen
->cpp
,
612 ctx
->Color
.ColorMask
[RCOMP
],
613 ctx
->Color
.ColorMask
[GCOMP
],
614 ctx
->Color
.ColorMask
[BCOMP
],
615 ctx
->Color
.ColorMask
[ACOMP
] );
617 GLuint flag
= rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] & ~R200_PLANE_MASK_ENABLE
;
619 if (!(r
&& g
&& b
&& a
))
620 flag
|= R200_PLANE_MASK_ENABLE
;
622 if ( rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] != flag
) {
623 R200_STATECHANGE( rmesa
, ctx
);
624 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] = flag
;
627 if ( rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] != mask
) {
628 R200_STATECHANGE( rmesa
, msk
);
629 rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
] = mask
;
634 /* =============================================================
638 static void r200PolygonOffset( GLcontext
*ctx
,
639 GLfloat factor
, GLfloat units
)
641 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
642 GLfloat constant
= units
* rmesa
->state
.depth
.scale
;
647 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
649 R200_STATECHANGE( rmesa
, zbs
);
650 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_FACTOR
] = *(GLuint
*)&factor
;
651 rmesa
->hw
.zbs
.cmd
[ZBS_SE_ZBIAS_CONSTANT
] = *(GLuint
*)&constant
;
654 static void r200PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
656 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
658 drmRadeonStipple stipple
;
660 /* Must flip pattern upside down.
662 for ( i
= 0 ; i
< 32 ; i
++ ) {
663 rmesa
->state
.stipple
.mask
[31 - i
] = ((GLuint
*) mask
)[i
];
666 /* TODO: push this into cmd mechanism
668 R200_FIREVERTICES( rmesa
);
669 LOCK_HARDWARE( rmesa
);
671 /* FIXME: Use window x,y offsets into stipple RAM.
673 stipple
.mask
= rmesa
->state
.stipple
.mask
;
674 drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_STIPPLE
,
675 &stipple
, sizeof(drmRadeonStipple
) );
676 UNLOCK_HARDWARE( rmesa
);
679 static void r200PolygonMode( GLcontext
*ctx
, GLenum face
, GLenum mode
)
681 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
682 GLboolean flag
= (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) != 0;
684 /* Can't generally do unfilled via tcl, but some good special
687 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_UNFILLED
, flag
);
688 if (rmesa
->TclFallback
) {
689 r200ChooseRenderState( ctx
);
690 r200ChooseVertexState( ctx
);
695 /* =============================================================
696 * Rendering attributes
698 * We really don't want to recalculate all this every time we bind a
699 * texture. These things shouldn't change all that often, so it makes
700 * sense to break them out of the core texture state update routines.
703 /* Examine lighting and texture state to determine if separate specular
706 static void r200UpdateSpecular( GLcontext
*ctx
)
708 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
709 CARD32 p
= rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
];
711 R200_STATECHANGE( rmesa
, tcl
);
712 R200_STATECHANGE( rmesa
, vtx
);
714 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_0_SHIFT
);
715 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] &= ~(3<<R200_VTX_COLOR_1_SHIFT
);
716 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_0
;
717 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] &= ~R200_OUTPUT_COLOR_1
;
718 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHTING_ENABLE
;
720 p
&= ~R200_SPECULAR_ENABLE
;
722 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_DIFFUSE_SPECULAR_COMBINE
;
725 if (ctx
->Light
.Enabled
&&
726 ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
) {
727 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
728 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
729 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
730 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
731 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
732 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
733 p
|= R200_SPECULAR_ENABLE
;
734 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &=
735 ~R200_DIFFUSE_SPECULAR_COMBINE
;
737 else if (ctx
->Light
.Enabled
) {
738 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
739 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
740 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_0
;
741 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHTING_ENABLE
;
742 } else if (ctx
->Fog
.ColorSumEnabled
) {
743 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
744 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
) |
745 (R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
746 p
|= R200_SPECULAR_ENABLE
;
748 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
749 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_0_SHIFT
));
752 if (ctx
->Fog
.Enabled
) {
753 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_0
] |=
754 ((R200_VTX_FP_RGBA
<< R200_VTX_COLOR_1_SHIFT
));
755 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] |= R200_OUTPUT_COLOR_1
;
758 if ( rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] != p
) {
759 R200_STATECHANGE( rmesa
, ctx
);
760 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] = p
;
763 /* Update vertex/render formats
765 if (rmesa
->TclFallback
) {
766 r200ChooseRenderState( ctx
);
767 r200ChooseVertexState( ctx
);
772 /* =============================================================
777 /* Update on colormaterial, material emmissive/ambient,
778 * lightmodel.globalambient
780 static void update_global_ambient( GLcontext
*ctx
)
782 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
783 float *fcmd
= (float *)R200_DB_STATE( glt
);
785 /* Need to do more if both emmissive & ambient are PREMULT:
787 if ((rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] &
788 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
789 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT
))) == 0)
791 COPY_3V( &fcmd
[GLT_RED
],
792 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_EMISSION
]);
793 ACC_SCALE_3V( &fcmd
[GLT_RED
],
794 ctx
->Light
.Model
.Ambient
,
795 ctx
->Light
.Material
.Attrib
[MAT_ATTRIB_FRONT_AMBIENT
]);
799 COPY_3V( &fcmd
[GLT_RED
], ctx
->Light
.Model
.Ambient
);
802 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.glt
);
805 /* Update on change to
809 * - colormaterial enabled
810 * - colormaterial bitmask
812 static void update_light_colors( GLcontext
*ctx
, GLuint p
)
814 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
816 /* fprintf(stderr, "%s\n", __FUNCTION__); */
819 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
820 float *fcmd
= (float *)R200_DB_STATE( lit
[p
] );
821 GLuint bitmask
= ctx
->Light
.ColorMaterialBitmask
;
822 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
824 COPY_4V( &fcmd
[LIT_AMBIENT_RED
], l
->Ambient
);
825 COPY_4V( &fcmd
[LIT_DIFFUSE_RED
], l
->Diffuse
);
826 COPY_4V( &fcmd
[LIT_SPECULAR_RED
], l
->Specular
);
828 if (!ctx
->Light
.ColorMaterialEnabled
)
831 if ((bitmask
& MAT_BIT_FRONT_AMBIENT
) == 0)
832 SELF_SCALE_3V( &fcmd
[LIT_AMBIENT_RED
], mat
[MAT_ATTRIB_FRONT_AMBIENT
] );
834 if ((bitmask
& MAT_BIT_FRONT_DIFFUSE
) == 0)
835 SELF_SCALE_3V( &fcmd
[LIT_DIFFUSE_RED
], mat
[MAT_ATTRIB_FRONT_DIFFUSE
] );
837 if ((bitmask
& MAT_BIT_FRONT_SPECULAR
) == 0)
838 SELF_SCALE_3V( &fcmd
[LIT_SPECULAR_RED
], mat
[MAT_ATTRIB_FRONT_SPECULAR
] );
840 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
844 /* Also fallback for asym colormaterial mode in twoside lighting...
846 static void check_twoside_fallback( GLcontext
*ctx
)
848 GLboolean fallback
= GL_FALSE
;
851 if (ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
) {
852 if (ctx
->Light
.ColorMaterialEnabled
&&
853 (ctx
->Light
.ColorMaterialBitmask
& BACK_MATERIAL_BITS
) !=
854 ((ctx
->Light
.ColorMaterialBitmask
& FRONT_MATERIAL_BITS
)<<1))
857 for (i
= MAT_ATTRIB_FRONT_AMBIENT
; i
< MAT_ATTRIB_FRONT_INDEXES
; i
+=2)
858 if (memcmp( ctx
->Light
.Material
.Attrib
[i
],
859 ctx
->Light
.Material
.Attrib
[i
+1],
860 sizeof(GLfloat
)*4) != 0) {
867 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_LIGHT_TWOSIDE
, fallback
);
870 static void r200ColorMaterial( GLcontext
*ctx
, GLenum face
, GLenum mode
)
872 if (ctx
->Light
.ColorMaterialEnabled
) {
873 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
874 GLuint light_model_ctl1
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
];
875 GLuint mask
= ctx
->Light
.ColorMaterialBitmask
;
877 /* Default to PREMULT:
879 light_model_ctl1
&= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT
) |
880 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT
) |
881 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT
) |
882 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT
));
884 if (mask
& MAT_BIT_FRONT_EMISSION
) {
885 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
886 R200_FRONT_EMISSIVE_SOURCE_SHIFT
);
889 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
890 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
891 R200_FRONT_AMBIENT_SOURCE_SHIFT
);
894 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
895 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
896 R200_FRONT_DIFFUSE_SOURCE_SHIFT
);
899 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
900 light_model_ctl1
|= (R200_LM1_SOURCE_VERTEX_COLOR_0
<<
901 R200_FRONT_SPECULAR_SOURCE_SHIFT
);
904 if (light_model_ctl1
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
]) {
907 R200_STATECHANGE( rmesa
, tcl
);
908 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_1
] = light_model_ctl1
;
910 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
911 update_light_colors( ctx
, p
);
912 update_global_ambient( ctx
);
916 check_twoside_fallback( ctx
);
919 void r200UpdateMaterial( GLcontext
*ctx
)
921 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
922 GLfloat (*mat
)[4] = ctx
->Light
.Material
.Attrib
;
923 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( mtl
[0] );
927 if (ctx
->Light
.ColorMaterialEnabled
)
928 mask
&= ~ctx
->Light
.ColorMaterialBitmask
;
930 if (R200_DEBUG
& DEBUG_STATE
)
931 fprintf(stderr
, "%s\n", __FUNCTION__
);
934 if (mask
& MAT_BIT_FRONT_EMISSION
) {
935 fcmd
[MTL_EMMISSIVE_RED
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][0];
936 fcmd
[MTL_EMMISSIVE_GREEN
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][1];
937 fcmd
[MTL_EMMISSIVE_BLUE
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][2];
938 fcmd
[MTL_EMMISSIVE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_EMISSION
][3];
940 if (mask
& MAT_BIT_FRONT_AMBIENT
) {
941 fcmd
[MTL_AMBIENT_RED
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][0];
942 fcmd
[MTL_AMBIENT_GREEN
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][1];
943 fcmd
[MTL_AMBIENT_BLUE
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][2];
944 fcmd
[MTL_AMBIENT_ALPHA
] = mat
[MAT_ATTRIB_FRONT_AMBIENT
][3];
946 if (mask
& MAT_BIT_FRONT_DIFFUSE
) {
947 fcmd
[MTL_DIFFUSE_RED
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][0];
948 fcmd
[MTL_DIFFUSE_GREEN
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][1];
949 fcmd
[MTL_DIFFUSE_BLUE
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][2];
950 fcmd
[MTL_DIFFUSE_ALPHA
] = mat
[MAT_ATTRIB_FRONT_DIFFUSE
][3];
952 if (mask
& MAT_BIT_FRONT_SPECULAR
) {
953 fcmd
[MTL_SPECULAR_RED
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][0];
954 fcmd
[MTL_SPECULAR_GREEN
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][1];
955 fcmd
[MTL_SPECULAR_BLUE
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][2];
956 fcmd
[MTL_SPECULAR_ALPHA
] = mat
[MAT_ATTRIB_FRONT_SPECULAR
][3];
958 if (mask
& MAT_BIT_FRONT_SHININESS
) {
959 fcmd
[MTL_SHININESS
] = mat
[MAT_ATTRIB_FRONT_SHININESS
][0];
962 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] );
964 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
965 update_light_colors( ctx
, p
);
967 check_twoside_fallback( ctx
);
968 update_global_ambient( ctx
);
973 * _MESA_NEW_NEED_EYE_COORDS
975 * Uses derived state from mesa:
984 * which are calculated in light.c and are correct for the current
985 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
986 * and _MESA_NEW_NEED_EYE_COORDS.
988 static void update_light( GLcontext
*ctx
)
990 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
992 /* Have to check these, or have an automatic shortcircuit mechanism
993 * to remove noop statechanges. (Or just do a better job on the
997 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
999 if (ctx
->_NeedEyeCoords
)
1000 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1002 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1004 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1006 R200_STATECHANGE( rmesa
, tcl
);
1007 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1012 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1013 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1014 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1015 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1016 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1017 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1022 if (ctx
->Light
.Enabled
) {
1024 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1025 if (ctx
->Light
.Light
[p
].Enabled
) {
1026 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1027 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1029 if (l
->EyePosition
[3] == 0.0) {
1030 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1031 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1032 fcmd
[LIT_POSITION_W
] = 0;
1033 fcmd
[LIT_DIRECTION_W
] = 0;
1035 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1036 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1037 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1038 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1039 fcmd
[LIT_DIRECTION_W
] = 0;
1042 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1048 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1049 GLenum pname
, const GLfloat
*params
)
1051 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1052 GLint p
= light
- GL_LIGHT0
;
1053 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1054 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1061 update_light_colors( ctx
, p
);
1064 case GL_SPOT_DIRECTION
:
1065 /* picked up in update_light */
1069 /* positions picked up in update_light, but can do flag here */
1070 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1071 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1073 R200_STATECHANGE(rmesa
, tcl
);
1074 if (l
->EyePosition
[3] != 0.0F
)
1075 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1077 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1081 case GL_SPOT_EXPONENT
:
1082 R200_STATECHANGE(rmesa
, lit
[p
]);
1083 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1086 case GL_SPOT_CUTOFF
: {
1087 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1088 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1090 R200_STATECHANGE(rmesa
, lit
[p
]);
1091 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1093 R200_STATECHANGE(rmesa
, tcl
);
1094 if (l
->SpotCutoff
!= 180.0F
)
1095 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1097 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1102 case GL_CONSTANT_ATTENUATION
:
1103 R200_STATECHANGE(rmesa
, lit
[p
]);
1104 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1105 if ( params
[0] == 0.0 )
1106 fcmd
[LIT_ATTEN_CONST_INV
] = FLT_MAX
;
1108 fcmd
[LIT_ATTEN_CONST_INV
] = 1.0 / params
[0];
1110 case GL_LINEAR_ATTENUATION
:
1111 R200_STATECHANGE(rmesa
, lit
[p
]);
1112 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1114 case GL_QUADRATIC_ATTENUATION
:
1115 R200_STATECHANGE(rmesa
, lit
[p
]);
1116 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1122 /* Set RANGE_ATTEN only when needed */
1125 case GL_CONSTANT_ATTENUATION
:
1126 case GL_LINEAR_ATTENUATION
:
1127 case GL_QUADRATIC_ATTENUATION
: {
1128 GLuint
*icmd
= (GLuint
*)R200_DB_STATE( tcl
);
1129 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1130 GLuint atten_flag
= ( p
&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1131 : R200_LIGHT_0_ENABLE_RANGE_ATTEN
;
1132 GLuint atten_const_flag
= ( p
&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1133 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN
;
1135 if ( l
->EyePosition
[3] == 0.0F
||
1136 ( ( fcmd
[LIT_ATTEN_CONST
] == 0.0 || fcmd
[LIT_ATTEN_CONST
] == 1.0 ) &&
1137 fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) ) {
1138 /* Disable attenuation */
1139 icmd
[idx
] &= ~atten_flag
;
1141 if ( fcmd
[LIT_ATTEN_QUADRATIC
] == 0.0 && fcmd
[LIT_ATTEN_LINEAR
] == 0.0 ) {
1142 /* Enable only constant portion of attenuation calculation */
1143 icmd
[idx
] |= ( atten_flag
| atten_const_flag
);
1145 /* Enable full attenuation calculation */
1146 icmd
[idx
] &= ~atten_const_flag
;
1147 icmd
[idx
] |= atten_flag
;
1151 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tcl
);
1162 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1163 const GLfloat
*param
)
1165 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1168 case GL_LIGHT_MODEL_AMBIENT
:
1169 update_global_ambient( ctx
);
1172 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1173 R200_STATECHANGE( rmesa
, tcl
);
1174 if (ctx
->Light
.Model
.LocalViewer
)
1175 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1177 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1180 case GL_LIGHT_MODEL_TWO_SIDE
:
1181 R200_STATECHANGE( rmesa
, tcl
);
1182 if (ctx
->Light
.Model
.TwoSide
)
1183 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1185 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHT_TWOSIDE
;
1187 check_twoside_fallback( ctx
);
1189 if (rmesa
->TclFallback
) {
1190 r200ChooseRenderState( ctx
);
1191 r200ChooseVertexState( ctx
);
1195 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1196 r200UpdateSpecular(ctx
);
1204 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1206 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1207 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1209 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1210 R200_ALPHA_SHADE_MASK
|
1211 R200_SPECULAR_SHADE_MASK
|
1212 R200_FOG_SHADE_MASK
);
1216 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1217 R200_ALPHA_SHADE_FLAT
|
1218 R200_SPECULAR_SHADE_FLAT
|
1219 R200_FOG_SHADE_FLAT
);
1222 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1223 R200_ALPHA_SHADE_GOURAUD
|
1224 R200_SPECULAR_SHADE_GOURAUD
|
1225 R200_FOG_SHADE_GOURAUD
);
1231 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1232 R200_STATECHANGE( rmesa
, set
);
1233 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1238 /* =============================================================
1242 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1244 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1245 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1246 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1248 R200_STATECHANGE( rmesa
, ucp
[p
] );
1249 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1250 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1251 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1252 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1255 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1257 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1260 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1261 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1262 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1264 R200_STATECHANGE( rmesa
, ucp
[p
] );
1265 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1266 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1267 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1268 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1274 /* =============================================================
1278 static void r200StencilFunc( GLcontext
*ctx
, GLenum func
,
1279 GLint ref
, GLuint mask
)
1281 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1282 GLuint refmask
= ((ctx
->Stencil
.Ref
[0] << R200_STENCIL_REF_SHIFT
) |
1283 (ctx
->Stencil
.ValueMask
[0] << R200_STENCIL_MASK_SHIFT
));
1285 R200_STATECHANGE( rmesa
, ctx
);
1286 R200_STATECHANGE( rmesa
, msk
);
1288 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1289 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1290 R200_STENCIL_VALUE_MASK
);
1292 switch ( ctx
->Stencil
.Function
[0] ) {
1294 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1297 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1300 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1303 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1306 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1309 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1312 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1315 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1319 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1322 static void r200StencilMask( GLcontext
*ctx
, GLuint mask
)
1324 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1326 R200_STATECHANGE( rmesa
, msk
);
1327 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1328 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1329 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
);
1332 static void r200StencilOp( GLcontext
*ctx
, GLenum fail
,
1333 GLenum zfail
, GLenum zpass
)
1335 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1337 R200_STATECHANGE( rmesa
, ctx
);
1338 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1339 R200_STENCIL_ZFAIL_MASK
|
1340 R200_STENCIL_ZPASS_MASK
);
1342 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1344 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1347 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1350 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1353 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1356 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1358 case GL_INCR_WRAP_EXT
:
1359 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1361 case GL_DECR_WRAP_EXT
:
1362 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1365 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1369 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1371 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1374 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1377 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1380 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1383 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1385 case GL_INCR_WRAP_EXT
:
1386 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1388 case GL_DECR_WRAP_EXT
:
1389 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1392 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1396 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1398 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1401 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1404 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1407 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1410 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1412 case GL_INCR_WRAP_EXT
:
1413 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1415 case GL_DECR_WRAP_EXT
:
1416 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1419 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1424 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1426 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1428 rmesa
->state
.stencil
.clear
=
1429 ((GLuint
) ctx
->Stencil
.Clear
|
1430 (0xff << R200_STENCIL_MASK_SHIFT
) |
1431 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
));
1435 /* =============================================================
1436 * Window position and viewport transformation
1440 * To correctly position primitives:
1442 #define SUBPIXEL_X 0.125
1443 #define SUBPIXEL_Y 0.125
1445 void r200UpdateWindow( GLcontext
*ctx
)
1447 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1448 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1449 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1450 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1451 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1453 GLfloat sx
= v
[MAT_SX
];
1454 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1455 GLfloat sy
= - v
[MAT_SY
];
1456 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1457 GLfloat sz
= v
[MAT_SZ
] * rmesa
->state
.depth
.scale
;
1458 GLfloat tz
= v
[MAT_TZ
] * rmesa
->state
.depth
.scale
;
1460 R200_FIREVERTICES( rmesa
);
1461 R200_STATECHANGE( rmesa
, vpt
);
1463 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = *(GLuint
*)&sx
;
1464 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1465 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = *(GLuint
*)&sy
;
1466 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1467 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = *(GLuint
*)&sz
;
1468 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = *(GLuint
*)&tz
;
1473 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1474 GLsizei width
, GLsizei height
)
1476 /* Don't pipeline viewport changes, conflict with window offset
1477 * setting below. Could apply deltas to rescue pipelined viewport
1478 * values, or keep the originals hanging around.
1480 R200_FIREVERTICES( R200_CONTEXT(ctx
) );
1481 r200UpdateWindow( ctx
);
1484 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1487 r200UpdateWindow( ctx
);
1490 void r200UpdateViewportOffset( GLcontext
*ctx
)
1492 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1493 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1494 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1495 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1496 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1498 GLfloat tx
= v
[MAT_TX
] + xoffset
;
1499 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
;
1501 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != *(GLuint
*)&tx
||
1502 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != *(GLuint
*)&ty
)
1504 /* Note: this should also modify whatever data the context reset
1507 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1508 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1510 /* update polygon stipple x/y screen offset */
1513 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1515 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1516 R200_STIPPLE_Y_OFFSET_MASK
);
1518 /* add magic offsets, then invert */
1519 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1520 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1521 & R200_STIPPLE_COORD_MASK
);
1523 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1524 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1526 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1527 R200_STATECHANGE( rmesa
, msc
);
1528 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1533 r200UpdateScissor( ctx
);
1538 /* =============================================================
1542 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1544 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1546 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1547 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1548 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1549 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1550 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1552 color
[2], color
[3] );
1556 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1558 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1559 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1563 static GLuint r200_rop_tab
[] = {
1566 R200_ROP_AND_REVERSE
,
1568 R200_ROP_AND_INVERTED
,
1575 R200_ROP_OR_REVERSE
,
1576 R200_ROP_COPY_INVERTED
,
1577 R200_ROP_OR_INVERTED
,
1582 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1584 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1585 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1589 R200_STATECHANGE( rmesa
, msk
);
1590 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1594 void r200SetCliprects( r200ContextPtr rmesa
, GLenum mode
)
1596 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1600 rmesa
->numClipRects
= dPriv
->numClipRects
;
1601 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1604 /* Can't ignore 2d windows if we are page flipping.
1606 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1607 rmesa
->numClipRects
= dPriv
->numClipRects
;
1608 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1611 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1612 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pBackClipRects
;
1616 fprintf(stderr
, "bad mode in r200SetCliprects\n");
1620 if (rmesa
->state
.scissor
.enabled
)
1621 r200RecalcScissorRects( rmesa
);
1625 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1627 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1629 if (R200_DEBUG
& DEBUG_DRI
)
1630 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1631 _mesa_lookup_enum_by_nr( mode
));
1633 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1636 * _DrawDestMask is easier to cope with than <mode>.
1638 switch ( ctx
->Color
._DrawDestMask
) {
1639 case FRONT_LEFT_BIT
:
1640 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1641 r200SetCliprects( rmesa
, GL_FRONT_LEFT
);
1644 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1645 r200SetCliprects( rmesa
, GL_BACK_LEFT
);
1648 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1649 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1653 /* We want to update the s/w rast state too so that r200SetBuffer()
1656 _swrast_DrawBuffer(ctx
, mode
);
1658 R200_STATECHANGE( rmesa
, ctx
);
1659 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = ((rmesa
->state
.color
.drawOffset
+
1660 rmesa
->r200Screen
->fbLocation
)
1661 & R200_COLOROFFSET_MASK
);
1662 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
1666 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1668 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1671 /* =============================================================
1672 * State enable/disable
1675 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1677 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1680 if ( R200_DEBUG
& DEBUG_STATE
)
1681 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1682 _mesa_lookup_enum_by_nr( cap
),
1683 state
? "GL_TRUE" : "GL_FALSE" );
1686 /* Fast track this one...
1694 R200_STATECHANGE( rmesa
, ctx
);
1696 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1698 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1703 R200_STATECHANGE( rmesa
, ctx
);
1705 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ALPHA_BLEND_ENABLE
;
1707 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ALPHA_BLEND_ENABLE
;
1709 if ( ctx
->Color
.ColorLogicOpEnabled
) {
1710 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
1712 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
1716 case GL_CLIP_PLANE0
:
1717 case GL_CLIP_PLANE1
:
1718 case GL_CLIP_PLANE2
:
1719 case GL_CLIP_PLANE3
:
1720 case GL_CLIP_PLANE4
:
1721 case GL_CLIP_PLANE5
:
1722 p
= cap
-GL_CLIP_PLANE0
;
1723 R200_STATECHANGE( rmesa
, tcl
);
1725 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1726 r200ClipPlane( ctx
, cap
, NULL
);
1729 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1733 case GL_COLOR_MATERIAL
:
1734 r200ColorMaterial( ctx
, 0, 0 );
1735 r200UpdateMaterial( ctx
);
1739 r200CullFace( ctx
, 0 );
1743 R200_STATECHANGE(rmesa
, ctx
);
1745 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1747 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1752 R200_STATECHANGE(rmesa
, ctx
);
1754 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1755 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1757 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1758 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1763 R200_STATECHANGE(rmesa
, ctx
);
1765 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1766 r200Fogfv( ctx
, GL_FOG_MODE
, 0 );
1768 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1769 R200_STATECHANGE(rmesa
, tcl
);
1770 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1772 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1773 if (rmesa
->TclFallback
)
1774 r200ChooseVertexState( ctx
);
1775 _mesa_allow_light_in_model( ctx
, !state
);
1786 R200_STATECHANGE(rmesa
, tcl
);
1787 p
= cap
- GL_LIGHT0
;
1789 flag
= (R200_LIGHT_1_ENABLE
|
1790 R200_LIGHT_1_ENABLE_AMBIENT
|
1791 R200_LIGHT_1_ENABLE_SPECULAR
);
1793 flag
= (R200_LIGHT_0_ENABLE
|
1794 R200_LIGHT_0_ENABLE_AMBIENT
|
1795 R200_LIGHT_0_ENABLE_SPECULAR
);
1798 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1800 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1804 update_light_colors( ctx
, p
);
1808 r200UpdateSpecular(ctx
);
1809 check_twoside_fallback( ctx
);
1812 case GL_LINE_SMOOTH
:
1813 R200_STATECHANGE( rmesa
, ctx
);
1815 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1817 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1821 case GL_LINE_STIPPLE
:
1822 R200_STATECHANGE( rmesa
, set
);
1824 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1826 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1830 case GL_COLOR_LOGIC_OP
:
1831 R200_STATECHANGE( rmesa
, ctx
);
1833 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
1835 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
1840 R200_STATECHANGE( rmesa
, tcl
);
1842 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1844 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1848 /* Pointsize registers on r200 don't seem to do anything. Maybe
1849 * have to pass pointsizes as vertex parameters? In any case,
1850 * setting pointmin == pointsizemax == 1.0, and doing nothing
1851 * for aa is enough to satisfy conform.
1853 case GL_POINT_SMOOTH
:
1856 /* These don't really do anything, as we don't use the 3vtx
1860 case GL_POLYGON_OFFSET_POINT
:
1861 R200_STATECHANGE( rmesa
, set
);
1863 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1865 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1869 case GL_POLYGON_OFFSET_LINE
:
1870 R200_STATECHANGE( rmesa
, set
);
1872 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1874 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1879 case GL_POLYGON_OFFSET_FILL
:
1880 R200_STATECHANGE( rmesa
, set
);
1882 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1884 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1888 case GL_POLYGON_SMOOTH
:
1889 R200_STATECHANGE( rmesa
, ctx
);
1891 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
1893 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
1897 case GL_POLYGON_STIPPLE
:
1898 R200_STATECHANGE(rmesa
, set
);
1900 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
1902 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
1906 case GL_RESCALE_NORMAL_EXT
: {
1907 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
1908 R200_STATECHANGE( rmesa
, tcl
);
1910 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1912 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1917 case GL_SCISSOR_TEST
:
1918 R200_FIREVERTICES( rmesa
);
1919 rmesa
->state
.scissor
.enabled
= state
;
1920 r200UpdateScissor( ctx
);
1923 case GL_STENCIL_TEST
:
1924 if ( rmesa
->state
.stencil
.hwBuffer
) {
1925 R200_STATECHANGE( rmesa
, ctx
);
1927 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
1929 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
1932 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
1936 case GL_TEXTURE_GEN_Q
:
1937 case GL_TEXTURE_GEN_R
:
1938 case GL_TEXTURE_GEN_S
:
1939 case GL_TEXTURE_GEN_T
:
1940 /* Picked up in r200UpdateTextureState.
1942 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
1945 case GL_COLOR_SUM_EXT
:
1946 r200UpdateSpecular ( ctx
);
1955 void r200LightingSpaceChange( GLcontext
*ctx
)
1957 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1960 if (R200_DEBUG
& DEBUG_STATE
)
1961 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1962 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
1964 if (ctx
->_NeedEyeCoords
)
1965 tmp
= ctx
->Transform
.RescaleNormals
;
1967 tmp
= !ctx
->Transform
.RescaleNormals
;
1969 R200_STATECHANGE( rmesa
, tcl
);
1971 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1973 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1976 if (R200_DEBUG
& DEBUG_STATE
)
1977 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1978 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
1981 /* =============================================================
1982 * Deferred state management - matrices, textures, other?
1988 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
1990 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
1994 for (i
= 0 ; i
< 4 ; i
++) {
1998 *dest
++ = src
[i
+12];
2001 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2004 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
2006 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
2007 memcpy(dest
, src
, 16*sizeof(float));
2008 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
2012 static void update_texturematrix( GLcontext
*ctx
)
2014 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
2015 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
2016 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
2019 if (R200_DEBUG
& DEBUG_STATE
)
2020 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
2021 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
2023 rmesa
->TexMatEnabled
= 0;
2024 rmesa
->TexMatCompSel
= 0;
2026 for (unit
= 0 ; unit
< 2; unit
++) {
2027 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
2030 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
2031 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
2032 R200_TEXMAT_0_ENABLE
) << unit
;
2034 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2036 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2037 /* Need to preconcatenate any active texgen
2038 * obj/eyeplane matrices:
2040 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2041 &rmesa
->TexGenMatrix
[unit
],
2042 ctx
->TextureMatrixStack
[unit
].Top
);
2043 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2046 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2047 R200_MTX_TEX0
+unit
);
2050 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2051 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2052 R200_MTX_TEX0
+unit
);
2056 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2057 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] ||
2058 rmesa
->TexGenInputs
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
]) {
2059 R200_STATECHANGE(rmesa
, tcg
);
2060 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2061 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = rmesa
->TexGenInputs
;
2064 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2065 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2066 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2067 R200_STATECHANGE(rmesa
, vtx
);
2068 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2074 void r200ValidateState( GLcontext
*ctx
)
2076 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2077 GLuint new_state
= rmesa
->NewGLState
;
2079 if (new_state
& _NEW_TEXTURE
) {
2080 r200UpdateTextureState( ctx
);
2081 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2084 /* Need an event driven matrix update?
2086 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2087 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2089 /* Need these for lighting (shouldn't upload otherwise)
2091 if (new_state
& (_NEW_MODELVIEW
)) {
2092 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2093 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2096 /* Does this need to be triggered on eg. modelview for
2097 * texgen-derived objplane/eyeplane matrices?
2099 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2100 update_texturematrix( ctx
);
2103 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2104 update_light( ctx
);
2107 /* emit all active clip planes if projection matrix changes.
2109 if (new_state
& (_NEW_PROJECTION
)) {
2110 if (ctx
->Transform
.ClipPlanesEnabled
)
2111 r200UpdateClipPlanes( ctx
);
2115 rmesa
->NewGLState
= 0;
2119 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2121 _swrast_InvalidateState( ctx
, new_state
);
2122 _swsetup_InvalidateState( ctx
, new_state
);
2123 _ac_InvalidateState( ctx
, new_state
);
2124 _tnl_InvalidateState( ctx
, new_state
);
2125 _ae_invalidate_state( ctx
, new_state
);
2126 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2127 r200VtxfmtInvalidate( ctx
);
2130 /* A hack. The r200 can actually cope just fine with materials
2131 * between begin/ends, so fix this.
2133 static GLboolean
check_material( GLcontext
*ctx
)
2135 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2138 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2139 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2141 if (tnl
->vb
.AttribPtr
[i
] &&
2142 tnl
->vb
.AttribPtr
[i
]->stride
)
2149 static void r200WrapRunPipeline( GLcontext
*ctx
)
2151 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2152 GLboolean has_material
;
2155 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2159 if (rmesa
->NewGLState
)
2160 r200ValidateState( ctx
);
2162 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2165 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2168 /* Run the pipeline.
2170 _tnl_run_pipeline( ctx
);
2173 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2178 /* Initialize the driver's state functions.
2180 void r200InitStateFuncs( struct dd_function_table
*functions
)
2182 functions
->UpdateState
= r200InvalidateState
;
2183 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2185 functions
->DrawBuffer
= r200DrawBuffer
;
2186 functions
->ReadBuffer
= r200ReadBuffer
;
2188 functions
->AlphaFunc
= r200AlphaFunc
;
2189 functions
->BlendEquation
= r200BlendEquation
;
2190 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2191 functions
->ClearColor
= r200ClearColor
;
2192 functions
->ClearDepth
= NULL
;
2193 functions
->ClearIndex
= NULL
;
2194 functions
->ClearStencil
= r200ClearStencil
;
2195 functions
->ClipPlane
= r200ClipPlane
;
2196 functions
->ColorMask
= r200ColorMask
;
2197 functions
->CullFace
= r200CullFace
;
2198 functions
->DepthFunc
= r200DepthFunc
;
2199 functions
->DepthMask
= r200DepthMask
;
2200 functions
->DepthRange
= r200DepthRange
;
2201 functions
->Enable
= r200Enable
;
2202 functions
->Fogfv
= r200Fogfv
;
2203 functions
->FrontFace
= r200FrontFace
;
2204 functions
->Hint
= NULL
;
2205 functions
->IndexMask
= NULL
;
2206 functions
->LightModelfv
= r200LightModelfv
;
2207 functions
->Lightfv
= r200Lightfv
;
2208 functions
->LineStipple
= r200LineStipple
;
2209 functions
->LineWidth
= r200LineWidth
;
2210 functions
->LogicOpcode
= r200LogicOpCode
;
2211 functions
->PolygonMode
= r200PolygonMode
;
2212 functions
->PolygonOffset
= r200PolygonOffset
;
2213 functions
->PolygonStipple
= r200PolygonStipple
;
2214 functions
->PointSize
= r200PointSize
;
2215 functions
->RenderMode
= r200RenderMode
;
2216 functions
->Scissor
= r200Scissor
;
2217 functions
->ShadeModel
= r200ShadeModel
;
2218 functions
->StencilFunc
= r200StencilFunc
;
2219 functions
->StencilMask
= r200StencilMask
;
2220 functions
->StencilOp
= r200StencilOp
;
2221 functions
->Viewport
= r200Viewport
;
2223 /* Swrast hooks for imaging extensions:
2225 functions
->CopyColorTable
= _swrast_CopyColorTable
;
2226 functions
->CopyColorSubTable
= _swrast_CopyColorSubTable
;
2227 functions
->CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2228 functions
->CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2232 void r200InitTnlFuncs( GLcontext
*ctx
)
2234 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2235 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;