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