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