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