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 if (R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mtl
[0] )) {
963 for (p
= 0 ; p
< MAX_LIGHTS
; p
++)
964 update_light_colors( ctx
, p
);
966 check_twoside_fallback( ctx
);
967 update_global_ambient( ctx
);
969 else if (R200_DEBUG
& (DEBUG_PRIMS
|DEBUG_STATE
))
970 fprintf(stderr
, "%s: Elided noop material call\n", __FUNCTION__
);
975 * _MESA_NEW_NEED_EYE_COORDS
977 * Uses derived state from mesa:
986 * which are calculated in light.c and are correct for the current
987 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
988 * and _MESA_NEW_NEED_EYE_COORDS.
990 static void update_light( GLcontext
*ctx
)
992 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
994 /* Have to check these, or have an automatic shortcircuit mechanism
995 * to remove noop statechanges. (Or just do a better job on the
999 GLuint tmp
= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
];
1001 if (ctx
->_NeedEyeCoords
)
1002 tmp
&= ~R200_LIGHT_IN_MODELSPACE
;
1004 tmp
|= R200_LIGHT_IN_MODELSPACE
;
1006 if (tmp
!= rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
])
1008 R200_STATECHANGE( rmesa
, tcl
);
1009 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] = tmp
;
1014 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( eye
);
1015 fcmd
[EYE_X
] = ctx
->_EyeZDir
[0];
1016 fcmd
[EYE_Y
] = ctx
->_EyeZDir
[1];
1017 fcmd
[EYE_Z
] = - ctx
->_EyeZDir
[2];
1018 fcmd
[EYE_RESCALE_FACTOR
] = ctx
->_ModelViewInvScale
;
1019 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.eye
);
1024 if (ctx
->Light
.Enabled
) {
1026 for (p
= 0 ; p
< MAX_LIGHTS
; p
++) {
1027 if (ctx
->Light
.Light
[p
].Enabled
) {
1028 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1029 GLfloat
*fcmd
= (GLfloat
*)R200_DB_STATE( lit
[p
] );
1031 if (l
->EyePosition
[3] == 0.0) {
1032 COPY_3FV( &fcmd
[LIT_POSITION_X
], l
->_VP_inf_norm
);
1033 COPY_3FV( &fcmd
[LIT_DIRECTION_X
], l
->_h_inf_norm
);
1034 fcmd
[LIT_POSITION_W
] = 0;
1035 fcmd
[LIT_DIRECTION_W
] = 0;
1037 COPY_4V( &fcmd
[LIT_POSITION_X
], l
->_Position
);
1038 fcmd
[LIT_DIRECTION_X
] = -l
->_NormDirection
[0];
1039 fcmd
[LIT_DIRECTION_Y
] = -l
->_NormDirection
[1];
1040 fcmd
[LIT_DIRECTION_Z
] = -l
->_NormDirection
[2];
1041 fcmd
[LIT_DIRECTION_W
] = 0;
1044 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.lit
[p
] );
1050 static void r200Lightfv( GLcontext
*ctx
, GLenum light
,
1051 GLenum pname
, const GLfloat
*params
)
1053 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1054 GLint p
= light
- GL_LIGHT0
;
1055 struct gl_light
*l
= &ctx
->Light
.Light
[p
];
1056 GLfloat
*fcmd
= (GLfloat
*)rmesa
->hw
.lit
[p
].cmd
;
1063 update_light_colors( ctx
, p
);
1066 case GL_SPOT_DIRECTION
:
1067 /* picked up in update_light */
1071 /* positions picked up in update_light, but can do flag here */
1072 GLuint flag
= (p
&1)? R200_LIGHT_1_IS_LOCAL
: R200_LIGHT_0_IS_LOCAL
;
1073 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1075 R200_STATECHANGE(rmesa
, tcl
);
1076 if (l
->EyePosition
[3] != 0.0F
)
1077 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1079 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1083 case GL_SPOT_EXPONENT
:
1084 R200_STATECHANGE(rmesa
, lit
[p
]);
1085 fcmd
[LIT_SPOT_EXPONENT
] = params
[0];
1088 case GL_SPOT_CUTOFF
: {
1089 GLuint flag
= (p
&1) ? R200_LIGHT_1_IS_SPOT
: R200_LIGHT_0_IS_SPOT
;
1090 GLuint idx
= TCL_PER_LIGHT_CTL_0
+ p
/2;
1092 R200_STATECHANGE(rmesa
, lit
[p
]);
1093 fcmd
[LIT_SPOT_CUTOFF
] = l
->_CosCutoff
;
1095 R200_STATECHANGE(rmesa
, tcl
);
1096 if (l
->SpotCutoff
!= 180.0F
)
1097 rmesa
->hw
.tcl
.cmd
[idx
] |= flag
;
1099 rmesa
->hw
.tcl
.cmd
[idx
] &= ~flag
;
1104 case GL_CONSTANT_ATTENUATION
:
1105 R200_STATECHANGE(rmesa
, lit
[p
]);
1106 fcmd
[LIT_ATTEN_CONST
] = params
[0];
1108 case GL_LINEAR_ATTENUATION
:
1109 R200_STATECHANGE(rmesa
, lit
[p
]);
1110 fcmd
[LIT_ATTEN_LINEAR
] = params
[0];
1112 case GL_QUADRATIC_ATTENUATION
:
1113 R200_STATECHANGE(rmesa
, lit
[p
]);
1114 fcmd
[LIT_ATTEN_QUADRATIC
] = params
[0];
1125 static void r200LightModelfv( GLcontext
*ctx
, GLenum pname
,
1126 const GLfloat
*param
)
1128 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1131 case GL_LIGHT_MODEL_AMBIENT
:
1132 update_global_ambient( ctx
);
1135 case GL_LIGHT_MODEL_LOCAL_VIEWER
:
1136 R200_STATECHANGE( rmesa
, tcl
);
1137 if (ctx
->Light
.Model
.LocalViewer
)
1138 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LOCAL_VIEWER
;
1140 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LOCAL_VIEWER
;
1143 case GL_LIGHT_MODEL_TWO_SIDE
:
1144 R200_STATECHANGE( rmesa
, tcl
);
1145 if (ctx
->Light
.Model
.TwoSide
)
1146 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_LIGHT_TWOSIDE
;
1148 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_LIGHT_TWOSIDE
;
1150 check_twoside_fallback( ctx
);
1152 if (rmesa
->TclFallback
) {
1153 r200ChooseRenderState( ctx
);
1154 r200ChooseVertexState( ctx
);
1158 case GL_LIGHT_MODEL_COLOR_CONTROL
:
1159 r200UpdateSpecular(ctx
);
1167 static void r200ShadeModel( GLcontext
*ctx
, GLenum mode
)
1169 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1170 GLuint s
= rmesa
->hw
.set
.cmd
[SET_SE_CNTL
];
1172 s
&= ~(R200_DIFFUSE_SHADE_MASK
|
1173 R200_ALPHA_SHADE_MASK
|
1174 R200_SPECULAR_SHADE_MASK
|
1175 R200_FOG_SHADE_MASK
);
1179 s
|= (R200_DIFFUSE_SHADE_FLAT
|
1180 R200_ALPHA_SHADE_FLAT
|
1181 R200_SPECULAR_SHADE_FLAT
|
1182 R200_FOG_SHADE_FLAT
);
1185 s
|= (R200_DIFFUSE_SHADE_GOURAUD
|
1186 R200_ALPHA_SHADE_GOURAUD
|
1187 R200_SPECULAR_SHADE_GOURAUD
|
1188 R200_FOG_SHADE_GOURAUD
);
1194 if ( rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] != s
) {
1195 R200_STATECHANGE( rmesa
, set
);
1196 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] = s
;
1201 /* =============================================================
1205 static void r200ClipPlane( GLcontext
*ctx
, GLenum plane
, const GLfloat
*eq
)
1207 GLint p
= (GLint
) plane
- (GLint
) GL_CLIP_PLANE0
;
1208 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1209 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1211 R200_STATECHANGE( rmesa
, ucp
[p
] );
1212 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1213 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1214 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1215 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1218 static void r200UpdateClipPlanes( GLcontext
*ctx
)
1220 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1223 for (p
= 0; p
< ctx
->Const
.MaxClipPlanes
; p
++) {
1224 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
1225 GLint
*ip
= (GLint
*)ctx
->Transform
._ClipUserPlane
[p
];
1227 R200_STATECHANGE( rmesa
, ucp
[p
] );
1228 rmesa
->hw
.ucp
[p
].cmd
[UCP_X
] = ip
[0];
1229 rmesa
->hw
.ucp
[p
].cmd
[UCP_Y
] = ip
[1];
1230 rmesa
->hw
.ucp
[p
].cmd
[UCP_Z
] = ip
[2];
1231 rmesa
->hw
.ucp
[p
].cmd
[UCP_W
] = ip
[3];
1237 /* =============================================================
1241 static void r200StencilFunc( GLcontext
*ctx
, GLenum func
,
1242 GLint ref
, GLuint mask
)
1244 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1245 GLuint refmask
= ((ctx
->Stencil
.Ref
[0] << R200_STENCIL_REF_SHIFT
) |
1246 (ctx
->Stencil
.ValueMask
[0] << R200_STENCIL_MASK_SHIFT
));
1248 R200_STATECHANGE( rmesa
, ctx
);
1249 R200_STATECHANGE( rmesa
, msk
);
1251 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~R200_STENCIL_TEST_MASK
;
1252 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~(R200_STENCIL_REF_MASK
|
1253 R200_STENCIL_VALUE_MASK
);
1255 switch ( ctx
->Stencil
.Function
[0] ) {
1257 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEVER
;
1260 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LESS
;
1263 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_EQUAL
;
1266 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_LEQUAL
;
1269 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GREATER
;
1272 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_NEQUAL
;
1275 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_GEQUAL
;
1278 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_TEST_ALWAYS
;
1282 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |= refmask
;
1285 static void r200StencilMask( GLcontext
*ctx
, GLuint mask
)
1287 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1289 R200_STATECHANGE( rmesa
, msk
);
1290 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] &= ~R200_STENCIL_WRITE_MASK
;
1291 rmesa
->hw
.msk
.cmd
[MSK_RB3D_STENCILREFMASK
] |=
1292 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
);
1295 static void r200StencilOp( GLcontext
*ctx
, GLenum fail
,
1296 GLenum zfail
, GLenum zpass
)
1298 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1300 R200_STATECHANGE( rmesa
, ctx
);
1301 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] &= ~(R200_STENCIL_FAIL_MASK
|
1302 R200_STENCIL_ZFAIL_MASK
|
1303 R200_STENCIL_ZPASS_MASK
);
1305 switch ( ctx
->Stencil
.FailFunc
[0] ) {
1307 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_KEEP
;
1310 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_ZERO
;
1313 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_REPLACE
;
1316 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC
;
1319 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC
;
1321 case GL_INCR_WRAP_EXT
:
1322 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INC_WRAP
;
1324 case GL_DECR_WRAP_EXT
:
1325 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_DEC_WRAP
;
1328 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_FAIL_INVERT
;
1332 switch ( ctx
->Stencil
.ZFailFunc
[0] ) {
1334 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_KEEP
;
1337 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_ZERO
;
1340 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_REPLACE
;
1343 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC
;
1346 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC
;
1348 case GL_INCR_WRAP_EXT
:
1349 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INC_WRAP
;
1351 case GL_DECR_WRAP_EXT
:
1352 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_DEC_WRAP
;
1355 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZFAIL_INVERT
;
1359 switch ( ctx
->Stencil
.ZPassFunc
[0] ) {
1361 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_KEEP
;
1364 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_ZERO
;
1367 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_REPLACE
;
1370 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC
;
1373 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC
;
1375 case GL_INCR_WRAP_EXT
:
1376 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INC_WRAP
;
1378 case GL_DECR_WRAP_EXT
:
1379 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_DEC_WRAP
;
1382 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_ZSTENCILCNTL
] |= R200_STENCIL_ZPASS_INVERT
;
1387 static void r200ClearStencil( GLcontext
*ctx
, GLint s
)
1389 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1391 rmesa
->state
.stencil
.clear
=
1392 ((GLuint
) ctx
->Stencil
.Clear
|
1393 (0xff << R200_STENCIL_MASK_SHIFT
) |
1394 (ctx
->Stencil
.WriteMask
[0] << R200_STENCIL_WRITEMASK_SHIFT
));
1398 /* =============================================================
1399 * Window position and viewport transformation
1403 * To correctly position primitives:
1405 #define SUBPIXEL_X 0.125
1406 #define SUBPIXEL_Y 0.125
1408 void r200UpdateWindow( GLcontext
*ctx
)
1410 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1411 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1412 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1413 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1414 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1416 GLfloat sx
= v
[MAT_SX
];
1417 GLfloat tx
= v
[MAT_TX
] + xoffset
+ SUBPIXEL_X
;
1418 GLfloat sy
= - v
[MAT_SY
];
1419 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
+ SUBPIXEL_Y
;
1420 GLfloat sz
= v
[MAT_SZ
] * rmesa
->state
.depth
.scale
;
1421 GLfloat tz
= v
[MAT_TZ
] * rmesa
->state
.depth
.scale
;
1423 R200_FIREVERTICES( rmesa
);
1424 R200_STATECHANGE( rmesa
, vpt
);
1426 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XSCALE
] = *(GLuint
*)&sx
;
1427 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1428 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YSCALE
] = *(GLuint
*)&sy
;
1429 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1430 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZSCALE
] = *(GLuint
*)&sz
;
1431 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_ZOFFSET
] = *(GLuint
*)&tz
;
1436 static void r200Viewport( GLcontext
*ctx
, GLint x
, GLint y
,
1437 GLsizei width
, GLsizei height
)
1439 /* Don't pipeline viewport changes, conflict with window offset
1440 * setting below. Could apply deltas to rescue pipelined viewport
1441 * values, or keep the originals hanging around.
1443 R200_FIREVERTICES( R200_CONTEXT(ctx
) );
1444 r200UpdateWindow( ctx
);
1447 static void r200DepthRange( GLcontext
*ctx
, GLclampd nearval
,
1450 r200UpdateWindow( ctx
);
1453 void r200UpdateViewportOffset( GLcontext
*ctx
)
1455 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1456 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1457 GLfloat xoffset
= (GLfloat
)dPriv
->x
;
1458 GLfloat yoffset
= (GLfloat
)dPriv
->y
+ dPriv
->h
;
1459 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
1461 GLfloat tx
= v
[MAT_TX
] + xoffset
;
1462 GLfloat ty
= (- v
[MAT_TY
]) + yoffset
;
1464 if ( rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] != *(GLuint
*)&tx
||
1465 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] != *(GLuint
*)&ty
)
1467 /* Note: this should also modify whatever data the context reset
1470 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_XOFFSET
] = *(GLuint
*)&tx
;
1471 rmesa
->hw
.vpt
.cmd
[VPT_SE_VPORT_YOFFSET
] = *(GLuint
*)&ty
;
1473 /* update polygon stipple x/y screen offset */
1476 GLuint m
= rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
];
1478 m
&= ~(R200_STIPPLE_X_OFFSET_MASK
|
1479 R200_STIPPLE_Y_OFFSET_MASK
);
1481 /* add magic offsets, then invert */
1482 stx
= 31 - ((rmesa
->dri
.drawable
->x
- 1) & R200_STIPPLE_COORD_MASK
);
1483 sty
= 31 - ((rmesa
->dri
.drawable
->y
+ rmesa
->dri
.drawable
->h
- 1)
1484 & R200_STIPPLE_COORD_MASK
);
1486 m
|= ((stx
<< R200_STIPPLE_X_OFFSET_SHIFT
) |
1487 (sty
<< R200_STIPPLE_Y_OFFSET_SHIFT
));
1489 if ( rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] != m
) {
1490 R200_STATECHANGE( rmesa
, msc
);
1491 rmesa
->hw
.msc
.cmd
[MSC_RE_MISC
] = m
;
1496 r200UpdateScissor( ctx
);
1501 /* =============================================================
1505 static void r200ClearColor( GLcontext
*ctx
, const GLfloat c
[4] )
1507 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1509 CLAMPED_FLOAT_TO_UBYTE(color
[0], c
[0]);
1510 CLAMPED_FLOAT_TO_UBYTE(color
[1], c
[1]);
1511 CLAMPED_FLOAT_TO_UBYTE(color
[2], c
[2]);
1512 CLAMPED_FLOAT_TO_UBYTE(color
[3], c
[3]);
1513 rmesa
->state
.color
.clear
= r200PackColor( rmesa
->r200Screen
->cpp
,
1515 color
[2], color
[3] );
1519 static void r200RenderMode( GLcontext
*ctx
, GLenum mode
)
1521 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1522 FALLBACK( rmesa
, R200_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
1526 static GLuint r200_rop_tab
[] = {
1529 R200_ROP_AND_REVERSE
,
1531 R200_ROP_AND_INVERTED
,
1538 R200_ROP_OR_REVERSE
,
1539 R200_ROP_COPY_INVERTED
,
1540 R200_ROP_OR_INVERTED
,
1545 static void r200LogicOpCode( GLcontext
*ctx
, GLenum opcode
)
1547 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1548 GLuint rop
= (GLuint
)opcode
- GL_CLEAR
;
1552 R200_STATECHANGE( rmesa
, msk
);
1553 rmesa
->hw
.msk
.cmd
[MSK_RB3D_ROPCNTL
] = r200_rop_tab
[rop
];
1557 void r200SetCliprects( r200ContextPtr rmesa
, GLenum mode
)
1559 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1563 rmesa
->numClipRects
= dPriv
->numClipRects
;
1564 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1567 /* Can't ignore 2d windows if we are page flipping.
1569 if ( dPriv
->numBackClipRects
== 0 || rmesa
->doPageFlip
) {
1570 rmesa
->numClipRects
= dPriv
->numClipRects
;
1571 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pClipRects
;
1574 rmesa
->numClipRects
= dPriv
->numBackClipRects
;
1575 rmesa
->pClipRects
= (XF86DRIClipRectPtr
)dPriv
->pBackClipRects
;
1579 fprintf(stderr
, "bad mode in r200SetCliprects\n");
1583 if (rmesa
->state
.scissor
.enabled
)
1584 r200RecalcScissorRects( rmesa
);
1588 static void r200DrawBuffer( GLcontext
*ctx
, GLenum mode
)
1590 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1592 if (R200_DEBUG
& DEBUG_DRI
)
1593 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
1594 _mesa_lookup_enum_by_nr( mode
));
1596 R200_FIREVERTICES(rmesa
); /* don't pipeline cliprect changes */
1599 * _DrawDestMask is easier to cope with than <mode>.
1601 switch ( ctx
->Color
._DrawDestMask
) {
1602 case FRONT_LEFT_BIT
:
1603 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1604 r200SetCliprects( rmesa
, GL_FRONT_LEFT
);
1607 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
1608 r200SetCliprects( rmesa
, GL_BACK_LEFT
);
1611 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1612 FALLBACK( rmesa
, R200_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
1616 /* We want to update the s/w rast state too so that r200SetBuffer()
1619 _swrast_DrawBuffer(ctx
, mode
);
1621 R200_STATECHANGE( rmesa
, ctx
);
1622 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = ((rmesa
->state
.color
.drawOffset
+
1623 rmesa
->r200Screen
->fbLocation
)
1624 & R200_COLOROFFSET_MASK
);
1625 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
1629 static void r200ReadBuffer( GLcontext
*ctx
, GLenum mode
)
1631 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1634 /* =============================================================
1635 * State enable/disable
1638 static void r200Enable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
1640 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1643 if ( R200_DEBUG
& DEBUG_STATE
)
1644 fprintf( stderr
, "%s( %s = %s )\n", __FUNCTION__
,
1645 _mesa_lookup_enum_by_nr( cap
),
1646 state
? "GL_TRUE" : "GL_FALSE" );
1649 /* Fast track this one...
1657 R200_STATECHANGE( rmesa
, ctx
);
1659 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ALPHA_TEST_ENABLE
;
1661 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ALPHA_TEST_ENABLE
;
1666 R200_STATECHANGE( rmesa
, ctx
);
1668 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ALPHA_BLEND_ENABLE
;
1670 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ALPHA_BLEND_ENABLE
;
1672 if ( ctx
->Color
.ColorLogicOpEnabled
) {
1673 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
1675 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
1679 case GL_CLIP_PLANE0
:
1680 case GL_CLIP_PLANE1
:
1681 case GL_CLIP_PLANE2
:
1682 case GL_CLIP_PLANE3
:
1683 case GL_CLIP_PLANE4
:
1684 case GL_CLIP_PLANE5
:
1685 p
= cap
-GL_CLIP_PLANE0
;
1686 R200_STATECHANGE( rmesa
, tcl
);
1688 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] |= (R200_UCP_ENABLE_0
<<p
);
1689 r200ClipPlane( ctx
, cap
, NULL
);
1692 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~(R200_UCP_ENABLE_0
<<p
);
1696 case GL_COLOR_MATERIAL
:
1697 r200ColorMaterial( ctx
, 0, 0 );
1699 r200UpdateMaterial( ctx
);
1703 r200CullFace( ctx
, 0 );
1707 R200_STATECHANGE(rmesa
, ctx
);
1709 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_Z_ENABLE
;
1711 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_Z_ENABLE
;
1716 R200_STATECHANGE(rmesa
, ctx
);
1718 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_DITHER_ENABLE
;
1719 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~rmesa
->state
.color
.roundEnable
;
1721 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_DITHER_ENABLE
;
1722 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= rmesa
->state
.color
.roundEnable
;
1727 R200_STATECHANGE(rmesa
, ctx
);
1729 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_FOG_ENABLE
;
1730 r200Fogfv( ctx
, GL_FOG_MODE
, 0 );
1732 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_FOG_ENABLE
;
1733 R200_STATECHANGE(rmesa
, tcl
);
1734 rmesa
->hw
.tcl
.cmd
[TCL_UCP_VERT_BLEND_CTL
] &= ~R200_TCL_FOG_MASK
;
1736 r200UpdateSpecular( ctx
); /* for PK_SPEC */
1737 if (rmesa
->TclFallback
)
1738 r200ChooseVertexState( ctx
);
1739 _mesa_allow_light_in_model( ctx
, !state
);
1750 R200_STATECHANGE(rmesa
, tcl
);
1751 p
= cap
- GL_LIGHT0
;
1753 flag
= (R200_LIGHT_1_ENABLE
|
1754 R200_LIGHT_1_ENABLE_AMBIENT
|
1755 R200_LIGHT_1_ENABLE_SPECULAR
);
1757 flag
= (R200_LIGHT_0_ENABLE
|
1758 R200_LIGHT_0_ENABLE_AMBIENT
|
1759 R200_LIGHT_0_ENABLE_SPECULAR
);
1762 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] |= flag
;
1764 rmesa
->hw
.tcl
.cmd
[p
/2 + TCL_PER_LIGHT_CTL_0
] &= ~flag
;
1768 update_light_colors( ctx
, p
);
1772 r200UpdateSpecular(ctx
);
1773 check_twoside_fallback( ctx
);
1776 case GL_LINE_SMOOTH
:
1777 R200_STATECHANGE( rmesa
, ctx
);
1779 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_LINE
;
1781 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_LINE
;
1785 case GL_LINE_STIPPLE
:
1786 R200_STATECHANGE( rmesa
, set
);
1788 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PATTERN_ENABLE
;
1790 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PATTERN_ENABLE
;
1794 case GL_COLOR_LOGIC_OP
:
1795 R200_STATECHANGE( rmesa
, ctx
);
1797 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_ROP_ENABLE
;
1799 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_ROP_ENABLE
;
1804 R200_STATECHANGE( rmesa
, tcl
);
1806 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_NORMALIZE_NORMALS
;
1808 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_NORMALIZE_NORMALS
;
1812 /* Pointsize registers on r200 don't seem to do anything. Maybe
1813 * have to pass pointsizes as vertex parameters? In any case,
1814 * setting pointmin == pointsizemax == 1.0, and doing nothing
1815 * for aa is enough to satisfy conform.
1817 case GL_POINT_SMOOTH
:
1820 /* These don't really do anything, as we don't use the 3vtx
1824 case GL_POLYGON_OFFSET_POINT
:
1825 R200_STATECHANGE( rmesa
, set
);
1827 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_POINT
;
1829 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_POINT
;
1833 case GL_POLYGON_OFFSET_LINE
:
1834 R200_STATECHANGE( rmesa
, set
);
1836 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_LINE
;
1838 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_LINE
;
1843 case GL_POLYGON_OFFSET_FILL
:
1844 R200_STATECHANGE( rmesa
, set
);
1846 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] |= R200_ZBIAS_ENABLE_TRI
;
1848 rmesa
->hw
.set
.cmd
[SET_SE_CNTL
] &= ~R200_ZBIAS_ENABLE_TRI
;
1852 case GL_POLYGON_SMOOTH
:
1853 R200_STATECHANGE( rmesa
, ctx
);
1855 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_ANTI_ALIAS_POLY
;
1857 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~R200_ANTI_ALIAS_POLY
;
1861 case GL_POLYGON_STIPPLE
:
1862 R200_STATECHANGE(rmesa
, set
);
1864 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_STIPPLE_ENABLE
;
1866 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_STIPPLE_ENABLE
;
1870 case GL_RESCALE_NORMAL_EXT
: {
1871 GLboolean tmp
= ctx
->_NeedEyeCoords
? state
: !state
;
1872 R200_STATECHANGE( rmesa
, tcl
);
1874 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1876 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1881 case GL_SCISSOR_TEST
:
1882 R200_FIREVERTICES( rmesa
);
1883 rmesa
->state
.scissor
.enabled
= state
;
1884 r200UpdateScissor( ctx
);
1887 case GL_STENCIL_TEST
:
1888 if ( rmesa
->state
.stencil
.hwBuffer
) {
1889 R200_STATECHANGE( rmesa
, ctx
);
1891 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] |= R200_STENCIL_ENABLE
;
1893 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_CNTL
] &= ~R200_STENCIL_ENABLE
;
1896 FALLBACK( rmesa
, R200_FALLBACK_STENCIL
, state
);
1900 case GL_TEXTURE_GEN_Q
:
1901 case GL_TEXTURE_GEN_R
:
1902 case GL_TEXTURE_GEN_S
:
1903 case GL_TEXTURE_GEN_T
:
1904 /* Picked up in r200UpdateTextureState.
1906 rmesa
->recheck_texgen
[ctx
->Texture
.CurrentUnit
] = GL_TRUE
;
1909 case GL_COLOR_SUM_EXT
:
1910 r200UpdateSpecular ( ctx
);
1919 void r200LightingSpaceChange( GLcontext
*ctx
)
1921 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1924 if (R200_DEBUG
& DEBUG_STATE
)
1925 fprintf(stderr
, "%s %d BEFORE %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1926 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
1928 if (ctx
->_NeedEyeCoords
)
1929 tmp
= ctx
->Transform
.RescaleNormals
;
1931 tmp
= !ctx
->Transform
.RescaleNormals
;
1933 R200_STATECHANGE( rmesa
, tcl
);
1935 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] |= R200_RESCALE_NORMALS
;
1937 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
] &= ~R200_RESCALE_NORMALS
;
1940 if (R200_DEBUG
& DEBUG_STATE
)
1941 fprintf(stderr
, "%s %d AFTER %x\n", __FUNCTION__
, ctx
->_NeedEyeCoords
,
1942 rmesa
->hw
.tcl
.cmd
[TCL_LIGHT_MODEL_CTL_0
]);
1945 /* =============================================================
1946 * Deferred state management - matrices, textures, other?
1952 static void upload_matrix( r200ContextPtr rmesa
, GLfloat
*src
, int idx
)
1954 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
1958 for (i
= 0 ; i
< 4 ; i
++) {
1962 *dest
++ = src
[i
+12];
1965 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
1968 static void upload_matrix_t( r200ContextPtr rmesa
, const GLfloat
*src
, int idx
)
1970 float *dest
= ((float *)R200_DB_STATE( mat
[idx
] ))+MAT_ELT_0
;
1971 memcpy(dest
, src
, 16*sizeof(float));
1972 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.mat
[idx
] );
1976 static void update_texturematrix( GLcontext
*ctx
)
1978 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
1979 GLuint tpc
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
];
1980 GLuint compsel
= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
];
1983 if (R200_DEBUG
& DEBUG_STATE
)
1984 fprintf(stderr
, "%s before COMPSEL: %x\n", __FUNCTION__
,
1985 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]);
1987 rmesa
->TexMatEnabled
= 0;
1988 rmesa
->TexMatCompSel
= 0;
1990 for (unit
= 0 ; unit
< 2; unit
++) {
1991 if (!ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
1994 if (ctx
->TextureMatrixStack
[unit
].Top
->type
!= MATRIX_IDENTITY
) {
1995 rmesa
->TexMatEnabled
|= (R200_TEXGEN_TEXMAT_0_ENABLE
|
1996 R200_TEXMAT_0_ENABLE
) << unit
;
1998 rmesa
->TexMatCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
2000 if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2001 /* Need to preconcatenate any active texgen
2002 * obj/eyeplane matrices:
2004 _math_matrix_mul_matrix( &rmesa
->tmpmat
,
2005 &rmesa
->TexGenMatrix
[unit
],
2006 ctx
->TextureMatrixStack
[unit
].Top
);
2007 upload_matrix( rmesa
, rmesa
->tmpmat
.m
, R200_MTX_TEX0
+unit
);
2010 upload_matrix( rmesa
, ctx
->TextureMatrixStack
[unit
].Top
->m
,
2011 R200_MTX_TEX0
+unit
);
2014 else if (rmesa
->TexGenEnabled
& (R200_TEXMAT_0_ENABLE
<< unit
)) {
2015 upload_matrix( rmesa
, rmesa
->TexGenMatrix
[unit
].m
,
2016 R200_MTX_TEX0
+unit
);
2020 tpc
= (rmesa
->TexMatEnabled
| rmesa
->TexGenEnabled
);
2021 if (tpc
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] ||
2022 rmesa
->TexGenInputs
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
]) {
2023 R200_STATECHANGE(rmesa
, tcg
);
2024 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_0
] = tpc
;
2025 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = rmesa
->TexGenInputs
;
2028 compsel
&= ~R200_OUTPUT_TEX_MASK
;
2029 compsel
|= rmesa
->TexMatCompSel
| rmesa
->TexGenCompSel
;
2030 if (compsel
!= rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
]) {
2031 R200_STATECHANGE(rmesa
, vtx
);
2032 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_COMPSEL
] = compsel
;
2038 void r200ValidateState( GLcontext
*ctx
)
2040 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2041 GLuint new_state
= rmesa
->NewGLState
;
2043 if (new_state
& _NEW_TEXTURE
) {
2044 r200UpdateTextureState( ctx
);
2045 new_state
|= rmesa
->NewGLState
; /* may add TEXTURE_MATRIX */
2048 /* Need an event driven matrix update?
2050 if (new_state
& (_NEW_MODELVIEW
|_NEW_PROJECTION
))
2051 upload_matrix( rmesa
, ctx
->_ModelProjectMatrix
.m
, R200_MTX_MVP
);
2053 /* Need these for lighting (shouldn't upload otherwise)
2055 if (new_state
& (_NEW_MODELVIEW
)) {
2056 upload_matrix( rmesa
, ctx
->ModelviewMatrixStack
.Top
->m
, R200_MTX_MV
);
2057 upload_matrix_t( rmesa
, ctx
->ModelviewMatrixStack
.Top
->inv
, R200_MTX_IMV
);
2060 /* Does this need to be triggered on eg. modelview for
2061 * texgen-derived objplane/eyeplane matrices?
2063 if (new_state
& (_NEW_TEXTURE
|_NEW_TEXTURE_MATRIX
)) {
2064 update_texturematrix( ctx
);
2067 if (new_state
& (_NEW_LIGHT
|_NEW_MODELVIEW
|_MESA_NEW_NEED_EYE_COORDS
)) {
2068 update_light( ctx
);
2071 /* emit all active clip planes if projection matrix changes.
2073 if (new_state
& (_NEW_PROJECTION
)) {
2074 if (ctx
->Transform
.ClipPlanesEnabled
)
2075 r200UpdateClipPlanes( ctx
);
2079 rmesa
->NewGLState
= 0;
2083 static void r200InvalidateState( GLcontext
*ctx
, GLuint new_state
)
2085 _swrast_InvalidateState( ctx
, new_state
);
2086 _swsetup_InvalidateState( ctx
, new_state
);
2087 _ac_InvalidateState( ctx
, new_state
);
2088 _tnl_InvalidateState( ctx
, new_state
);
2089 _ae_invalidate_state( ctx
, new_state
);
2090 R200_CONTEXT(ctx
)->NewGLState
|= new_state
;
2091 r200VtxfmtInvalidate( ctx
);
2094 /* A hack. The r200 can actually cope just fine with materials
2095 * between begin/ends, so fix this.
2097 static GLboolean
check_material( GLcontext
*ctx
)
2099 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
2102 for (i
= _TNL_ATTRIB_MAT_FRONT_AMBIENT
;
2103 i
< _TNL_ATTRIB_MAT_BACK_INDEXES
;
2105 if (tnl
->vb
.AttribPtr
[i
] &&
2106 tnl
->vb
.AttribPtr
[i
]->stride
)
2113 static void r200WrapRunPipeline( GLcontext
*ctx
)
2115 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
2116 GLboolean has_material
;
2119 fprintf(stderr
, "%s, newstate: %x\n", __FUNCTION__
, rmesa
->NewGLState
);
2123 if (rmesa
->NewGLState
)
2124 r200ValidateState( ctx
);
2126 has_material
= (ctx
->Light
.Enabled
&& check_material( ctx
));
2129 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_TRUE
);
2132 /* Run the pipeline.
2134 _tnl_run_pipeline( ctx
);
2137 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_MATERIAL
, GL_FALSE
);
2142 /* Initialize the driver's state functions.
2144 void r200InitStateFuncs( struct dd_function_table
*functions
)
2146 functions
->UpdateState
= r200InvalidateState
;
2147 functions
->LightingSpaceChange
= r200LightingSpaceChange
;
2149 functions
->DrawBuffer
= r200DrawBuffer
;
2150 functions
->ReadBuffer
= r200ReadBuffer
;
2152 functions
->AlphaFunc
= r200AlphaFunc
;
2153 functions
->BlendEquation
= r200BlendEquation
;
2154 functions
->BlendFuncSeparate
= r200BlendFuncSeparate
;
2155 functions
->ClearColor
= r200ClearColor
;
2156 functions
->ClearDepth
= NULL
;
2157 functions
->ClearIndex
= NULL
;
2158 functions
->ClearStencil
= r200ClearStencil
;
2159 functions
->ClipPlane
= r200ClipPlane
;
2160 functions
->ColorMask
= r200ColorMask
;
2161 functions
->CullFace
= r200CullFace
;
2162 functions
->DepthFunc
= r200DepthFunc
;
2163 functions
->DepthMask
= r200DepthMask
;
2164 functions
->DepthRange
= r200DepthRange
;
2165 functions
->Enable
= r200Enable
;
2166 functions
->Fogfv
= r200Fogfv
;
2167 functions
->FrontFace
= r200FrontFace
;
2168 functions
->Hint
= NULL
;
2169 functions
->IndexMask
= NULL
;
2170 functions
->LightModelfv
= r200LightModelfv
;
2171 functions
->Lightfv
= r200Lightfv
;
2172 functions
->LineStipple
= r200LineStipple
;
2173 functions
->LineWidth
= r200LineWidth
;
2174 functions
->LogicOpcode
= r200LogicOpCode
;
2175 functions
->PolygonMode
= r200PolygonMode
;
2176 functions
->PolygonOffset
= r200PolygonOffset
;
2177 functions
->PolygonStipple
= r200PolygonStipple
;
2178 functions
->PointSize
= r200PointSize
;
2179 functions
->RenderMode
= r200RenderMode
;
2180 functions
->Scissor
= r200Scissor
;
2181 functions
->ShadeModel
= r200ShadeModel
;
2182 functions
->StencilFunc
= r200StencilFunc
;
2183 functions
->StencilMask
= r200StencilMask
;
2184 functions
->StencilOp
= r200StencilOp
;
2185 functions
->Viewport
= r200Viewport
;
2187 /* Swrast hooks for imaging extensions:
2189 functions
->CopyColorTable
= _swrast_CopyColorTable
;
2190 functions
->CopyColorSubTable
= _swrast_CopyColorSubTable
;
2191 functions
->CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
2192 functions
->CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
2196 void r200InitTnlFuncs( GLcontext
*ctx
)
2198 TNL_CONTEXT(ctx
)->Driver
.NotifyMaterialChange
= r200UpdateMaterial
;
2199 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= r200WrapRunPipeline
;