mesa: rename some gl_light fields to be clearer
[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 "main/glheader.h"
37 #include "main/imports.h"
38 #include "main/api_arrayelt.h"
39 #include "main/enums.h"
40 #include "main/colormac.h"
41 #include "main/light.h"
42 #include "main/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 * Same min/max limits for AA, non-AA lines.
776 */
777 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
778 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)
779 (CLAMP(widthf, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth) * 16.0);
780
781 if ( widthf > 1.0 ) {
782 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE;
783 } else {
784 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
785 }
786 }
787
788 static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
789 {
790 r200ContextPtr rmesa = R200_CONTEXT(ctx);
791
792 R200_STATECHANGE( rmesa, lin );
793 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
794 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
795 }
796
797
798 /* =============================================================
799 * Masks
800 */
801 static void r200ColorMask( GLcontext *ctx,
802 GLboolean r, GLboolean g,
803 GLboolean b, GLboolean a )
804 {
805 r200ContextPtr rmesa = R200_CONTEXT(ctx);
806 GLuint mask = r200PackColor( rmesa->r200Screen->cpp,
807 ctx->Color.ColorMask[RCOMP],
808 ctx->Color.ColorMask[GCOMP],
809 ctx->Color.ColorMask[BCOMP],
810 ctx->Color.ColorMask[ACOMP] );
811
812 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
813
814 if (!(r && g && b && a))
815 flag |= R200_PLANE_MASK_ENABLE;
816
817 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
818 R200_STATECHANGE( rmesa, ctx );
819 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
820 }
821
822 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
823 R200_STATECHANGE( rmesa, msk );
824 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
825 }
826 }
827
828
829 /* =============================================================
830 * Polygon state
831 */
832
833 static void r200PolygonOffset( GLcontext *ctx,
834 GLfloat factor, GLfloat units )
835 {
836 r200ContextPtr rmesa = R200_CONTEXT(ctx);
837 float_ui32_type constant = { units * rmesa->state.depth.scale };
838 float_ui32_type factoru = { factor };
839
840 /* factor *= 2; */
841 /* constant *= 2; */
842
843 /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
844
845 R200_STATECHANGE( rmesa, zbs );
846 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32;
847 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
848 }
849
850 static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
851 {
852 r200ContextPtr rmesa = R200_CONTEXT(ctx);
853 GLuint i;
854 drm_radeon_stipple_t stipple;
855
856 /* Must flip pattern upside down.
857 */
858 for ( i = 0 ; i < 32 ; i++ ) {
859 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
860 }
861
862 /* TODO: push this into cmd mechanism
863 */
864 R200_FIREVERTICES( rmesa );
865 LOCK_HARDWARE( rmesa );
866
867 /* FIXME: Use window x,y offsets into stipple RAM.
868 */
869 stipple.mask = rmesa->state.stipple.mask;
870 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
871 &stipple, sizeof(stipple) );
872 UNLOCK_HARDWARE( rmesa );
873 }
874
875 static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
876 {
877 r200ContextPtr rmesa = R200_CONTEXT(ctx);
878 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
879
880 /* Can't generally do unfilled via tcl, but some good special
881 * cases work.
882 */
883 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
884 if (rmesa->TclFallback) {
885 r200ChooseRenderState( ctx );
886 r200ChooseVertexState( ctx );
887 }
888 }
889
890
891 /* =============================================================
892 * Rendering attributes
893 *
894 * We really don't want to recalculate all this every time we bind a
895 * texture. These things shouldn't change all that often, so it makes
896 * sense to break them out of the core texture state update routines.
897 */
898
899 /* Examine lighting and texture state to determine if separate specular
900 * should be enabled.
901 */
902 static void r200UpdateSpecular( GLcontext *ctx )
903 {
904 r200ContextPtr rmesa = R200_CONTEXT(ctx);
905 uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
906
907 R200_STATECHANGE( rmesa, tcl );
908 R200_STATECHANGE( rmesa, vtx );
909
910 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
911 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
912 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
913 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
914 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
915
916 p &= ~R200_SPECULAR_ENABLE;
917
918 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
919
920
921 if (ctx->Light.Enabled &&
922 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
923 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
924 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
925 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
926 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
927 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
928 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
929 p |= R200_SPECULAR_ENABLE;
930 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
931 ~R200_DIFFUSE_SPECULAR_COMBINE;
932 }
933 else if (ctx->Light.Enabled) {
934 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
935 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
936 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
937 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
938 } else if (ctx->Fog.ColorSumEnabled ) {
939 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
940 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
941 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
942 p |= R200_SPECULAR_ENABLE;
943 } else {
944 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
945 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
946 }
947
948 if (ctx->Fog.Enabled) {
949 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
950 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
951 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
952 }
953
954 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
955 R200_STATECHANGE( rmesa, ctx );
956 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
957 }
958
959 /* Update vertex/render formats
960 */
961 if (rmesa->TclFallback) {
962 r200ChooseRenderState( ctx );
963 r200ChooseVertexState( ctx );
964 }
965 }
966
967
968 /* =============================================================
969 * Materials
970 */
971
972
973 /* Update on colormaterial, material emmissive/ambient,
974 * lightmodel.globalambient
975 */
976 static void update_global_ambient( GLcontext *ctx )
977 {
978 r200ContextPtr rmesa = R200_CONTEXT(ctx);
979 float *fcmd = (float *)R200_DB_STATE( glt );
980
981 /* Need to do more if both emmissive & ambient are PREMULT:
982 * I believe this is not nessary when using source_material. This condition thus
983 * will never happen currently, and the function has no dependencies on materials now
984 */
985 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
986 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
987 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
988 {
989 COPY_3V( &fcmd[GLT_RED],
990 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
991 ACC_SCALE_3V( &fcmd[GLT_RED],
992 ctx->Light.Model.Ambient,
993 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
994 }
995 else
996 {
997 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
998 }
999
1000 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
1001 }
1002
1003 /* Update on change to
1004 * - light[p].colors
1005 * - light[p].enabled
1006 */
1007 static void update_light_colors( GLcontext *ctx, GLuint p )
1008 {
1009 struct gl_light *l = &ctx->Light.Light[p];
1010
1011 /* fprintf(stderr, "%s\n", __FUNCTION__); */
1012
1013 if (l->Enabled) {
1014 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1015 float *fcmd = (float *)R200_DB_STATE( lit[p] );
1016
1017 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
1018 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
1019 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
1020
1021 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1022 }
1023 }
1024
1025 static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
1026 {
1027 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1028 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
1029 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
1030 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
1031 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
1032 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
1033 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
1034 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) |
1035 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
1036 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT));
1037
1038 if (ctx->Light.ColorMaterialEnabled) {
1039 GLuint mask = ctx->Light.ColorMaterialBitmask;
1040
1041 if (mask & MAT_BIT_FRONT_EMISSION) {
1042 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1043 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
1044 }
1045 else
1046 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
1047 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
1048
1049 if (mask & MAT_BIT_FRONT_AMBIENT) {
1050 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1051 R200_FRONT_AMBIENT_SOURCE_SHIFT);
1052 }
1053 else
1054 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
1055 R200_FRONT_AMBIENT_SOURCE_SHIFT);
1056
1057 if (mask & MAT_BIT_FRONT_DIFFUSE) {
1058 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1059 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
1060 }
1061 else
1062 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
1063 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
1064
1065 if (mask & MAT_BIT_FRONT_SPECULAR) {
1066 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1067 R200_FRONT_SPECULAR_SOURCE_SHIFT);
1068 }
1069 else {
1070 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
1071 R200_FRONT_SPECULAR_SOURCE_SHIFT);
1072 }
1073
1074 if (mask & MAT_BIT_BACK_EMISSION) {
1075 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1076 R200_BACK_EMISSIVE_SOURCE_SHIFT);
1077 }
1078
1079 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1080 R200_BACK_EMISSIVE_SOURCE_SHIFT);
1081
1082 if (mask & MAT_BIT_BACK_AMBIENT) {
1083 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1084 R200_BACK_AMBIENT_SOURCE_SHIFT);
1085 }
1086 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1087 R200_BACK_AMBIENT_SOURCE_SHIFT);
1088
1089 if (mask & MAT_BIT_BACK_DIFFUSE) {
1090 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1091 R200_BACK_DIFFUSE_SOURCE_SHIFT);
1092 }
1093 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1094 R200_BACK_DIFFUSE_SOURCE_SHIFT);
1095
1096 if (mask & MAT_BIT_BACK_SPECULAR) {
1097 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1098 R200_BACK_SPECULAR_SOURCE_SHIFT);
1099 }
1100 else {
1101 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1102 R200_BACK_SPECULAR_SOURCE_SHIFT);
1103 }
1104 }
1105 else {
1106 /* Default to SOURCE_MATERIAL:
1107 */
1108 light_model_ctl1 |=
1109 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
1110 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
1111 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
1112 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
1113 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
1114 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) |
1115 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
1116 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT);
1117 }
1118
1119 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
1120 R200_STATECHANGE( rmesa, tcl );
1121 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
1122 }
1123
1124
1125 }
1126
1127 void r200UpdateMaterial( GLcontext *ctx )
1128 {
1129 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1130 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
1131 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
1132 GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] );
1133 GLuint mask = ~0;
1134
1135 /* Might be possible and faster to update everything unconditionally? */
1136 if (ctx->Light.ColorMaterialEnabled)
1137 mask &= ~ctx->Light.ColorMaterialBitmask;
1138
1139 if (R200_DEBUG & DEBUG_STATE)
1140 fprintf(stderr, "%s\n", __FUNCTION__);
1141
1142 if (mask & MAT_BIT_FRONT_EMISSION) {
1143 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
1144 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
1145 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
1146 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
1147 }
1148 if (mask & MAT_BIT_FRONT_AMBIENT) {
1149 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
1150 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
1151 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
1152 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
1153 }
1154 if (mask & MAT_BIT_FRONT_DIFFUSE) {
1155 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
1156 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
1157 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
1158 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
1159 }
1160 if (mask & MAT_BIT_FRONT_SPECULAR) {
1161 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
1162 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
1163 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
1164 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
1165 }
1166 if (mask & MAT_BIT_FRONT_SHININESS) {
1167 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
1168 }
1169
1170 if (mask & MAT_BIT_BACK_EMISSION) {
1171 fcmd2[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_BACK_EMISSION][0];
1172 fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1];
1173 fcmd2[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_BACK_EMISSION][2];
1174 fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3];
1175 }
1176 if (mask & MAT_BIT_BACK_AMBIENT) {
1177 fcmd2[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_BACK_AMBIENT][0];
1178 fcmd2[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_BACK_AMBIENT][1];
1179 fcmd2[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_BACK_AMBIENT][2];
1180 fcmd2[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_BACK_AMBIENT][3];
1181 }
1182 if (mask & MAT_BIT_BACK_DIFFUSE) {
1183 fcmd2[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_BACK_DIFFUSE][0];
1184 fcmd2[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_BACK_DIFFUSE][1];
1185 fcmd2[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_BACK_DIFFUSE][2];
1186 fcmd2[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_BACK_DIFFUSE][3];
1187 }
1188 if (mask & MAT_BIT_BACK_SPECULAR) {
1189 fcmd2[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_BACK_SPECULAR][0];
1190 fcmd2[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_BACK_SPECULAR][1];
1191 fcmd2[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_BACK_SPECULAR][2];
1192 fcmd2[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_BACK_SPECULAR][3];
1193 }
1194 if (mask & MAT_BIT_BACK_SHININESS) {
1195 fcmd2[MTL_SHININESS] = mat[MAT_ATTRIB_BACK_SHININESS][0];
1196 }
1197
1198 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] );
1199 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] );
1200
1201 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1202 update_global_ambient( ctx ); */
1203 }
1204
1205 /* _NEW_LIGHT
1206 * _NEW_MODELVIEW
1207 * _MESA_NEW_NEED_EYE_COORDS
1208 *
1209 * Uses derived state from mesa:
1210 * _VP_inf_norm
1211 * _h_inf_norm
1212 * _Position
1213 * _NormSpotDirection
1214 * _ModelViewInvScale
1215 * _NeedEyeCoords
1216 * _EyeZDir
1217 *
1218 * which are calculated in light.c and are correct for the current
1219 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1220 * and _MESA_NEW_NEED_EYE_COORDS.
1221 */
1222 static void update_light( GLcontext *ctx )
1223 {
1224 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1225
1226 /* Have to check these, or have an automatic shortcircuit mechanism
1227 * to remove noop statechanges. (Or just do a better job on the
1228 * front end).
1229 */
1230 {
1231 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
1232
1233 if (ctx->_NeedEyeCoords)
1234 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1235 else
1236 tmp |= R200_LIGHT_IN_MODELSPACE;
1237
1238 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1239 {
1240 R200_STATECHANGE( rmesa, tcl );
1241 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1242 }
1243 }
1244
1245 {
1246 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1247 fcmd[EYE_X] = ctx->_EyeZDir[0];
1248 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1249 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1250 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1251 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1252 }
1253
1254
1255
1256 if (ctx->Light.Enabled) {
1257 GLint p;
1258 for (p = 0 ; p < MAX_LIGHTS; p++) {
1259 if (ctx->Light.Light[p].Enabled) {
1260 struct gl_light *l = &ctx->Light.Light[p];
1261 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1262
1263 if (l->EyePosition[3] == 0.0) {
1264 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1265 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1266 fcmd[LIT_POSITION_W] = 0;
1267 fcmd[LIT_DIRECTION_W] = 0;
1268 } else {
1269 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1270 fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0];
1271 fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1];
1272 fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2];
1273 fcmd[LIT_DIRECTION_W] = 0;
1274 }
1275
1276 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1277 }
1278 }
1279 }
1280 }
1281
1282 static void r200Lightfv( GLcontext *ctx, GLenum light,
1283 GLenum pname, const GLfloat *params )
1284 {
1285 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1286 GLint p = light - GL_LIGHT0;
1287 struct gl_light *l = &ctx->Light.Light[p];
1288 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1289
1290
1291 switch (pname) {
1292 case GL_AMBIENT:
1293 case GL_DIFFUSE:
1294 case GL_SPECULAR:
1295 update_light_colors( ctx, p );
1296 break;
1297
1298 case GL_SPOT_DIRECTION:
1299 /* picked up in update_light */
1300 break;
1301
1302 case GL_POSITION: {
1303 /* positions picked up in update_light, but can do flag here */
1304 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1305 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1306
1307 R200_STATECHANGE(rmesa, tcl);
1308 if (l->EyePosition[3] != 0.0F)
1309 rmesa->hw.tcl.cmd[idx] |= flag;
1310 else
1311 rmesa->hw.tcl.cmd[idx] &= ~flag;
1312 break;
1313 }
1314
1315 case GL_SPOT_EXPONENT:
1316 R200_STATECHANGE(rmesa, lit[p]);
1317 fcmd[LIT_SPOT_EXPONENT] = params[0];
1318 break;
1319
1320 case GL_SPOT_CUTOFF: {
1321 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1322 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1323
1324 R200_STATECHANGE(rmesa, lit[p]);
1325 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1326
1327 R200_STATECHANGE(rmesa, tcl);
1328 if (l->SpotCutoff != 180.0F)
1329 rmesa->hw.tcl.cmd[idx] |= flag;
1330 else
1331 rmesa->hw.tcl.cmd[idx] &= ~flag;
1332
1333 break;
1334 }
1335
1336 case GL_CONSTANT_ATTENUATION:
1337 R200_STATECHANGE(rmesa, lit[p]);
1338 fcmd[LIT_ATTEN_CONST] = params[0];
1339 if ( params[0] == 0.0 )
1340 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1341 else
1342 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1343 break;
1344 case GL_LINEAR_ATTENUATION:
1345 R200_STATECHANGE(rmesa, lit[p]);
1346 fcmd[LIT_ATTEN_LINEAR] = params[0];
1347 break;
1348 case GL_QUADRATIC_ATTENUATION:
1349 R200_STATECHANGE(rmesa, lit[p]);
1350 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1351 break;
1352 default:
1353 return;
1354 }
1355
1356 /* Set RANGE_ATTEN only when needed */
1357 switch (pname) {
1358 case GL_POSITION:
1359 case GL_CONSTANT_ATTENUATION:
1360 case GL_LINEAR_ATTENUATION:
1361 case GL_QUADRATIC_ATTENUATION: {
1362 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1363 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1364 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1365 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1366 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1367 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1368
1369 if ( l->EyePosition[3] == 0.0F ||
1370 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1371 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1372 /* Disable attenuation */
1373 icmd[idx] &= ~atten_flag;
1374 } else {
1375 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1376 /* Enable only constant portion of attenuation calculation */
1377 icmd[idx] |= ( atten_flag | atten_const_flag );
1378 } else {
1379 /* Enable full attenuation calculation */
1380 icmd[idx] &= ~atten_const_flag;
1381 icmd[idx] |= atten_flag;
1382 }
1383 }
1384
1385 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1386 break;
1387 }
1388 default:
1389 break;
1390 }
1391 }
1392
1393 static void r200UpdateLocalViewer ( GLcontext *ctx )
1394 {
1395 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1396 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1397 for these and only these modes). This means specular highlights may turn out
1398 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1399 is not set, though it seems to happen rarely and the effect seems quite
1400 subtle. May need TCL fallback to fix it completely, though I'm not sure
1401 how you'd identify the cases where the specular highlights indeed will
1402 be wrong. Don't know if fglrx does something special in that case.
1403 */
1404 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1405 R200_STATECHANGE( rmesa, tcl );
1406 if (ctx->Light.Model.LocalViewer ||
1407 ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
1408 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1409 else
1410 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1411 }
1412
1413 static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1414 const GLfloat *param )
1415 {
1416 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1417
1418 switch (pname) {
1419 case GL_LIGHT_MODEL_AMBIENT:
1420 update_global_ambient( ctx );
1421 break;
1422
1423 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1424 r200UpdateLocalViewer( ctx );
1425 break;
1426
1427 case GL_LIGHT_MODEL_TWO_SIDE:
1428 R200_STATECHANGE( rmesa, tcl );
1429 if (ctx->Light.Model.TwoSide)
1430 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1431 else
1432 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1433 if (rmesa->TclFallback) {
1434 r200ChooseRenderState( ctx );
1435 r200ChooseVertexState( ctx );
1436 }
1437 break;
1438
1439 case GL_LIGHT_MODEL_COLOR_CONTROL:
1440 r200UpdateSpecular(ctx);
1441 break;
1442
1443 default:
1444 break;
1445 }
1446 }
1447
1448 static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1449 {
1450 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1451 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1452
1453 s &= ~(R200_DIFFUSE_SHADE_MASK |
1454 R200_ALPHA_SHADE_MASK |
1455 R200_SPECULAR_SHADE_MASK |
1456 R200_FOG_SHADE_MASK |
1457 R200_DISC_FOG_SHADE_MASK);
1458
1459 switch ( mode ) {
1460 case GL_FLAT:
1461 s |= (R200_DIFFUSE_SHADE_FLAT |
1462 R200_ALPHA_SHADE_FLAT |
1463 R200_SPECULAR_SHADE_FLAT |
1464 R200_FOG_SHADE_FLAT |
1465 R200_DISC_FOG_SHADE_FLAT);
1466 break;
1467 case GL_SMOOTH:
1468 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1469 R200_ALPHA_SHADE_GOURAUD |
1470 R200_SPECULAR_SHADE_GOURAUD |
1471 R200_FOG_SHADE_GOURAUD |
1472 R200_DISC_FOG_SHADE_GOURAUD);
1473 break;
1474 default:
1475 return;
1476 }
1477
1478 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1479 R200_STATECHANGE( rmesa, set );
1480 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1481 }
1482 }
1483
1484
1485 /* =============================================================
1486 * User clip planes
1487 */
1488
1489 static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1490 {
1491 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1492 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1493 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1494
1495 R200_STATECHANGE( rmesa, ucp[p] );
1496 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1497 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1498 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1499 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1500 }
1501
1502 static void r200UpdateClipPlanes( GLcontext *ctx )
1503 {
1504 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1505 GLuint p;
1506
1507 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1508 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1509 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1510
1511 R200_STATECHANGE( rmesa, ucp[p] );
1512 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1513 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1514 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1515 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1516 }
1517 }
1518 }
1519
1520
1521 /* =============================================================
1522 * Stencil
1523 */
1524
1525 static void
1526 r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
1527 GLint ref, GLuint mask )
1528 {
1529 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1530 GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R200_STENCIL_REF_SHIFT) |
1531 ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT));
1532
1533 R200_STATECHANGE( rmesa, ctx );
1534 R200_STATECHANGE( rmesa, msk );
1535
1536 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1537 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1538 R200_STENCIL_VALUE_MASK);
1539
1540 switch ( ctx->Stencil.Function[0] ) {
1541 case GL_NEVER:
1542 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1543 break;
1544 case GL_LESS:
1545 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1546 break;
1547 case GL_EQUAL:
1548 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1549 break;
1550 case GL_LEQUAL:
1551 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1552 break;
1553 case GL_GREATER:
1554 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1555 break;
1556 case GL_NOTEQUAL:
1557 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1558 break;
1559 case GL_GEQUAL:
1560 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1561 break;
1562 case GL_ALWAYS:
1563 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1564 break;
1565 }
1566
1567 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1568 }
1569
1570 static void
1571 r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
1572 {
1573 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1574
1575 R200_STATECHANGE( rmesa, msk );
1576 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1577 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1578 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT);
1579 }
1580
1581 static void
1582 r200StencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
1583 GLenum zfail, GLenum zpass )
1584 {
1585 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1586
1587 R200_STATECHANGE( rmesa, ctx );
1588 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1589 R200_STENCIL_ZFAIL_MASK |
1590 R200_STENCIL_ZPASS_MASK);
1591
1592 switch ( ctx->Stencil.FailFunc[0] ) {
1593 case GL_KEEP:
1594 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1595 break;
1596 case GL_ZERO:
1597 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1598 break;
1599 case GL_REPLACE:
1600 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1601 break;
1602 case GL_INCR:
1603 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1604 break;
1605 case GL_DECR:
1606 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1607 break;
1608 case GL_INCR_WRAP_EXT:
1609 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1610 break;
1611 case GL_DECR_WRAP_EXT:
1612 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1613 break;
1614 case GL_INVERT:
1615 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1616 break;
1617 }
1618
1619 switch ( ctx->Stencil.ZFailFunc[0] ) {
1620 case GL_KEEP:
1621 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1622 break;
1623 case GL_ZERO:
1624 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1625 break;
1626 case GL_REPLACE:
1627 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1628 break;
1629 case GL_INCR:
1630 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1631 break;
1632 case GL_DECR:
1633 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1634 break;
1635 case GL_INCR_WRAP_EXT:
1636 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1637 break;
1638 case GL_DECR_WRAP_EXT:
1639 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1640 break;
1641 case GL_INVERT:
1642 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1643 break;
1644 }
1645
1646 switch ( ctx->Stencil.ZPassFunc[0] ) {
1647 case GL_KEEP:
1648 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1649 break;
1650 case GL_ZERO:
1651 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1652 break;
1653 case GL_REPLACE:
1654 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1655 break;
1656 case GL_INCR:
1657 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1658 break;
1659 case GL_DECR:
1660 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1661 break;
1662 case GL_INCR_WRAP_EXT:
1663 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1664 break;
1665 case GL_DECR_WRAP_EXT:
1666 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1667 break;
1668 case GL_INVERT:
1669 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1670 break;
1671 }
1672 }
1673
1674 static void r200ClearStencil( GLcontext *ctx, GLint s )
1675 {
1676 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1677
1678 rmesa->state.stencil.clear =
1679 ((GLuint) (ctx->Stencil.Clear & 0xff) |
1680 (0xff << R200_STENCIL_MASK_SHIFT) |
1681 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT));
1682 }
1683
1684
1685 /* =============================================================
1686 * Window position and viewport transformation
1687 */
1688
1689 /*
1690 * To correctly position primitives:
1691 */
1692 #define SUBPIXEL_X 0.125
1693 #define SUBPIXEL_Y 0.125
1694
1695
1696 /**
1697 * Called when window size or position changes or viewport or depth range
1698 * state is changed. We update the hardware viewport state here.
1699 */
1700 void r200UpdateWindow( GLcontext *ctx )
1701 {
1702 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1703 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1704 GLfloat xoffset = (GLfloat)dPriv->x;
1705 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1706 const GLfloat *v = ctx->Viewport._WindowMap.m;
1707
1708 float_ui32_type sx = { v[MAT_SX] };
1709 float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
1710 float_ui32_type sy = { - v[MAT_SY] };
1711 float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
1712 float_ui32_type sz = { v[MAT_SZ] * rmesa->state.depth.scale };
1713 float_ui32_type tz = { v[MAT_TZ] * rmesa->state.depth.scale };
1714
1715 R200_FIREVERTICES( rmesa );
1716 R200_STATECHANGE( rmesa, vpt );
1717
1718 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32;
1719 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1720 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32;
1721 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1722 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32;
1723 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1724 }
1725
1726
1727
1728 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1729 GLsizei width, GLsizei height )
1730 {
1731 /* Don't pipeline viewport changes, conflict with window offset
1732 * setting below. Could apply deltas to rescue pipelined viewport
1733 * values, or keep the originals hanging around.
1734 */
1735 r200UpdateWindow( ctx );
1736 }
1737
1738 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1739 GLclampd farval )
1740 {
1741 r200UpdateWindow( ctx );
1742 }
1743
1744 void r200UpdateViewportOffset( GLcontext *ctx )
1745 {
1746 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1747 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1748 GLfloat xoffset = (GLfloat)dPriv->x;
1749 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1750 const GLfloat *v = ctx->Viewport._WindowMap.m;
1751
1752 float_ui32_type tx;
1753 float_ui32_type ty;
1754
1755 tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X;
1756 ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1757
1758 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
1759 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
1760 {
1761 /* Note: this should also modify whatever data the context reset
1762 * code uses...
1763 */
1764 R200_STATECHANGE( rmesa, vpt );
1765 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1766 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1767
1768 /* update polygon stipple x/y screen offset */
1769 {
1770 GLuint stx, sty;
1771 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1772
1773 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1774 R200_STIPPLE_Y_OFFSET_MASK);
1775
1776 /* add magic offsets, then invert */
1777 stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1778 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1779 & R200_STIPPLE_COORD_MASK);
1780
1781 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1782 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1783
1784 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1785 R200_STATECHANGE( rmesa, msc );
1786 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1787 }
1788 }
1789 }
1790
1791 r200UpdateScissor( ctx );
1792 }
1793
1794
1795
1796 /* =============================================================
1797 * Miscellaneous
1798 */
1799
1800 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1801 {
1802 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1803 GLubyte color[4];
1804 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1805 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1806 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1807 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1808 rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp,
1809 color[0], color[1],
1810 color[2], color[3] );
1811 }
1812
1813
1814 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1815 {
1816 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1817 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1818 }
1819
1820
1821 static GLuint r200_rop_tab[] = {
1822 R200_ROP_CLEAR,
1823 R200_ROP_AND,
1824 R200_ROP_AND_REVERSE,
1825 R200_ROP_COPY,
1826 R200_ROP_AND_INVERTED,
1827 R200_ROP_NOOP,
1828 R200_ROP_XOR,
1829 R200_ROP_OR,
1830 R200_ROP_NOR,
1831 R200_ROP_EQUIV,
1832 R200_ROP_INVERT,
1833 R200_ROP_OR_REVERSE,
1834 R200_ROP_COPY_INVERTED,
1835 R200_ROP_OR_INVERTED,
1836 R200_ROP_NAND,
1837 R200_ROP_SET,
1838 };
1839
1840 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1841 {
1842 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1843 GLuint rop = (GLuint)opcode - GL_CLEAR;
1844
1845 ASSERT( rop < 16 );
1846
1847 R200_STATECHANGE( rmesa, msk );
1848 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1849 }
1850
1851
1852 /*
1853 * Set up the cliprects for either front or back-buffer drawing.
1854 */
1855 void r200SetCliprects( r200ContextPtr rmesa )
1856 {
1857 __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
1858 __DRIdrawablePrivate *const readable = rmesa->dri.readable;
1859 GLframebuffer *const draw_fb = (GLframebuffer*) drawable->driverPrivate;
1860 GLframebuffer *const read_fb = (GLframebuffer*) readable->driverPrivate;
1861
1862 if (draw_fb->_ColorDrawBufferIndexes[0] == BUFFER_BIT_BACK_LEFT) {
1863 /* Can't ignore 2d windows if we are page flipping.
1864 */
1865 if ( drawable->numBackClipRects == 0 || rmesa->doPageFlip ) {
1866 rmesa->numClipRects = drawable->numClipRects;
1867 rmesa->pClipRects = drawable->pClipRects;
1868 }
1869 else {
1870 rmesa->numClipRects = drawable->numBackClipRects;
1871 rmesa->pClipRects = drawable->pBackClipRects;
1872 }
1873 }
1874 else {
1875 /* front buffer (or none, or multiple buffers) */
1876 rmesa->numClipRects = drawable->numClipRects;
1877 rmesa->pClipRects = drawable->pClipRects;
1878 }
1879
1880 if ((draw_fb->Width != drawable->w) || (draw_fb->Height != drawable->h)) {
1881 _mesa_resize_framebuffer(rmesa->glCtx, draw_fb,
1882 drawable->w, drawable->h);
1883 draw_fb->Initialized = GL_TRUE;
1884 }
1885
1886 if (drawable != readable) {
1887 if ((read_fb->Width != readable->w) ||
1888 (read_fb->Height != readable->h)) {
1889 _mesa_resize_framebuffer(rmesa->glCtx, read_fb,
1890 readable->w, readable->h);
1891 read_fb->Initialized = GL_TRUE;
1892 }
1893 }
1894
1895 if (rmesa->state.scissor.enabled)
1896 r200RecalcScissorRects( rmesa );
1897
1898 rmesa->lastStamp = drawable->lastStamp;
1899 }
1900
1901
1902 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1903 {
1904 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1905
1906 if (R200_DEBUG & DEBUG_DRI)
1907 fprintf(stderr, "%s %s\n", __FUNCTION__,
1908 _mesa_lookup_enum_by_nr( mode ));
1909
1910 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1911
1912 if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
1913 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1914 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1915 return;
1916 }
1917
1918 switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
1919 case BUFFER_FRONT_LEFT:
1920 case BUFFER_BACK_LEFT:
1921 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1922 break;
1923 default:
1924 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1925 return;
1926 }
1927
1928 r200SetCliprects( rmesa );
1929
1930 /* We'll set the drawing engine's offset/pitch parameters later
1931 * when we update other state.
1932 */
1933 }
1934
1935
1936 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1937 {
1938 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1939 }
1940
1941 /* =============================================================
1942 * State enable/disable
1943 */
1944
1945 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1946 {
1947 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1948 GLuint p, flag;
1949
1950 if ( R200_DEBUG & DEBUG_STATE )
1951 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1952 _mesa_lookup_enum_by_nr( cap ),
1953 state ? "GL_TRUE" : "GL_FALSE" );
1954
1955 switch ( cap ) {
1956 /* Fast track this one...
1957 */
1958 case GL_TEXTURE_1D:
1959 case GL_TEXTURE_2D:
1960 case GL_TEXTURE_3D:
1961 break;
1962
1963 case GL_ALPHA_TEST:
1964 R200_STATECHANGE( rmesa, ctx );
1965 if (state) {
1966 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1967 } else {
1968 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1969 }
1970 break;
1971
1972 case GL_BLEND:
1973 case GL_COLOR_LOGIC_OP:
1974 r200_set_blend_state( ctx );
1975 break;
1976
1977 case GL_CLIP_PLANE0:
1978 case GL_CLIP_PLANE1:
1979 case GL_CLIP_PLANE2:
1980 case GL_CLIP_PLANE3:
1981 case GL_CLIP_PLANE4:
1982 case GL_CLIP_PLANE5:
1983 p = cap-GL_CLIP_PLANE0;
1984 R200_STATECHANGE( rmesa, tcl );
1985 if (state) {
1986 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1987 r200ClipPlane( ctx, cap, NULL );
1988 }
1989 else {
1990 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1991 }
1992 break;
1993
1994 case GL_COLOR_MATERIAL:
1995 r200ColorMaterial( ctx, 0, 0 );
1996 r200UpdateMaterial( ctx );
1997 break;
1998
1999 case GL_CULL_FACE:
2000 r200CullFace( ctx, 0 );
2001 break;
2002
2003 case GL_DEPTH_TEST:
2004 R200_STATECHANGE(rmesa, ctx );
2005 if ( state ) {
2006 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
2007 } else {
2008 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
2009 }
2010 break;
2011
2012 case GL_DITHER:
2013 R200_STATECHANGE(rmesa, ctx );
2014 if ( state ) {
2015 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
2016 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
2017 } else {
2018 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
2019 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
2020 }
2021 break;
2022
2023 case GL_FOG:
2024 R200_STATECHANGE(rmesa, ctx );
2025 if ( state ) {
2026 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
2027 r200Fogfv( ctx, GL_FOG_MODE, NULL );
2028 } else {
2029 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
2030 R200_STATECHANGE(rmesa, tcl);
2031 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
2032 }
2033 r200UpdateSpecular( ctx ); /* for PK_SPEC */
2034 if (rmesa->TclFallback)
2035 r200ChooseVertexState( ctx );
2036 _mesa_allow_light_in_model( ctx, !state );
2037 break;
2038
2039 case GL_LIGHT0:
2040 case GL_LIGHT1:
2041 case GL_LIGHT2:
2042 case GL_LIGHT3:
2043 case GL_LIGHT4:
2044 case GL_LIGHT5:
2045 case GL_LIGHT6:
2046 case GL_LIGHT7:
2047 R200_STATECHANGE(rmesa, tcl);
2048 p = cap - GL_LIGHT0;
2049 if (p&1)
2050 flag = (R200_LIGHT_1_ENABLE |
2051 R200_LIGHT_1_ENABLE_AMBIENT |
2052 R200_LIGHT_1_ENABLE_SPECULAR);
2053 else
2054 flag = (R200_LIGHT_0_ENABLE |
2055 R200_LIGHT_0_ENABLE_AMBIENT |
2056 R200_LIGHT_0_ENABLE_SPECULAR);
2057
2058 if (state)
2059 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
2060 else
2061 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
2062
2063 /*
2064 */
2065 update_light_colors( ctx, p );
2066 break;
2067
2068 case GL_LIGHTING:
2069 r200UpdateSpecular(ctx);
2070 /* for reflection map fixup - might set recheck_texgen for all units too */
2071 rmesa->NewGLState |= _NEW_TEXTURE;
2072 break;
2073
2074 case GL_LINE_SMOOTH:
2075 R200_STATECHANGE( rmesa, ctx );
2076 if ( state ) {
2077 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
2078 } else {
2079 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
2080 }
2081 break;
2082
2083 case GL_LINE_STIPPLE:
2084 R200_STATECHANGE( rmesa, set );
2085 if ( state ) {
2086 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
2087 } else {
2088 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
2089 }
2090 break;
2091
2092 case GL_NORMALIZE:
2093 R200_STATECHANGE( rmesa, tcl );
2094 if ( state ) {
2095 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
2096 } else {
2097 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
2098 }
2099 break;
2100
2101 /* Pointsize registers on r200 only work for point sprites, and point smooth
2102 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
2103 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
2104 * is enough to satisfy conform.
2105 */
2106 case GL_POINT_SMOOTH:
2107 break;
2108
2109 /* These don't really do anything, as we don't use the 3vtx
2110 * primitives yet.
2111 */
2112 #if 0
2113 case GL_POLYGON_OFFSET_POINT:
2114 R200_STATECHANGE( rmesa, set );
2115 if ( state ) {
2116 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
2117 } else {
2118 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
2119 }
2120 break;
2121
2122 case GL_POLYGON_OFFSET_LINE:
2123 R200_STATECHANGE( rmesa, set );
2124 if ( state ) {
2125 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
2126 } else {
2127 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
2128 }
2129 break;
2130 #endif
2131
2132 case GL_POINT_SPRITE_ARB:
2133 R200_STATECHANGE( rmesa, spr );
2134 if ( state ) {
2135 int i;
2136 for (i = 0; i < 6; i++) {
2137 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
2138 ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i);
2139 }
2140 } else {
2141 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
2142 }
2143 break;
2144
2145 case GL_POLYGON_OFFSET_FILL:
2146 R200_STATECHANGE( rmesa, set );
2147 if ( state ) {
2148 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
2149 } else {
2150 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
2151 }
2152 break;
2153
2154 case GL_POLYGON_SMOOTH:
2155 R200_STATECHANGE( rmesa, ctx );
2156 if ( state ) {
2157 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
2158 } else {
2159 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
2160 }
2161 break;
2162
2163 case GL_POLYGON_STIPPLE:
2164 R200_STATECHANGE(rmesa, set );
2165 if ( state ) {
2166 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
2167 } else {
2168 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
2169 }
2170 break;
2171
2172 case GL_RESCALE_NORMAL_EXT: {
2173 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
2174 R200_STATECHANGE( rmesa, tcl );
2175 if ( tmp ) {
2176 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2177 } else {
2178 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2179 }
2180 break;
2181 }
2182
2183 case GL_SCISSOR_TEST:
2184 R200_FIREVERTICES( rmesa );
2185 rmesa->state.scissor.enabled = state;
2186 r200UpdateScissor( ctx );
2187 break;
2188
2189 case GL_STENCIL_TEST:
2190 if ( rmesa->state.stencil.hwBuffer ) {
2191 R200_STATECHANGE( rmesa, ctx );
2192 if ( state ) {
2193 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
2194 } else {
2195 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
2196 }
2197 } else {
2198 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
2199 }
2200 break;
2201
2202 case GL_TEXTURE_GEN_Q:
2203 case GL_TEXTURE_GEN_R:
2204 case GL_TEXTURE_GEN_S:
2205 case GL_TEXTURE_GEN_T:
2206 /* Picked up in r200UpdateTextureState.
2207 */
2208 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
2209 break;
2210
2211 case GL_COLOR_SUM_EXT:
2212 r200UpdateSpecular ( ctx );
2213 break;
2214
2215 case GL_VERTEX_PROGRAM_ARB:
2216 if (!state) {
2217 GLuint i;
2218 rmesa->curr_vp_hw = NULL;
2219 R200_STATECHANGE( rmesa, vap );
2220 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
2221 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2222 not sure about tcl scalar state - we need at least grd
2223 with vert progs too.
2224 ucp looks like it doesn't get overwritten (may even work
2225 with vp for pos-invariant progs if we're lucky) */
2226 R200_STATECHANGE( rmesa, mtl[0] );
2227 R200_STATECHANGE( rmesa, mtl[1] );
2228 R200_STATECHANGE( rmesa, fog );
2229 R200_STATECHANGE( rmesa, glt );
2230 R200_STATECHANGE( rmesa, eye );
2231 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
2232 R200_STATECHANGE( rmesa, mat[i] );
2233 }
2234 for (i = 0 ; i < 8; i++) {
2235 R200_STATECHANGE( rmesa, lit[i] );
2236 }
2237 R200_STATECHANGE( rmesa, tcl );
2238 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
2239 if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
2240 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
2241 }
2242 /* else {
2243 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2244 }*/
2245 }
2246 /* ugly. Need to call everything which might change compsel. */
2247 r200UpdateSpecular( ctx );
2248 #if 0
2249 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2250 but without it doom3 locks up at always the same places. Why? */
2251 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2252 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2253 r200UpdateTextureState( ctx );
2254 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2255 non-current derived enabled values which may revert the state atoms for frag progs even when
2256 they already got disabled... ugh
2257 Should really figure out why we need to call r200UpdateTextureState in the first place */
2258 GLuint unit;
2259 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2260 R200_STATECHANGE( rmesa, pix[unit] );
2261 R200_STATECHANGE( rmesa, tex[unit] );
2262 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2263 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2264 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2265 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2266 we don't announce ATI_fs, right? */
2267 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2268 }
2269 R200_STATECHANGE( rmesa, cst );
2270 R200_STATECHANGE( rmesa, tf );
2271 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2272 #endif
2273 }
2274 else {
2275 /* picked up later */
2276 }
2277 /* call functions which change hw state based on ARB_vp enabled or not. */
2278 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2279 r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
2280 break;
2281
2282 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
2283 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2284 break;
2285
2286 case GL_FRAGMENT_SHADER_ATI:
2287 if ( !state ) {
2288 /* restore normal tex env colors and make sure tex env combine will get updated
2289 mark env atoms dirty (as their data was overwritten by afs even
2290 if they didn't change) and restore tex coord routing */
2291 GLuint unit;
2292 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2293 R200_STATECHANGE( rmesa, pix[unit] );
2294 R200_STATECHANGE( rmesa, tex[unit] );
2295 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2296 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2297 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2298 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2299 we don't announce ATI_fs, right? */
2300 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2301 }
2302 R200_STATECHANGE( rmesa, cst );
2303 R200_STATECHANGE( rmesa, tf );
2304 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2305 }
2306 else {
2307 /* need to mark this dirty as pix/tf atoms have overwritten the data
2308 even if the data in the atoms didn't change */
2309 R200_STATECHANGE( rmesa, atf );
2310 R200_STATECHANGE( rmesa, afs[1] );
2311 /* everything else picked up in r200UpdateTextureState hopefully */
2312 }
2313 break;
2314 default:
2315 return;
2316 }
2317 }
2318
2319
2320 void r200LightingSpaceChange( GLcontext *ctx )
2321 {
2322 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2323 GLboolean tmp;
2324
2325 if (R200_DEBUG & DEBUG_STATE)
2326 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2327 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2328
2329 if (ctx->_NeedEyeCoords)
2330 tmp = ctx->Transform.RescaleNormals;
2331 else
2332 tmp = !ctx->Transform.RescaleNormals;
2333
2334 R200_STATECHANGE( rmesa, tcl );
2335 if ( tmp ) {
2336 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2337 } else {
2338 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2339 }
2340
2341 if (R200_DEBUG & DEBUG_STATE)
2342 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2343 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2344 }
2345
2346 /* =============================================================
2347 * Deferred state management - matrices, textures, other?
2348 */
2349
2350
2351
2352
2353 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2354 {
2355 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2356 int i;
2357
2358
2359 for (i = 0 ; i < 4 ; i++) {
2360 *dest++ = src[i];
2361 *dest++ = src[i+4];
2362 *dest++ = src[i+8];
2363 *dest++ = src[i+12];
2364 }
2365
2366 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2367 }
2368
2369 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2370 {
2371 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2372 memcpy(dest, src, 16*sizeof(float));
2373 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2374 }
2375
2376
2377 static void update_texturematrix( GLcontext *ctx )
2378 {
2379 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2380 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2381 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2382 int unit;
2383
2384 if (R200_DEBUG & DEBUG_STATE)
2385 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2386 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2387
2388 rmesa->TexMatEnabled = 0;
2389 rmesa->TexMatCompSel = 0;
2390
2391 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2392 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2393 continue;
2394
2395 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2396 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2397 R200_TEXMAT_0_ENABLE) << unit;
2398
2399 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2400
2401 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2402 /* Need to preconcatenate any active texgen
2403 * obj/eyeplane matrices:
2404 */
2405 _math_matrix_mul_matrix( &rmesa->tmpmat,
2406 ctx->TextureMatrixStack[unit].Top,
2407 &rmesa->TexGenMatrix[unit] );
2408 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2409 }
2410 else {
2411 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2412 R200_MTX_TEX0+unit );
2413 }
2414 }
2415 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2416 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2417 R200_MTX_TEX0+unit );
2418 }
2419 }
2420
2421 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2422 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2423 R200_STATECHANGE(rmesa, tcg);
2424 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2425 }
2426
2427 compsel &= ~R200_OUTPUT_TEX_MASK;
2428 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2429 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2430 R200_STATECHANGE(rmesa, vtx);
2431 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2432 }
2433 }
2434
2435
2436
2437 /**
2438 * Tell the card where to render (offset, pitch).
2439 * Effected by glDrawBuffer, etc
2440 */
2441 void
2442 r200UpdateDrawBuffer(GLcontext *ctx)
2443 {
2444 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2445 struct gl_framebuffer *fb = ctx->DrawBuffer;
2446 driRenderbuffer *drb;
2447
2448 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
2449 /* draw to front */
2450 drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2451 }
2452 else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
2453 /* draw to back */
2454 drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2455 }
2456 else {
2457 /* drawing to multiple buffers, or none */
2458 return;
2459 }
2460
2461 assert(drb);
2462 assert(drb->flippedPitch);
2463
2464 R200_STATECHANGE( rmesa, ctx );
2465
2466 /* Note: we used the (possibly) page-flipped values */
2467 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2468 = ((drb->flippedOffset + rmesa->r200Screen->fbLocation)
2469 & R200_COLOROFFSET_MASK);
2470 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2471 if (rmesa->sarea->tiling_enabled) {
2472 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
2473 }
2474 }
2475
2476
2477
2478 void r200ValidateState( GLcontext *ctx )
2479 {
2480 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2481 GLuint new_state = rmesa->NewGLState;
2482
2483 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2484 r200UpdateDrawBuffer(ctx);
2485 }
2486
2487 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) {
2488 r200UpdateTextureState( ctx );
2489 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2490 r200UpdateLocalViewer( ctx );
2491 }
2492
2493 /* FIXME: don't really need most of these when vertex progs are enabled */
2494
2495 /* Need an event driven matrix update?
2496 */
2497 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2498 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2499
2500 /* Need these for lighting (shouldn't upload otherwise)
2501 */
2502 if (new_state & (_NEW_MODELVIEW)) {
2503 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2504 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2505 }
2506
2507 /* Does this need to be triggered on eg. modelview for
2508 * texgen-derived objplane/eyeplane matrices?
2509 */
2510 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2511 update_texturematrix( ctx );
2512 }
2513
2514 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2515 update_light( ctx );
2516 }
2517
2518 /* emit all active clip planes if projection matrix changes.
2519 */
2520 if (new_state & (_NEW_PROJECTION)) {
2521 if (ctx->Transform.ClipPlanesEnabled)
2522 r200UpdateClipPlanes( ctx );
2523 }
2524
2525 if (new_state & (_NEW_PROGRAM|
2526 /* need to test for pretty much anything due to possible parameter bindings */
2527 _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2528 _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2529 _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2530 if (ctx->VertexProgram._Enabled) {
2531 r200SetupVertexProg( ctx );
2532 }
2533 else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2534 }
2535
2536 rmesa->NewGLState = 0;
2537 }
2538
2539
2540 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2541 {
2542 _swrast_InvalidateState( ctx, new_state );
2543 _swsetup_InvalidateState( ctx, new_state );
2544 _vbo_InvalidateState( ctx, new_state );
2545 _tnl_InvalidateState( ctx, new_state );
2546 _ae_invalidate_state( ctx, new_state );
2547 R200_CONTEXT(ctx)->NewGLState |= new_state;
2548 }
2549
2550 /* A hack. The r200 can actually cope just fine with materials
2551 * between begin/ends, so fix this.
2552 * Should map to inputs just like the generic vertex arrays for vertex progs.
2553 * In theory there could still be too many and we'd still need a fallback.
2554 */
2555 static GLboolean check_material( GLcontext *ctx )
2556 {
2557 TNLcontext *tnl = TNL_CONTEXT(ctx);
2558 GLint i;
2559
2560 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2561 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2562 i++)
2563 if (tnl->vb.AttribPtr[i] &&
2564 tnl->vb.AttribPtr[i]->stride)
2565 return GL_TRUE;
2566
2567 return GL_FALSE;
2568 }
2569
2570 static void r200WrapRunPipeline( GLcontext *ctx )
2571 {
2572 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2573 GLboolean has_material;
2574
2575 if (0)
2576 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2577
2578 /* Validate state:
2579 */
2580 if (rmesa->NewGLState)
2581 r200ValidateState( ctx );
2582
2583 has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx );
2584
2585 if (has_material) {
2586 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2587 }
2588
2589 /* Run the pipeline.
2590 */
2591 _tnl_run_pipeline( ctx );
2592
2593 if (has_material) {
2594 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2595 }
2596 }
2597
2598
2599 /* Initialize the driver's state functions.
2600 */
2601 void r200InitStateFuncs( struct dd_function_table *functions )
2602 {
2603 functions->UpdateState = r200InvalidateState;
2604 functions->LightingSpaceChange = r200LightingSpaceChange;
2605
2606 functions->DrawBuffer = r200DrawBuffer;
2607 functions->ReadBuffer = r200ReadBuffer;
2608
2609 functions->AlphaFunc = r200AlphaFunc;
2610 functions->BlendColor = r200BlendColor;
2611 functions->BlendEquationSeparate = r200BlendEquationSeparate;
2612 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2613 functions->ClearColor = r200ClearColor;
2614 functions->ClearDepth = r200ClearDepth;
2615 functions->ClearIndex = NULL;
2616 functions->ClearStencil = r200ClearStencil;
2617 functions->ClipPlane = r200ClipPlane;
2618 functions->ColorMask = r200ColorMask;
2619 functions->CullFace = r200CullFace;
2620 functions->DepthFunc = r200DepthFunc;
2621 functions->DepthMask = r200DepthMask;
2622 functions->DepthRange = r200DepthRange;
2623 functions->Enable = r200Enable;
2624 functions->Fogfv = r200Fogfv;
2625 functions->FrontFace = r200FrontFace;
2626 functions->Hint = NULL;
2627 functions->IndexMask = NULL;
2628 functions->LightModelfv = r200LightModelfv;
2629 functions->Lightfv = r200Lightfv;
2630 functions->LineStipple = r200LineStipple;
2631 functions->LineWidth = r200LineWidth;
2632 functions->LogicOpcode = r200LogicOpCode;
2633 functions->PolygonMode = r200PolygonMode;
2634 functions->PolygonOffset = r200PolygonOffset;
2635 functions->PolygonStipple = r200PolygonStipple;
2636 functions->PointParameterfv = r200PointParameter;
2637 functions->PointSize = r200PointSize;
2638 functions->RenderMode = r200RenderMode;
2639 functions->Scissor = r200Scissor;
2640 functions->ShadeModel = r200ShadeModel;
2641 functions->StencilFuncSeparate = r200StencilFuncSeparate;
2642 functions->StencilMaskSeparate = r200StencilMaskSeparate;
2643 functions->StencilOpSeparate = r200StencilOpSeparate;
2644 functions->Viewport = r200Viewport;
2645 }
2646
2647
2648 void r200InitTnlFuncs( GLcontext *ctx )
2649 {
2650 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2651 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2652 }