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