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