Implemented support for software-based AUX color buffers.
[mesa.git] / src / mesa / drivers / dri / r200 / r200_state.c
1 /* $XFree86$ */
2 /**************************************************************************
3
4 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5
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.
9
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:
17
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.
21
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.
29
30 **************************************************************************/
31
32 /*
33 * Authors:
34 * Keith Whitwell <keith@tungstengraphics.com>
35 */
36
37 #include "glheader.h"
38 #include "imports.h"
39 #include "api_arrayelt.h"
40 #include "enums.h"
41 #include "colormac.h"
42 #include "light.h"
43
44 #include "swrast/swrast.h"
45 #include "array_cache/acache.h"
46 #include "tnl/tnl.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
49
50
51 #include "r200_context.h"
52 #include "r200_ioctl.h"
53 #include "r200_state.h"
54 #include "r200_tcl.h"
55 #include "r200_tex.h"
56 #include "r200_swtcl.h"
57 #include "r200_vtxfmt.h"
58
59
60 /* =============================================================
61 * Alpha blending
62 */
63
64 static void r200AlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
65 {
66 r200ContextPtr rmesa = R200_CONTEXT(ctx);
67 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
68 GLubyte refByte;
69
70 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
71
72 R200_STATECHANGE( rmesa, ctx );
73
74 pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK);
75 pp_misc |= (refByte & R200_REF_ALPHA_MASK);
76
77 switch ( func ) {
78 case GL_NEVER:
79 pp_misc |= R200_ALPHA_TEST_FAIL;
80 break;
81 case GL_LESS:
82 pp_misc |= R200_ALPHA_TEST_LESS;
83 break;
84 case GL_EQUAL:
85 pp_misc |= R200_ALPHA_TEST_EQUAL;
86 break;
87 case GL_LEQUAL:
88 pp_misc |= R200_ALPHA_TEST_LEQUAL;
89 break;
90 case GL_GREATER:
91 pp_misc |= R200_ALPHA_TEST_GREATER;
92 break;
93 case GL_NOTEQUAL:
94 pp_misc |= R200_ALPHA_TEST_NEQUAL;
95 break;
96 case GL_GEQUAL:
97 pp_misc |= R200_ALPHA_TEST_GEQUAL;
98 break;
99 case GL_ALWAYS:
100 pp_misc |= R200_ALPHA_TEST_PASS;
101 break;
102 }
103
104 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
105 }
106
107 static void r200BlendEquationSeparate( GLcontext *ctx,
108 GLenum modeRGB, GLenum modeA )
109 {
110 r200ContextPtr rmesa = R200_CONTEXT(ctx);
111 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~R200_COMB_FCN_MASK;
112
113 assert( modeRGB == modeA );
114
115 switch ( modeRGB ) {
116 case GL_FUNC_ADD:
117 case GL_LOGIC_OP:
118 b |= R200_COMB_FCN_ADD_CLAMP;
119 break;
120
121 case GL_FUNC_SUBTRACT:
122 b |= R200_COMB_FCN_SUB_CLAMP;
123 break;
124
125 case GL_FUNC_REVERSE_SUBTRACT:
126 b |= R200_COMB_FCN_RSUB_CLAMP;
127 break;
128
129 case GL_MIN:
130 b |= R200_COMB_FCN_MIN;
131 break;
132
133 case GL_MAX:
134 b |= R200_COMB_FCN_MAX;
135 break;
136
137 default:
138 break;
139 }
140
141 R200_STATECHANGE( rmesa, ctx );
142 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
143 if ( ctx->Color._LogicOpEnabled ) {
144 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
145 } else {
146 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
147 }
148 }
149
150 static void r200BlendFuncSeparate( GLcontext *ctx,
151 GLenum sfactorRGB, GLenum dfactorRGB,
152 GLenum sfactorA, GLenum dfactorA )
153 {
154 r200ContextPtr rmesa = R200_CONTEXT(ctx);
155 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] &
156 ~(R200_SRC_BLEND_MASK | R200_DST_BLEND_MASK);
157
158 switch ( ctx->Color.BlendSrcRGB ) {
159 case GL_ZERO:
160 b |= R200_SRC_BLEND_GL_ZERO;
161 break;
162 case GL_ONE:
163 b |= R200_SRC_BLEND_GL_ONE;
164 break;
165 case GL_DST_COLOR:
166 b |= R200_SRC_BLEND_GL_DST_COLOR;
167 break;
168 case GL_ONE_MINUS_DST_COLOR:
169 b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR;
170 break;
171 case GL_SRC_COLOR:
172 b |= R200_SRC_BLEND_GL_SRC_COLOR;
173 break;
174 case GL_ONE_MINUS_SRC_COLOR:
175 b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR;
176 break;
177 case GL_SRC_ALPHA:
178 b |= R200_SRC_BLEND_GL_SRC_ALPHA;
179 break;
180 case GL_ONE_MINUS_SRC_ALPHA:
181 b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
182 break;
183 case GL_DST_ALPHA:
184 b |= R200_SRC_BLEND_GL_DST_ALPHA;
185 break;
186 case GL_ONE_MINUS_DST_ALPHA:
187 b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
188 break;
189 case GL_SRC_ALPHA_SATURATE:
190 b |= R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
191 break;
192 case GL_CONSTANT_COLOR:
193 b |= R200_SRC_BLEND_GL_CONST_COLOR;
194 break;
195 case GL_ONE_MINUS_CONSTANT_COLOR:
196 b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR;
197 break;
198 case GL_CONSTANT_ALPHA:
199 b |= R200_SRC_BLEND_GL_CONST_ALPHA;
200 break;
201 case GL_ONE_MINUS_CONSTANT_ALPHA:
202 b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA;
203 break;
204 default:
205 break;
206 }
207
208 switch ( ctx->Color.BlendDstRGB ) {
209 case GL_ZERO:
210 b |= R200_DST_BLEND_GL_ZERO;
211 break;
212 case GL_ONE:
213 b |= R200_DST_BLEND_GL_ONE;
214 break;
215 case GL_SRC_COLOR:
216 b |= R200_DST_BLEND_GL_SRC_COLOR;
217 break;
218 case GL_ONE_MINUS_SRC_COLOR:
219 b |= R200_DST_BLEND_GL_ONE_MINUS_SRC_COLOR;
220 break;
221 case GL_SRC_ALPHA:
222 b |= R200_DST_BLEND_GL_SRC_ALPHA;
223 break;
224 case GL_ONE_MINUS_SRC_ALPHA:
225 b |= R200_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA;
226 break;
227 case GL_DST_COLOR:
228 b |= R200_DST_BLEND_GL_DST_COLOR;
229 break;
230 case GL_ONE_MINUS_DST_COLOR:
231 b |= R200_DST_BLEND_GL_ONE_MINUS_DST_COLOR;
232 break;
233 case GL_DST_ALPHA:
234 b |= R200_DST_BLEND_GL_DST_ALPHA;
235 break;
236 case GL_ONE_MINUS_DST_ALPHA:
237 b |= R200_DST_BLEND_GL_ONE_MINUS_DST_ALPHA;
238 break;
239 case GL_CONSTANT_COLOR:
240 b |= R200_DST_BLEND_GL_CONST_COLOR;
241 break;
242 case GL_ONE_MINUS_CONSTANT_COLOR:
243 b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR;
244 break;
245 case GL_CONSTANT_ALPHA:
246 b |= R200_DST_BLEND_GL_CONST_ALPHA;
247 break;
248 case GL_ONE_MINUS_CONSTANT_ALPHA:
249 b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA;
250 break;
251 default:
252 break;
253 }
254
255 R200_STATECHANGE( rmesa, ctx );
256 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
257 }
258
259
260 /* =============================================================
261 * Depth testing
262 */
263
264 static void r200DepthFunc( GLcontext *ctx, GLenum func )
265 {
266 r200ContextPtr rmesa = R200_CONTEXT(ctx);
267
268 R200_STATECHANGE( rmesa, ctx );
269 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK;
270
271 switch ( ctx->Depth.Func ) {
272 case GL_NEVER:
273 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER;
274 break;
275 case GL_LESS:
276 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS;
277 break;
278 case GL_EQUAL:
279 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL;
280 break;
281 case GL_LEQUAL:
282 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL;
283 break;
284 case GL_GREATER:
285 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER;
286 break;
287 case GL_NOTEQUAL:
288 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL;
289 break;
290 case GL_GEQUAL:
291 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL;
292 break;
293 case GL_ALWAYS:
294 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS;
295 break;
296 }
297 }
298
299
300 static void r200DepthMask( GLcontext *ctx, GLboolean flag )
301 {
302 r200ContextPtr rmesa = R200_CONTEXT(ctx);
303 R200_STATECHANGE( rmesa, ctx );
304
305 if ( ctx->Depth.Mask ) {
306 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE;
307 } else {
308 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE;
309 }
310 }
311
312
313 /* =============================================================
314 * Fog
315 */
316
317
318 static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
319 {
320 r200ContextPtr rmesa = R200_CONTEXT(ctx);
321 union { int i; float f; } c, d;
322 GLchan col[4];
323 GLuint i;
324
325 c.i = rmesa->hw.fog.cmd[FOG_C];
326 d.i = rmesa->hw.fog.cmd[FOG_D];
327
328 switch (pname) {
329 case GL_FOG_MODE:
330 if (!ctx->Fog.Enabled)
331 return;
332 R200_STATECHANGE(rmesa, tcl);
333 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
334 switch (ctx->Fog.Mode) {
335 case GL_LINEAR:
336 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR;
337 if (ctx->Fog.Start == ctx->Fog.End) {
338 c.f = 1.0F;
339 d.f = 1.0F;
340 }
341 else {
342 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
343 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
344 }
345 break;
346 case GL_EXP:
347 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP;
348 c.f = 0.0;
349 d.f = -ctx->Fog.Density;
350 break;
351 case GL_EXP2:
352 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2;
353 c.f = 0.0;
354 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
355 break;
356 default:
357 return;
358 }
359 break;
360 case GL_FOG_DENSITY:
361 switch (ctx->Fog.Mode) {
362 case GL_EXP:
363 c.f = 0.0;
364 d.f = -ctx->Fog.Density;
365 break;
366 case GL_EXP2:
367 c.f = 0.0;
368 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
369 break;
370 default:
371 break;
372 }
373 break;
374 case GL_FOG_START:
375 case GL_FOG_END:
376 if (ctx->Fog.Mode == GL_LINEAR) {
377 if (ctx->Fog.Start == ctx->Fog.End) {
378 c.f = 1.0F;
379 d.f = 1.0F;
380 } else {
381 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
382 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
383 }
384 }
385 break;
386 case GL_FOG_COLOR:
387 R200_STATECHANGE( rmesa, ctx );
388 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
389 i = r200PackColor( 4, col[0], col[1], col[2], 0 );
390 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK;
391 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
392 break;
393 case GL_FOG_COORDINATE_SOURCE_EXT:
394 /* What to do?
395 */
396 break;
397 default:
398 return;
399 }
400
401 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
402 R200_STATECHANGE( rmesa, fog );
403 rmesa->hw.fog.cmd[FOG_C] = c.i;
404 rmesa->hw.fog.cmd[FOG_D] = d.i;
405 }
406 }
407
408
409 /* =============================================================
410 * Scissoring
411 */
412
413
414 static GLboolean intersect_rect( drm_clip_rect_t *out,
415 drm_clip_rect_t *a,
416 drm_clip_rect_t *b )
417 {
418 *out = *a;
419 if ( b->x1 > out->x1 ) out->x1 = b->x1;
420 if ( b->y1 > out->y1 ) out->y1 = b->y1;
421 if ( b->x2 < out->x2 ) out->x2 = b->x2;
422 if ( b->y2 < out->y2 ) out->y2 = b->y2;
423 if ( out->x1 >= out->x2 ) return GL_FALSE;
424 if ( out->y1 >= out->y2 ) return GL_FALSE;
425 return GL_TRUE;
426 }
427
428
429 void r200RecalcScissorRects( r200ContextPtr rmesa )
430 {
431 drm_clip_rect_t *out;
432 int i;
433
434 /* Grow cliprect store?
435 */
436 if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
437 while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
438 rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
439 rmesa->state.scissor.numAllocedClipRects *= 2;
440 }
441
442 if (rmesa->state.scissor.pClipRects)
443 FREE(rmesa->state.scissor.pClipRects);
444
445 rmesa->state.scissor.pClipRects =
446 MALLOC( rmesa->state.scissor.numAllocedClipRects *
447 sizeof(drm_clip_rect_t) );
448
449 if ( rmesa->state.scissor.pClipRects == NULL ) {
450 rmesa->state.scissor.numAllocedClipRects = 0;
451 return;
452 }
453 }
454
455 out = rmesa->state.scissor.pClipRects;
456 rmesa->state.scissor.numClipRects = 0;
457
458 for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
459 if ( intersect_rect( out,
460 &rmesa->pClipRects[i],
461 &rmesa->state.scissor.rect ) ) {
462 rmesa->state.scissor.numClipRects++;
463 out++;
464 }
465 }
466 }
467
468
469 static void r200UpdateScissor( GLcontext *ctx )
470 {
471 r200ContextPtr rmesa = R200_CONTEXT(ctx);
472
473 if ( rmesa->dri.drawable ) {
474 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
475
476 int x = ctx->Scissor.X;
477 int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
478 int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
479 int h = dPriv->h - ctx->Scissor.Y - 1;
480
481 rmesa->state.scissor.rect.x1 = x + dPriv->x;
482 rmesa->state.scissor.rect.y1 = y + dPriv->y;
483 rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
484 rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
485
486 r200RecalcScissorRects( rmesa );
487 }
488 }
489
490
491 static void r200Scissor( GLcontext *ctx,
492 GLint x, GLint y, GLsizei w, GLsizei h )
493 {
494 r200ContextPtr rmesa = R200_CONTEXT(ctx);
495
496 if ( ctx->Scissor.Enabled ) {
497 R200_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
498 r200UpdateScissor( ctx );
499 }
500
501 }
502
503
504 /* =============================================================
505 * Culling
506 */
507
508 static void r200CullFace( GLcontext *ctx, GLenum unused )
509 {
510 r200ContextPtr rmesa = R200_CONTEXT(ctx);
511 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
512 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
513
514 s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
515 t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
516
517 if ( ctx->Polygon.CullFlag ) {
518 switch ( ctx->Polygon.CullFaceMode ) {
519 case GL_FRONT:
520 s &= ~R200_FFACE_SOLID;
521 t |= R200_CULL_FRONT;
522 break;
523 case GL_BACK:
524 s &= ~R200_BFACE_SOLID;
525 t |= R200_CULL_BACK;
526 break;
527 case GL_FRONT_AND_BACK:
528 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
529 t |= (R200_CULL_FRONT | R200_CULL_BACK);
530 break;
531 }
532 }
533
534 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
535 R200_STATECHANGE(rmesa, set );
536 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
537 }
538
539 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
540 R200_STATECHANGE(rmesa, tcl );
541 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
542 }
543 }
544
545 static void r200FrontFace( GLcontext *ctx, GLenum mode )
546 {
547 r200ContextPtr rmesa = R200_CONTEXT(ctx);
548
549 R200_STATECHANGE( rmesa, set );
550 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
551
552 R200_STATECHANGE( rmesa, tcl );
553 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
554
555 switch ( mode ) {
556 case GL_CW:
557 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW;
558 break;
559 case GL_CCW:
560 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CCW;
561 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW;
562 break;
563 }
564 }
565
566 /* =============================================================
567 * Point state
568 */
569 static void r200PointSize( GLcontext *ctx, GLfloat size )
570 {
571 if (0) fprintf(stderr, "%s: %f\n", __FUNCTION__, size );
572 }
573
574 /* =============================================================
575 * Line state
576 */
577 static void r200LineWidth( GLcontext *ctx, GLfloat widthf )
578 {
579 r200ContextPtr rmesa = R200_CONTEXT(ctx);
580
581 R200_STATECHANGE( rmesa, lin );
582 R200_STATECHANGE( rmesa, set );
583
584 /* Line width is stored in U6.4 format.
585 */
586 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
587 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Line._Width * 16.0);
588
589 if ( widthf > 1.0 ) {
590 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE;
591 } else {
592 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
593 }
594 }
595
596 static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
597 {
598 r200ContextPtr rmesa = R200_CONTEXT(ctx);
599
600 R200_STATECHANGE( rmesa, lin );
601 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
602 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
603 }
604
605
606 /* =============================================================
607 * Masks
608 */
609 static void r200ColorMask( GLcontext *ctx,
610 GLboolean r, GLboolean g,
611 GLboolean b, GLboolean a )
612 {
613 r200ContextPtr rmesa = R200_CONTEXT(ctx);
614 GLuint mask = r200PackColor( rmesa->r200Screen->cpp,
615 ctx->Color.ColorMask[RCOMP],
616 ctx->Color.ColorMask[GCOMP],
617 ctx->Color.ColorMask[BCOMP],
618 ctx->Color.ColorMask[ACOMP] );
619
620 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
621
622 if (!(r && g && b && a))
623 flag |= R200_PLANE_MASK_ENABLE;
624
625 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
626 R200_STATECHANGE( rmesa, ctx );
627 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
628 }
629
630 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
631 R200_STATECHANGE( rmesa, msk );
632 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
633 }
634 }
635
636
637 /* =============================================================
638 * Polygon state
639 */
640
641 static void r200PolygonOffset( GLcontext *ctx,
642 GLfloat factor, GLfloat units )
643 {
644 r200ContextPtr rmesa = R200_CONTEXT(ctx);
645 GLfloat constant = units * rmesa->state.depth.scale;
646
647 /* factor *= 2; */
648 /* constant *= 2; */
649
650 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
651
652 R200_STATECHANGE( rmesa, zbs );
653 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = *(GLuint *)&factor;
654 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = *(GLuint *)&constant;
655 }
656
657 static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
658 {
659 r200ContextPtr rmesa = R200_CONTEXT(ctx);
660 GLuint i;
661 drm_radeon_stipple_t stipple;
662
663 /* Must flip pattern upside down.
664 */
665 for ( i = 0 ; i < 32 ; i++ ) {
666 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
667 }
668
669 /* TODO: push this into cmd mechanism
670 */
671 R200_FIREVERTICES( rmesa );
672 LOCK_HARDWARE( rmesa );
673
674 /* FIXME: Use window x,y offsets into stipple RAM.
675 */
676 stipple.mask = rmesa->state.stipple.mask;
677 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
678 &stipple, sizeof(stipple) );
679 UNLOCK_HARDWARE( rmesa );
680 }
681
682 static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
683 {
684 r200ContextPtr rmesa = R200_CONTEXT(ctx);
685 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
686
687 /* Can't generally do unfilled via tcl, but some good special
688 * cases work.
689 */
690 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
691 if (rmesa->TclFallback) {
692 r200ChooseRenderState( ctx );
693 r200ChooseVertexState( ctx );
694 }
695 }
696
697
698 /* =============================================================
699 * Rendering attributes
700 *
701 * We really don't want to recalculate all this every time we bind a
702 * texture. These things shouldn't change all that often, so it makes
703 * sense to break them out of the core texture state update routines.
704 */
705
706 /* Examine lighting and texture state to determine if separate specular
707 * should be enabled.
708 */
709 static void r200UpdateSpecular( GLcontext *ctx )
710 {
711 r200ContextPtr rmesa = R200_CONTEXT(ctx);
712 uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
713
714 R200_STATECHANGE( rmesa, tcl );
715 R200_STATECHANGE( rmesa, vtx );
716
717 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
718 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
719 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
720 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
721 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
722
723 p &= ~R200_SPECULAR_ENABLE;
724
725 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
726
727
728 if (ctx->Light.Enabled &&
729 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
730 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
731 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
732 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
733 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
734 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
735 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
736 p |= R200_SPECULAR_ENABLE;
737 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
738 ~R200_DIFFUSE_SPECULAR_COMBINE;
739 }
740 else if (ctx->Light.Enabled) {
741 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
742 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
743 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
744 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
745 } else if (ctx->Fog.ColorSumEnabled ) {
746 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
747 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
748 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
749 p |= R200_SPECULAR_ENABLE;
750 } else {
751 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
752 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
753 }
754
755 if (ctx->Fog.Enabled) {
756 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
757 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
758 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
759 }
760
761 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
762 R200_STATECHANGE( rmesa, ctx );
763 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
764 }
765
766 /* Update vertex/render formats
767 */
768 if (rmesa->TclFallback) {
769 r200ChooseRenderState( ctx );
770 r200ChooseVertexState( ctx );
771 }
772 }
773
774
775 /* =============================================================
776 * Materials
777 */
778
779
780 /* Update on colormaterial, material emmissive/ambient,
781 * lightmodel.globalambient
782 */
783 static void update_global_ambient( GLcontext *ctx )
784 {
785 r200ContextPtr rmesa = R200_CONTEXT(ctx);
786 float *fcmd = (float *)R200_DB_STATE( glt );
787
788 /* Need to do more if both emmissive & ambient are PREMULT:
789 * I believe this is not nessary when using source_material. This condition thus
790 * will never happen currently, and the function has no dependencies on materials now
791 */
792 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
793 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
794 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
795 {
796 COPY_3V( &fcmd[GLT_RED],
797 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
798 ACC_SCALE_3V( &fcmd[GLT_RED],
799 ctx->Light.Model.Ambient,
800 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
801 }
802 else
803 {
804 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
805 }
806
807 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
808 }
809
810 /* Update on change to
811 * - light[p].colors
812 * - light[p].enabled
813 */
814 static void update_light_colors( GLcontext *ctx, GLuint p )
815 {
816 struct gl_light *l = &ctx->Light.Light[p];
817
818 /* fprintf(stderr, "%s\n", __FUNCTION__); */
819
820 if (l->Enabled) {
821 r200ContextPtr rmesa = R200_CONTEXT(ctx);
822 float *fcmd = (float *)R200_DB_STATE( lit[p] );
823
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 );
827
828 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
829 }
830 }
831
832 static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
833 {
834 r200ContextPtr rmesa = R200_CONTEXT(ctx);
835 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
836 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
837 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
838 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
839 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
840 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
841 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) |
842 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
843 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT));
844
845 if (ctx->Light.ColorMaterialEnabled) {
846 GLuint mask = ctx->Light.ColorMaterialBitmask;
847
848 if (mask & MAT_BIT_FRONT_EMISSION) {
849 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
850 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
851 }
852 else
853 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
854 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
855
856 if (mask & MAT_BIT_FRONT_AMBIENT) {
857 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
858 R200_FRONT_AMBIENT_SOURCE_SHIFT);
859 }
860 else
861 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
862 R200_FRONT_AMBIENT_SOURCE_SHIFT);
863
864 if (mask & MAT_BIT_FRONT_DIFFUSE) {
865 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
866 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
867 }
868 else
869 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
870 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
871
872 if (mask & MAT_BIT_FRONT_SPECULAR) {
873 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
874 R200_FRONT_SPECULAR_SOURCE_SHIFT);
875 }
876 else {
877 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
878 R200_FRONT_SPECULAR_SOURCE_SHIFT);
879 }
880
881 if (mask & MAT_BIT_BACK_EMISSION) {
882 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
883 R200_BACK_EMISSIVE_SOURCE_SHIFT);
884 }
885
886 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
887 R200_BACK_EMISSIVE_SOURCE_SHIFT);
888
889 if (mask & MAT_BIT_BACK_AMBIENT) {
890 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
891 R200_BACK_AMBIENT_SOURCE_SHIFT);
892 }
893 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
894 R200_BACK_AMBIENT_SOURCE_SHIFT);
895
896 if (mask & MAT_BIT_BACK_DIFFUSE) {
897 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
898 R200_BACK_DIFFUSE_SOURCE_SHIFT);
899 }
900 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
901 R200_BACK_DIFFUSE_SOURCE_SHIFT);
902
903 if (mask & MAT_BIT_BACK_SPECULAR) {
904 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
905 R200_BACK_SPECULAR_SOURCE_SHIFT);
906 }
907 else {
908 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
909 R200_BACK_SPECULAR_SOURCE_SHIFT);
910 }
911 }
912 else {
913 /* Default to SOURCE_MATERIAL:
914 */
915 light_model_ctl1 |=
916 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
917 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
918 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
919 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
920 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
921 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) |
922 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
923 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT);
924 }
925
926 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
927 R200_STATECHANGE( rmesa, tcl );
928 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
929 }
930
931
932 }
933
934 void r200UpdateMaterial( GLcontext *ctx )
935 {
936 r200ContextPtr rmesa = R200_CONTEXT(ctx);
937 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
938 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
939 GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] );
940 GLuint mask = ~0;
941
942 /* Might be possible and faster to update everything unconditionally? */
943 if (ctx->Light.ColorMaterialEnabled)
944 mask &= ~ctx->Light.ColorMaterialBitmask;
945
946 if (R200_DEBUG & DEBUG_STATE)
947 fprintf(stderr, "%s\n", __FUNCTION__);
948
949 if (mask & MAT_BIT_FRONT_EMISSION) {
950 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
951 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
952 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
953 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
954 }
955 if (mask & MAT_BIT_FRONT_AMBIENT) {
956 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
957 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
958 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
959 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
960 }
961 if (mask & MAT_BIT_FRONT_DIFFUSE) {
962 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
963 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
964 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
965 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
966 }
967 if (mask & MAT_BIT_FRONT_SPECULAR) {
968 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
969 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
970 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
971 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
972 }
973 if (mask & MAT_BIT_FRONT_SHININESS) {
974 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
975 }
976
977 if (mask & MAT_BIT_BACK_EMISSION) {
978 fcmd2[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_BACK_EMISSION][0];
979 fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1];
980 fcmd2[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_BACK_EMISSION][2];
981 fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3];
982 }
983 if (mask & MAT_BIT_BACK_AMBIENT) {
984 fcmd2[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_BACK_AMBIENT][0];
985 fcmd2[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_BACK_AMBIENT][1];
986 fcmd2[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_BACK_AMBIENT][2];
987 fcmd2[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_BACK_AMBIENT][3];
988 }
989 if (mask & MAT_BIT_BACK_DIFFUSE) {
990 fcmd2[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_BACK_DIFFUSE][0];
991 fcmd2[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_BACK_DIFFUSE][1];
992 fcmd2[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_BACK_DIFFUSE][2];
993 fcmd2[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_BACK_DIFFUSE][3];
994 }
995 if (mask & MAT_BIT_BACK_SPECULAR) {
996 fcmd2[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_BACK_SPECULAR][0];
997 fcmd2[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_BACK_SPECULAR][1];
998 fcmd2[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_BACK_SPECULAR][2];
999 fcmd2[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_BACK_SPECULAR][3];
1000 }
1001 if (mask & MAT_BIT_BACK_SHININESS) {
1002 fcmd2[MTL_SHININESS] = mat[MAT_ATTRIB_BACK_SHININESS][0];
1003 }
1004
1005 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] );
1006 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] );
1007
1008 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1009 update_global_ambient( ctx ); */
1010 }
1011
1012 /* _NEW_LIGHT
1013 * _NEW_MODELVIEW
1014 * _MESA_NEW_NEED_EYE_COORDS
1015 *
1016 * Uses derived state from mesa:
1017 * _VP_inf_norm
1018 * _h_inf_norm
1019 * _Position
1020 * _NormDirection
1021 * _ModelViewInvScale
1022 * _NeedEyeCoords
1023 * _EyeZDir
1024 *
1025 * which are calculated in light.c and are correct for the current
1026 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1027 * and _MESA_NEW_NEED_EYE_COORDS.
1028 */
1029 static void update_light( GLcontext *ctx )
1030 {
1031 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1032
1033 /* Have to check these, or have an automatic shortcircuit mechanism
1034 * to remove noop statechanges. (Or just do a better job on the
1035 * front end).
1036 */
1037 {
1038 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
1039
1040 if (ctx->_NeedEyeCoords)
1041 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1042 else
1043 tmp |= R200_LIGHT_IN_MODELSPACE;
1044
1045 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1046 {
1047 R200_STATECHANGE( rmesa, tcl );
1048 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1049 }
1050 }
1051
1052 {
1053 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1054 fcmd[EYE_X] = ctx->_EyeZDir[0];
1055 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1056 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1057 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1058 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1059 }
1060
1061
1062
1063 if (ctx->Light.Enabled) {
1064 GLint p;
1065 for (p = 0 ; p < MAX_LIGHTS; p++) {
1066 if (ctx->Light.Light[p].Enabled) {
1067 struct gl_light *l = &ctx->Light.Light[p];
1068 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1069
1070 if (l->EyePosition[3] == 0.0) {
1071 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1072 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1073 fcmd[LIT_POSITION_W] = 0;
1074 fcmd[LIT_DIRECTION_W] = 0;
1075 } else {
1076 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1077 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1078 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1079 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1080 fcmd[LIT_DIRECTION_W] = 0;
1081 }
1082
1083 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1084 }
1085 }
1086 }
1087 }
1088
1089 static void r200Lightfv( GLcontext *ctx, GLenum light,
1090 GLenum pname, const GLfloat *params )
1091 {
1092 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1093 GLint p = light - GL_LIGHT0;
1094 struct gl_light *l = &ctx->Light.Light[p];
1095 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1096
1097
1098 switch (pname) {
1099 case GL_AMBIENT:
1100 case GL_DIFFUSE:
1101 case GL_SPECULAR:
1102 update_light_colors( ctx, p );
1103 break;
1104
1105 case GL_SPOT_DIRECTION:
1106 /* picked up in update_light */
1107 break;
1108
1109 case GL_POSITION: {
1110 /* positions picked up in update_light, but can do flag here */
1111 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1112 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1113
1114 R200_STATECHANGE(rmesa, tcl);
1115 if (l->EyePosition[3] != 0.0F)
1116 rmesa->hw.tcl.cmd[idx] |= flag;
1117 else
1118 rmesa->hw.tcl.cmd[idx] &= ~flag;
1119 break;
1120 }
1121
1122 case GL_SPOT_EXPONENT:
1123 R200_STATECHANGE(rmesa, lit[p]);
1124 fcmd[LIT_SPOT_EXPONENT] = params[0];
1125 break;
1126
1127 case GL_SPOT_CUTOFF: {
1128 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1129 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1130
1131 R200_STATECHANGE(rmesa, lit[p]);
1132 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1133
1134 R200_STATECHANGE(rmesa, tcl);
1135 if (l->SpotCutoff != 180.0F)
1136 rmesa->hw.tcl.cmd[idx] |= flag;
1137 else
1138 rmesa->hw.tcl.cmd[idx] &= ~flag;
1139
1140 break;
1141 }
1142
1143 case GL_CONSTANT_ATTENUATION:
1144 R200_STATECHANGE(rmesa, lit[p]);
1145 fcmd[LIT_ATTEN_CONST] = params[0];
1146 if ( params[0] == 0.0 )
1147 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1148 else
1149 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1150 break;
1151 case GL_LINEAR_ATTENUATION:
1152 R200_STATECHANGE(rmesa, lit[p]);
1153 fcmd[LIT_ATTEN_LINEAR] = params[0];
1154 break;
1155 case GL_QUADRATIC_ATTENUATION:
1156 R200_STATECHANGE(rmesa, lit[p]);
1157 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1158 break;
1159 default:
1160 return;
1161 }
1162
1163 /* Set RANGE_ATTEN only when needed */
1164 switch (pname) {
1165 case GL_POSITION:
1166 case GL_CONSTANT_ATTENUATION:
1167 case GL_LINEAR_ATTENUATION:
1168 case GL_QUADRATIC_ATTENUATION: {
1169 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1170 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1171 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1172 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1173 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1174 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1175
1176 if ( l->EyePosition[3] == 0.0F ||
1177 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1178 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1179 /* Disable attenuation */
1180 icmd[idx] &= ~atten_flag;
1181 } else {
1182 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1183 /* Enable only constant portion of attenuation calculation */
1184 icmd[idx] |= ( atten_flag | atten_const_flag );
1185 } else {
1186 /* Enable full attenuation calculation */
1187 icmd[idx] &= ~atten_const_flag;
1188 icmd[idx] |= atten_flag;
1189 }
1190 }
1191
1192 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1193 break;
1194 }
1195 default:
1196 break;
1197 }
1198 }
1199
1200
1201
1202
1203 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1204 const GLfloat *param )
1205 {
1206 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1207
1208 switch (pname) {
1209 case GL_LIGHT_MODEL_AMBIENT:
1210 update_global_ambient( ctx );
1211 break;
1212
1213 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1214 R200_STATECHANGE( rmesa, tcl );
1215 if (ctx->Light.Model.LocalViewer)
1216 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1217 else
1218 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1219 break;
1220
1221 case GL_LIGHT_MODEL_TWO_SIDE:
1222 R200_STATECHANGE( rmesa, tcl );
1223 if (ctx->Light.Model.TwoSide)
1224 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1225 else
1226 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1227 if (rmesa->TclFallback) {
1228 r200ChooseRenderState( ctx );
1229 r200ChooseVertexState( ctx );
1230 }
1231 break;
1232
1233 case GL_LIGHT_MODEL_COLOR_CONTROL:
1234 r200UpdateSpecular(ctx);
1235 break;
1236
1237 default:
1238 break;
1239 }
1240 }
1241
1242 static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1243 {
1244 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1245 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1246
1247 s &= ~(R200_DIFFUSE_SHADE_MASK |
1248 R200_ALPHA_SHADE_MASK |
1249 R200_SPECULAR_SHADE_MASK |
1250 R200_FOG_SHADE_MASK);
1251
1252 switch ( mode ) {
1253 case GL_FLAT:
1254 s |= (R200_DIFFUSE_SHADE_FLAT |
1255 R200_ALPHA_SHADE_FLAT |
1256 R200_SPECULAR_SHADE_FLAT |
1257 R200_FOG_SHADE_FLAT);
1258 break;
1259 case GL_SMOOTH:
1260 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1261 R200_ALPHA_SHADE_GOURAUD |
1262 R200_SPECULAR_SHADE_GOURAUD |
1263 R200_FOG_SHADE_GOURAUD);
1264 break;
1265 default:
1266 return;
1267 }
1268
1269 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1270 R200_STATECHANGE( rmesa, set );
1271 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1272 }
1273 }
1274
1275
1276 /* =============================================================
1277 * User clip planes
1278 */
1279
1280 static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1281 {
1282 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1283 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1284 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1285
1286 R200_STATECHANGE( rmesa, ucp[p] );
1287 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1288 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1289 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1290 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1291 }
1292
1293 static void r200UpdateClipPlanes( GLcontext *ctx )
1294 {
1295 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1296 GLuint p;
1297
1298 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1299 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1300 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1301
1302 R200_STATECHANGE( rmesa, ucp[p] );
1303 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1304 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1305 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1306 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1307 }
1308 }
1309 }
1310
1311
1312 /* =============================================================
1313 * Stencil
1314 */
1315
1316 static void r200StencilFunc( GLcontext *ctx, GLenum func,
1317 GLint ref, GLuint mask )
1318 {
1319 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1320 GLuint refmask = ((ctx->Stencil.Ref[0] << R200_STENCIL_REF_SHIFT) |
1321 (ctx->Stencil.ValueMask[0] << R200_STENCIL_MASK_SHIFT));
1322
1323 R200_STATECHANGE( rmesa, ctx );
1324 R200_STATECHANGE( rmesa, msk );
1325
1326 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1327 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1328 R200_STENCIL_VALUE_MASK);
1329
1330 switch ( ctx->Stencil.Function[0] ) {
1331 case GL_NEVER:
1332 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1333 break;
1334 case GL_LESS:
1335 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1336 break;
1337 case GL_EQUAL:
1338 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1339 break;
1340 case GL_LEQUAL:
1341 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1342 break;
1343 case GL_GREATER:
1344 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1345 break;
1346 case GL_NOTEQUAL:
1347 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1348 break;
1349 case GL_GEQUAL:
1350 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1351 break;
1352 case GL_ALWAYS:
1353 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1354 break;
1355 }
1356
1357 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1358 }
1359
1360 static void r200StencilMask( GLcontext *ctx, GLuint mask )
1361 {
1362 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1363
1364 R200_STATECHANGE( rmesa, msk );
1365 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1366 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1367 (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT);
1368 }
1369
1370 static void r200StencilOp( GLcontext *ctx, GLenum fail,
1371 GLenum zfail, GLenum zpass )
1372 {
1373 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1374
1375 R200_STATECHANGE( rmesa, ctx );
1376 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1377 R200_STENCIL_ZFAIL_MASK |
1378 R200_STENCIL_ZPASS_MASK);
1379
1380 switch ( ctx->Stencil.FailFunc[0] ) {
1381 case GL_KEEP:
1382 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1383 break;
1384 case GL_ZERO:
1385 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1386 break;
1387 case GL_REPLACE:
1388 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1389 break;
1390 case GL_INCR:
1391 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1392 break;
1393 case GL_DECR:
1394 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1395 break;
1396 case GL_INCR_WRAP_EXT:
1397 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1398 break;
1399 case GL_DECR_WRAP_EXT:
1400 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1401 break;
1402 case GL_INVERT:
1403 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1404 break;
1405 }
1406
1407 switch ( ctx->Stencil.ZFailFunc[0] ) {
1408 case GL_KEEP:
1409 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1410 break;
1411 case GL_ZERO:
1412 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1413 break;
1414 case GL_REPLACE:
1415 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1416 break;
1417 case GL_INCR:
1418 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1419 break;
1420 case GL_DECR:
1421 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1422 break;
1423 case GL_INCR_WRAP_EXT:
1424 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1425 break;
1426 case GL_DECR_WRAP_EXT:
1427 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1428 break;
1429 case GL_INVERT:
1430 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1431 break;
1432 }
1433
1434 switch ( ctx->Stencil.ZPassFunc[0] ) {
1435 case GL_KEEP:
1436 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1437 break;
1438 case GL_ZERO:
1439 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1440 break;
1441 case GL_REPLACE:
1442 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1443 break;
1444 case GL_INCR:
1445 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1446 break;
1447 case GL_DECR:
1448 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1449 break;
1450 case GL_INCR_WRAP_EXT:
1451 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1452 break;
1453 case GL_DECR_WRAP_EXT:
1454 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1455 break;
1456 case GL_INVERT:
1457 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1458 break;
1459 }
1460 }
1461
1462 static void r200ClearStencil( GLcontext *ctx, GLint s )
1463 {
1464 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1465
1466 rmesa->state.stencil.clear =
1467 ((GLuint) ctx->Stencil.Clear |
1468 (0xff << R200_STENCIL_MASK_SHIFT) |
1469 (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT));
1470 }
1471
1472
1473 /* =============================================================
1474 * Window position and viewport transformation
1475 */
1476
1477 /*
1478 * To correctly position primitives:
1479 */
1480 #define SUBPIXEL_X 0.125
1481 #define SUBPIXEL_Y 0.125
1482
1483 void r200UpdateWindow( GLcontext *ctx )
1484 {
1485 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1486 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1487 GLfloat xoffset = (GLfloat)dPriv->x;
1488 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1489 const GLfloat *v = ctx->Viewport._WindowMap.m;
1490
1491 GLfloat sx = v[MAT_SX];
1492 GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
1493 GLfloat sy = - v[MAT_SY];
1494 GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1495 GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
1496 GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
1497
1498 R200_FIREVERTICES( rmesa );
1499 R200_STATECHANGE( rmesa, vpt );
1500
1501 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = *(GLuint *)&sx;
1502 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1503 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = *(GLuint *)&sy;
1504 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1505 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = *(GLuint *)&sz;
1506 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
1507 }
1508
1509
1510
1511 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1512 GLsizei width, GLsizei height )
1513 {
1514 /* Don't pipeline viewport changes, conflict with window offset
1515 * setting below. Could apply deltas to rescue pipelined viewport
1516 * values, or keep the originals hanging around.
1517 */
1518 R200_FIREVERTICES( R200_CONTEXT(ctx) );
1519 r200UpdateWindow( ctx );
1520 }
1521
1522 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1523 GLclampd farval )
1524 {
1525 r200UpdateWindow( ctx );
1526 }
1527
1528 void r200UpdateViewportOffset( GLcontext *ctx )
1529 {
1530 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1531 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1532 GLfloat xoffset = (GLfloat)dPriv->x;
1533 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1534 const GLfloat *v = ctx->Viewport._WindowMap.m;
1535
1536 GLfloat tx = v[MAT_TX] + xoffset;
1537 GLfloat ty = (- v[MAT_TY]) + yoffset;
1538
1539 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
1540 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
1541 {
1542 /* Note: this should also modify whatever data the context reset
1543 * code uses...
1544 */
1545 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1546 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1547
1548 /* update polygon stipple x/y screen offset */
1549 {
1550 GLuint stx, sty;
1551 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1552
1553 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1554 R200_STIPPLE_Y_OFFSET_MASK);
1555
1556 /* add magic offsets, then invert */
1557 stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1558 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1559 & R200_STIPPLE_COORD_MASK);
1560
1561 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1562 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1563
1564 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1565 R200_STATECHANGE( rmesa, msc );
1566 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1567 }
1568 }
1569 }
1570
1571 r200UpdateScissor( ctx );
1572 }
1573
1574
1575
1576 /* =============================================================
1577 * Miscellaneous
1578 */
1579
1580 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1581 {
1582 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1583 GLubyte color[4];
1584 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1585 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1586 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1587 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1588 rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp,
1589 color[0], color[1],
1590 color[2], color[3] );
1591 }
1592
1593
1594 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1595 {
1596 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1597 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1598 }
1599
1600
1601 static GLuint r200_rop_tab[] = {
1602 R200_ROP_CLEAR,
1603 R200_ROP_AND,
1604 R200_ROP_AND_REVERSE,
1605 R200_ROP_COPY,
1606 R200_ROP_AND_INVERTED,
1607 R200_ROP_NOOP,
1608 R200_ROP_XOR,
1609 R200_ROP_OR,
1610 R200_ROP_NOR,
1611 R200_ROP_EQUIV,
1612 R200_ROP_INVERT,
1613 R200_ROP_OR_REVERSE,
1614 R200_ROP_COPY_INVERTED,
1615 R200_ROP_OR_INVERTED,
1616 R200_ROP_NAND,
1617 R200_ROP_SET,
1618 };
1619
1620 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1621 {
1622 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1623 GLuint rop = (GLuint)opcode - GL_CLEAR;
1624
1625 ASSERT( rop < 16 );
1626
1627 R200_STATECHANGE( rmesa, msk );
1628 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1629 }
1630
1631
1632 void r200SetCliprects( r200ContextPtr rmesa, GLenum mode )
1633 {
1634 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1635
1636 switch ( mode ) {
1637 case GL_FRONT_LEFT:
1638 rmesa->numClipRects = dPriv->numClipRects;
1639 rmesa->pClipRects = dPriv->pClipRects;
1640 break;
1641 case GL_BACK_LEFT:
1642 /* Can't ignore 2d windows if we are page flipping.
1643 */
1644 if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
1645 rmesa->numClipRects = dPriv->numClipRects;
1646 rmesa->pClipRects = dPriv->pClipRects;
1647 }
1648 else {
1649 rmesa->numClipRects = dPriv->numBackClipRects;
1650 rmesa->pClipRects = dPriv->pBackClipRects;
1651 }
1652 break;
1653 default:
1654 fprintf(stderr, "bad mode in r200SetCliprects\n");
1655 return;
1656 }
1657
1658 if (rmesa->state.scissor.enabled)
1659 r200RecalcScissorRects( rmesa );
1660 }
1661
1662
1663 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1664 {
1665 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1666
1667 if (R200_DEBUG & DEBUG_DRI)
1668 fprintf(stderr, "%s %s\n", __FUNCTION__,
1669 _mesa_lookup_enum_by_nr( mode ));
1670
1671 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1672
1673 /*
1674 * _DrawDestMask is easier to cope with than <mode>.
1675 */
1676 switch ( ctx->Color._DrawDestMask ) {
1677 case DD_FRONT_LEFT_BIT:
1678 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1679 r200SetCliprects( rmesa, GL_FRONT_LEFT );
1680 break;
1681 case DD_BACK_LEFT_BIT:
1682 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1683 r200SetCliprects( rmesa, GL_BACK_LEFT );
1684 break;
1685 default:
1686 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1687 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1688 return;
1689 }
1690
1691 /* We want to update the s/w rast state too so that r200SetBuffer()
1692 * gets called.
1693 */
1694 _swrast_DrawBuffer(ctx, mode);
1695
1696 R200_STATECHANGE( rmesa, ctx );
1697 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((rmesa->state.color.drawOffset +
1698 rmesa->r200Screen->fbLocation)
1699 & R200_COLOROFFSET_MASK);
1700 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
1701 }
1702
1703
1704 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1705 {
1706 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1707 }
1708
1709 /* =============================================================
1710 * State enable/disable
1711 */
1712
1713 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1714 {
1715 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1716 GLuint p, flag;
1717
1718 if ( R200_DEBUG & DEBUG_STATE )
1719 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1720 _mesa_lookup_enum_by_nr( cap ),
1721 state ? "GL_TRUE" : "GL_FALSE" );
1722
1723 switch ( cap ) {
1724 /* Fast track this one...
1725 */
1726 case GL_TEXTURE_1D:
1727 case GL_TEXTURE_2D:
1728 case GL_TEXTURE_3D:
1729 break;
1730
1731 case GL_ALPHA_TEST:
1732 R200_STATECHANGE( rmesa, ctx );
1733 if (state) {
1734 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1735 } else {
1736 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1737 }
1738 break;
1739
1740 case GL_BLEND:
1741 R200_STATECHANGE( rmesa, ctx );
1742 if (state) {
1743 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ALPHA_BLEND_ENABLE;
1744 } else {
1745 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ALPHA_BLEND_ENABLE;
1746 }
1747 if ( ctx->Color._LogicOpEnabled ) {
1748 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
1749 } else {
1750 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
1751 }
1752 break;
1753
1754 case GL_CLIP_PLANE0:
1755 case GL_CLIP_PLANE1:
1756 case GL_CLIP_PLANE2:
1757 case GL_CLIP_PLANE3:
1758 case GL_CLIP_PLANE4:
1759 case GL_CLIP_PLANE5:
1760 p = cap-GL_CLIP_PLANE0;
1761 R200_STATECHANGE( rmesa, tcl );
1762 if (state) {
1763 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1764 r200ClipPlane( ctx, cap, NULL );
1765 }
1766 else {
1767 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1768 }
1769 break;
1770
1771 case GL_COLOR_MATERIAL:
1772 r200ColorMaterial( ctx, 0, 0 );
1773 r200UpdateMaterial( ctx );
1774 break;
1775
1776 case GL_CULL_FACE:
1777 r200CullFace( ctx, 0 );
1778 break;
1779
1780 case GL_DEPTH_TEST:
1781 R200_STATECHANGE(rmesa, ctx );
1782 if ( state ) {
1783 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1784 } else {
1785 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1786 }
1787 break;
1788
1789 case GL_DITHER:
1790 R200_STATECHANGE(rmesa, ctx );
1791 if ( state ) {
1792 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1793 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
1794 } else {
1795 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1796 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
1797 }
1798 break;
1799
1800 case GL_FOG:
1801 R200_STATECHANGE(rmesa, ctx );
1802 if ( state ) {
1803 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1804 r200Fogfv( ctx, GL_FOG_MODE, 0 );
1805 } else {
1806 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1807 R200_STATECHANGE(rmesa, tcl);
1808 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1809 }
1810 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1811 if (rmesa->TclFallback)
1812 r200ChooseVertexState( ctx );
1813 _mesa_allow_light_in_model( ctx, !state );
1814 break;
1815
1816 case GL_LIGHT0:
1817 case GL_LIGHT1:
1818 case GL_LIGHT2:
1819 case GL_LIGHT3:
1820 case GL_LIGHT4:
1821 case GL_LIGHT5:
1822 case GL_LIGHT6:
1823 case GL_LIGHT7:
1824 R200_STATECHANGE(rmesa, tcl);
1825 p = cap - GL_LIGHT0;
1826 if (p&1)
1827 flag = (R200_LIGHT_1_ENABLE |
1828 R200_LIGHT_1_ENABLE_AMBIENT |
1829 R200_LIGHT_1_ENABLE_SPECULAR);
1830 else
1831 flag = (R200_LIGHT_0_ENABLE |
1832 R200_LIGHT_0_ENABLE_AMBIENT |
1833 R200_LIGHT_0_ENABLE_SPECULAR);
1834
1835 if (state)
1836 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1837 else
1838 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1839
1840 /*
1841 */
1842 update_light_colors( ctx, p );
1843 break;
1844
1845 case GL_LIGHTING:
1846 r200UpdateSpecular(ctx);
1847 break;
1848
1849 case GL_LINE_SMOOTH:
1850 R200_STATECHANGE( rmesa, ctx );
1851 if ( state ) {
1852 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1853 } else {
1854 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1855 }
1856 break;
1857
1858 case GL_LINE_STIPPLE:
1859 R200_STATECHANGE( rmesa, set );
1860 if ( state ) {
1861 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1862 } else {
1863 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1864 }
1865 break;
1866
1867 case GL_COLOR_LOGIC_OP:
1868 R200_STATECHANGE( rmesa, ctx );
1869 if ( ctx->Color._LogicOpEnabled ) {
1870 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE;
1871 } else {
1872 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE;
1873 }
1874 break;
1875
1876 case GL_NORMALIZE:
1877 R200_STATECHANGE( rmesa, tcl );
1878 if ( state ) {
1879 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1880 } else {
1881 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1882 }
1883 break;
1884
1885 /* Pointsize registers on r200 don't seem to do anything. Maybe
1886 * have to pass pointsizes as vertex parameters? In any case,
1887 * setting pointmin == pointsizemax == 1.0, and doing nothing
1888 * for aa is enough to satisfy conform.
1889 */
1890 case GL_POINT_SMOOTH:
1891 break;
1892
1893 /* These don't really do anything, as we don't use the 3vtx
1894 * primitives yet.
1895 */
1896 #if 0
1897 case GL_POLYGON_OFFSET_POINT:
1898 R200_STATECHANGE( rmesa, set );
1899 if ( state ) {
1900 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1901 } else {
1902 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1903 }
1904 break;
1905
1906 case GL_POLYGON_OFFSET_LINE:
1907 R200_STATECHANGE( rmesa, set );
1908 if ( state ) {
1909 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
1910 } else {
1911 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1912 }
1913 break;
1914 #endif
1915
1916 case GL_POLYGON_OFFSET_FILL:
1917 R200_STATECHANGE( rmesa, set );
1918 if ( state ) {
1919 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
1920 } else {
1921 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1922 }
1923 break;
1924
1925 case GL_POLYGON_SMOOTH:
1926 R200_STATECHANGE( rmesa, ctx );
1927 if ( state ) {
1928 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
1929 } else {
1930 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
1931 }
1932 break;
1933
1934 case GL_POLYGON_STIPPLE:
1935 R200_STATECHANGE(rmesa, set );
1936 if ( state ) {
1937 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
1938 } else {
1939 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
1940 }
1941 break;
1942
1943 case GL_RESCALE_NORMAL_EXT: {
1944 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1945 R200_STATECHANGE( rmesa, tcl );
1946 if ( tmp ) {
1947 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1948 } else {
1949 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1950 }
1951 break;
1952 }
1953
1954 case GL_SCISSOR_TEST:
1955 R200_FIREVERTICES( rmesa );
1956 rmesa->state.scissor.enabled = state;
1957 r200UpdateScissor( ctx );
1958 break;
1959
1960 case GL_STENCIL_TEST:
1961 if ( rmesa->state.stencil.hwBuffer ) {
1962 R200_STATECHANGE( rmesa, ctx );
1963 if ( state ) {
1964 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
1965 } else {
1966 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
1967 }
1968 } else {
1969 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
1970 }
1971 break;
1972
1973 case GL_TEXTURE_GEN_Q:
1974 case GL_TEXTURE_GEN_R:
1975 case GL_TEXTURE_GEN_S:
1976 case GL_TEXTURE_GEN_T:
1977 /* Picked up in r200UpdateTextureState.
1978 */
1979 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1980 break;
1981
1982 case GL_COLOR_SUM_EXT:
1983 r200UpdateSpecular ( ctx );
1984 break;
1985
1986 default:
1987 return;
1988 }
1989 }
1990
1991
1992 void r200LightingSpaceChange( GLcontext *ctx )
1993 {
1994 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1995 GLboolean tmp;
1996
1997 if (R200_DEBUG & DEBUG_STATE)
1998 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
1999 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2000
2001 if (ctx->_NeedEyeCoords)
2002 tmp = ctx->Transform.RescaleNormals;
2003 else
2004 tmp = !ctx->Transform.RescaleNormals;
2005
2006 R200_STATECHANGE( rmesa, tcl );
2007 if ( tmp ) {
2008 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2009 } else {
2010 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2011 }
2012
2013 if (R200_DEBUG & DEBUG_STATE)
2014 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2015 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2016 }
2017
2018 /* =============================================================
2019 * Deferred state management - matrices, textures, other?
2020 */
2021
2022
2023
2024
2025 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2026 {
2027 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2028 int i;
2029
2030
2031 for (i = 0 ; i < 4 ; i++) {
2032 *dest++ = src[i];
2033 *dest++ = src[i+4];
2034 *dest++ = src[i+8];
2035 *dest++ = src[i+12];
2036 }
2037
2038 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2039 }
2040
2041 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2042 {
2043 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2044 memcpy(dest, src, 16*sizeof(float));
2045 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2046 }
2047
2048
2049 static void update_texturematrix( GLcontext *ctx )
2050 {
2051 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2052 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2053 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2054 int unit;
2055
2056 if (R200_DEBUG & DEBUG_STATE)
2057 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2058 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2059
2060 rmesa->TexMatEnabled = 0;
2061 rmesa->TexMatCompSel = 0;
2062
2063 for (unit = 0 ; unit < 2; unit++) {
2064 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2065 continue;
2066
2067 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2068 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2069 R200_TEXMAT_0_ENABLE) << unit;
2070
2071 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2072
2073 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2074 /* Need to preconcatenate any active texgen
2075 * obj/eyeplane matrices:
2076 */
2077 _math_matrix_mul_matrix( &rmesa->tmpmat,
2078 &rmesa->TexGenMatrix[unit],
2079 ctx->TextureMatrixStack[unit].Top );
2080 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2081 }
2082 else {
2083 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2084 R200_MTX_TEX0+unit );
2085 }
2086 }
2087 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2088 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2089 R200_MTX_TEX0+unit );
2090 }
2091 }
2092
2093 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2094 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] ||
2095 rmesa->TexGenInputs != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1]) {
2096 R200_STATECHANGE(rmesa, tcg);
2097 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2098 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = rmesa->TexGenInputs;
2099 }
2100
2101 compsel &= ~R200_OUTPUT_TEX_MASK;
2102 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2103 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2104 R200_STATECHANGE(rmesa, vtx);
2105 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2106 }
2107 }
2108
2109
2110
2111 void r200ValidateState( GLcontext *ctx )
2112 {
2113 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2114 GLuint new_state = rmesa->NewGLState;
2115
2116 if (new_state & _NEW_TEXTURE) {
2117 r200UpdateTextureState( ctx );
2118 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2119 }
2120
2121 /* Need an event driven matrix update?
2122 */
2123 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2124 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2125
2126 /* Need these for lighting (shouldn't upload otherwise)
2127 */
2128 if (new_state & (_NEW_MODELVIEW)) {
2129 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2130 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2131 }
2132
2133 /* Does this need to be triggered on eg. modelview for
2134 * texgen-derived objplane/eyeplane matrices?
2135 */
2136 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2137 update_texturematrix( ctx );
2138 }
2139
2140 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2141 update_light( ctx );
2142 }
2143
2144 /* emit all active clip planes if projection matrix changes.
2145 */
2146 if (new_state & (_NEW_PROJECTION)) {
2147 if (ctx->Transform.ClipPlanesEnabled)
2148 r200UpdateClipPlanes( ctx );
2149 }
2150
2151
2152 rmesa->NewGLState = 0;
2153 }
2154
2155
2156 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2157 {
2158 _swrast_InvalidateState( ctx, new_state );
2159 _swsetup_InvalidateState( ctx, new_state );
2160 _ac_InvalidateState( ctx, new_state );
2161 _tnl_InvalidateState( ctx, new_state );
2162 _ae_invalidate_state( ctx, new_state );
2163 R200_CONTEXT(ctx)->NewGLState |= new_state;
2164 r200VtxfmtInvalidate( ctx );
2165 }
2166
2167 /* A hack. The r200 can actually cope just fine with materials
2168 * between begin/ends, so fix this. But how ?
2169 */
2170 static GLboolean check_material( GLcontext *ctx )
2171 {
2172 TNLcontext *tnl = TNL_CONTEXT(ctx);
2173 GLint i;
2174
2175 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2176 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2177 i++)
2178 if (tnl->vb.AttribPtr[i] &&
2179 tnl->vb.AttribPtr[i]->stride)
2180 return GL_TRUE;
2181
2182 return GL_FALSE;
2183 }
2184
2185 static void r200WrapRunPipeline( GLcontext *ctx )
2186 {
2187 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2188 GLboolean has_material;
2189
2190 if (0)
2191 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2192
2193 /* Validate state:
2194 */
2195 if (rmesa->NewGLState)
2196 r200ValidateState( ctx );
2197
2198 has_material = (ctx->Light.Enabled && check_material( ctx ));
2199
2200 if (has_material) {
2201 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2202 }
2203
2204 /* Run the pipeline.
2205 */
2206 _tnl_run_pipeline( ctx );
2207
2208 if (has_material) {
2209 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2210 }
2211 }
2212
2213
2214 /* Initialize the driver's state functions.
2215 */
2216 void r200InitStateFuncs( struct dd_function_table *functions )
2217 {
2218 functions->UpdateState = r200InvalidateState;
2219 functions->LightingSpaceChange = r200LightingSpaceChange;
2220
2221 functions->DrawBuffer = r200DrawBuffer;
2222 functions->ReadBuffer = r200ReadBuffer;
2223
2224 functions->AlphaFunc = r200AlphaFunc;
2225 functions->BlendEquationSeparate = r200BlendEquationSeparate;
2226 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2227 functions->ClearColor = r200ClearColor;
2228 functions->ClearDepth = NULL;
2229 functions->ClearIndex = NULL;
2230 functions->ClearStencil = r200ClearStencil;
2231 functions->ClipPlane = r200ClipPlane;
2232 functions->ColorMask = r200ColorMask;
2233 functions->CullFace = r200CullFace;
2234 functions->DepthFunc = r200DepthFunc;
2235 functions->DepthMask = r200DepthMask;
2236 functions->DepthRange = r200DepthRange;
2237 functions->Enable = r200Enable;
2238 functions->Fogfv = r200Fogfv;
2239 functions->FrontFace = r200FrontFace;
2240 functions->Hint = NULL;
2241 functions->IndexMask = NULL;
2242 functions->LightModelfv = r200LightModelfv;
2243 functions->Lightfv = r200Lightfv;
2244 functions->LineStipple = r200LineStipple;
2245 functions->LineWidth = r200LineWidth;
2246 functions->LogicOpcode = r200LogicOpCode;
2247 functions->PolygonMode = r200PolygonMode;
2248 functions->PolygonOffset = r200PolygonOffset;
2249 functions->PolygonStipple = r200PolygonStipple;
2250 functions->PointSize = r200PointSize;
2251 functions->RenderMode = r200RenderMode;
2252 functions->Scissor = r200Scissor;
2253 functions->ShadeModel = r200ShadeModel;
2254 functions->StencilFunc = r200StencilFunc;
2255 functions->StencilMask = r200StencilMask;
2256 functions->StencilOp = r200StencilOp;
2257 functions->Viewport = r200Viewport;
2258
2259 /* Swrast hooks for imaging extensions:
2260 */
2261 functions->CopyColorTable = _swrast_CopyColorTable;
2262 functions->CopyColorSubTable = _swrast_CopyColorSubTable;
2263 functions->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
2264 functions->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
2265 }
2266
2267
2268 void r200InitTnlFuncs( GLcontext *ctx )
2269 {
2270 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2271 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2272 }