mesa: remove Driver.Hint
[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/colormac.h"
41 #include "main/light.h"
42 #include "main/framebuffer.h"
43 #include "main/fbobject.h"
44 #include "main/stencil.h"
45 #include "main/viewport.h"
46
47 #include "swrast/swrast.h"
48 #include "vbo/vbo.h"
49 #include "tnl/tnl.h"
50 #include "tnl/t_pipeline.h"
51 #include "swrast_setup/swrast_setup.h"
52 #include "drivers/common/meta.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 GLint p;
1117 for (p = 0 ; p < MAX_LIGHTS; p++) {
1118 if (ctx->Light.Light[p].Enabled) {
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
1141 static void r200Lightfv( struct gl_context *ctx, GLenum light,
1142 GLenum pname, const GLfloat *params )
1143 {
1144 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1145 GLint p = light - GL_LIGHT0;
1146 struct gl_light *l = &ctx->Light.Light[p];
1147 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1148
1149
1150 switch (pname) {
1151 case GL_AMBIENT:
1152 case GL_DIFFUSE:
1153 case GL_SPECULAR:
1154 update_light_colors( ctx, p );
1155 break;
1156
1157 case GL_SPOT_DIRECTION:
1158 /* picked up in update_light */
1159 break;
1160
1161 case GL_POSITION: {
1162 /* positions picked up in update_light, but can do flag here */
1163 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1164 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1165
1166 R200_STATECHANGE(rmesa, tcl);
1167 if (l->EyePosition[3] != 0.0F)
1168 rmesa->hw.tcl.cmd[idx] |= flag;
1169 else
1170 rmesa->hw.tcl.cmd[idx] &= ~flag;
1171 break;
1172 }
1173
1174 case GL_SPOT_EXPONENT:
1175 R200_STATECHANGE(rmesa, lit[p]);
1176 fcmd[LIT_SPOT_EXPONENT] = params[0];
1177 break;
1178
1179 case GL_SPOT_CUTOFF: {
1180 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1181 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1182
1183 R200_STATECHANGE(rmesa, lit[p]);
1184 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1185
1186 R200_STATECHANGE(rmesa, tcl);
1187 if (l->SpotCutoff != 180.0F)
1188 rmesa->hw.tcl.cmd[idx] |= flag;
1189 else
1190 rmesa->hw.tcl.cmd[idx] &= ~flag;
1191
1192 break;
1193 }
1194
1195 case GL_CONSTANT_ATTENUATION:
1196 R200_STATECHANGE(rmesa, lit[p]);
1197 fcmd[LIT_ATTEN_CONST] = params[0];
1198 if ( params[0] == 0.0 )
1199 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1200 else
1201 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1202 break;
1203 case GL_LINEAR_ATTENUATION:
1204 R200_STATECHANGE(rmesa, lit[p]);
1205 fcmd[LIT_ATTEN_LINEAR] = params[0];
1206 break;
1207 case GL_QUADRATIC_ATTENUATION:
1208 R200_STATECHANGE(rmesa, lit[p]);
1209 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1210 break;
1211 default:
1212 return;
1213 }
1214
1215 /* Set RANGE_ATTEN only when needed */
1216 switch (pname) {
1217 case GL_POSITION:
1218 case GL_CONSTANT_ATTENUATION:
1219 case GL_LINEAR_ATTENUATION:
1220 case GL_QUADRATIC_ATTENUATION: {
1221 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1222 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1223 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1224 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1225 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1226 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1227
1228 if ( l->EyePosition[3] == 0.0F ||
1229 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1230 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1231 /* Disable attenuation */
1232 icmd[idx] &= ~atten_flag;
1233 } else {
1234 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1235 /* Enable only constant portion of attenuation calculation */
1236 icmd[idx] |= ( atten_flag | atten_const_flag );
1237 } else {
1238 /* Enable full attenuation calculation */
1239 icmd[idx] &= ~atten_const_flag;
1240 icmd[idx] |= atten_flag;
1241 }
1242 }
1243
1244 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1245 break;
1246 }
1247 default:
1248 break;
1249 }
1250 }
1251
1252 static void r200UpdateLocalViewer ( struct gl_context *ctx )
1253 {
1254 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1255 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1256 for these and only these modes). This means specular highlights may turn out
1257 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1258 is not set, though it seems to happen rarely and the effect seems quite
1259 subtle. May need TCL fallback to fix it completely, though I'm not sure
1260 how you'd identify the cases where the specular highlights indeed will
1261 be wrong. Don't know if fglrx does something special in that case.
1262 */
1263 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1264 R200_STATECHANGE( rmesa, tcl );
1265 if (ctx->Light.Model.LocalViewer ||
1266 ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
1267 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1268 else
1269 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1270 }
1271
1272 static void r200LightModelfv( struct gl_context *ctx, GLenum pname,
1273 const GLfloat *param )
1274 {
1275 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1276
1277 switch (pname) {
1278 case GL_LIGHT_MODEL_AMBIENT:
1279 update_global_ambient( ctx );
1280 break;
1281
1282 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1283 r200UpdateLocalViewer( ctx );
1284 break;
1285
1286 case GL_LIGHT_MODEL_TWO_SIDE:
1287 R200_STATECHANGE( rmesa, tcl );
1288 if (ctx->Light.Model.TwoSide)
1289 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1290 else
1291 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1292 if (rmesa->radeon.TclFallback) {
1293 r200ChooseRenderState( ctx );
1294 r200ChooseVertexState( ctx );
1295 }
1296 break;
1297
1298 case GL_LIGHT_MODEL_COLOR_CONTROL:
1299 r200UpdateSpecular(ctx);
1300 break;
1301
1302 default:
1303 break;
1304 }
1305 }
1306
1307 static void r200ShadeModel( struct gl_context *ctx, GLenum mode )
1308 {
1309 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1310 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1311
1312 s &= ~(R200_DIFFUSE_SHADE_MASK |
1313 R200_ALPHA_SHADE_MASK |
1314 R200_SPECULAR_SHADE_MASK |
1315 R200_FOG_SHADE_MASK |
1316 R200_DISC_FOG_SHADE_MASK);
1317
1318 switch ( mode ) {
1319 case GL_FLAT:
1320 s |= (R200_DIFFUSE_SHADE_FLAT |
1321 R200_ALPHA_SHADE_FLAT |
1322 R200_SPECULAR_SHADE_FLAT |
1323 R200_FOG_SHADE_FLAT |
1324 R200_DISC_FOG_SHADE_FLAT);
1325 break;
1326 case GL_SMOOTH:
1327 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1328 R200_ALPHA_SHADE_GOURAUD |
1329 R200_SPECULAR_SHADE_GOURAUD |
1330 R200_FOG_SHADE_GOURAUD |
1331 R200_DISC_FOG_SHADE_GOURAUD);
1332 break;
1333 default:
1334 return;
1335 }
1336
1337 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1338 R200_STATECHANGE( rmesa, set );
1339 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1340 }
1341 }
1342
1343
1344 /* =============================================================
1345 * User clip planes
1346 */
1347
1348 static void r200ClipPlane( struct gl_context *ctx, GLenum plane, const GLfloat *eq )
1349 {
1350 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1351 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1352 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1353
1354 R200_STATECHANGE( rmesa, ucp[p] );
1355 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1356 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1357 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1358 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1359 }
1360
1361 static void r200UpdateClipPlanes( struct gl_context *ctx )
1362 {
1363 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1364 GLuint p;
1365
1366 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1367 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1368 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1369
1370 R200_STATECHANGE( rmesa, ucp[p] );
1371 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1372 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1373 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1374 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1375 }
1376 }
1377 }
1378
1379
1380 /* =============================================================
1381 * Stencil
1382 */
1383
1384 static void
1385 r200StencilFuncSeparate( struct gl_context *ctx, GLenum face, GLenum func,
1386 GLint ref, GLuint mask )
1387 {
1388 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1389 GLuint refmask = ((_mesa_get_stencil_ref(ctx, 0) << R200_STENCIL_REF_SHIFT) |
1390 ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT));
1391
1392 R200_STATECHANGE( rmesa, ctx );
1393 R200_STATECHANGE( rmesa, msk );
1394
1395 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1396 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1397 R200_STENCIL_VALUE_MASK);
1398
1399 switch ( ctx->Stencil.Function[0] ) {
1400 case GL_NEVER:
1401 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1402 break;
1403 case GL_LESS:
1404 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1405 break;
1406 case GL_EQUAL:
1407 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1408 break;
1409 case GL_LEQUAL:
1410 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1411 break;
1412 case GL_GREATER:
1413 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1414 break;
1415 case GL_NOTEQUAL:
1416 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1417 break;
1418 case GL_GEQUAL:
1419 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1420 break;
1421 case GL_ALWAYS:
1422 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1423 break;
1424 }
1425
1426 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1427 }
1428
1429 static void
1430 r200StencilMaskSeparate( struct gl_context *ctx, GLenum face, GLuint mask )
1431 {
1432 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1433
1434 R200_STATECHANGE( rmesa, msk );
1435 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1436 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1437 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT);
1438 }
1439
1440 static void
1441 r200StencilOpSeparate( struct gl_context *ctx, GLenum face, GLenum fail,
1442 GLenum zfail, GLenum zpass )
1443 {
1444 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1445
1446 R200_STATECHANGE( rmesa, ctx );
1447 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1448 R200_STENCIL_ZFAIL_MASK |
1449 R200_STENCIL_ZPASS_MASK);
1450
1451 switch ( ctx->Stencil.FailFunc[0] ) {
1452 case GL_KEEP:
1453 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1454 break;
1455 case GL_ZERO:
1456 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1457 break;
1458 case GL_REPLACE:
1459 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1460 break;
1461 case GL_INCR:
1462 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1463 break;
1464 case GL_DECR:
1465 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1466 break;
1467 case GL_INCR_WRAP_EXT:
1468 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1469 break;
1470 case GL_DECR_WRAP_EXT:
1471 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1472 break;
1473 case GL_INVERT:
1474 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1475 break;
1476 }
1477
1478 switch ( ctx->Stencil.ZFailFunc[0] ) {
1479 case GL_KEEP:
1480 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1481 break;
1482 case GL_ZERO:
1483 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1484 break;
1485 case GL_REPLACE:
1486 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1487 break;
1488 case GL_INCR:
1489 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1490 break;
1491 case GL_DECR:
1492 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1493 break;
1494 case GL_INCR_WRAP_EXT:
1495 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1496 break;
1497 case GL_DECR_WRAP_EXT:
1498 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1499 break;
1500 case GL_INVERT:
1501 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1502 break;
1503 }
1504
1505 switch ( ctx->Stencil.ZPassFunc[0] ) {
1506 case GL_KEEP:
1507 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1508 break;
1509 case GL_ZERO:
1510 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1511 break;
1512 case GL_REPLACE:
1513 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1514 break;
1515 case GL_INCR:
1516 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1517 break;
1518 case GL_DECR:
1519 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1520 break;
1521 case GL_INCR_WRAP_EXT:
1522 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1523 break;
1524 case GL_DECR_WRAP_EXT:
1525 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1526 break;
1527 case GL_INVERT:
1528 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1529 break;
1530 }
1531 }
1532
1533
1534 /* =============================================================
1535 * Window position and viewport transformation
1536 */
1537
1538 /**
1539 * Called when window size or position changes or viewport or depth range
1540 * state is changed. We update the hardware viewport state here.
1541 */
1542 void r200UpdateWindow( struct gl_context *ctx )
1543 {
1544 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1545 __DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon);
1546 GLfloat xoffset = 0;
1547 GLfloat yoffset = dPriv ? (GLfloat) dPriv->h : 0;
1548 const GLboolean render_to_fbo = (ctx->DrawBuffer ? _mesa_is_user_fbo(ctx->DrawBuffer) : 0);
1549 float scale[3], translate[3];
1550 GLfloat y_scale, y_bias;
1551
1552 if (render_to_fbo) {
1553 y_scale = 1.0;
1554 y_bias = 0;
1555 } else {
1556 y_scale = -1.0;
1557 y_bias = yoffset;
1558 }
1559
1560 _mesa_get_viewport_xform(ctx, 0, scale, translate);
1561 float_ui32_type sx = { scale[0] };
1562 float_ui32_type sy = { scale[1] * y_scale };
1563 float_ui32_type sz = { scale[2] };
1564 float_ui32_type tx = { translate[0] + xoffset };
1565 float_ui32_type ty = { (translate[1] * y_scale) + y_bias };
1566 float_ui32_type tz = { translate[2] };
1567
1568 R200_STATECHANGE( rmesa, vpt );
1569
1570 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32;
1571 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1572 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32;
1573 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1574 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32;
1575 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1576 }
1577
1578 void r200_vtbl_update_scissor( struct gl_context *ctx )
1579 {
1580 r200ContextPtr r200 = R200_CONTEXT(ctx);
1581 unsigned x1, y1, x2, y2;
1582 struct radeon_renderbuffer *rrb;
1583
1584 R200_SET_STATE(r200, set, SET_RE_CNTL, R200_SCISSOR_ENABLE | r200->hw.set.cmd[SET_RE_CNTL]);
1585
1586 if (r200->radeon.state.scissor.enabled) {
1587 x1 = r200->radeon.state.scissor.rect.x1;
1588 y1 = r200->radeon.state.scissor.rect.y1;
1589 x2 = r200->radeon.state.scissor.rect.x2;
1590 y2 = r200->radeon.state.scissor.rect.y2;
1591 } else {
1592 rrb = radeon_get_colorbuffer(&r200->radeon);
1593 x1 = 0;
1594 y1 = 0;
1595 x2 = rrb->base.Base.Width - 1;
1596 y2 = rrb->base.Base.Height - 1;
1597 }
1598
1599 R200_SET_STATE(r200, sci, SCI_XY_1, x1 | (y1 << 16));
1600 R200_SET_STATE(r200, sci, SCI_XY_2, x2 | (y2 << 16));
1601 }
1602
1603
1604 static void r200Viewport(struct gl_context *ctx)
1605 {
1606 /* Don't pipeline viewport changes, conflict with window offset
1607 * setting below. Could apply deltas to rescue pipelined viewport
1608 * values, or keep the originals hanging around.
1609 */
1610 r200UpdateWindow( ctx );
1611
1612 radeon_viewport(ctx);
1613 }
1614
1615 static void r200DepthRange(struct gl_context *ctx)
1616 {
1617 r200UpdateWindow( ctx );
1618 }
1619
1620 /* =============================================================
1621 * Miscellaneous
1622 */
1623
1624 static void r200RenderMode( struct gl_context *ctx, GLenum mode )
1625 {
1626 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1627 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1628 }
1629
1630
1631 static GLuint r200_rop_tab[] = {
1632 R200_ROP_CLEAR,
1633 R200_ROP_AND,
1634 R200_ROP_AND_REVERSE,
1635 R200_ROP_COPY,
1636 R200_ROP_AND_INVERTED,
1637 R200_ROP_NOOP,
1638 R200_ROP_XOR,
1639 R200_ROP_OR,
1640 R200_ROP_NOR,
1641 R200_ROP_EQUIV,
1642 R200_ROP_INVERT,
1643 R200_ROP_OR_REVERSE,
1644 R200_ROP_COPY_INVERTED,
1645 R200_ROP_OR_INVERTED,
1646 R200_ROP_NAND,
1647 R200_ROP_SET,
1648 };
1649
1650 static void r200LogicOpCode( struct gl_context *ctx, GLenum opcode )
1651 {
1652 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1653 GLuint rop = (GLuint)opcode - GL_CLEAR;
1654
1655 assert( rop < 16 );
1656
1657 R200_STATECHANGE( rmesa, msk );
1658 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1659 }
1660
1661 /* =============================================================
1662 * State enable/disable
1663 */
1664
1665 static void r200Enable( struct gl_context *ctx, GLenum cap, GLboolean state )
1666 {
1667 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1668 GLuint p, flag;
1669
1670 if ( R200_DEBUG & RADEON_STATE )
1671 fprintf( stderr, "%s( %s = %s )\n", __func__,
1672 _mesa_enum_to_string( cap ),
1673 state ? "GL_TRUE" : "GL_FALSE" );
1674
1675 switch ( cap ) {
1676 /* Fast track this one...
1677 */
1678 case GL_TEXTURE_1D:
1679 case GL_TEXTURE_2D:
1680 case GL_TEXTURE_3D:
1681 break;
1682
1683 case GL_ALPHA_TEST:
1684 R200_STATECHANGE( rmesa, ctx );
1685 if (state) {
1686 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1687 } else {
1688 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1689 }
1690 break;
1691
1692 case GL_BLEND:
1693 case GL_COLOR_LOGIC_OP:
1694 r200_set_blend_state( ctx );
1695 break;
1696
1697 case GL_CLIP_PLANE0:
1698 case GL_CLIP_PLANE1:
1699 case GL_CLIP_PLANE2:
1700 case GL_CLIP_PLANE3:
1701 case GL_CLIP_PLANE4:
1702 case GL_CLIP_PLANE5:
1703 p = cap-GL_CLIP_PLANE0;
1704 R200_STATECHANGE( rmesa, tcl );
1705 if (state) {
1706 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1707 r200ClipPlane( ctx, cap, NULL );
1708 }
1709 else {
1710 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1711 }
1712 break;
1713
1714 case GL_COLOR_MATERIAL:
1715 r200ColorMaterial( ctx, 0, 0 );
1716 r200UpdateMaterial( ctx );
1717 break;
1718
1719 case GL_CULL_FACE:
1720 r200CullFace( ctx, 0 );
1721 break;
1722
1723 case GL_DEPTH_TEST:
1724 R200_STATECHANGE(rmesa, ctx );
1725 if ( state ) {
1726 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1727 } else {
1728 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1729 }
1730 break;
1731
1732 case GL_DITHER:
1733 R200_STATECHANGE(rmesa, ctx );
1734 if ( state ) {
1735 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1736 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
1737 } else {
1738 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1739 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable;
1740 }
1741 break;
1742
1743 case GL_FOG:
1744 R200_STATECHANGE(rmesa, ctx );
1745 if ( state ) {
1746 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1747 r200Fogfv( ctx, GL_FOG_MODE, NULL );
1748 } else {
1749 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1750 R200_STATECHANGE(rmesa, tcl);
1751 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1752 }
1753 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1754 if (rmesa->radeon.TclFallback)
1755 r200ChooseVertexState( ctx );
1756 _mesa_allow_light_in_model( ctx, !state );
1757 break;
1758
1759 case GL_LIGHT0:
1760 case GL_LIGHT1:
1761 case GL_LIGHT2:
1762 case GL_LIGHT3:
1763 case GL_LIGHT4:
1764 case GL_LIGHT5:
1765 case GL_LIGHT6:
1766 case GL_LIGHT7:
1767 R200_STATECHANGE(rmesa, tcl);
1768 p = cap - GL_LIGHT0;
1769 if (p&1)
1770 flag = (R200_LIGHT_1_ENABLE |
1771 R200_LIGHT_1_ENABLE_AMBIENT |
1772 R200_LIGHT_1_ENABLE_SPECULAR);
1773 else
1774 flag = (R200_LIGHT_0_ENABLE |
1775 R200_LIGHT_0_ENABLE_AMBIENT |
1776 R200_LIGHT_0_ENABLE_SPECULAR);
1777
1778 if (state)
1779 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1780 else
1781 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1782
1783 /*
1784 */
1785 update_light_colors( ctx, p );
1786 break;
1787
1788 case GL_LIGHTING:
1789 r200UpdateSpecular(ctx);
1790 /* for reflection map fixup - might set recheck_texgen for all units too */
1791 rmesa->radeon.NewGLState |= _NEW_TEXTURE;
1792 break;
1793
1794 case GL_LINE_SMOOTH:
1795 R200_STATECHANGE( rmesa, ctx );
1796 if ( state ) {
1797 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1798 } else {
1799 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1800 }
1801 break;
1802
1803 case GL_LINE_STIPPLE:
1804 R200_STATECHANGE( rmesa, set );
1805 if ( state ) {
1806 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1807 } else {
1808 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1809 }
1810 break;
1811
1812 case GL_NORMALIZE:
1813 R200_STATECHANGE( rmesa, tcl );
1814 if ( state ) {
1815 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1816 } else {
1817 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1818 }
1819 break;
1820
1821 /* Pointsize registers on r200 only work for point sprites, and point smooth
1822 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1823 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1824 * is enough to satisfy conform.
1825 */
1826 case GL_POINT_SMOOTH:
1827 break;
1828
1829 /* These don't really do anything, as we don't use the 3vtx
1830 * primitives yet.
1831 */
1832 #if 0
1833 case GL_POLYGON_OFFSET_POINT:
1834 R200_STATECHANGE( rmesa, set );
1835 if ( state ) {
1836 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1837 } else {
1838 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1839 }
1840 break;
1841
1842 case GL_POLYGON_OFFSET_LINE:
1843 R200_STATECHANGE( rmesa, set );
1844 if ( state ) {
1845 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
1846 } else {
1847 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1848 }
1849 break;
1850 #endif
1851
1852 case GL_POINT_SPRITE_ARB:
1853 R200_STATECHANGE( rmesa, spr );
1854 if ( state ) {
1855 int i;
1856 for (i = 0; i < 6; i++) {
1857 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
1858 ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i);
1859 }
1860 } else {
1861 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
1862 }
1863 break;
1864
1865 case GL_POLYGON_OFFSET_FILL:
1866 R200_STATECHANGE( rmesa, set );
1867 if ( state ) {
1868 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
1869 } else {
1870 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1871 }
1872 break;
1873
1874 case GL_POLYGON_SMOOTH:
1875 R200_STATECHANGE( rmesa, ctx );
1876 if ( state ) {
1877 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
1878 } else {
1879 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
1880 }
1881 break;
1882
1883 case GL_POLYGON_STIPPLE:
1884 R200_STATECHANGE(rmesa, set );
1885 if ( state ) {
1886 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
1887 } else {
1888 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
1889 }
1890 break;
1891
1892 case GL_RESCALE_NORMAL_EXT: {
1893 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1894 R200_STATECHANGE( rmesa, tcl );
1895 if ( tmp ) {
1896 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1897 } else {
1898 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1899 }
1900 break;
1901 }
1902
1903 case GL_SCISSOR_TEST:
1904 radeon_firevertices(&rmesa->radeon);
1905 rmesa->radeon.state.scissor.enabled = state;
1906 radeonUpdateScissor( ctx );
1907 break;
1908
1909 case GL_STENCIL_TEST:
1910 {
1911 GLboolean hw_stencil = GL_FALSE;
1912 if (ctx->DrawBuffer) {
1913 struct radeon_renderbuffer *rrbStencil
1914 = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
1915 hw_stencil = (rrbStencil && rrbStencil->bo);
1916 }
1917
1918 if (hw_stencil) {
1919 R200_STATECHANGE( rmesa, ctx );
1920 if ( state ) {
1921 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
1922 } else {
1923 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
1924 }
1925 } else {
1926 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
1927 }
1928 }
1929 break;
1930
1931 case GL_TEXTURE_GEN_Q:
1932 case GL_TEXTURE_GEN_R:
1933 case GL_TEXTURE_GEN_S:
1934 case GL_TEXTURE_GEN_T:
1935 /* Picked up in r200UpdateTextureState.
1936 */
1937 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1938 break;
1939
1940 case GL_COLOR_SUM_EXT:
1941 r200UpdateSpecular ( ctx );
1942 break;
1943
1944 case GL_VERTEX_PROGRAM_ARB:
1945 if (!state) {
1946 GLuint i;
1947 rmesa->curr_vp_hw = NULL;
1948 R200_STATECHANGE( rmesa, vap );
1949 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
1950 /* mark all tcl atoms (tcl vector state got overwritten) dirty
1951 not sure about tcl scalar state - we need at least grd
1952 with vert progs too.
1953 ucp looks like it doesn't get overwritten (may even work
1954 with vp for pos-invariant progs if we're lucky) */
1955 R200_STATECHANGE( rmesa, mtl[0] );
1956 R200_STATECHANGE( rmesa, mtl[1] );
1957 R200_STATECHANGE( rmesa, fog );
1958 R200_STATECHANGE( rmesa, glt );
1959 R200_STATECHANGE( rmesa, eye );
1960 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
1961 R200_STATECHANGE( rmesa, mat[i] );
1962 }
1963 for (i = 0 ; i < 8; i++) {
1964 R200_STATECHANGE( rmesa, lit[i] );
1965 }
1966 R200_STATECHANGE( rmesa, tcl );
1967 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
1968 if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
1969 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
1970 }
1971 /* else {
1972 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
1973 }*/
1974 }
1975 /* ugly. Need to call everything which might change compsel. */
1976 r200UpdateSpecular( ctx );
1977 #if 0
1978 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
1979 but without it doom3 locks up at always the same places. Why? */
1980 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
1981 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
1982 r200UpdateTextureState( ctx );
1983 /* if we call r200UpdateTextureState we need the code below because we are calling it with
1984 non-current derived enabled values which may revert the state atoms for frag progs even when
1985 they already got disabled... ugh
1986 Should really figure out why we need to call r200UpdateTextureState in the first place */
1987 GLuint unit;
1988 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
1989 R200_STATECHANGE( rmesa, pix[unit] );
1990 R200_STATECHANGE( rmesa, tex[unit] );
1991 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
1992 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
1993 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
1994 /* need to guard this with drmSupportsFragmentShader? Should never get here if
1995 we don't announce ATI_fs, right? */
1996 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
1997 }
1998 R200_STATECHANGE( rmesa, cst );
1999 R200_STATECHANGE( rmesa, tf );
2000 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2001 #endif
2002 }
2003 else {
2004 /* picked up later */
2005 }
2006 /* call functions which change hw state based on ARB_vp enabled or not. */
2007 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2008 r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
2009 break;
2010
2011 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
2012 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2013 break;
2014
2015 case GL_FRAGMENT_SHADER_ATI:
2016 if ( !state ) {
2017 /* restore normal tex env colors and make sure tex env combine will get updated
2018 mark env atoms dirty (as their data was overwritten by afs even
2019 if they didn't change) and restore tex coord routing */
2020 GLuint unit;
2021 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2022 R200_STATECHANGE( rmesa, pix[unit] );
2023 R200_STATECHANGE( rmesa, tex[unit] );
2024 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2025 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2026 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2027 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2028 }
2029 R200_STATECHANGE( rmesa, cst );
2030 R200_STATECHANGE( rmesa, tf );
2031 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2032 }
2033 else {
2034 /* need to mark this dirty as pix/tf atoms have overwritten the data
2035 even if the data in the atoms didn't change */
2036 R200_STATECHANGE( rmesa, atf );
2037 R200_STATECHANGE( rmesa, afs[1] );
2038 /* everything else picked up in r200UpdateTextureState hopefully */
2039 }
2040 break;
2041 default:
2042 return;
2043 }
2044 }
2045
2046
2047 void r200LightingSpaceChange( struct gl_context *ctx )
2048 {
2049 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2050 GLboolean tmp;
2051
2052 if (R200_DEBUG & RADEON_STATE)
2053 fprintf(stderr, "%s %d BEFORE %x\n", __func__, ctx->_NeedEyeCoords,
2054 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2055
2056 if (ctx->_NeedEyeCoords)
2057 tmp = ctx->Transform.RescaleNormals;
2058 else
2059 tmp = !ctx->Transform.RescaleNormals;
2060
2061 R200_STATECHANGE( rmesa, tcl );
2062 if ( tmp ) {
2063 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2064 } else {
2065 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2066 }
2067
2068 if (R200_DEBUG & RADEON_STATE)
2069 fprintf(stderr, "%s %d AFTER %x\n", __func__, ctx->_NeedEyeCoords,
2070 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2071 }
2072
2073 /* =============================================================
2074 * Deferred state management - matrices, textures, other?
2075 */
2076
2077
2078
2079
2080 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2081 {
2082 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2083 int i;
2084
2085
2086 for (i = 0 ; i < 4 ; i++) {
2087 *dest++ = src[i];
2088 *dest++ = src[i+4];
2089 *dest++ = src[i+8];
2090 *dest++ = src[i+12];
2091 }
2092
2093 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2094 }
2095
2096 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2097 {
2098 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2099 memcpy(dest, src, 16*sizeof(float));
2100 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2101 }
2102
2103
2104 static void update_texturematrix( struct gl_context *ctx )
2105 {
2106 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2107 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2108 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2109 int unit;
2110
2111 if (R200_DEBUG & RADEON_STATE)
2112 fprintf(stderr, "%s before COMPSEL: %x\n", __func__,
2113 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2114
2115 rmesa->TexMatEnabled = 0;
2116 rmesa->TexMatCompSel = 0;
2117
2118 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2119 if (!ctx->Texture.Unit[unit]._Current)
2120 continue;
2121
2122 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2123 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2124 R200_TEXMAT_0_ENABLE) << unit;
2125
2126 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2127
2128 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2129 /* Need to preconcatenate any active texgen
2130 * obj/eyeplane matrices:
2131 */
2132 _math_matrix_mul_matrix( &rmesa->tmpmat,
2133 ctx->TextureMatrixStack[unit].Top,
2134 &rmesa->TexGenMatrix[unit] );
2135 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2136 }
2137 else {
2138 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2139 R200_MTX_TEX0+unit );
2140 }
2141 }
2142 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2143 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2144 R200_MTX_TEX0+unit );
2145 }
2146 }
2147
2148 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2149 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2150 R200_STATECHANGE(rmesa, tcg);
2151 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2152 }
2153
2154 compsel &= ~R200_OUTPUT_TEX_MASK;
2155 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2156 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2157 R200_STATECHANGE(rmesa, vtx);
2158 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2159 }
2160 }
2161
2162 GLboolean r200ValidateBuffers(struct gl_context *ctx)
2163 {
2164 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2165 struct radeon_renderbuffer *rrb;
2166 struct radeon_dma_bo *dma_bo;
2167 int i, ret;
2168
2169 if (RADEON_DEBUG & RADEON_IOCTL)
2170 fprintf(stderr, "%s\n", __func__);
2171 radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
2172
2173 rrb = radeon_get_colorbuffer(&rmesa->radeon);
2174 /* color buffer */
2175 if (rrb && rrb->bo) {
2176 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2177 0, RADEON_GEM_DOMAIN_VRAM);
2178 }
2179
2180 /* depth buffer */
2181 rrb = radeon_get_depthbuffer(&rmesa->radeon);
2182 /* color buffer */
2183 if (rrb && rrb->bo) {
2184 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2185 0, RADEON_GEM_DOMAIN_VRAM);
2186 }
2187
2188 for (i = 0; i < ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits; ++i) {
2189 radeonTexObj *t;
2190
2191 if (!ctx->Texture.Unit[i]._Current)
2192 continue;
2193
2194 t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
2195 if (t->image_override && t->bo)
2196 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo,
2197 RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2198 else if (t->mt->bo)
2199 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo,
2200 RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2201 }
2202
2203 dma_bo = first_elem(&rmesa->radeon.dma.reserved);
2204 {
2205 ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, dma_bo->bo, RADEON_GEM_DOMAIN_GTT, 0);
2206 if (ret)
2207 return GL_FALSE;
2208 }
2209 return GL_TRUE;
2210 }
2211
2212 GLboolean r200ValidateState( struct gl_context *ctx )
2213 {
2214 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2215 GLuint new_state = rmesa->radeon.NewGLState;
2216
2217 if (new_state & _NEW_BUFFERS) {
2218 _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer);
2219 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2220 _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
2221
2222 R200_STATECHANGE(rmesa, ctx);
2223 }
2224
2225 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) {
2226 r200UpdateTextureState( ctx );
2227 new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
2228 r200UpdateLocalViewer( ctx );
2229 }
2230
2231 /* we need to do a space check here */
2232 if (!r200ValidateBuffers(ctx))
2233 return GL_FALSE;
2234
2235 /* FIXME: don't really need most of these when vertex progs are enabled */
2236
2237 /* Need an event driven matrix update?
2238 */
2239 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2240 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2241
2242 /* Need these for lighting (shouldn't upload otherwise)
2243 */
2244 if (new_state & (_NEW_MODELVIEW)) {
2245 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2246 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2247 }
2248
2249 /* Does this need to be triggered on eg. modelview for
2250 * texgen-derived objplane/eyeplane matrices?
2251 */
2252 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2253 update_texturematrix( ctx );
2254 }
2255
2256 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2257 update_light( ctx );
2258 }
2259
2260 /* emit all active clip planes if projection matrix changes.
2261 */
2262 if (new_state & (_NEW_PROJECTION)) {
2263 if (ctx->Transform.ClipPlanesEnabled)
2264 r200UpdateClipPlanes( ctx );
2265 }
2266
2267 if (new_state & (_NEW_PROGRAM|
2268 _NEW_PROGRAM_CONSTANTS |
2269 /* need to test for pretty much anything due to possible parameter bindings */
2270 _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2271 _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2272 _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2273 if (ctx->VertexProgram._Enabled) {
2274 r200SetupVertexProg( ctx );
2275 }
2276 else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2277 }
2278
2279 rmesa->radeon.NewGLState = 0;
2280 return GL_TRUE;
2281 }
2282
2283
2284 static void r200InvalidateState( struct gl_context *ctx, GLuint new_state )
2285 {
2286 _swrast_InvalidateState( ctx, new_state );
2287 _swsetup_InvalidateState( ctx, new_state );
2288 _vbo_InvalidateState( ctx, new_state );
2289 _tnl_InvalidateState( ctx, new_state );
2290 _ae_invalidate_state( ctx, new_state );
2291 R200_CONTEXT(ctx)->radeon.NewGLState |= new_state;
2292 }
2293
2294 /* A hack. The r200 can actually cope just fine with materials
2295 * between begin/ends, so fix this.
2296 * Should map to inputs just like the generic vertex arrays for vertex progs.
2297 * In theory there could still be too many and we'd still need a fallback.
2298 */
2299 static GLboolean check_material( struct gl_context *ctx )
2300 {
2301 TNLcontext *tnl = TNL_CONTEXT(ctx);
2302 GLint i;
2303
2304 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2305 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2306 i++)
2307 if (tnl->vb.AttribPtr[i] &&
2308 tnl->vb.AttribPtr[i]->stride)
2309 return GL_TRUE;
2310
2311 return GL_FALSE;
2312 }
2313
2314 static void r200WrapRunPipeline( struct gl_context *ctx )
2315 {
2316 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2317 GLboolean has_material;
2318
2319 if (0)
2320 fprintf(stderr, "%s, newstate: %x\n", __func__, rmesa->radeon.NewGLState);
2321
2322 /* Validate state:
2323 */
2324 if (rmesa->radeon.NewGLState)
2325 if (!r200ValidateState( ctx ))
2326 FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
2327
2328 has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx );
2329
2330 if (has_material) {
2331 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2332 }
2333
2334 /* Run the pipeline.
2335 */
2336 _tnl_run_pipeline( ctx );
2337
2338 if (has_material) {
2339 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2340 }
2341 }
2342
2343
2344 static void r200PolygonStipple( struct gl_context *ctx, const GLubyte *mask )
2345 {
2346 r200ContextPtr r200 = R200_CONTEXT(ctx);
2347 GLint i;
2348
2349 radeon_firevertices(&r200->radeon);
2350
2351 radeon_print(RADEON_STATE, RADEON_TRACE,
2352 "%s(%p) first 32 bits are %x.\n",
2353 __func__,
2354 ctx,
2355 *(uint32_t*)mask);
2356
2357 R200_STATECHANGE(r200, stp);
2358
2359 /* Must flip pattern upside down.
2360 */
2361 for ( i = 31 ; i >= 0; i--) {
2362 r200->hw.stp.cmd[3 + i] = ((GLuint *) mask)[i];
2363 }
2364 }
2365 /* Initialize the driver's state functions.
2366 */
2367 void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *functions )
2368 {
2369 functions->UpdateState = r200InvalidateState;
2370 functions->LightingSpaceChange = r200LightingSpaceChange;
2371
2372 functions->DrawBuffer = radeonDrawBuffer;
2373 functions->ReadBuffer = radeonReadBuffer;
2374
2375 functions->CopyPixels = _mesa_meta_CopyPixels;
2376 functions->DrawPixels = _mesa_meta_DrawPixels;
2377 functions->ReadPixels = radeonReadPixels;
2378
2379 functions->AlphaFunc = r200AlphaFunc;
2380 functions->BlendColor = r200BlendColor;
2381 functions->BlendEquationSeparate = r200BlendEquationSeparate;
2382 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2383 functions->ClipPlane = r200ClipPlane;
2384 functions->ColorMask = r200ColorMask;
2385 functions->CullFace = r200CullFace;
2386 functions->DepthFunc = r200DepthFunc;
2387 functions->DepthMask = r200DepthMask;
2388 functions->DepthRange = r200DepthRange;
2389 functions->Enable = r200Enable;
2390 functions->Fogfv = r200Fogfv;
2391 functions->FrontFace = r200FrontFace;
2392 functions->LightModelfv = r200LightModelfv;
2393 functions->Lightfv = r200Lightfv;
2394 functions->LineStipple = r200LineStipple;
2395 functions->LineWidth = r200LineWidth;
2396 functions->LogicOpcode = r200LogicOpCode;
2397 functions->PolygonMode = r200PolygonMode;
2398 functions->PolygonOffset = r200PolygonOffset;
2399 functions->PolygonStipple = r200PolygonStipple;
2400 functions->PointParameterfv = r200PointParameter;
2401 functions->PointSize = r200PointSize;
2402 functions->RenderMode = r200RenderMode;
2403 functions->Scissor = radeonScissor;
2404 functions->ShadeModel = r200ShadeModel;
2405 functions->StencilFuncSeparate = r200StencilFuncSeparate;
2406 functions->StencilMaskSeparate = r200StencilMaskSeparate;
2407 functions->StencilOpSeparate = r200StencilOpSeparate;
2408 functions->Viewport = r200Viewport;
2409 }
2410
2411
2412 void r200InitTnlFuncs( struct gl_context *ctx )
2413 {
2414 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2415 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2416 }