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