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