2115799b9b6f0402ec3881e79385e25300961b4c
[mesa.git] / src / mesa / drivers / dri / r200 / r200_state.c
1 /**************************************************************************
2
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "api_arrayelt.h"
39 #include "enums.h"
40 #include "colormac.h"
41 #include "light.h"
42 #include "framebuffer.h"
43
44 #include "swrast/swrast.h"
45 #include "vbo/vbo.h"
46 #include "tnl/tnl.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
49
50 #include "r200_context.h"
51 #include "r200_ioctl.h"
52 #include "r200_state.h"
53 #include "r200_tcl.h"
54 #include "r200_tex.h"
55 #include "r200_swtcl.h"
56 #include "r200_vertprog.h"
57
58 #include "drirenderbuffer.h"
59
60
61 /* =============================================================
62 * Alpha blending
63 */
64
65 static void r200AlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
66 {
67 r200ContextPtr rmesa = R200_CONTEXT(ctx);
68 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
69 GLubyte refByte;
70
71 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
72
73 R200_STATECHANGE( rmesa, ctx );
74
75 pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK);
76 pp_misc |= (refByte & R200_REF_ALPHA_MASK);
77
78 switch ( func ) {
79 case GL_NEVER:
80 pp_misc |= R200_ALPHA_TEST_FAIL;
81 break;
82 case GL_LESS:
83 pp_misc |= R200_ALPHA_TEST_LESS;
84 break;
85 case GL_EQUAL:
86 pp_misc |= R200_ALPHA_TEST_EQUAL;
87 break;
88 case GL_LEQUAL:
89 pp_misc |= R200_ALPHA_TEST_LEQUAL;
90 break;
91 case GL_GREATER:
92 pp_misc |= R200_ALPHA_TEST_GREATER;
93 break;
94 case GL_NOTEQUAL:
95 pp_misc |= R200_ALPHA_TEST_NEQUAL;
96 break;
97 case GL_GEQUAL:
98 pp_misc |= R200_ALPHA_TEST_GEQUAL;
99 break;
100 case GL_ALWAYS:
101 pp_misc |= R200_ALPHA_TEST_PASS;
102 break;
103 }
104
105 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
106 }
107
108 static void r200BlendColor( GLcontext *ctx, const GLfloat cf[4] )
109 {
110 GLubyte color[4];
111 r200ContextPtr rmesa = R200_CONTEXT(ctx);
112 R200_STATECHANGE( rmesa, ctx );
113 CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]);
114 CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]);
115 CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]);
116 CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]);
117 if (rmesa->r200Screen->drmSupportsBlendColor)
118 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = r200PackColor( 4, color[0], color[1], color[2], color[3] );
119 }
120
121 /**
122 * Calculate the hardware blend factor setting. This same function is used
123 * for source and destination of both alpha and RGB.
124 *
125 * \returns
126 * The hardware register value for the specified blend factor. This value
127 * will need to be shifted into the correct position for either source or
128 * destination factor.
129 *
130 * \todo
131 * Since the two cases where source and destination are handled differently
132 * are essentially error cases, they should never happen. Determine if these
133 * cases can be removed.
134 */
135 static int blend_factor( GLenum factor, GLboolean is_src )
136 {
137 int func;
138
139 switch ( factor ) {
140 case GL_ZERO:
141 func = R200_BLEND_GL_ZERO;
142 break;
143 case GL_ONE:
144 func = R200_BLEND_GL_ONE;
145 break;
146 case GL_DST_COLOR:
147 func = R200_BLEND_GL_DST_COLOR;
148 break;
149 case GL_ONE_MINUS_DST_COLOR:
150 func = R200_BLEND_GL_ONE_MINUS_DST_COLOR;
151 break;
152 case GL_SRC_COLOR:
153 func = R200_BLEND_GL_SRC_COLOR;
154 break;
155 case GL_ONE_MINUS_SRC_COLOR:
156 func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR;
157 break;
158 case GL_SRC_ALPHA:
159 func = R200_BLEND_GL_SRC_ALPHA;
160 break;
161 case GL_ONE_MINUS_SRC_ALPHA:
162 func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA;
163 break;
164 case GL_DST_ALPHA:
165 func = R200_BLEND_GL_DST_ALPHA;
166 break;
167 case GL_ONE_MINUS_DST_ALPHA:
168 func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA;
169 break;
170 case GL_SRC_ALPHA_SATURATE:
171 func = (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : R200_BLEND_GL_ZERO;
172 break;
173 case GL_CONSTANT_COLOR:
174 func = R200_BLEND_GL_CONST_COLOR;
175 break;
176 case GL_ONE_MINUS_CONSTANT_COLOR:
177 func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR;
178 break;
179 case GL_CONSTANT_ALPHA:
180 func = R200_BLEND_GL_CONST_ALPHA;
181 break;
182 case GL_ONE_MINUS_CONSTANT_ALPHA:
183 func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA;
184 break;
185 default:
186 func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO;
187 }
188 return func;
189 }
190
191 /**
192 * Sets both the blend equation and the blend function.
193 * This is done in a single
194 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
195 * change the interpretation of the blend function.
196 * Also, make sure that blend function and blend equation are set to their default
197 * value if color blending is not enabled, since at least blend equations GL_MIN
198 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
199 * unknown reasons.
200 */
201 static void r200_set_blend_state( GLcontext * ctx )
202 {
203 r200ContextPtr rmesa = R200_CONTEXT(ctx);
204 GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &
205 ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE);
206
207 int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
208 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
209 int eqn = R200_COMB_FCN_ADD_CLAMP;
210 int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
211 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
212 int eqnA = R200_COMB_FCN_ADD_CLAMP;
213
214 R200_STATECHANGE( rmesa, ctx );
215
216 if (rmesa->r200Screen->drmSupportsBlendColor) {
217 if (ctx->Color.ColorLogicOpEnabled) {
218 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
219 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
220 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
221 return;
222 } else if (ctx->Color.BlendEnabled) {
223 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE;
224 }
225 else {
226 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
227 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
228 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
229 return;
230 }
231 }
232 else {
233 if (ctx->Color.ColorLogicOpEnabled) {
234 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
235 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
236 return;
237 } else if (ctx->Color.BlendEnabled) {
238 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE;
239 }
240 else {
241 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
242 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
243 return;
244 }
245 }
246
247 func = (blend_factor( ctx->Color.BlendSrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
248 (blend_factor( ctx->Color.BlendDstRGB, GL_FALSE ) << R200_DST_BLEND_SHIFT);
249
250 switch(ctx->Color.BlendEquationRGB) {
251 case GL_FUNC_ADD:
252 eqn = R200_COMB_FCN_ADD_CLAMP;
253 break;
254
255 case GL_FUNC_SUBTRACT:
256 eqn = R200_COMB_FCN_SUB_CLAMP;
257 break;
258
259 case GL_FUNC_REVERSE_SUBTRACT:
260 eqn = R200_COMB_FCN_RSUB_CLAMP;
261 break;
262
263 case GL_MIN:
264 eqn = R200_COMB_FCN_MIN;
265 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
266 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
267 break;
268
269 case GL_MAX:
270 eqn = R200_COMB_FCN_MAX;
271 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
272 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
273 break;
274
275 default:
276 fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
277 __FUNCTION__, __LINE__, ctx->Color.BlendEquationRGB );
278 return;
279 }
280
281 if (!rmesa->r200Screen->drmSupportsBlendColor) {
282 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
283 return;
284 }
285
286 funcA = (blend_factor( ctx->Color.BlendSrcA, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
287 (blend_factor( ctx->Color.BlendDstA, GL_FALSE ) << R200_DST_BLEND_SHIFT);
288
289 switch(ctx->Color.BlendEquationA) {
290 case GL_FUNC_ADD:
291 eqnA = R200_COMB_FCN_ADD_CLAMP;
292 break;
293
294 case GL_FUNC_SUBTRACT:
295 eqnA = R200_COMB_FCN_SUB_CLAMP;
296 break;
297
298 case GL_FUNC_REVERSE_SUBTRACT:
299 eqnA = R200_COMB_FCN_RSUB_CLAMP;
300 break;
301
302 case GL_MIN:
303 eqnA = R200_COMB_FCN_MIN;
304 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
305 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
306 break;
307
308 case GL_MAX:
309 eqnA = R200_COMB_FCN_MAX;
310 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
311 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
312 break;
313
314 default:
315 fprintf( stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n",
316 __FUNCTION__, __LINE__, ctx->Color.BlendEquationA );
317 return;
318 }
319
320 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqnA | funcA;
321 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
322
323 }
324
325 static void r200BlendEquationSeparate( GLcontext *ctx,
326 GLenum modeRGB, GLenum modeA )
327 {
328 r200_set_blend_state( ctx );
329 }
330
331 static void r200BlendFuncSeparate( GLcontext *ctx,
332 GLenum sfactorRGB, GLenum dfactorRGB,
333 GLenum sfactorA, GLenum dfactorA )
334 {
335 r200_set_blend_state( ctx );
336 }
337
338
339 /* =============================================================
340 * Depth testing
341 */
342
343 static void r200DepthFunc( GLcontext *ctx, GLenum func )
344 {
345 r200ContextPtr rmesa = R200_CONTEXT(ctx);
346
347 R200_STATECHANGE( rmesa, ctx );
348 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK;
349
350 switch ( ctx->Depth.Func ) {
351 case GL_NEVER:
352 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER;
353 break;
354 case GL_LESS:
355 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS;
356 break;
357 case GL_EQUAL:
358 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL;
359 break;
360 case GL_LEQUAL:
361 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL;
362 break;
363 case GL_GREATER:
364 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER;
365 break;
366 case GL_NOTEQUAL:
367 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL;
368 break;
369 case GL_GEQUAL:
370 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL;
371 break;
372 case GL_ALWAYS:
373 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS;
374 break;
375 }
376 }
377
378 static void r200ClearDepth( GLcontext *ctx, GLclampd d )
379 {
380 r200ContextPtr rmesa = R200_CONTEXT(ctx);
381 GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
382 R200_DEPTH_FORMAT_MASK);
383
384 switch ( format ) {
385 case R200_DEPTH_FORMAT_16BIT_INT_Z:
386 rmesa->state.depth.clear = d * 0x0000ffff;
387 break;
388 case R200_DEPTH_FORMAT_24BIT_INT_Z:
389 rmesa->state.depth.clear = d * 0x00ffffff;
390 break;
391 }
392 }
393
394 static void r200DepthMask( GLcontext *ctx, GLboolean flag )
395 {
396 r200ContextPtr rmesa = R200_CONTEXT(ctx);
397 R200_STATECHANGE( rmesa, ctx );
398
399 if ( ctx->Depth.Mask ) {
400 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE;
401 } else {
402 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE;
403 }
404 }
405
406
407 /* =============================================================
408 * Fog
409 */
410
411
412 static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
413 {
414 r200ContextPtr rmesa = R200_CONTEXT(ctx);
415 union { int i; float f; } c, d;
416 GLchan col[4];
417 GLuint i;
418
419 c.i = rmesa->hw.fog.cmd[FOG_C];
420 d.i = rmesa->hw.fog.cmd[FOG_D];
421
422 switch (pname) {
423 case GL_FOG_MODE:
424 if (!ctx->Fog.Enabled)
425 return;
426 R200_STATECHANGE(rmesa, tcl);
427 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
428 switch (ctx->Fog.Mode) {
429 case GL_LINEAR:
430 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR;
431 if (ctx->Fog.Start == ctx->Fog.End) {
432 c.f = 1.0F;
433 d.f = 1.0F;
434 }
435 else {
436 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
437 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
438 }
439 break;
440 case GL_EXP:
441 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP;
442 c.f = 0.0;
443 d.f = -ctx->Fog.Density;
444 break;
445 case GL_EXP2:
446 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2;
447 c.f = 0.0;
448 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
449 break;
450 default:
451 return;
452 }
453 break;
454 case GL_FOG_DENSITY:
455 switch (ctx->Fog.Mode) {
456 case GL_EXP:
457 c.f = 0.0;
458 d.f = -ctx->Fog.Density;
459 break;
460 case GL_EXP2:
461 c.f = 0.0;
462 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
463 break;
464 default:
465 break;
466 }
467 break;
468 case GL_FOG_START:
469 case GL_FOG_END:
470 if (ctx->Fog.Mode == GL_LINEAR) {
471 if (ctx->Fog.Start == ctx->Fog.End) {
472 c.f = 1.0F;
473 d.f = 1.0F;
474 } else {
475 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
476 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
477 }
478 }
479 break;
480 case GL_FOG_COLOR:
481 R200_STATECHANGE( rmesa, ctx );
482 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
483 i = r200PackColor( 4, col[0], col[1], col[2], 0 );
484 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK;
485 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
486 break;
487 case GL_FOG_COORD_SRC: {
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 || ctx->VertexProgram.Enabled) {
493 fog |= R200_FOG_USE_VTX_FOG;
494 out_0 |= R200_VTX_DISCRETE_FOG;
495 }
496 else {
497 fog |= R200_FOG_USE_SPEC_ALPHA;
498 out_0 &= ~R200_VTX_DISCRETE_FOG;
499 }
500
501 if ( fog != rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] ) {
502 R200_STATECHANGE( rmesa, ctx );
503 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog;
504 }
505
506 if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) {
507 R200_STATECHANGE( rmesa, vtx );
508 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0;
509 }
510
511 break;
512 }
513 default:
514 return;
515 }
516
517 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
518 R200_STATECHANGE( rmesa, fog );
519 rmesa->hw.fog.cmd[FOG_C] = c.i;
520 rmesa->hw.fog.cmd[FOG_D] = d.i;
521 }
522 }
523
524
525 /* =============================================================
526 * Scissoring
527 */
528
529
530 static GLboolean intersect_rect( drm_clip_rect_t *out,
531 drm_clip_rect_t *a,
532 drm_clip_rect_t *b )
533 {
534 *out = *a;
535 if ( b->x1 > out->x1 ) out->x1 = b->x1;
536 if ( b->y1 > out->y1 ) out->y1 = b->y1;
537 if ( b->x2 < out->x2 ) out->x2 = b->x2;
538 if ( b->y2 < out->y2 ) out->y2 = b->y2;
539 if ( out->x1 >= out->x2 ) return GL_FALSE;
540 if ( out->y1 >= out->y2 ) return GL_FALSE;
541 return GL_TRUE;
542 }
543
544
545 void r200RecalcScissorRects( r200ContextPtr rmesa )
546 {
547 drm_clip_rect_t *out;
548 int i;
549
550 /* Grow cliprect store?
551 */
552 if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
553 while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
554 rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
555 rmesa->state.scissor.numAllocedClipRects *= 2;
556 }
557
558 if (rmesa->state.scissor.pClipRects)
559 FREE(rmesa->state.scissor.pClipRects);
560
561 rmesa->state.scissor.pClipRects =
562 MALLOC( rmesa->state.scissor.numAllocedClipRects *
563 sizeof(drm_clip_rect_t) );
564
565 if ( rmesa->state.scissor.pClipRects == NULL ) {
566 rmesa->state.scissor.numAllocedClipRects = 0;
567 return;
568 }
569 }
570
571 out = rmesa->state.scissor.pClipRects;
572 rmesa->state.scissor.numClipRects = 0;
573
574 for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
575 if ( intersect_rect( out,
576 &rmesa->pClipRects[i],
577 &rmesa->state.scissor.rect ) ) {
578 rmesa->state.scissor.numClipRects++;
579 out++;
580 }
581 }
582 }
583
584
585 static void r200UpdateScissor( GLcontext *ctx )
586 {
587 r200ContextPtr rmesa = R200_CONTEXT(ctx);
588
589 if ( rmesa->dri.drawable ) {
590 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
591
592 int x = ctx->Scissor.X;
593 int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
594 int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
595 int h = dPriv->h - ctx->Scissor.Y - 1;
596
597 rmesa->state.scissor.rect.x1 = x + dPriv->x;
598 rmesa->state.scissor.rect.y1 = y + dPriv->y;
599 rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
600 rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
601
602 r200RecalcScissorRects( rmesa );
603 }
604 }
605
606
607 static void r200Scissor( GLcontext *ctx,
608 GLint x, GLint y, GLsizei w, GLsizei h )
609 {
610 r200ContextPtr rmesa = R200_CONTEXT(ctx);
611
612 if ( ctx->Scissor.Enabled ) {
613 R200_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
614 r200UpdateScissor( ctx );
615 }
616
617 }
618
619
620 /* =============================================================
621 * Culling
622 */
623
624 static void r200CullFace( GLcontext *ctx, GLenum unused )
625 {
626 r200ContextPtr rmesa = R200_CONTEXT(ctx);
627 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
628 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
629
630 s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
631 t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
632
633 if ( ctx->Polygon.CullFlag ) {
634 switch ( ctx->Polygon.CullFaceMode ) {
635 case GL_FRONT:
636 s &= ~R200_FFACE_SOLID;
637 t |= R200_CULL_FRONT;
638 break;
639 case GL_BACK:
640 s &= ~R200_BFACE_SOLID;
641 t |= R200_CULL_BACK;
642 break;
643 case GL_FRONT_AND_BACK:
644 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
645 t |= (R200_CULL_FRONT | R200_CULL_BACK);
646 break;
647 }
648 }
649
650 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
651 R200_STATECHANGE(rmesa, set );
652 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
653 }
654
655 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
656 R200_STATECHANGE(rmesa, tcl );
657 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
658 }
659 }
660
661 static void r200FrontFace( GLcontext *ctx, GLenum mode )
662 {
663 r200ContextPtr rmesa = R200_CONTEXT(ctx);
664
665 R200_STATECHANGE( rmesa, set );
666 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
667
668 R200_STATECHANGE( rmesa, tcl );
669 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
670
671 switch ( mode ) {
672 case GL_CW:
673 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW;
674 break;
675 case GL_CCW:
676 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CCW;
677 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW;
678 break;
679 }
680 }
681
682 /* =============================================================
683 * Point state
684 */
685 static void r200PointSize( GLcontext *ctx, GLfloat size )
686 {
687 r200ContextPtr rmesa = R200_CONTEXT(ctx);
688 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
689
690 R200_STATECHANGE( rmesa, cst );
691 R200_STATECHANGE( rmesa, ptp );
692 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff;
693 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0));
694 /* this is the size param of the point size calculation (point size reg value
695 is not used when calculation is active). */
696 fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size;
697 }
698
699 static void r200PointParameter( GLcontext *ctx, GLenum pname, const GLfloat *params)
700 {
701 r200ContextPtr rmesa = R200_CONTEXT(ctx);
702 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
703
704 switch (pname) {
705 case GL_POINT_SIZE_MIN:
706 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
707 R200_STATECHANGE( rmesa, lin );
708 R200_STATECHANGE( rmesa, ptp );
709 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff;
710 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16;
711 fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize;
712 break;
713 case GL_POINT_SIZE_MAX:
714 R200_STATECHANGE( rmesa, cst );
715 R200_STATECHANGE( rmesa, ptp );
716 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff;
717 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16;
718 fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize;
719 break;
720 case GL_POINT_DISTANCE_ATTENUATION:
721 R200_STATECHANGE( rmesa, vtx );
722 R200_STATECHANGE( rmesa, spr );
723 R200_STATECHANGE( rmesa, ptp );
724 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
725 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &=
726 ~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE);
727 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
728 r200ValidateState looks like overkill */
729 if (ctx->Point.Params[0] != 1.0 ||
730 ctx->Point.Params[1] != 0.0 ||
731 ctx->Point.Params[2] != 0.0 ||
732 (ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) {
733 /* all we care for vp would be the ps_se_sel_state setting */
734 fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2];
735 fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1];
736 fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0];
737 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST;
738 if (ctx->Point.Params[1] == 0.0)
739 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO;
740 /* FIXME: setting this here doesn't look quite ok - we only want to do
741 that if we're actually drawing points probably */
742 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE;
743 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE;
744 }
745 else {
746 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
747 R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST;
748 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE;
749 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE;
750 }
751 break;
752 case GL_POINT_FADE_THRESHOLD_SIZE:
753 /* don't support multisampling, so doesn't matter. */
754 break;
755 /* can't do these but don't need them.
756 case GL_POINT_SPRITE_R_MODE_NV:
757 case GL_POINT_SPRITE_COORD_ORIGIN: */
758 default:
759 fprintf(stderr, "bad pname parameter in r200PointParameter\n");
760 return;
761 }
762 }
763
764 /* =============================================================
765 * Line state
766 */
767 static void r200LineWidth( GLcontext *ctx, GLfloat widthf )
768 {
769 r200ContextPtr rmesa = R200_CONTEXT(ctx);
770
771 R200_STATECHANGE( rmesa, lin );
772 R200_STATECHANGE( rmesa, set );
773
774 /* Line width is stored in U6.4 format.
775 */
776 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
777 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Line._Width * 16.0);
778
779 if ( widthf > 1.0 ) {
780 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE;
781 } else {
782 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
783 }
784 }
785
786 static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
787 {
788 r200ContextPtr rmesa = R200_CONTEXT(ctx);
789
790 R200_STATECHANGE( rmesa, lin );
791 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
792 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
793 }
794
795
796 /* =============================================================
797 * Masks
798 */
799 static void r200ColorMask( GLcontext *ctx,
800 GLboolean r, GLboolean g,
801 GLboolean b, GLboolean a )
802 {
803 r200ContextPtr rmesa = R200_CONTEXT(ctx);
804 GLuint mask = r200PackColor( rmesa->r200Screen->cpp,
805 ctx->Color.ColorMask[RCOMP],
806 ctx->Color.ColorMask[GCOMP],
807 ctx->Color.ColorMask[BCOMP],
808 ctx->Color.ColorMask[ACOMP] );
809
810 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
811
812 if (!(r && g && b && a))
813 flag |= R200_PLANE_MASK_ENABLE;
814
815 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
816 R200_STATECHANGE( rmesa, ctx );
817 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
818 }
819
820 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
821 R200_STATECHANGE( rmesa, msk );
822 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
823 }
824 }
825
826
827 /* =============================================================
828 * Polygon state
829 */
830
831 static void r200PolygonOffset( GLcontext *ctx,
832 GLfloat factor, GLfloat units )
833 {
834 r200ContextPtr rmesa = R200_CONTEXT(ctx);
835 float_ui32_type constant = { units * rmesa->state.depth.scale };
836 float_ui32_type factoru = { factor };
837
838 /* factor *= 2; */
839 /* constant *= 2; */
840
841 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
842
843 R200_STATECHANGE( rmesa, zbs );
844 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32;
845 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
846 }
847
848 static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
849 {
850 r200ContextPtr rmesa = R200_CONTEXT(ctx);
851 GLuint i;
852 drm_radeon_stipple_t stipple;
853
854 /* Must flip pattern upside down.
855 */
856 for ( i = 0 ; i < 32 ; i++ ) {
857 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
858 }
859
860 /* TODO: push this into cmd mechanism
861 */
862 R200_FIREVERTICES( rmesa );
863 LOCK_HARDWARE( rmesa );
864
865 /* FIXME: Use window x,y offsets into stipple RAM.
866 */
867 stipple.mask = rmesa->state.stipple.mask;
868 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
869 &stipple, sizeof(stipple) );
870 UNLOCK_HARDWARE( rmesa );
871 }
872
873 static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
874 {
875 r200ContextPtr rmesa = R200_CONTEXT(ctx);
876 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
877
878 /* Can't generally do unfilled via tcl, but some good special
879 * cases work.
880 */
881 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
882 if (rmesa->TclFallback) {
883 r200ChooseRenderState( ctx );
884 r200ChooseVertexState( ctx );
885 }
886 }
887
888
889 /* =============================================================
890 * Rendering attributes
891 *
892 * We really don't want to recalculate all this every time we bind a
893 * texture. These things shouldn't change all that often, so it makes
894 * sense to break them out of the core texture state update routines.
895 */
896
897 /* Examine lighting and texture state to determine if separate specular
898 * should be enabled.
899 */
900 static void r200UpdateSpecular( GLcontext *ctx )
901 {
902 r200ContextPtr rmesa = R200_CONTEXT(ctx);
903 u_int32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
904
905 R200_STATECHANGE( rmesa, tcl );
906 R200_STATECHANGE( rmesa, vtx );
907
908 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
909 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
910 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
911 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
912 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
913
914 p &= ~R200_SPECULAR_ENABLE;
915
916 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
917
918
919 if (ctx->Light.Enabled &&
920 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
921 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
922 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
923 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
924 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
925 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
926 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
927 p |= R200_SPECULAR_ENABLE;
928 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
929 ~R200_DIFFUSE_SPECULAR_COMBINE;
930 }
931 else if (ctx->Light.Enabled) {
932 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
933 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
934 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
935 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
936 } else if (ctx->Fog.ColorSumEnabled ) {
937 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
938 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
939 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
940 p |= R200_SPECULAR_ENABLE;
941 } else {
942 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
943 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
944 }
945
946 if (ctx->Fog.Enabled) {
947 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
948 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
949 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
950 }
951
952 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
953 R200_STATECHANGE( rmesa, ctx );
954 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
955 }
956
957 /* Update vertex/render formats
958 */
959 if (rmesa->TclFallback) {
960 r200ChooseRenderState( ctx );
961 r200ChooseVertexState( ctx );
962 }
963 }
964
965
966 /* =============================================================
967 * Materials
968 */
969
970
971 /* Update on colormaterial, material emmissive/ambient,
972 * lightmodel.globalambient
973 */
974 static void update_global_ambient( GLcontext *ctx )
975 {
976 r200ContextPtr rmesa = R200_CONTEXT(ctx);
977 float *fcmd = (float *)R200_DB_STATE( glt );
978
979 /* Need to do more if both emmissive & ambient are PREMULT:
980 * I believe this is not nessary when using source_material. This condition thus
981 * will never happen currently, and the function has no dependencies on materials now
982 */
983 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
984 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
985 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
986 {
987 COPY_3V( &fcmd[GLT_RED],
988 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
989 ACC_SCALE_3V( &fcmd[GLT_RED],
990 ctx->Light.Model.Ambient,
991 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
992 }
993 else
994 {
995 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
996 }
997
998 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
999 }
1000
1001 /* Update on change to
1002 * - light[p].colors
1003 * - light[p].enabled
1004 */
1005 static void update_light_colors( GLcontext *ctx, GLuint p )
1006 {
1007 struct gl_light *l = &ctx->Light.Light[p];
1008
1009 /* fprintf(stderr, "%s\n", __FUNCTION__); */
1010
1011 if (l->Enabled) {
1012 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1013 float *fcmd = (float *)R200_DB_STATE( lit[p] );
1014
1015 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
1016 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
1017 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
1018
1019 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1020 }
1021 }
1022
1023 static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
1024 {
1025 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1026 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
1027 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
1028 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
1029 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
1030 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
1031 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
1032 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) |
1033 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
1034 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT));
1035
1036 if (ctx->Light.ColorMaterialEnabled) {
1037 GLuint mask = ctx->Light.ColorMaterialBitmask;
1038
1039 if (mask & MAT_BIT_FRONT_EMISSION) {
1040 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1041 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
1042 }
1043 else
1044 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
1045 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
1046
1047 if (mask & MAT_BIT_FRONT_AMBIENT) {
1048 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1049 R200_FRONT_AMBIENT_SOURCE_SHIFT);
1050 }
1051 else
1052 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
1053 R200_FRONT_AMBIENT_SOURCE_SHIFT);
1054
1055 if (mask & MAT_BIT_FRONT_DIFFUSE) {
1056 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1057 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
1058 }
1059 else
1060 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
1061 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
1062
1063 if (mask & MAT_BIT_FRONT_SPECULAR) {
1064 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1065 R200_FRONT_SPECULAR_SOURCE_SHIFT);
1066 }
1067 else {
1068 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
1069 R200_FRONT_SPECULAR_SOURCE_SHIFT);
1070 }
1071
1072 if (mask & MAT_BIT_BACK_EMISSION) {
1073 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1074 R200_BACK_EMISSIVE_SOURCE_SHIFT);
1075 }
1076
1077 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1078 R200_BACK_EMISSIVE_SOURCE_SHIFT);
1079
1080 if (mask & MAT_BIT_BACK_AMBIENT) {
1081 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1082 R200_BACK_AMBIENT_SOURCE_SHIFT);
1083 }
1084 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1085 R200_BACK_AMBIENT_SOURCE_SHIFT);
1086
1087 if (mask & MAT_BIT_BACK_DIFFUSE) {
1088 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1089 R200_BACK_DIFFUSE_SOURCE_SHIFT);
1090 }
1091 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1092 R200_BACK_DIFFUSE_SOURCE_SHIFT);
1093
1094 if (mask & MAT_BIT_BACK_SPECULAR) {
1095 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1096 R200_BACK_SPECULAR_SOURCE_SHIFT);
1097 }
1098 else {
1099 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1100 R200_BACK_SPECULAR_SOURCE_SHIFT);
1101 }
1102 }
1103 else {
1104 /* Default to SOURCE_MATERIAL:
1105 */
1106 light_model_ctl1 |=
1107 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
1108 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
1109 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
1110 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
1111 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
1112 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) |
1113 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
1114 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT);
1115 }
1116
1117 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
1118 R200_STATECHANGE( rmesa, tcl );
1119 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
1120 }
1121
1122
1123 }
1124
1125 void r200UpdateMaterial( GLcontext *ctx )
1126 {
1127 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1128 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
1129 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
1130 GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] );
1131 GLuint mask = ~0;
1132
1133 /* Might be possible and faster to update everything unconditionally? */
1134 if (ctx->Light.ColorMaterialEnabled)
1135 mask &= ~ctx->Light.ColorMaterialBitmask;
1136
1137 if (R200_DEBUG & DEBUG_STATE)
1138 fprintf(stderr, "%s\n", __FUNCTION__);
1139
1140 if (mask & MAT_BIT_FRONT_EMISSION) {
1141 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
1142 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
1143 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
1144 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
1145 }
1146 if (mask & MAT_BIT_FRONT_AMBIENT) {
1147 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
1148 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
1149 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
1150 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
1151 }
1152 if (mask & MAT_BIT_FRONT_DIFFUSE) {
1153 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
1154 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
1155 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
1156 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
1157 }
1158 if (mask & MAT_BIT_FRONT_SPECULAR) {
1159 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
1160 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
1161 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
1162 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
1163 }
1164 if (mask & MAT_BIT_FRONT_SHININESS) {
1165 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
1166 }
1167
1168 if (mask & MAT_BIT_BACK_EMISSION) {
1169 fcmd2[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_BACK_EMISSION][0];
1170 fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1];
1171 fcmd2[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_BACK_EMISSION][2];
1172 fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3];
1173 }
1174 if (mask & MAT_BIT_BACK_AMBIENT) {
1175 fcmd2[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_BACK_AMBIENT][0];
1176 fcmd2[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_BACK_AMBIENT][1];
1177 fcmd2[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_BACK_AMBIENT][2];
1178 fcmd2[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_BACK_AMBIENT][3];
1179 }
1180 if (mask & MAT_BIT_BACK_DIFFUSE) {
1181 fcmd2[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_BACK_DIFFUSE][0];
1182 fcmd2[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_BACK_DIFFUSE][1];
1183 fcmd2[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_BACK_DIFFUSE][2];
1184 fcmd2[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_BACK_DIFFUSE][3];
1185 }
1186 if (mask & MAT_BIT_BACK_SPECULAR) {
1187 fcmd2[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_BACK_SPECULAR][0];
1188 fcmd2[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_BACK_SPECULAR][1];
1189 fcmd2[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_BACK_SPECULAR][2];
1190 fcmd2[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_BACK_SPECULAR][3];
1191 }
1192 if (mask & MAT_BIT_BACK_SHININESS) {
1193 fcmd2[MTL_SHININESS] = mat[MAT_ATTRIB_BACK_SHININESS][0];
1194 }
1195
1196 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] );
1197 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] );
1198
1199 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1200 update_global_ambient( ctx ); */
1201 }
1202
1203 /* _NEW_LIGHT
1204 * _NEW_MODELVIEW
1205 * _MESA_NEW_NEED_EYE_COORDS
1206 *
1207 * Uses derived state from mesa:
1208 * _VP_inf_norm
1209 * _h_inf_norm
1210 * _Position
1211 * _NormDirection
1212 * _ModelViewInvScale
1213 * _NeedEyeCoords
1214 * _EyeZDir
1215 *
1216 * which are calculated in light.c and are correct for the current
1217 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1218 * and _MESA_NEW_NEED_EYE_COORDS.
1219 */
1220 static void update_light( GLcontext *ctx )
1221 {
1222 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1223
1224 /* Have to check these, or have an automatic shortcircuit mechanism
1225 * to remove noop statechanges. (Or just do a better job on the
1226 * front end).
1227 */
1228 {
1229 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
1230
1231 if (ctx->_NeedEyeCoords)
1232 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1233 else
1234 tmp |= R200_LIGHT_IN_MODELSPACE;
1235
1236 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1237 {
1238 R200_STATECHANGE( rmesa, tcl );
1239 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1240 }
1241 }
1242
1243 {
1244 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1245 fcmd[EYE_X] = ctx->_EyeZDir[0];
1246 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1247 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1248 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1249 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1250 }
1251
1252
1253
1254 if (ctx->Light.Enabled) {
1255 GLint p;
1256 for (p = 0 ; p < MAX_LIGHTS; p++) {
1257 if (ctx->Light.Light[p].Enabled) {
1258 struct gl_light *l = &ctx->Light.Light[p];
1259 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1260
1261 if (l->EyePosition[3] == 0.0) {
1262 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1263 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1264 fcmd[LIT_POSITION_W] = 0;
1265 fcmd[LIT_DIRECTION_W] = 0;
1266 } else {
1267 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1268 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1269 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1270 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1271 fcmd[LIT_DIRECTION_W] = 0;
1272 }
1273
1274 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1275 }
1276 }
1277 }
1278 }
1279
1280 static void r200Lightfv( GLcontext *ctx, GLenum light,
1281 GLenum pname, const GLfloat *params )
1282 {
1283 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1284 GLint p = light - GL_LIGHT0;
1285 struct gl_light *l = &ctx->Light.Light[p];
1286 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1287
1288
1289 switch (pname) {
1290 case GL_AMBIENT:
1291 case GL_DIFFUSE:
1292 case GL_SPECULAR:
1293 update_light_colors( ctx, p );
1294 break;
1295
1296 case GL_SPOT_DIRECTION:
1297 /* picked up in update_light */
1298 break;
1299
1300 case GL_POSITION: {
1301 /* positions picked up in update_light, but can do flag here */
1302 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1303 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1304
1305 R200_STATECHANGE(rmesa, tcl);
1306 if (l->EyePosition[3] != 0.0F)
1307 rmesa->hw.tcl.cmd[idx] |= flag;
1308 else
1309 rmesa->hw.tcl.cmd[idx] &= ~flag;
1310 break;
1311 }
1312
1313 case GL_SPOT_EXPONENT:
1314 R200_STATECHANGE(rmesa, lit[p]);
1315 fcmd[LIT_SPOT_EXPONENT] = params[0];
1316 break;
1317
1318 case GL_SPOT_CUTOFF: {
1319 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1320 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1321
1322 R200_STATECHANGE(rmesa, lit[p]);
1323 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1324
1325 R200_STATECHANGE(rmesa, tcl);
1326 if (l->SpotCutoff != 180.0F)
1327 rmesa->hw.tcl.cmd[idx] |= flag;
1328 else
1329 rmesa->hw.tcl.cmd[idx] &= ~flag;
1330
1331 break;
1332 }
1333
1334 case GL_CONSTANT_ATTENUATION:
1335 R200_STATECHANGE(rmesa, lit[p]);
1336 fcmd[LIT_ATTEN_CONST] = params[0];
1337 if ( params[0] == 0.0 )
1338 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1339 else
1340 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1341 break;
1342 case GL_LINEAR_ATTENUATION:
1343 R200_STATECHANGE(rmesa, lit[p]);
1344 fcmd[LIT_ATTEN_LINEAR] = params[0];
1345 break;
1346 case GL_QUADRATIC_ATTENUATION:
1347 R200_STATECHANGE(rmesa, lit[p]);
1348 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1349 break;
1350 default:
1351 return;
1352 }
1353
1354 /* Set RANGE_ATTEN only when needed */
1355 switch (pname) {
1356 case GL_POSITION:
1357 case GL_CONSTANT_ATTENUATION:
1358 case GL_LINEAR_ATTENUATION:
1359 case GL_QUADRATIC_ATTENUATION: {
1360 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1361 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1362 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1363 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1364 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1365 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1366
1367 if ( l->EyePosition[3] == 0.0F ||
1368 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1369 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1370 /* Disable attenuation */
1371 icmd[idx] &= ~atten_flag;
1372 } else {
1373 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1374 /* Enable only constant portion of attenuation calculation */
1375 icmd[idx] |= ( atten_flag | atten_const_flag );
1376 } else {
1377 /* Enable full attenuation calculation */
1378 icmd[idx] &= ~atten_const_flag;
1379 icmd[idx] |= atten_flag;
1380 }
1381 }
1382
1383 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1384 break;
1385 }
1386 default:
1387 break;
1388 }
1389 }
1390
1391 static void r200UpdateLocalViewer ( GLcontext *ctx )
1392 {
1393 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1394 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1395 for these and only these modes). This means specular highlights may turn out
1396 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1397 is not set, though it seems to happen rarely and the effect seems quite
1398 subtle. May need TCL fallback to fix it completely, though I'm not sure
1399 how you'd identify the cases where the specular highlights indeed will
1400 be wrong. Don't know if fglrx does something special in that case.
1401 */
1402 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1403 R200_STATECHANGE( rmesa, tcl );
1404 if (ctx->Light.Model.LocalViewer ||
1405 ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
1406 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1407 else
1408 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1409 }
1410
1411 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1412 const GLfloat *param )
1413 {
1414 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1415
1416 switch (pname) {
1417 case GL_LIGHT_MODEL_AMBIENT:
1418 update_global_ambient( ctx );
1419 break;
1420
1421 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1422 r200UpdateLocalViewer( ctx );
1423 break;
1424
1425 case GL_LIGHT_MODEL_TWO_SIDE:
1426 R200_STATECHANGE( rmesa, tcl );
1427 if (ctx->Light.Model.TwoSide)
1428 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1429 else
1430 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1431 if (rmesa->TclFallback) {
1432 r200ChooseRenderState( ctx );
1433 r200ChooseVertexState( ctx );
1434 }
1435 break;
1436
1437 case GL_LIGHT_MODEL_COLOR_CONTROL:
1438 r200UpdateSpecular(ctx);
1439 break;
1440
1441 default:
1442 break;
1443 }
1444 }
1445
1446 static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1447 {
1448 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1449 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1450
1451 s &= ~(R200_DIFFUSE_SHADE_MASK |
1452 R200_ALPHA_SHADE_MASK |
1453 R200_SPECULAR_SHADE_MASK |
1454 R200_FOG_SHADE_MASK |
1455 R200_DISC_FOG_SHADE_MASK);
1456
1457 switch ( mode ) {
1458 case GL_FLAT:
1459 s |= (R200_DIFFUSE_SHADE_FLAT |
1460 R200_ALPHA_SHADE_FLAT |
1461 R200_SPECULAR_SHADE_FLAT |
1462 R200_FOG_SHADE_FLAT |
1463 R200_DISC_FOG_SHADE_FLAT);
1464 break;
1465 case GL_SMOOTH:
1466 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1467 R200_ALPHA_SHADE_GOURAUD |
1468 R200_SPECULAR_SHADE_GOURAUD |
1469 R200_FOG_SHADE_GOURAUD |
1470 R200_DISC_FOG_SHADE_GOURAUD);
1471 break;
1472 default:
1473 return;
1474 }
1475
1476 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1477 R200_STATECHANGE( rmesa, set );
1478 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1479 }
1480 }
1481
1482
1483 /* =============================================================
1484 * User clip planes
1485 */
1486
1487 static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1488 {
1489 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1490 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1491 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1492
1493 R200_STATECHANGE( rmesa, ucp[p] );
1494 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1495 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1496 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1497 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1498 }
1499
1500 static void r200UpdateClipPlanes( GLcontext *ctx )
1501 {
1502 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1503 GLuint p;
1504
1505 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1506 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1507 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1508
1509 R200_STATECHANGE( rmesa, ucp[p] );
1510 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1511 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1512 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1513 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1514 }
1515 }
1516 }
1517
1518
1519 /* =============================================================
1520 * Stencil
1521 */
1522
1523 static void
1524 r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
1525 GLint ref, GLuint mask )
1526 {
1527 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1528 GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R200_STENCIL_REF_SHIFT) |
1529 ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT));
1530
1531 R200_STATECHANGE( rmesa, ctx );
1532 R200_STATECHANGE( rmesa, msk );
1533
1534 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1535 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1536 R200_STENCIL_VALUE_MASK);
1537
1538 switch ( ctx->Stencil.Function[0] ) {
1539 case GL_NEVER:
1540 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1541 break;
1542 case GL_LESS:
1543 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1544 break;
1545 case GL_EQUAL:
1546 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1547 break;
1548 case GL_LEQUAL:
1549 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1550 break;
1551 case GL_GREATER:
1552 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1553 break;
1554 case GL_NOTEQUAL:
1555 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1556 break;
1557 case GL_GEQUAL:
1558 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1559 break;
1560 case GL_ALWAYS:
1561 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1562 break;
1563 }
1564
1565 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1566 }
1567
1568 static void
1569 r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
1570 {
1571 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1572
1573 R200_STATECHANGE( rmesa, msk );
1574 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1575 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1576 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT);
1577 }
1578
1579 static void
1580 r200StencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
1581 GLenum zfail, GLenum zpass )
1582 {
1583 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1584
1585 R200_STATECHANGE( rmesa, ctx );
1586 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1587 R200_STENCIL_ZFAIL_MASK |
1588 R200_STENCIL_ZPASS_MASK);
1589
1590 switch ( ctx->Stencil.FailFunc[0] ) {
1591 case GL_KEEP:
1592 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1593 break;
1594 case GL_ZERO:
1595 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1596 break;
1597 case GL_REPLACE:
1598 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1599 break;
1600 case GL_INCR:
1601 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1602 break;
1603 case GL_DECR:
1604 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1605 break;
1606 case GL_INCR_WRAP_EXT:
1607 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1608 break;
1609 case GL_DECR_WRAP_EXT:
1610 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1611 break;
1612 case GL_INVERT:
1613 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1614 break;
1615 }
1616
1617 switch ( ctx->Stencil.ZFailFunc[0] ) {
1618 case GL_KEEP:
1619 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1620 break;
1621 case GL_ZERO:
1622 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1623 break;
1624 case GL_REPLACE:
1625 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1626 break;
1627 case GL_INCR:
1628 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1629 break;
1630 case GL_DECR:
1631 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1632 break;
1633 case GL_INCR_WRAP_EXT:
1634 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1635 break;
1636 case GL_DECR_WRAP_EXT:
1637 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1638 break;
1639 case GL_INVERT:
1640 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1641 break;
1642 }
1643
1644 switch ( ctx->Stencil.ZPassFunc[0] ) {
1645 case GL_KEEP:
1646 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1647 break;
1648 case GL_ZERO:
1649 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1650 break;
1651 case GL_REPLACE:
1652 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1653 break;
1654 case GL_INCR:
1655 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1656 break;
1657 case GL_DECR:
1658 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1659 break;
1660 case GL_INCR_WRAP_EXT:
1661 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1662 break;
1663 case GL_DECR_WRAP_EXT:
1664 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1665 break;
1666 case GL_INVERT:
1667 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1668 break;
1669 }
1670 }
1671
1672 static void r200ClearStencil( GLcontext *ctx, GLint s )
1673 {
1674 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1675
1676 rmesa->state.stencil.clear =
1677 ((GLuint) (ctx->Stencil.Clear & 0xff) |
1678 (0xff << R200_STENCIL_MASK_SHIFT) |
1679 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT));
1680 }
1681
1682
1683 /* =============================================================
1684 * Window position and viewport transformation
1685 */
1686
1687 /*
1688 * To correctly position primitives:
1689 */
1690 #define SUBPIXEL_X 0.125
1691 #define SUBPIXEL_Y 0.125
1692
1693
1694 /**
1695 * Called when window size or position changes or viewport or depth range
1696 * state is changed. We update the hardware viewport state here.
1697 */
1698 void r200UpdateWindow( GLcontext *ctx )
1699 {
1700 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1701 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1702 GLfloat xoffset = (GLfloat)dPriv->x;
1703 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1704 const GLfloat *v = ctx->Viewport._WindowMap.m;
1705
1706 float_ui32_type sx = { v[MAT_SX] };
1707 float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
1708 float_ui32_type sy = { - v[MAT_SY] };
1709 float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
1710 float_ui32_type sz = { v[MAT_SZ] * rmesa->state.depth.scale };
1711 float_ui32_type tz = { v[MAT_TZ] * rmesa->state.depth.scale };
1712
1713 R200_FIREVERTICES( rmesa );
1714 R200_STATECHANGE( rmesa, vpt );
1715
1716 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32;
1717 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1718 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32;
1719 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1720 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32;
1721 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1722 }
1723
1724
1725
1726 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1727 GLsizei width, GLsizei height )
1728 {
1729 /* Don't pipeline viewport changes, conflict with window offset
1730 * setting below. Could apply deltas to rescue pipelined viewport
1731 * values, or keep the originals hanging around.
1732 */
1733 r200UpdateWindow( ctx );
1734 }
1735
1736 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1737 GLclampd farval )
1738 {
1739 r200UpdateWindow( ctx );
1740 }
1741
1742 void r200UpdateViewportOffset( GLcontext *ctx )
1743 {
1744 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1745 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1746 GLfloat xoffset = (GLfloat)dPriv->x;
1747 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1748 const GLfloat *v = ctx->Viewport._WindowMap.m;
1749
1750 float_ui32_type tx;
1751 float_ui32_type ty;
1752
1753 tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X;
1754 ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1755
1756 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
1757 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
1758 {
1759 /* Note: this should also modify whatever data the context reset
1760 * code uses...
1761 */
1762 R200_STATECHANGE( rmesa, vpt );
1763 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1764 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1765
1766 /* update polygon stipple x/y screen offset */
1767 {
1768 GLuint stx, sty;
1769 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1770
1771 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1772 R200_STIPPLE_Y_OFFSET_MASK);
1773
1774 /* add magic offsets, then invert */
1775 stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1776 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1777 & R200_STIPPLE_COORD_MASK);
1778
1779 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1780 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1781
1782 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1783 R200_STATECHANGE( rmesa, msc );
1784 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1785 }
1786 }
1787 }
1788
1789 r200UpdateScissor( ctx );
1790 }
1791
1792
1793
1794 /* =============================================================
1795 * Miscellaneous
1796 */
1797
1798 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1799 {
1800 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1801 GLubyte color[4];
1802 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1803 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1804 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1805 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1806 rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp,
1807 color[0], color[1],
1808 color[2], color[3] );
1809 }
1810
1811
1812 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1813 {
1814 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1815 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1816 }
1817
1818
1819 static GLuint r200_rop_tab[] = {
1820 R200_ROP_CLEAR,
1821 R200_ROP_AND,
1822 R200_ROP_AND_REVERSE,
1823 R200_ROP_COPY,
1824 R200_ROP_AND_INVERTED,
1825 R200_ROP_NOOP,
1826 R200_ROP_XOR,
1827 R200_ROP_OR,
1828 R200_ROP_NOR,
1829 R200_ROP_EQUIV,
1830 R200_ROP_INVERT,
1831 R200_ROP_OR_REVERSE,
1832 R200_ROP_COPY_INVERTED,
1833 R200_ROP_OR_INVERTED,
1834 R200_ROP_NAND,
1835 R200_ROP_SET,
1836 };
1837
1838 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1839 {
1840 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1841 GLuint rop = (GLuint)opcode - GL_CLEAR;
1842
1843 ASSERT( rop < 16 );
1844
1845 R200_STATECHANGE( rmesa, msk );
1846 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1847 }
1848
1849
1850 /*
1851 * Set up the cliprects for either front or back-buffer drawing.
1852 */
1853 void r200SetCliprects( r200ContextPtr rmesa )
1854 {
1855 __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
1856 __DRIdrawablePrivate *const readable = rmesa->dri.readable;
1857 GLframebuffer *const draw_fb = (GLframebuffer*) drawable->driverPrivate;
1858 GLframebuffer *const read_fb = (GLframebuffer*) readable->driverPrivate;
1859
1860 if (draw_fb->_ColorDrawBufferMask[0]
1861 == BUFFER_BIT_BACK_LEFT) {
1862 /* Can't ignore 2d windows if we are page flipping.
1863 */
1864 if ( drawable->numBackClipRects == 0 || rmesa->doPageFlip ) {
1865 rmesa->numClipRects = drawable->numClipRects;
1866 rmesa->pClipRects = drawable->pClipRects;
1867 }
1868 else {
1869 rmesa->numClipRects = drawable->numBackClipRects;
1870 rmesa->pClipRects = drawable->pBackClipRects;
1871 }
1872 }
1873 else {
1874 /* front buffer (or none, or multiple buffers) */
1875 rmesa->numClipRects = drawable->numClipRects;
1876 rmesa->pClipRects = drawable->pClipRects;
1877 }
1878
1879 if ((draw_fb->Width != drawable->w) || (draw_fb->Height != drawable->h)) {
1880 _mesa_resize_framebuffer(rmesa->glCtx, draw_fb,
1881 drawable->w, drawable->h);
1882 draw_fb->Initialized = GL_TRUE;
1883 }
1884
1885 if (drawable != readable) {
1886 if ((read_fb->Width != readable->w) ||
1887 (read_fb->Height != readable->h)) {
1888 _mesa_resize_framebuffer(rmesa->glCtx, read_fb,
1889 readable->w, readable->h);
1890 read_fb->Initialized = GL_TRUE;
1891 }
1892 }
1893
1894 if (rmesa->state.scissor.enabled)
1895 r200RecalcScissorRects( rmesa );
1896
1897 rmesa->lastStamp = drawable->lastStamp;
1898 }
1899
1900
1901 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1902 {
1903 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1904
1905 if (R200_DEBUG & DEBUG_DRI)
1906 fprintf(stderr, "%s %s\n", __FUNCTION__,
1907 _mesa_lookup_enum_by_nr( mode ));
1908
1909 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1910
1911 /*
1912 * _ColorDrawBufferMask is easier to cope with than <mode>.
1913 * Check for software fallback, update cliprects.
1914 */
1915 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
1916 case BUFFER_BIT_FRONT_LEFT:
1917 case BUFFER_BIT_BACK_LEFT:
1918 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1919 break;
1920 default:
1921 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1922 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1923 return;
1924 }
1925
1926 r200SetCliprects( rmesa );
1927
1928 /* We'll set the drawing engine's offset/pitch parameters later
1929 * when we update other state.
1930 */
1931 }
1932
1933
1934 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1935 {
1936 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1937 }
1938
1939 /* =============================================================
1940 * State enable/disable
1941 */
1942
1943 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1944 {
1945 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1946 GLuint p, flag;
1947
1948 if ( R200_DEBUG & DEBUG_STATE )
1949 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1950 _mesa_lookup_enum_by_nr( cap ),
1951 state ? "GL_TRUE" : "GL_FALSE" );
1952
1953 switch ( cap ) {
1954 /* Fast track this one...
1955 */
1956 case GL_TEXTURE_1D:
1957 case GL_TEXTURE_2D:
1958 case GL_TEXTURE_3D:
1959 break;
1960
1961 case GL_ALPHA_TEST:
1962 R200_STATECHANGE( rmesa, ctx );
1963 if (state) {
1964 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1965 } else {
1966 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1967 }
1968 break;
1969
1970 case GL_BLEND:
1971 case GL_COLOR_LOGIC_OP:
1972 r200_set_blend_state( ctx );
1973 break;
1974
1975 case GL_CLIP_PLANE0:
1976 case GL_CLIP_PLANE1:
1977 case GL_CLIP_PLANE2:
1978 case GL_CLIP_PLANE3:
1979 case GL_CLIP_PLANE4:
1980 case GL_CLIP_PLANE5:
1981 p = cap-GL_CLIP_PLANE0;
1982 R200_STATECHANGE( rmesa, tcl );
1983 if (state) {
1984 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1985 r200ClipPlane( ctx, cap, NULL );
1986 }
1987 else {
1988 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1989 }
1990 break;
1991
1992 case GL_COLOR_MATERIAL:
1993 r200ColorMaterial( ctx, 0, 0 );
1994 r200UpdateMaterial( ctx );
1995 break;
1996
1997 case GL_CULL_FACE:
1998 r200CullFace( ctx, 0 );
1999 break;
2000
2001 case GL_DEPTH_TEST:
2002 R200_STATECHANGE(rmesa, ctx );
2003 if ( state ) {
2004 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
2005 } else {
2006 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
2007 }
2008 break;
2009
2010 case GL_DITHER:
2011 R200_STATECHANGE(rmesa, ctx );
2012 if ( state ) {
2013 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
2014 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
2015 } else {
2016 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
2017 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
2018 }
2019 break;
2020
2021 case GL_FOG:
2022 R200_STATECHANGE(rmesa, ctx );
2023 if ( state ) {
2024 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
2025 r200Fogfv( ctx, GL_FOG_MODE, NULL );
2026 } else {
2027 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
2028 R200_STATECHANGE(rmesa, tcl);
2029 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
2030 }
2031 r200UpdateSpecular( ctx ); /* for PK_SPEC */
2032 if (rmesa->TclFallback)
2033 r200ChooseVertexState( ctx );
2034 _mesa_allow_light_in_model( ctx, !state );
2035 break;
2036
2037 case GL_LIGHT0:
2038 case GL_LIGHT1:
2039 case GL_LIGHT2:
2040 case GL_LIGHT3:
2041 case GL_LIGHT4:
2042 case GL_LIGHT5:
2043 case GL_LIGHT6:
2044 case GL_LIGHT7:
2045 R200_STATECHANGE(rmesa, tcl);
2046 p = cap - GL_LIGHT0;
2047 if (p&1)
2048 flag = (R200_LIGHT_1_ENABLE |
2049 R200_LIGHT_1_ENABLE_AMBIENT |
2050 R200_LIGHT_1_ENABLE_SPECULAR);
2051 else
2052 flag = (R200_LIGHT_0_ENABLE |
2053 R200_LIGHT_0_ENABLE_AMBIENT |
2054 R200_LIGHT_0_ENABLE_SPECULAR);
2055
2056 if (state)
2057 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
2058 else
2059 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
2060
2061 /*
2062 */
2063 update_light_colors( ctx, p );
2064 break;
2065
2066 case GL_LIGHTING:
2067 r200UpdateSpecular(ctx);
2068 /* for reflection map fixup - might set recheck_texgen for all units too */
2069 rmesa->NewGLState |= _NEW_TEXTURE;
2070 break;
2071
2072 case GL_LINE_SMOOTH:
2073 R200_STATECHANGE( rmesa, ctx );
2074 if ( state ) {
2075 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
2076 } else {
2077 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
2078 }
2079 break;
2080
2081 case GL_LINE_STIPPLE:
2082 R200_STATECHANGE( rmesa, set );
2083 if ( state ) {
2084 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
2085 } else {
2086 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
2087 }
2088 break;
2089
2090 case GL_NORMALIZE:
2091 R200_STATECHANGE( rmesa, tcl );
2092 if ( state ) {
2093 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
2094 } else {
2095 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
2096 }
2097 break;
2098
2099 /* Pointsize registers on r200 only work for point sprites, and point smooth
2100 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
2101 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
2102 * is enough to satisfy conform.
2103 */
2104 case GL_POINT_SMOOTH:
2105 break;
2106
2107 /* These don't really do anything, as we don't use the 3vtx
2108 * primitives yet.
2109 */
2110 #if 0
2111 case GL_POLYGON_OFFSET_POINT:
2112 R200_STATECHANGE( rmesa, set );
2113 if ( state ) {
2114 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
2115 } else {
2116 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
2117 }
2118 break;
2119
2120 case GL_POLYGON_OFFSET_LINE:
2121 R200_STATECHANGE( rmesa, set );
2122 if ( state ) {
2123 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
2124 } else {
2125 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
2126 }
2127 break;
2128 #endif
2129
2130 case GL_POINT_SPRITE_ARB:
2131 R200_STATECHANGE( rmesa, spr );
2132 if ( state ) {
2133 int i;
2134 for (i = 0; i < 6; i++) {
2135 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
2136 ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i);
2137 }
2138 } else {
2139 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
2140 }
2141 break;
2142
2143 case GL_POLYGON_OFFSET_FILL:
2144 R200_STATECHANGE( rmesa, set );
2145 if ( state ) {
2146 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
2147 } else {
2148 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
2149 }
2150 break;
2151
2152 case GL_POLYGON_SMOOTH:
2153 R200_STATECHANGE( rmesa, ctx );
2154 if ( state ) {
2155 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
2156 } else {
2157 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
2158 }
2159 break;
2160
2161 case GL_POLYGON_STIPPLE:
2162 R200_STATECHANGE(rmesa, set );
2163 if ( state ) {
2164 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
2165 } else {
2166 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
2167 }
2168 break;
2169
2170 case GL_RESCALE_NORMAL_EXT: {
2171 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
2172 R200_STATECHANGE( rmesa, tcl );
2173 if ( tmp ) {
2174 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2175 } else {
2176 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2177 }
2178 break;
2179 }
2180
2181 case GL_SCISSOR_TEST:
2182 R200_FIREVERTICES( rmesa );
2183 rmesa->state.scissor.enabled = state;
2184 r200UpdateScissor( ctx );
2185 break;
2186
2187 case GL_STENCIL_TEST:
2188 if ( rmesa->state.stencil.hwBuffer ) {
2189 R200_STATECHANGE( rmesa, ctx );
2190 if ( state ) {
2191 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
2192 } else {
2193 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
2194 }
2195 } else {
2196 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
2197 }
2198 break;
2199
2200 case GL_TEXTURE_GEN_Q:
2201 case GL_TEXTURE_GEN_R:
2202 case GL_TEXTURE_GEN_S:
2203 case GL_TEXTURE_GEN_T:
2204 /* Picked up in r200UpdateTextureState.
2205 */
2206 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
2207 break;
2208
2209 case GL_COLOR_SUM_EXT:
2210 r200UpdateSpecular ( ctx );
2211 break;
2212
2213 case GL_VERTEX_PROGRAM_ARB:
2214 if (!state) {
2215 GLuint i;
2216 rmesa->curr_vp_hw = NULL;
2217 R200_STATECHANGE( rmesa, vap );
2218 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
2219 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2220 not sure about tcl scalar state - we need at least grd
2221 with vert progs too.
2222 ucp looks like it doesn't get overwritten (may even work
2223 with vp for pos-invariant progs if we're lucky) */
2224 R200_STATECHANGE( rmesa, mtl[0] );
2225 R200_STATECHANGE( rmesa, mtl[1] );
2226 R200_STATECHANGE( rmesa, fog );
2227 R200_STATECHANGE( rmesa, glt );
2228 R200_STATECHANGE( rmesa, eye );
2229 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
2230 R200_STATECHANGE( rmesa, mat[i] );
2231 }
2232 for (i = 0 ; i < 8; i++) {
2233 R200_STATECHANGE( rmesa, lit[i] );
2234 }
2235 R200_STATECHANGE( rmesa, tcl );
2236 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
2237 if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
2238 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
2239 }
2240 /* else {
2241 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2242 }*/
2243 }
2244 /* ugly. Need to call everything which might change compsel. */
2245 r200UpdateSpecular( ctx );
2246 #if 0
2247 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2248 but without it doom3 locks up at always the same places. Why? */
2249 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2250 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2251 r200UpdateTextureState( ctx );
2252 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2253 non-current derived enabled values which may revert the state atoms for frag progs even when
2254 they already got disabled... ugh
2255 Should really figure out why we need to call r200UpdateTextureState in the first place */
2256 GLuint unit;
2257 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2258 R200_STATECHANGE( rmesa, pix[unit] );
2259 R200_STATECHANGE( rmesa, tex[unit] );
2260 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2261 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2262 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2263 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2264 we don't announce ATI_fs, right? */
2265 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2266 }
2267 R200_STATECHANGE( rmesa, cst );
2268 R200_STATECHANGE( rmesa, tf );
2269 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2270 #endif
2271 }
2272 else {
2273 /* picked up later */
2274 }
2275 /* call functions which change hw state based on ARB_vp enabled or not. */
2276 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2277 r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
2278 break;
2279
2280 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
2281 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2282 break;
2283
2284 case GL_FRAGMENT_SHADER_ATI:
2285 if ( !state ) {
2286 /* restore normal tex env colors and make sure tex env combine will get updated
2287 mark env atoms dirty (as their data was overwritten by afs even
2288 if they didn't change) and restore tex coord routing */
2289 GLuint unit;
2290 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2291 R200_STATECHANGE( rmesa, pix[unit] );
2292 R200_STATECHANGE( rmesa, tex[unit] );
2293 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2294 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2295 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2296 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2297 we don't announce ATI_fs, right? */
2298 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2299 }
2300 R200_STATECHANGE( rmesa, cst );
2301 R200_STATECHANGE( rmesa, tf );
2302 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2303 }
2304 else {
2305 /* need to mark this dirty as pix/tf atoms have overwritten the data
2306 even if the data in the atoms didn't change */
2307 R200_STATECHANGE( rmesa, atf );
2308 R200_STATECHANGE( rmesa, afs[1] );
2309 /* everything else picked up in r200UpdateTextureState hopefully */
2310 }
2311 break;
2312 default:
2313 return;
2314 }
2315 }
2316
2317
2318 void r200LightingSpaceChange( GLcontext *ctx )
2319 {
2320 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2321 GLboolean tmp;
2322
2323 if (R200_DEBUG & DEBUG_STATE)
2324 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2325 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2326
2327 if (ctx->_NeedEyeCoords)
2328 tmp = ctx->Transform.RescaleNormals;
2329 else
2330 tmp = !ctx->Transform.RescaleNormals;
2331
2332 R200_STATECHANGE( rmesa, tcl );
2333 if ( tmp ) {
2334 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2335 } else {
2336 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2337 }
2338
2339 if (R200_DEBUG & DEBUG_STATE)
2340 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2341 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2342 }
2343
2344 /* =============================================================
2345 * Deferred state management - matrices, textures, other?
2346 */
2347
2348
2349
2350
2351 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2352 {
2353 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2354 int i;
2355
2356
2357 for (i = 0 ; i < 4 ; i++) {
2358 *dest++ = src[i];
2359 *dest++ = src[i+4];
2360 *dest++ = src[i+8];
2361 *dest++ = src[i+12];
2362 }
2363
2364 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2365 }
2366
2367 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2368 {
2369 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2370 memcpy(dest, src, 16*sizeof(float));
2371 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2372 }
2373
2374
2375 static void update_texturematrix( GLcontext *ctx )
2376 {
2377 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2378 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2379 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2380 int unit;
2381
2382 if (R200_DEBUG & DEBUG_STATE)
2383 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2384 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2385
2386 rmesa->TexMatEnabled = 0;
2387 rmesa->TexMatCompSel = 0;
2388
2389 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2390 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2391 continue;
2392
2393 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2394 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2395 R200_TEXMAT_0_ENABLE) << unit;
2396
2397 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2398
2399 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2400 /* Need to preconcatenate any active texgen
2401 * obj/eyeplane matrices:
2402 */
2403 _math_matrix_mul_matrix( &rmesa->tmpmat,
2404 ctx->TextureMatrixStack[unit].Top,
2405 &rmesa->TexGenMatrix[unit] );
2406 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2407 }
2408 else {
2409 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2410 R200_MTX_TEX0+unit );
2411 }
2412 }
2413 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2414 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2415 R200_MTX_TEX0+unit );
2416 }
2417 }
2418
2419 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2420 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2421 R200_STATECHANGE(rmesa, tcg);
2422 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2423 }
2424
2425 compsel &= ~R200_OUTPUT_TEX_MASK;
2426 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2427 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2428 R200_STATECHANGE(rmesa, vtx);
2429 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2430 }
2431 }
2432
2433
2434
2435 /**
2436 * Tell the card where to render (offset, pitch).
2437 * Effected by glDrawBuffer, etc
2438 */
2439 void
2440 r200UpdateDrawBuffer(GLcontext *ctx)
2441 {
2442 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2443 struct gl_framebuffer *fb = ctx->DrawBuffer;
2444 driRenderbuffer *drb;
2445
2446 if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
2447 /* draw to front */
2448 drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2449 }
2450 else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) {
2451 /* draw to back */
2452 drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2453 }
2454 else {
2455 /* drawing to multiple buffers, or none */
2456 return;
2457 }
2458
2459 assert(drb);
2460 assert(drb->flippedPitch);
2461
2462 R200_STATECHANGE( rmesa, ctx );
2463
2464 /* Note: we used the (possibly) page-flipped values */
2465 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2466 = ((drb->flippedOffset + rmesa->r200Screen->fbLocation)
2467 & R200_COLOROFFSET_MASK);
2468 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2469 if (rmesa->sarea->tiling_enabled) {
2470 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
2471 }
2472 }
2473
2474
2475
2476 void r200ValidateState( GLcontext *ctx )
2477 {
2478 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2479 GLuint new_state = rmesa->NewGLState;
2480
2481 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2482 r200UpdateDrawBuffer(ctx);
2483 }
2484
2485 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) {
2486 r200UpdateTextureState( ctx );
2487 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2488 r200UpdateLocalViewer( ctx );
2489 }
2490
2491 /* FIXME: don't really need most of these when vertex progs are enabled */
2492
2493 /* Need an event driven matrix update?
2494 */
2495 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2496 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2497
2498 /* Need these for lighting (shouldn't upload otherwise)
2499 */
2500 if (new_state & (_NEW_MODELVIEW)) {
2501 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2502 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2503 }
2504
2505 /* Does this need to be triggered on eg. modelview for
2506 * texgen-derived objplane/eyeplane matrices?
2507 */
2508 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2509 update_texturematrix( ctx );
2510 }
2511
2512 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2513 update_light( ctx );
2514 }
2515
2516 /* emit all active clip planes if projection matrix changes.
2517 */
2518 if (new_state & (_NEW_PROJECTION)) {
2519 if (ctx->Transform.ClipPlanesEnabled)
2520 r200UpdateClipPlanes( ctx );
2521 }
2522
2523 if (new_state & (_NEW_PROGRAM|
2524 /* need to test for pretty much anything due to possible parameter bindings */
2525 _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2526 _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2527 _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2528 if (ctx->VertexProgram._Enabled) {
2529 r200SetupVertexProg( ctx );
2530 }
2531 else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2532 }
2533
2534 rmesa->NewGLState = 0;
2535 }
2536
2537
2538 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2539 {
2540 _swrast_InvalidateState( ctx, new_state );
2541 _swsetup_InvalidateState( ctx, new_state );
2542 _vbo_InvalidateState( ctx, new_state );
2543 _tnl_InvalidateState( ctx, new_state );
2544 _ae_invalidate_state( ctx, new_state );
2545 R200_CONTEXT(ctx)->NewGLState |= new_state;
2546 }
2547
2548 /* A hack. The r200 can actually cope just fine with materials
2549 * between begin/ends, so fix this.
2550 * Should map to inputs just like the generic vertex arrays for vertex progs.
2551 * In theory there could still be too many and we'd still need a fallback.
2552 */
2553 static GLboolean check_material( GLcontext *ctx )
2554 {
2555 TNLcontext *tnl = TNL_CONTEXT(ctx);
2556 GLint i;
2557
2558 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2559 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2560 i++)
2561 if (tnl->vb.AttribPtr[i] &&
2562 tnl->vb.AttribPtr[i]->stride)
2563 return GL_TRUE;
2564
2565 return GL_FALSE;
2566 }
2567
2568 static void r200WrapRunPipeline( GLcontext *ctx )
2569 {
2570 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2571 GLboolean has_material;
2572
2573 if (0)
2574 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2575
2576 /* Validate state:
2577 */
2578 if (rmesa->NewGLState)
2579 r200ValidateState( ctx );
2580
2581 has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx );
2582
2583 if (has_material) {
2584 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2585 }
2586
2587 /* Run the pipeline.
2588 */
2589 _tnl_run_pipeline( ctx );
2590
2591 if (has_material) {
2592 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2593 }
2594 }
2595
2596
2597 /* Initialize the driver's state functions.
2598 */
2599 void r200InitStateFuncs( struct dd_function_table *functions )
2600 {
2601 functions->UpdateState = r200InvalidateState;
2602 functions->LightingSpaceChange = r200LightingSpaceChange;
2603
2604 functions->DrawBuffer = r200DrawBuffer;
2605 functions->ReadBuffer = r200ReadBuffer;
2606
2607 functions->AlphaFunc = r200AlphaFunc;
2608 functions->BlendColor = r200BlendColor;
2609 functions->BlendEquationSeparate = r200BlendEquationSeparate;
2610 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2611 functions->ClearColor = r200ClearColor;
2612 functions->ClearDepth = r200ClearDepth;
2613 functions->ClearIndex = NULL;
2614 functions->ClearStencil = r200ClearStencil;
2615 functions->ClipPlane = r200ClipPlane;
2616 functions->ColorMask = r200ColorMask;
2617 functions->CullFace = r200CullFace;
2618 functions->DepthFunc = r200DepthFunc;
2619 functions->DepthMask = r200DepthMask;
2620 functions->DepthRange = r200DepthRange;
2621 functions->Enable = r200Enable;
2622 functions->Fogfv = r200Fogfv;
2623 functions->FrontFace = r200FrontFace;
2624 functions->Hint = NULL;
2625 functions->IndexMask = NULL;
2626 functions->LightModelfv = r200LightModelfv;
2627 functions->Lightfv = r200Lightfv;
2628 functions->LineStipple = r200LineStipple;
2629 functions->LineWidth = r200LineWidth;
2630 functions->LogicOpcode = r200LogicOpCode;
2631 functions->PolygonMode = r200PolygonMode;
2632 functions->PolygonOffset = r200PolygonOffset;
2633 functions->PolygonStipple = r200PolygonStipple;
2634 functions->PointParameterfv = r200PointParameter;
2635 functions->PointSize = r200PointSize;
2636 functions->RenderMode = r200RenderMode;
2637 functions->Scissor = r200Scissor;
2638 functions->ShadeModel = r200ShadeModel;
2639 functions->StencilFuncSeparate = r200StencilFuncSeparate;
2640 functions->StencilMaskSeparate = r200StencilMaskSeparate;
2641 functions->StencilOpSeparate = r200StencilOpSeparate;
2642 functions->Viewport = r200Viewport;
2643 }
2644
2645
2646 void r200InitTnlFuncs( GLcontext *ctx )
2647 {
2648 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2649 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2650 }