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