Remove use of GetBufferSize (depreciated).
[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 "array_cache/acache.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_vtxfmt.h"
58 #include "r200_vertprog.h"
59
60 #include "drirenderbuffer.h"
61
62
63 /* =============================================================
64 * Alpha blending
65 */
66
67 static void r200AlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
68 {
69 r200ContextPtr rmesa = R200_CONTEXT(ctx);
70 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
71 GLubyte refByte;
72
73 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
74
75 R200_STATECHANGE( rmesa, ctx );
76
77 pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK);
78 pp_misc |= (refByte & R200_REF_ALPHA_MASK);
79
80 switch ( func ) {
81 case GL_NEVER:
82 pp_misc |= R200_ALPHA_TEST_FAIL;
83 break;
84 case GL_LESS:
85 pp_misc |= R200_ALPHA_TEST_LESS;
86 break;
87 case GL_EQUAL:
88 pp_misc |= R200_ALPHA_TEST_EQUAL;
89 break;
90 case GL_LEQUAL:
91 pp_misc |= R200_ALPHA_TEST_LEQUAL;
92 break;
93 case GL_GREATER:
94 pp_misc |= R200_ALPHA_TEST_GREATER;
95 break;
96 case GL_NOTEQUAL:
97 pp_misc |= R200_ALPHA_TEST_NEQUAL;
98 break;
99 case GL_GEQUAL:
100 pp_misc |= R200_ALPHA_TEST_GEQUAL;
101 break;
102 case GL_ALWAYS:
103 pp_misc |= R200_ALPHA_TEST_PASS;
104 break;
105 }
106
107 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
108 }
109
110 static void r200BlendColor( GLcontext *ctx, const GLfloat cf[4] )
111 {
112 GLubyte color[4];
113 r200ContextPtr rmesa = R200_CONTEXT(ctx);
114 R200_STATECHANGE( rmesa, ctx );
115 CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]);
116 CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]);
117 CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]);
118 CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]);
119 if (rmesa->r200Screen->drmSupportsBlendColor)
120 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = r200PackColor( 4, color[0], color[1], color[2], color[3] );
121 }
122
123 /**
124 * Calculate the hardware blend factor setting. This same function is used
125 * for source and destination of both alpha and RGB.
126 *
127 * \returns
128 * The hardware register value for the specified blend factor. This value
129 * will need to be shifted into the correct position for either source or
130 * destination factor.
131 *
132 * \todo
133 * Since the two cases where source and destination are handled differently
134 * are essentially error cases, they should never happen. Determine if these
135 * cases can be removed.
136 */
137 static int blend_factor( GLenum factor, GLboolean is_src )
138 {
139 int func;
140
141 switch ( factor ) {
142 case GL_ZERO:
143 func = R200_BLEND_GL_ZERO;
144 break;
145 case GL_ONE:
146 func = R200_BLEND_GL_ONE;
147 break;
148 case GL_DST_COLOR:
149 func = R200_BLEND_GL_DST_COLOR;
150 break;
151 case GL_ONE_MINUS_DST_COLOR:
152 func = R200_BLEND_GL_ONE_MINUS_DST_COLOR;
153 break;
154 case GL_SRC_COLOR:
155 func = R200_BLEND_GL_SRC_COLOR;
156 break;
157 case GL_ONE_MINUS_SRC_COLOR:
158 func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR;
159 break;
160 case GL_SRC_ALPHA:
161 func = R200_BLEND_GL_SRC_ALPHA;
162 break;
163 case GL_ONE_MINUS_SRC_ALPHA:
164 func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA;
165 break;
166 case GL_DST_ALPHA:
167 func = R200_BLEND_GL_DST_ALPHA;
168 break;
169 case GL_ONE_MINUS_DST_ALPHA:
170 func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA;
171 break;
172 case GL_SRC_ALPHA_SATURATE:
173 func = (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : R200_BLEND_GL_ZERO;
174 break;
175 case GL_CONSTANT_COLOR:
176 func = R200_BLEND_GL_CONST_COLOR;
177 break;
178 case GL_ONE_MINUS_CONSTANT_COLOR:
179 func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR;
180 break;
181 case GL_CONSTANT_ALPHA:
182 func = R200_BLEND_GL_CONST_ALPHA;
183 break;
184 case GL_ONE_MINUS_CONSTANT_ALPHA:
185 func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA;
186 break;
187 default:
188 func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO;
189 }
190 return func;
191 }
192
193 /**
194 * Sets both the blend equation and the blend function.
195 * This is done in a single
196 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
197 * change the interpretation of the blend function.
198 * Also, make sure that blend function and blend equation are set to their default
199 * value if color blending is not enabled, since at least blend equations GL_MIN
200 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
201 * unknown reasons.
202 */
203 static void r200_set_blend_state( GLcontext * ctx )
204 {
205 r200ContextPtr rmesa = R200_CONTEXT(ctx);
206 GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &
207 ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE);
208
209 int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
210 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
211 int eqn = R200_COMB_FCN_ADD_CLAMP;
212 int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
213 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
214 int eqnA = R200_COMB_FCN_ADD_CLAMP;
215
216 R200_STATECHANGE( rmesa, ctx );
217
218 if (rmesa->r200Screen->drmSupportsBlendColor) {
219 if (ctx->Color.ColorLogicOpEnabled) {
220 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
221 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
222 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
223 return;
224 } else if (ctx->Color.BlendEnabled) {
225 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE;
226 }
227 else {
228 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
229 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
230 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
231 return;
232 }
233 }
234 else {
235 if (ctx->Color.ColorLogicOpEnabled) {
236 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
237 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
238 return;
239 } else if (ctx->Color.BlendEnabled) {
240 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE;
241 }
242 else {
243 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
244 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
245 return;
246 }
247 }
248
249 func = (blend_factor( ctx->Color.BlendSrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
250 (blend_factor( ctx->Color.BlendDstRGB, GL_FALSE ) << R200_DST_BLEND_SHIFT);
251
252 switch(ctx->Color.BlendEquationRGB) {
253 case GL_FUNC_ADD:
254 eqn = R200_COMB_FCN_ADD_CLAMP;
255 break;
256
257 case GL_FUNC_SUBTRACT:
258 eqn = R200_COMB_FCN_SUB_CLAMP;
259 break;
260
261 case GL_FUNC_REVERSE_SUBTRACT:
262 eqn = R200_COMB_FCN_RSUB_CLAMP;
263 break;
264
265 case GL_MIN:
266 eqn = R200_COMB_FCN_MIN;
267 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
268 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
269 break;
270
271 case GL_MAX:
272 eqn = R200_COMB_FCN_MAX;
273 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
274 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
275 break;
276
277 default:
278 fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
279 __FUNCTION__, __LINE__, ctx->Color.BlendEquationRGB );
280 return;
281 }
282
283 if (!rmesa->r200Screen->drmSupportsBlendColor) {
284 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
285 return;
286 }
287
288 funcA = (blend_factor( ctx->Color.BlendSrcA, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
289 (blend_factor( ctx->Color.BlendDstA, GL_FALSE ) << R200_DST_BLEND_SHIFT);
290
291 switch(ctx->Color.BlendEquationA) {
292 case GL_FUNC_ADD:
293 eqnA = R200_COMB_FCN_ADD_CLAMP;
294 break;
295
296 case GL_FUNC_SUBTRACT:
297 eqnA = R200_COMB_FCN_SUB_CLAMP;
298 break;
299
300 case GL_FUNC_REVERSE_SUBTRACT:
301 eqnA = R200_COMB_FCN_RSUB_CLAMP;
302 break;
303
304 case GL_MIN:
305 eqnA = R200_COMB_FCN_MIN;
306 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
307 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
308 break;
309
310 case GL_MAX:
311 eqnA = R200_COMB_FCN_MAX;
312 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
313 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
314 break;
315
316 default:
317 fprintf( stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n",
318 __FUNCTION__, __LINE__, ctx->Color.BlendEquationA );
319 return;
320 }
321
322 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqnA | funcA;
323 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
324
325 }
326
327 static void r200BlendEquationSeparate( GLcontext *ctx,
328 GLenum modeRGB, GLenum modeA )
329 {
330 r200_set_blend_state( ctx );
331 }
332
333 static void r200BlendFuncSeparate( GLcontext *ctx,
334 GLenum sfactorRGB, GLenum dfactorRGB,
335 GLenum sfactorA, GLenum dfactorA )
336 {
337 r200_set_blend_state( ctx );
338 }
339
340
341 /* =============================================================
342 * Depth testing
343 */
344
345 static void r200DepthFunc( GLcontext *ctx, GLenum func )
346 {
347 r200ContextPtr rmesa = R200_CONTEXT(ctx);
348
349 R200_STATECHANGE( rmesa, ctx );
350 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK;
351
352 switch ( ctx->Depth.Func ) {
353 case GL_NEVER:
354 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER;
355 break;
356 case GL_LESS:
357 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS;
358 break;
359 case GL_EQUAL:
360 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL;
361 break;
362 case GL_LEQUAL:
363 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL;
364 break;
365 case GL_GREATER:
366 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER;
367 break;
368 case GL_NOTEQUAL:
369 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL;
370 break;
371 case GL_GEQUAL:
372 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL;
373 break;
374 case GL_ALWAYS:
375 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS;
376 break;
377 }
378 }
379
380 static void r200ClearDepth( GLcontext *ctx, GLclampd d )
381 {
382 r200ContextPtr rmesa = R200_CONTEXT(ctx);
383 GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
384 R200_DEPTH_FORMAT_MASK);
385
386 switch ( format ) {
387 case R200_DEPTH_FORMAT_16BIT_INT_Z:
388 rmesa->state.depth.clear = d * 0x0000ffff;
389 break;
390 case R200_DEPTH_FORMAT_24BIT_INT_Z:
391 rmesa->state.depth.clear = d * 0x00ffffff;
392 break;
393 }
394 }
395
396 static void r200DepthMask( GLcontext *ctx, GLboolean flag )
397 {
398 r200ContextPtr rmesa = R200_CONTEXT(ctx);
399 R200_STATECHANGE( rmesa, ctx );
400
401 if ( ctx->Depth.Mask ) {
402 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE;
403 } else {
404 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE;
405 }
406 }
407
408
409 /* =============================================================
410 * Fog
411 */
412
413
414 static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
415 {
416 r200ContextPtr rmesa = R200_CONTEXT(ctx);
417 union { int i; float f; } c, d;
418 GLchan col[4];
419 GLuint i;
420
421 c.i = rmesa->hw.fog.cmd[FOG_C];
422 d.i = rmesa->hw.fog.cmd[FOG_D];
423
424 switch (pname) {
425 case GL_FOG_MODE:
426 if (!ctx->Fog.Enabled)
427 return;
428 R200_STATECHANGE(rmesa, tcl);
429 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
430 switch (ctx->Fog.Mode) {
431 case GL_LINEAR:
432 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR;
433 if (ctx->Fog.Start == ctx->Fog.End) {
434 c.f = 1.0F;
435 d.f = 1.0F;
436 }
437 else {
438 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
439 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
440 }
441 break;
442 case GL_EXP:
443 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP;
444 c.f = 0.0;
445 d.f = -ctx->Fog.Density;
446 break;
447 case GL_EXP2:
448 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2;
449 c.f = 0.0;
450 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
451 break;
452 default:
453 return;
454 }
455 break;
456 case GL_FOG_DENSITY:
457 switch (ctx->Fog.Mode) {
458 case GL_EXP:
459 c.f = 0.0;
460 d.f = -ctx->Fog.Density;
461 break;
462 case GL_EXP2:
463 c.f = 0.0;
464 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
465 break;
466 default:
467 break;
468 }
469 break;
470 case GL_FOG_START:
471 case GL_FOG_END:
472 if (ctx->Fog.Mode == GL_LINEAR) {
473 if (ctx->Fog.Start == ctx->Fog.End) {
474 c.f = 1.0F;
475 d.f = 1.0F;
476 } else {
477 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
478 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
479 }
480 }
481 break;
482 case GL_FOG_COLOR:
483 R200_STATECHANGE( rmesa, ctx );
484 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
485 i = r200PackColor( 4, col[0], col[1], col[2], 0 );
486 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK;
487 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
488 break;
489 case GL_FOG_COORD_SRC: {
490 GLuint out_0 = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0];
491 GLuint fog = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR];
492
493 fog &= ~R200_FOG_USE_MASK;
494 if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD || ctx->VertexProgram.Enabled) {
495 fog |= R200_FOG_USE_VTX_FOG;
496 out_0 |= R200_VTX_DISCRETE_FOG;
497 }
498 else {
499 fog |= R200_FOG_USE_SPEC_ALPHA;
500 out_0 &= ~R200_VTX_DISCRETE_FOG;
501 }
502
503 if ( fog != rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] ) {
504 R200_STATECHANGE( rmesa, ctx );
505 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog;
506 }
507
508 if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) {
509 R200_STATECHANGE( rmesa, vtx );
510 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0;
511 }
512
513 break;
514 }
515 default:
516 return;
517 }
518
519 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
520 R200_STATECHANGE( rmesa, fog );
521 rmesa->hw.fog.cmd[FOG_C] = c.i;
522 rmesa->hw.fog.cmd[FOG_D] = d.i;
523 }
524 }
525
526
527 /* =============================================================
528 * Scissoring
529 */
530
531
532 static GLboolean intersect_rect( drm_clip_rect_t *out,
533 drm_clip_rect_t *a,
534 drm_clip_rect_t *b )
535 {
536 *out = *a;
537 if ( b->x1 > out->x1 ) out->x1 = b->x1;
538 if ( b->y1 > out->y1 ) out->y1 = b->y1;
539 if ( b->x2 < out->x2 ) out->x2 = b->x2;
540 if ( b->y2 < out->y2 ) out->y2 = b->y2;
541 if ( out->x1 >= out->x2 ) return GL_FALSE;
542 if ( out->y1 >= out->y2 ) return GL_FALSE;
543 return GL_TRUE;
544 }
545
546
547 void r200RecalcScissorRects( r200ContextPtr rmesa )
548 {
549 drm_clip_rect_t *out;
550 int i;
551
552 /* Grow cliprect store?
553 */
554 if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
555 while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
556 rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
557 rmesa->state.scissor.numAllocedClipRects *= 2;
558 }
559
560 if (rmesa->state.scissor.pClipRects)
561 FREE(rmesa->state.scissor.pClipRects);
562
563 rmesa->state.scissor.pClipRects =
564 MALLOC( rmesa->state.scissor.numAllocedClipRects *
565 sizeof(drm_clip_rect_t) );
566
567 if ( rmesa->state.scissor.pClipRects == NULL ) {
568 rmesa->state.scissor.numAllocedClipRects = 0;
569 return;
570 }
571 }
572
573 out = rmesa->state.scissor.pClipRects;
574 rmesa->state.scissor.numClipRects = 0;
575
576 for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
577 if ( intersect_rect( out,
578 &rmesa->pClipRects[i],
579 &rmesa->state.scissor.rect ) ) {
580 rmesa->state.scissor.numClipRects++;
581 out++;
582 }
583 }
584 }
585
586
587 static void r200UpdateScissor( GLcontext *ctx )
588 {
589 r200ContextPtr rmesa = R200_CONTEXT(ctx);
590
591 if ( rmesa->dri.drawable ) {
592 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
593
594 int x = ctx->Scissor.X;
595 int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
596 int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
597 int h = dPriv->h - ctx->Scissor.Y - 1;
598
599 rmesa->state.scissor.rect.x1 = x + dPriv->x;
600 rmesa->state.scissor.rect.y1 = y + dPriv->y;
601 rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
602 rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
603
604 r200RecalcScissorRects( rmesa );
605 }
606 }
607
608
609 static void r200Scissor( GLcontext *ctx,
610 GLint x, GLint y, GLsizei w, GLsizei h )
611 {
612 r200ContextPtr rmesa = R200_CONTEXT(ctx);
613
614 if ( ctx->Scissor.Enabled ) {
615 R200_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
616 r200UpdateScissor( ctx );
617 }
618
619 }
620
621
622 /* =============================================================
623 * Culling
624 */
625
626 static void r200CullFace( GLcontext *ctx, GLenum unused )
627 {
628 r200ContextPtr rmesa = R200_CONTEXT(ctx);
629 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
630 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
631
632 s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
633 t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
634
635 if ( ctx->Polygon.CullFlag ) {
636 switch ( ctx->Polygon.CullFaceMode ) {
637 case GL_FRONT:
638 s &= ~R200_FFACE_SOLID;
639 t |= R200_CULL_FRONT;
640 break;
641 case GL_BACK:
642 s &= ~R200_BFACE_SOLID;
643 t |= R200_CULL_BACK;
644 break;
645 case GL_FRONT_AND_BACK:
646 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
647 t |= (R200_CULL_FRONT | R200_CULL_BACK);
648 break;
649 }
650 }
651
652 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
653 R200_STATECHANGE(rmesa, set );
654 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
655 }
656
657 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
658 R200_STATECHANGE(rmesa, tcl );
659 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
660 }
661 }
662
663 static void r200FrontFace( GLcontext *ctx, GLenum mode )
664 {
665 r200ContextPtr rmesa = R200_CONTEXT(ctx);
666
667 R200_STATECHANGE( rmesa, set );
668 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
669
670 R200_STATECHANGE( rmesa, tcl );
671 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
672
673 switch ( mode ) {
674 case GL_CW:
675 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW;
676 break;
677 case GL_CCW:
678 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CCW;
679 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW;
680 break;
681 }
682 }
683
684 /* =============================================================
685 * Point state
686 */
687 static void r200PointSize( GLcontext *ctx, GLfloat size )
688 {
689 r200ContextPtr rmesa = R200_CONTEXT(ctx);
690 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
691
692 R200_STATECHANGE( rmesa, cst );
693 R200_STATECHANGE( rmesa, ptp );
694 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff;
695 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0));
696 /* this is the size param of the point size calculation (point size reg value
697 is not used when calculation is active). */
698 fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size;
699 }
700
701 static void r200PointParameter( GLcontext *ctx, GLenum pname, const GLfloat *params)
702 {
703 r200ContextPtr rmesa = R200_CONTEXT(ctx);
704 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
705
706 switch (pname) {
707 case GL_POINT_SIZE_MIN:
708 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
709 R200_STATECHANGE( rmesa, lin );
710 R200_STATECHANGE( rmesa, ptp );
711 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff;
712 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16;
713 fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize;
714 break;
715 case GL_POINT_SIZE_MAX:
716 R200_STATECHANGE( rmesa, cst );
717 R200_STATECHANGE( rmesa, ptp );
718 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff;
719 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16;
720 fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize;
721 break;
722 case GL_POINT_DISTANCE_ATTENUATION:
723 R200_STATECHANGE( rmesa, vtx );
724 R200_STATECHANGE( rmesa, spr );
725 R200_STATECHANGE( rmesa, ptp );
726 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
727 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &=
728 ~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE);
729 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
730 r200ValidateState looks like overkill */
731 if (ctx->Point.Params[0] != 1.0 ||
732 ctx->Point.Params[1] != 0.0 ||
733 ctx->Point.Params[2] != 0.0 ||
734 (ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) {
735 /* all we care for vp would be the ps_se_sel_state setting */
736 fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2];
737 fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1];
738 fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0];
739 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST;
740 if (ctx->Point.Params[1] == 0.0)
741 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO;
742 /* FIXME: setting this here doesn't look quite ok - we only want to do
743 that if we're actually drawing points probably */
744 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE;
745 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE;
746 }
747 else {
748 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
749 R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST;
750 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE;
751 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE;
752 }
753 break;
754 case GL_POINT_FADE_THRESHOLD_SIZE:
755 /* don't support multisampling, so doesn't matter. */
756 break;
757 /* can't do these but don't need them.
758 case GL_POINT_SPRITE_R_MODE_NV:
759 case GL_POINT_SPRITE_COORD_ORIGIN: */
760 default:
761 fprintf(stderr, "bad pname parameter in r200PointParameter\n");
762 return;
763 }
764 }
765
766 /* =============================================================
767 * Line state
768 */
769 static void r200LineWidth( GLcontext *ctx, GLfloat widthf )
770 {
771 r200ContextPtr rmesa = R200_CONTEXT(ctx);
772
773 R200_STATECHANGE( rmesa, lin );
774 R200_STATECHANGE( rmesa, set );
775
776 /* Line width is stored in U6.4 format.
777 */
778 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
779 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Line._Width * 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 u_int32_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 * _NormDirection
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->_NormDirection[0];
1271 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1272 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[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 void r200UpdateWindow( GLcontext *ctx )
1696 {
1697 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1698 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1699 GLfloat xoffset = (GLfloat)dPriv->x;
1700 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1701 const GLfloat *v = ctx->Viewport._WindowMap.m;
1702
1703 float_ui32_type sx = { v[MAT_SX] };
1704 float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
1705 float_ui32_type sy = { - v[MAT_SY] };
1706 float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
1707 float_ui32_type sz = { v[MAT_SZ] * rmesa->state.depth.scale };
1708 float_ui32_type tz = { v[MAT_TZ] * rmesa->state.depth.scale };
1709
1710 R200_FIREVERTICES( rmesa );
1711 R200_STATECHANGE( rmesa, vpt );
1712
1713 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32;
1714 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1715 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32;
1716 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1717 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32;
1718 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1719 }
1720
1721
1722
1723 static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1724 GLsizei width, GLsizei height )
1725 {
1726 /* Don't pipeline viewport changes, conflict with window offset
1727 * setting below. Could apply deltas to rescue pipelined viewport
1728 * values, or keep the originals hanging around.
1729 */
1730 r200UpdateWindow( ctx );
1731 }
1732
1733 static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1734 GLclampd farval )
1735 {
1736 r200UpdateWindow( ctx );
1737 }
1738
1739 void r200UpdateViewportOffset( GLcontext *ctx )
1740 {
1741 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1742 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1743 GLfloat xoffset = (GLfloat)dPriv->x;
1744 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1745 const GLfloat *v = ctx->Viewport._WindowMap.m;
1746
1747 float_ui32_type tx;
1748 float_ui32_type ty;
1749
1750 tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X;
1751 ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1752
1753 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
1754 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
1755 {
1756 /* Note: this should also modify whatever data the context reset
1757 * code uses...
1758 */
1759 R200_STATECHANGE( rmesa, vpt );
1760 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1761 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1762
1763 /* update polygon stipple x/y screen offset */
1764 {
1765 GLuint stx, sty;
1766 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1767
1768 m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1769 R200_STIPPLE_Y_OFFSET_MASK);
1770
1771 /* add magic offsets, then invert */
1772 stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1773 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1774 & R200_STIPPLE_COORD_MASK);
1775
1776 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1777 (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1778
1779 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1780 R200_STATECHANGE( rmesa, msc );
1781 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1782 }
1783 }
1784 }
1785
1786 r200UpdateScissor( ctx );
1787 }
1788
1789
1790
1791 /* =============================================================
1792 * Miscellaneous
1793 */
1794
1795 static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1796 {
1797 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1798 GLubyte color[4];
1799 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1800 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1801 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1802 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1803 rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp,
1804 color[0], color[1],
1805 color[2], color[3] );
1806 }
1807
1808
1809 static void r200RenderMode( GLcontext *ctx, GLenum mode )
1810 {
1811 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1812 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1813 }
1814
1815
1816 static GLuint r200_rop_tab[] = {
1817 R200_ROP_CLEAR,
1818 R200_ROP_AND,
1819 R200_ROP_AND_REVERSE,
1820 R200_ROP_COPY,
1821 R200_ROP_AND_INVERTED,
1822 R200_ROP_NOOP,
1823 R200_ROP_XOR,
1824 R200_ROP_OR,
1825 R200_ROP_NOR,
1826 R200_ROP_EQUIV,
1827 R200_ROP_INVERT,
1828 R200_ROP_OR_REVERSE,
1829 R200_ROP_COPY_INVERTED,
1830 R200_ROP_OR_INVERTED,
1831 R200_ROP_NAND,
1832 R200_ROP_SET,
1833 };
1834
1835 static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1836 {
1837 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1838 GLuint rop = (GLuint)opcode - GL_CLEAR;
1839
1840 ASSERT( rop < 16 );
1841
1842 R200_STATECHANGE( rmesa, msk );
1843 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1844 }
1845
1846
1847 void r200SetCliprects( r200ContextPtr rmesa, GLenum mode )
1848 {
1849 __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
1850 __DRIdrawablePrivate *const readable = rmesa->dri.readable;
1851 GLframebuffer *const draw_fb = (GLframebuffer*) drawable->driverPrivate;
1852 GLframebuffer *const read_fb = (GLframebuffer*) readable->driverPrivate;
1853
1854 switch ( mode ) {
1855 case GL_FRONT_LEFT:
1856 rmesa->numClipRects = drawable->numClipRects;
1857 rmesa->pClipRects = drawable->pClipRects;
1858 break;
1859 case GL_BACK_LEFT:
1860 /* Can't ignore 2d windows if we are page flipping.
1861 */
1862 if ( drawable->numBackClipRects == 0 || rmesa->doPageFlip ) {
1863 rmesa->numClipRects = drawable->numClipRects;
1864 rmesa->pClipRects = drawable->pClipRects;
1865 }
1866 else {
1867 rmesa->numClipRects = drawable->numBackClipRects;
1868 rmesa->pClipRects = drawable->pBackClipRects;
1869 }
1870 break;
1871 default:
1872 fprintf(stderr, "bad mode in r200SetCliprects\n");
1873 return;
1874 }
1875
1876 if ((draw_fb->Width != drawable->w) || (draw_fb->Height != drawable->h)) {
1877 _mesa_resize_framebuffer(rmesa->glCtx, draw_fb,
1878 drawable->w, drawable->h);
1879 draw_fb->Initialized = GL_TRUE;
1880 }
1881
1882 if (drawable != readable) {
1883 if ((read_fb->Width != readable->w) ||
1884 (read_fb->Height != readable->h)) {
1885 _mesa_resize_framebuffer(rmesa->glCtx, read_fb,
1886 readable->w, readable->h);
1887 read_fb->Initialized = GL_TRUE;
1888 }
1889 }
1890
1891 if (rmesa->state.scissor.enabled)
1892 r200RecalcScissorRects( rmesa );
1893 }
1894
1895
1896 static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1897 {
1898 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1899
1900 if (R200_DEBUG & DEBUG_DRI)
1901 fprintf(stderr, "%s %s\n", __FUNCTION__,
1902 _mesa_lookup_enum_by_nr( mode ));
1903
1904 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1905
1906 /*
1907 * _ColorDrawBufferMask is easier to cope with than <mode>.
1908 * Check for software fallback, update cliprects.
1909 */
1910 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
1911 case BUFFER_BIT_FRONT_LEFT:
1912 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1913 r200SetCliprects( rmesa, GL_FRONT_LEFT );
1914 break;
1915 case BUFFER_BIT_BACK_LEFT:
1916 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1917 r200SetCliprects( rmesa, GL_BACK_LEFT );
1918 break;
1919 default:
1920 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1921 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1922 return;
1923 }
1924
1925 /* We'll set the drawing engine's offset/pitch parameters later
1926 * when we update other state.
1927 */
1928 }
1929
1930
1931 static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1932 {
1933 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1934 }
1935
1936 /* =============================================================
1937 * State enable/disable
1938 */
1939
1940 static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1941 {
1942 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1943 GLuint p, flag;
1944
1945 if ( R200_DEBUG & DEBUG_STATE )
1946 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1947 _mesa_lookup_enum_by_nr( cap ),
1948 state ? "GL_TRUE" : "GL_FALSE" );
1949
1950 switch ( cap ) {
1951 /* Fast track this one...
1952 */
1953 case GL_TEXTURE_1D:
1954 case GL_TEXTURE_2D:
1955 case GL_TEXTURE_3D:
1956 break;
1957
1958 case GL_ALPHA_TEST:
1959 R200_STATECHANGE( rmesa, ctx );
1960 if (state) {
1961 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1962 } else {
1963 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1964 }
1965 break;
1966
1967 case GL_BLEND:
1968 case GL_COLOR_LOGIC_OP:
1969 r200_set_blend_state( ctx );
1970 break;
1971
1972 case GL_CLIP_PLANE0:
1973 case GL_CLIP_PLANE1:
1974 case GL_CLIP_PLANE2:
1975 case GL_CLIP_PLANE3:
1976 case GL_CLIP_PLANE4:
1977 case GL_CLIP_PLANE5:
1978 p = cap-GL_CLIP_PLANE0;
1979 R200_STATECHANGE( rmesa, tcl );
1980 if (state) {
1981 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1982 r200ClipPlane( ctx, cap, NULL );
1983 }
1984 else {
1985 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1986 }
1987 break;
1988
1989 case GL_COLOR_MATERIAL:
1990 r200ColorMaterial( ctx, 0, 0 );
1991 r200UpdateMaterial( ctx );
1992 break;
1993
1994 case GL_CULL_FACE:
1995 r200CullFace( ctx, 0 );
1996 break;
1997
1998 case GL_DEPTH_TEST:
1999 R200_STATECHANGE(rmesa, ctx );
2000 if ( state ) {
2001 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
2002 } else {
2003 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
2004 }
2005 break;
2006
2007 case GL_DITHER:
2008 R200_STATECHANGE(rmesa, ctx );
2009 if ( state ) {
2010 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
2011 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
2012 } else {
2013 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
2014 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
2015 }
2016 break;
2017
2018 case GL_FOG:
2019 R200_STATECHANGE(rmesa, ctx );
2020 if ( state ) {
2021 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
2022 r200Fogfv( ctx, GL_FOG_MODE, NULL );
2023 } else {
2024 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
2025 R200_STATECHANGE(rmesa, tcl);
2026 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
2027 }
2028 r200UpdateSpecular( ctx ); /* for PK_SPEC */
2029 if (rmesa->TclFallback)
2030 r200ChooseVertexState( ctx );
2031 _mesa_allow_light_in_model( ctx, !state );
2032 break;
2033
2034 case GL_LIGHT0:
2035 case GL_LIGHT1:
2036 case GL_LIGHT2:
2037 case GL_LIGHT3:
2038 case GL_LIGHT4:
2039 case GL_LIGHT5:
2040 case GL_LIGHT6:
2041 case GL_LIGHT7:
2042 R200_STATECHANGE(rmesa, tcl);
2043 p = cap - GL_LIGHT0;
2044 if (p&1)
2045 flag = (R200_LIGHT_1_ENABLE |
2046 R200_LIGHT_1_ENABLE_AMBIENT |
2047 R200_LIGHT_1_ENABLE_SPECULAR);
2048 else
2049 flag = (R200_LIGHT_0_ENABLE |
2050 R200_LIGHT_0_ENABLE_AMBIENT |
2051 R200_LIGHT_0_ENABLE_SPECULAR);
2052
2053 if (state)
2054 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
2055 else
2056 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
2057
2058 /*
2059 */
2060 update_light_colors( ctx, p );
2061 break;
2062
2063 case GL_LIGHTING:
2064 r200UpdateSpecular(ctx);
2065 /* for reflection map fixup - might set recheck_texgen for all units too */
2066 rmesa->NewGLState |= _NEW_TEXTURE;
2067 break;
2068
2069 case GL_LINE_SMOOTH:
2070 R200_STATECHANGE( rmesa, ctx );
2071 if ( state ) {
2072 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
2073 } else {
2074 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
2075 }
2076 break;
2077
2078 case GL_LINE_STIPPLE:
2079 R200_STATECHANGE( rmesa, set );
2080 if ( state ) {
2081 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
2082 } else {
2083 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
2084 }
2085 break;
2086
2087 case GL_NORMALIZE:
2088 R200_STATECHANGE( rmesa, tcl );
2089 if ( state ) {
2090 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
2091 } else {
2092 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
2093 }
2094 break;
2095
2096 /* Pointsize registers on r200 only work for point sprites, and point smooth
2097 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
2098 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
2099 * is enough to satisfy conform.
2100 */
2101 case GL_POINT_SMOOTH:
2102 break;
2103
2104 /* These don't really do anything, as we don't use the 3vtx
2105 * primitives yet.
2106 */
2107 #if 0
2108 case GL_POLYGON_OFFSET_POINT:
2109 R200_STATECHANGE( rmesa, set );
2110 if ( state ) {
2111 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
2112 } else {
2113 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
2114 }
2115 break;
2116
2117 case GL_POLYGON_OFFSET_LINE:
2118 R200_STATECHANGE( rmesa, set );
2119 if ( state ) {
2120 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
2121 } else {
2122 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
2123 }
2124 break;
2125 #endif
2126
2127 case GL_POINT_SPRITE_ARB:
2128 R200_STATECHANGE( rmesa, spr );
2129 if ( state ) {
2130 int i;
2131 for (i = 0; i < 6; i++) {
2132 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
2133 ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i);
2134 }
2135 } else {
2136 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
2137 }
2138 break;
2139
2140 case GL_POLYGON_OFFSET_FILL:
2141 R200_STATECHANGE( rmesa, set );
2142 if ( state ) {
2143 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
2144 } else {
2145 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
2146 }
2147 break;
2148
2149 case GL_POLYGON_SMOOTH:
2150 R200_STATECHANGE( rmesa, ctx );
2151 if ( state ) {
2152 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
2153 } else {
2154 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
2155 }
2156 break;
2157
2158 case GL_POLYGON_STIPPLE:
2159 R200_STATECHANGE(rmesa, set );
2160 if ( state ) {
2161 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
2162 } else {
2163 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
2164 }
2165 break;
2166
2167 case GL_RESCALE_NORMAL_EXT: {
2168 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
2169 R200_STATECHANGE( rmesa, tcl );
2170 if ( tmp ) {
2171 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2172 } else {
2173 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2174 }
2175 break;
2176 }
2177
2178 case GL_SCISSOR_TEST:
2179 R200_FIREVERTICES( rmesa );
2180 rmesa->state.scissor.enabled = state;
2181 r200UpdateScissor( ctx );
2182 break;
2183
2184 case GL_STENCIL_TEST:
2185 if ( rmesa->state.stencil.hwBuffer ) {
2186 R200_STATECHANGE( rmesa, ctx );
2187 if ( state ) {
2188 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
2189 } else {
2190 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
2191 }
2192 } else {
2193 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
2194 }
2195 break;
2196
2197 case GL_TEXTURE_GEN_Q:
2198 case GL_TEXTURE_GEN_R:
2199 case GL_TEXTURE_GEN_S:
2200 case GL_TEXTURE_GEN_T:
2201 /* Picked up in r200UpdateTextureState.
2202 */
2203 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
2204 break;
2205
2206 case GL_COLOR_SUM_EXT:
2207 r200UpdateSpecular ( ctx );
2208 break;
2209
2210 case GL_VERTEX_PROGRAM_ARB:
2211 if (!state) {
2212 GLuint i;
2213 rmesa->curr_vp_hw = NULL;
2214 R200_STATECHANGE( rmesa, vap );
2215 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
2216 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2217 not sure about tcl scalar state - we need at least grd
2218 with vert progs too.
2219 ucp looks like it doesn't get overwritten (may even work
2220 with vp for pos-invariant progs if we're lucky) */
2221 R200_STATECHANGE( rmesa, mtl[0] );
2222 R200_STATECHANGE( rmesa, mtl[1] );
2223 R200_STATECHANGE( rmesa, fog );
2224 R200_STATECHANGE( rmesa, glt );
2225 R200_STATECHANGE( rmesa, eye );
2226 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
2227 R200_STATECHANGE( rmesa, mat[i] );
2228 }
2229 for (i = 0 ; i < 8; i++) {
2230 R200_STATECHANGE( rmesa, lit[i] );
2231 }
2232 R200_STATECHANGE( rmesa, tcl );
2233 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
2234 if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
2235 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
2236 }
2237 /* else {
2238 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2239 }*/
2240 }
2241 /* ugly. Need to call everything which might change compsel. */
2242 r200UpdateSpecular( ctx );
2243 #if 0
2244 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2245 but without it doom3 locks up at always the same places. Why? */
2246 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2247 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2248 r200UpdateTextureState( ctx );
2249 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2250 non-current derived enabled values which may revert the state atoms for frag progs even when
2251 they already got disabled... ugh
2252 Should really figure out why we need to call r200UpdateTextureState in the first place */
2253 GLuint unit;
2254 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2255 R200_STATECHANGE( rmesa, pix[unit] );
2256 R200_STATECHANGE( rmesa, tex[unit] );
2257 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2258 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2259 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2260 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2261 we don't announce ATI_fs, right? */
2262 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2263 }
2264 R200_STATECHANGE( rmesa, cst );
2265 R200_STATECHANGE( rmesa, tf );
2266 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2267 #endif
2268 }
2269 else {
2270 /* picked up later */
2271 }
2272 /* call functions which change hw state based on ARB_vp enabled or not. */
2273 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2274 r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
2275 break;
2276
2277 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
2278 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2279 break;
2280
2281 case GL_FRAGMENT_SHADER_ATI:
2282 if ( !state ) {
2283 /* restore normal tex env colors and make sure tex env combine will get updated
2284 mark env atoms dirty (as their data was overwritten by afs even
2285 if they didn't change) and restore tex coord routing */
2286 GLuint unit;
2287 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2288 R200_STATECHANGE( rmesa, pix[unit] );
2289 R200_STATECHANGE( rmesa, tex[unit] );
2290 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2291 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2292 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2293 /* need to guard this with drmSupportsFragmentShader? Should never get here if
2294 we don't announce ATI_fs, right? */
2295 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2296 }
2297 R200_STATECHANGE( rmesa, cst );
2298 R200_STATECHANGE( rmesa, tf );
2299 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2300 }
2301 else {
2302 /* need to mark this dirty as pix/tf atoms have overwritten the data
2303 even if the data in the atoms didn't change */
2304 R200_STATECHANGE( rmesa, atf );
2305 R200_STATECHANGE( rmesa, afs[1] );
2306 /* everything else picked up in r200UpdateTextureState hopefully */
2307 }
2308 break;
2309 default:
2310 return;
2311 }
2312 }
2313
2314
2315 void r200LightingSpaceChange( GLcontext *ctx )
2316 {
2317 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2318 GLboolean tmp;
2319
2320 if (R200_DEBUG & DEBUG_STATE)
2321 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2322 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2323
2324 if (ctx->_NeedEyeCoords)
2325 tmp = ctx->Transform.RescaleNormals;
2326 else
2327 tmp = !ctx->Transform.RescaleNormals;
2328
2329 R200_STATECHANGE( rmesa, tcl );
2330 if ( tmp ) {
2331 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2332 } else {
2333 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2334 }
2335
2336 if (R200_DEBUG & DEBUG_STATE)
2337 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2338 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2339 }
2340
2341 /* =============================================================
2342 * Deferred state management - matrices, textures, other?
2343 */
2344
2345
2346
2347
2348 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2349 {
2350 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2351 int i;
2352
2353
2354 for (i = 0 ; i < 4 ; i++) {
2355 *dest++ = src[i];
2356 *dest++ = src[i+4];
2357 *dest++ = src[i+8];
2358 *dest++ = src[i+12];
2359 }
2360
2361 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2362 }
2363
2364 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2365 {
2366 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2367 memcpy(dest, src, 16*sizeof(float));
2368 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2369 }
2370
2371
2372 static void update_texturematrix( GLcontext *ctx )
2373 {
2374 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2375 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2376 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2377 int unit;
2378
2379 if (R200_DEBUG & DEBUG_STATE)
2380 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2381 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2382
2383 rmesa->TexMatEnabled = 0;
2384 rmesa->TexMatCompSel = 0;
2385
2386 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2387 if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2388 continue;
2389
2390 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2391 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2392 R200_TEXMAT_0_ENABLE) << unit;
2393
2394 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2395
2396 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2397 /* Need to preconcatenate any active texgen
2398 * obj/eyeplane matrices:
2399 */
2400 _math_matrix_mul_matrix( &rmesa->tmpmat,
2401 ctx->TextureMatrixStack[unit].Top,
2402 &rmesa->TexGenMatrix[unit] );
2403 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2404 }
2405 else {
2406 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2407 R200_MTX_TEX0+unit );
2408 }
2409 }
2410 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2411 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2412 R200_MTX_TEX0+unit );
2413 }
2414 }
2415
2416 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2417 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2418 R200_STATECHANGE(rmesa, tcg);
2419 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2420 }
2421
2422 compsel &= ~R200_OUTPUT_TEX_MASK;
2423 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2424 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2425 R200_STATECHANGE(rmesa, vtx);
2426 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2427 }
2428 }
2429
2430
2431
2432 /**
2433 * Tell the card where to render (offset, pitch).
2434 * Effected by glDrawBuffer, etc
2435 */
2436 void
2437 r200UpdateDrawBuffer(GLcontext *ctx)
2438 {
2439 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2440 struct gl_framebuffer *fb = ctx->DrawBuffer;
2441 driRenderbuffer *drb;
2442
2443 if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
2444 /* draw to front */
2445 drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2446 }
2447 else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) {
2448 /* draw to back */
2449 drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2450 }
2451 else {
2452 /* drawing to multiple buffers, or none */
2453 return;
2454 }
2455
2456 assert(drb);
2457 assert(drb->flippedPitch);
2458
2459 R200_STATECHANGE( rmesa, ctx );
2460
2461 /* Note: we used the (possibly) page-flipped values */
2462 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2463 = ((drb->flippedOffset + rmesa->r200Screen->fbLocation)
2464 & R200_COLOROFFSET_MASK);
2465 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2466 if (rmesa->sarea->tiling_enabled) {
2467 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
2468 }
2469 }
2470
2471
2472
2473 void r200ValidateState( GLcontext *ctx )
2474 {
2475 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2476 GLuint new_state = rmesa->NewGLState;
2477
2478 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2479 r200UpdateDrawBuffer(ctx);
2480 }
2481
2482 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) {
2483 r200UpdateTextureState( ctx );
2484 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2485 r200UpdateLocalViewer( ctx );
2486 }
2487
2488 /* FIXME: don't really need most of these when vertex progs are enabled */
2489
2490 /* Need an event driven matrix update?
2491 */
2492 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2493 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2494
2495 /* Need these for lighting (shouldn't upload otherwise)
2496 */
2497 if (new_state & (_NEW_MODELVIEW)) {
2498 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2499 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2500 }
2501
2502 /* Does this need to be triggered on eg. modelview for
2503 * texgen-derived objplane/eyeplane matrices?
2504 */
2505 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2506 update_texturematrix( ctx );
2507 }
2508
2509 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2510 update_light( ctx );
2511 }
2512
2513 /* emit all active clip planes if projection matrix changes.
2514 */
2515 if (new_state & (_NEW_PROJECTION)) {
2516 if (ctx->Transform.ClipPlanesEnabled)
2517 r200UpdateClipPlanes( ctx );
2518 }
2519
2520 if (new_state & (_NEW_PROGRAM|
2521 /* need to test for pretty much anything due to possible parameter bindings */
2522 _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2523 _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2524 _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2525 if (ctx->VertexProgram._Enabled) {
2526 r200SetupVertexProg( ctx );
2527 }
2528 else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2529 }
2530
2531 rmesa->NewGLState = 0;
2532 }
2533
2534
2535 static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2536 {
2537 _swrast_InvalidateState( ctx, new_state );
2538 _swsetup_InvalidateState( ctx, new_state );
2539 _ac_InvalidateState( ctx, new_state );
2540 _tnl_InvalidateState( ctx, new_state );
2541 _ae_invalidate_state( ctx, new_state );
2542 R200_CONTEXT(ctx)->NewGLState |= new_state;
2543 r200VtxfmtInvalidate( ctx );
2544 }
2545
2546 /* A hack. The r200 can actually cope just fine with materials
2547 * between begin/ends, so fix this. But how ?
2548 */
2549 static GLboolean check_material( GLcontext *ctx )
2550 {
2551 TNLcontext *tnl = TNL_CONTEXT(ctx);
2552 GLint i;
2553
2554 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2555 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2556 i++)
2557 if (tnl->vb.AttribPtr[i] &&
2558 tnl->vb.AttribPtr[i]->stride)
2559 return GL_TRUE;
2560
2561 return GL_FALSE;
2562 }
2563
2564 static void r200WrapRunPipeline( GLcontext *ctx )
2565 {
2566 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2567 GLboolean has_material;
2568
2569 if (0)
2570 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2571
2572 /* Validate state:
2573 */
2574 if (rmesa->NewGLState)
2575 r200ValidateState( ctx );
2576
2577 has_material = (ctx->Light.Enabled && check_material( ctx ));
2578
2579 if (has_material) {
2580 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2581 }
2582
2583 /* Run the pipeline.
2584 */
2585 _tnl_run_pipeline( ctx );
2586
2587 if (has_material) {
2588 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2589 }
2590 }
2591
2592
2593 /* Initialize the driver's state functions.
2594 */
2595 void r200InitStateFuncs( struct dd_function_table *functions )
2596 {
2597 functions->UpdateState = r200InvalidateState;
2598 functions->LightingSpaceChange = r200LightingSpaceChange;
2599
2600 functions->DrawBuffer = r200DrawBuffer;
2601 functions->ReadBuffer = r200ReadBuffer;
2602
2603 functions->AlphaFunc = r200AlphaFunc;
2604 functions->BlendColor = r200BlendColor;
2605 functions->BlendEquationSeparate = r200BlendEquationSeparate;
2606 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2607 functions->ClearColor = r200ClearColor;
2608 functions->ClearDepth = r200ClearDepth;
2609 functions->ClearIndex = NULL;
2610 functions->ClearStencil = r200ClearStencil;
2611 functions->ClipPlane = r200ClipPlane;
2612 functions->ColorMask = r200ColorMask;
2613 functions->CullFace = r200CullFace;
2614 functions->DepthFunc = r200DepthFunc;
2615 functions->DepthMask = r200DepthMask;
2616 functions->DepthRange = r200DepthRange;
2617 functions->Enable = r200Enable;
2618 functions->Fogfv = r200Fogfv;
2619 functions->FrontFace = r200FrontFace;
2620 functions->Hint = NULL;
2621 functions->IndexMask = NULL;
2622 functions->LightModelfv = r200LightModelfv;
2623 functions->Lightfv = r200Lightfv;
2624 functions->LineStipple = r200LineStipple;
2625 functions->LineWidth = r200LineWidth;
2626 functions->LogicOpcode = r200LogicOpCode;
2627 functions->PolygonMode = r200PolygonMode;
2628 functions->PolygonOffset = r200PolygonOffset;
2629 functions->PolygonStipple = r200PolygonStipple;
2630 functions->PointParameterfv = r200PointParameter;
2631 functions->PointSize = r200PointSize;
2632 functions->RenderMode = r200RenderMode;
2633 functions->Scissor = r200Scissor;
2634 functions->ShadeModel = r200ShadeModel;
2635 functions->StencilFuncSeparate = r200StencilFuncSeparate;
2636 functions->StencilMaskSeparate = r200StencilMaskSeparate;
2637 functions->StencilOpSeparate = r200StencilOpSeparate;
2638 functions->Viewport = r200Viewport;
2639 }
2640
2641
2642 void r200InitTnlFuncs( GLcontext *ctx )
2643 {
2644 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2645 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2646 }