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