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
38 #include "main/enums.h"
39 #include "main/light.h"
40 #include "main/framebuffer.h"
41 #include "main/fbobject.h"
42 #include "main/state.h"
43 #include "main/stencil.h"
44 #include "main/viewport.h"
45
46 #include "swrast/swrast.h"
47 #include "vbo/vbo.h"
48 #include "tnl/tnl.h"
49 #include "tnl/t_pipeline.h"
50 #include "swrast_setup/swrast_setup.h"
51 #include "drivers/common/meta.h"
52 #include "util/bitscan.h"
53
54 #include "radeon_common.h"
55 #include "radeon_mipmap_tree.h"
56 #include "r200_context.h"
57 #include "r200_ioctl.h"
58 #include "r200_state.h"
59 #include "r200_tcl.h"
60 #include "r200_tex.h"
61 #include "r200_swtcl.h"
62 #include "r200_vertprog.h"
63
64 #include "util/simple_list.h"
65
66 /* =============================================================
67 * Alpha blending
68 */
69
r200AlphaFunc(struct gl_context * ctx,GLenum func,GLfloat ref)70 static void r200AlphaFunc( struct gl_context *ctx, GLenum func, GLfloat ref )
71 {
72 r200ContextPtr rmesa = R200_CONTEXT(ctx);
73 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
74 GLubyte refByte;
75
76 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
77
78 R200_STATECHANGE( rmesa, ctx );
79
80 pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK);
81 pp_misc |= (refByte & R200_REF_ALPHA_MASK);
82
83 switch ( func ) {
84 case GL_NEVER:
85 pp_misc |= R200_ALPHA_TEST_FAIL;
86 break;
87 case GL_LESS:
88 pp_misc |= R200_ALPHA_TEST_LESS;
89 break;
90 case GL_EQUAL:
91 pp_misc |= R200_ALPHA_TEST_EQUAL;
92 break;
93 case GL_LEQUAL:
94 pp_misc |= R200_ALPHA_TEST_LEQUAL;
95 break;
96 case GL_GREATER:
97 pp_misc |= R200_ALPHA_TEST_GREATER;
98 break;
99 case GL_NOTEQUAL:
100 pp_misc |= R200_ALPHA_TEST_NEQUAL;
101 break;
102 case GL_GEQUAL:
103 pp_misc |= R200_ALPHA_TEST_GEQUAL;
104 break;
105 case GL_ALWAYS:
106 pp_misc |= R200_ALPHA_TEST_PASS;
107 break;
108 }
109
110 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
111 }
112
r200BlendColor(struct gl_context * ctx,const GLfloat cf[4])113 static void r200BlendColor( struct gl_context *ctx, const GLfloat cf[4] )
114 {
115 GLubyte color[4];
116 r200ContextPtr rmesa = R200_CONTEXT(ctx);
117 R200_STATECHANGE( rmesa, ctx );
118 CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]);
119 CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]);
120 CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]);
121 CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]);
122 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = radeonPackColor( 4, color[0], color[1], color[2], color[3] );
123 }
124
125 /**
126 * Calculate the hardware blend factor setting. This same function is used
127 * for source and destination of both alpha and RGB.
128 *
129 * \returns
130 * The hardware register value for the specified blend factor. This value
131 * will need to be shifted into the correct position for either source or
132 * destination factor.
133 *
134 * \todo
135 * Since the two cases where source and destination are handled differently
136 * are essentially error cases, they should never happen. Determine if these
137 * cases can be removed.
138 */
blend_factor(GLenum factor,GLboolean is_src)139 static int blend_factor( GLenum factor, GLboolean is_src )
140 {
141 int func;
142
143 switch ( factor ) {
144 case GL_ZERO:
145 func = R200_BLEND_GL_ZERO;
146 break;
147 case GL_ONE:
148 func = R200_BLEND_GL_ONE;
149 break;
150 case GL_DST_COLOR:
151 func = R200_BLEND_GL_DST_COLOR;
152 break;
153 case GL_ONE_MINUS_DST_COLOR:
154 func = R200_BLEND_GL_ONE_MINUS_DST_COLOR;
155 break;
156 case GL_SRC_COLOR:
157 func = R200_BLEND_GL_SRC_COLOR;
158 break;
159 case GL_ONE_MINUS_SRC_COLOR:
160 func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR;
161 break;
162 case GL_SRC_ALPHA:
163 func = R200_BLEND_GL_SRC_ALPHA;
164 break;
165 case GL_ONE_MINUS_SRC_ALPHA:
166 func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA;
167 break;
168 case GL_DST_ALPHA:
169 func = R200_BLEND_GL_DST_ALPHA;
170 break;
171 case GL_ONE_MINUS_DST_ALPHA:
172 func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA;
173 break;
174 case GL_SRC_ALPHA_SATURATE:
175 func = (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : R200_BLEND_GL_ZERO;
176 break;
177 case GL_CONSTANT_COLOR:
178 func = R200_BLEND_GL_CONST_COLOR;
179 break;
180 case GL_ONE_MINUS_CONSTANT_COLOR:
181 func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR;
182 break;
183 case GL_CONSTANT_ALPHA:
184 func = R200_BLEND_GL_CONST_ALPHA;
185 break;
186 case GL_ONE_MINUS_CONSTANT_ALPHA:
187 func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA;
188 break;
189 default:
190 func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO;
191 }
192 return func;
193 }
194
195 /**
196 * Sets both the blend equation and the blend function.
197 * This is done in a single
198 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
199 * change the interpretation of the blend function.
200 * Also, make sure that blend function and blend equation are set to their default
201 * value if color blending is not enabled, since at least blend equations GL_MIN
202 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
203 * unknown reasons.
204 */
r200_set_blend_state(struct gl_context * ctx)205 static void r200_set_blend_state( struct gl_context * ctx )
206 {
207 r200ContextPtr rmesa = R200_CONTEXT(ctx);
208 GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &
209 ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE);
210
211 int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
212 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
213 int eqn = R200_COMB_FCN_ADD_CLAMP;
214 int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
215 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
216 int eqnA = R200_COMB_FCN_ADD_CLAMP;
217
218 R200_STATECHANGE( rmesa, ctx );
219
220 if (ctx->Color.ColorLogicOpEnabled) {
221 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
222 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
223 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
224 return;
225 } else if (ctx->Color.BlendEnabled) {
226 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE;
227 }
228 else {
229 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
230 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
231 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
232 return;
233 }
234
235 func = (blend_factor( ctx->Color.Blend[0].SrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
236 (blend_factor( ctx->Color.Blend[0].DstRGB, GL_FALSE ) << R200_DST_BLEND_SHIFT);
237
238 switch(ctx->Color.Blend[0].EquationRGB) {
239 case GL_FUNC_ADD:
240 eqn = R200_COMB_FCN_ADD_CLAMP;
241 break;
242
243 case GL_FUNC_SUBTRACT:
244 eqn = R200_COMB_FCN_SUB_CLAMP;
245 break;
246
247 case GL_FUNC_REVERSE_SUBTRACT:
248 eqn = R200_COMB_FCN_RSUB_CLAMP;
249 break;
250
251 case GL_MIN:
252 eqn = R200_COMB_FCN_MIN;
253 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
254 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
255 break;
256
257 case GL_MAX:
258 eqn = R200_COMB_FCN_MAX;
259 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
260 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
261 break;
262
263 default:
264 fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
265 __func__, __LINE__, ctx->Color.Blend[0].EquationRGB );
266 return;
267 }
268
269 funcA = (blend_factor( ctx->Color.Blend[0].SrcA, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
270 (blend_factor( ctx->Color.Blend[0].DstA, GL_FALSE ) << R200_DST_BLEND_SHIFT);
271
272 switch(ctx->Color.Blend[0].EquationA) {
273 case GL_FUNC_ADD:
274 eqnA = R200_COMB_FCN_ADD_CLAMP;
275 break;
276
277 case GL_FUNC_SUBTRACT:
278 eqnA = R200_COMB_FCN_SUB_CLAMP;
279 break;
280
281 case GL_FUNC_REVERSE_SUBTRACT:
282 eqnA = R200_COMB_FCN_RSUB_CLAMP;
283 break;
284
285 case GL_MIN:
286 eqnA = R200_COMB_FCN_MIN;
287 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
288 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
289 break;
290
291 case GL_MAX:
292 eqnA = R200_COMB_FCN_MAX;
293 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
294 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
295 break;
296
297 default:
298 fprintf( stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n",
299 __func__, __LINE__, ctx->Color.Blend[0].EquationA );
300 return;
301 }
302
303 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqnA | funcA;
304 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
305
306 }
307
r200BlendEquationSeparate(struct gl_context * ctx,GLenum modeRGB,GLenum modeA)308 static void r200BlendEquationSeparate( struct gl_context *ctx,
309 GLenum modeRGB, GLenum modeA )
310 {
311 r200_set_blend_state( ctx );
312 }
313
r200BlendFuncSeparate(struct gl_context * ctx,GLenum sfactorRGB,GLenum dfactorRGB,GLenum sfactorA,GLenum dfactorA)314 static void r200BlendFuncSeparate( struct gl_context *ctx,
315 GLenum sfactorRGB, GLenum dfactorRGB,
316 GLenum sfactorA, GLenum dfactorA )
317 {
318 r200_set_blend_state( ctx );
319 }
320
321
322 /* =============================================================
323 * Depth testing
324 */
325
r200DepthFunc(struct gl_context * ctx,GLenum func)326 static void r200DepthFunc( struct gl_context *ctx, GLenum func )
327 {
328 r200ContextPtr rmesa = R200_CONTEXT(ctx);
329
330 R200_STATECHANGE( rmesa, ctx );
331 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK;
332
333 switch ( ctx->Depth.Func ) {
334 case GL_NEVER:
335 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER;
336 break;
337 case GL_LESS:
338 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS;
339 break;
340 case GL_EQUAL:
341 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL;
342 break;
343 case GL_LEQUAL:
344 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL;
345 break;
346 case GL_GREATER:
347 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER;
348 break;
349 case GL_NOTEQUAL:
350 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL;
351 break;
352 case GL_GEQUAL:
353 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL;
354 break;
355 case GL_ALWAYS:
356 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS;
357 break;
358 }
359 }
360
r200DepthMask(struct gl_context * ctx,GLboolean flag)361 static void r200DepthMask( struct gl_context *ctx, GLboolean flag )
362 {
363 r200ContextPtr rmesa = R200_CONTEXT(ctx);
364 R200_STATECHANGE( rmesa, ctx );
365
366 if ( ctx->Depth.Mask ) {
367 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE;
368 } else {
369 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE;
370 }
371 }
372
373
374 /* =============================================================
375 * Fog
376 */
377
378
r200Fogfv(struct gl_context * ctx,GLenum pname,const GLfloat * param)379 static void r200Fogfv( struct gl_context *ctx, GLenum pname, const GLfloat *param )
380 {
381 r200ContextPtr rmesa = R200_CONTEXT(ctx);
382 union { int i; float f; } c, d;
383 GLubyte col[4];
384 GLuint i;
385
386 c.i = rmesa->hw.fog.cmd[FOG_C];
387 d.i = rmesa->hw.fog.cmd[FOG_D];
388
389 switch (pname) {
390 case GL_FOG_MODE:
391 if (!ctx->Fog.Enabled)
392 return;
393 R200_STATECHANGE(rmesa, tcl);
394 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
395 switch (ctx->Fog.Mode) {
396 case GL_LINEAR:
397 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR;
398 if (ctx->Fog.Start == ctx->Fog.End) {
399 c.f = 1.0F;
400 d.f = 1.0F;
401 }
402 else {
403 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
404 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
405 }
406 break;
407 case GL_EXP:
408 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP;
409 c.f = 0.0;
410 d.f = -ctx->Fog.Density;
411 break;
412 case GL_EXP2:
413 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2;
414 c.f = 0.0;
415 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
416 break;
417 default:
418 return;
419 }
420 break;
421 case GL_FOG_DENSITY:
422 switch (ctx->Fog.Mode) {
423 case GL_EXP:
424 c.f = 0.0;
425 d.f = -ctx->Fog.Density;
426 break;
427 case GL_EXP2:
428 c.f = 0.0;
429 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
430 break;
431 default:
432 break;
433 }
434 break;
435 case GL_FOG_START:
436 case GL_FOG_END:
437 if (ctx->Fog.Mode == GL_LINEAR) {
438 if (ctx->Fog.Start == ctx->Fog.End) {
439 c.f = 1.0F;
440 d.f = 1.0F;
441 } else {
442 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
443 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
444 }
445 }
446 break;
447 case GL_FOG_COLOR:
448 R200_STATECHANGE( rmesa, ctx );
449 _mesa_unclamped_float_rgba_to_ubyte(col, ctx->Fog.Color );
450 i = radeonPackColor( 4, col[0], col[1], col[2], 0 );
451 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK;
452 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
453 break;
454 case GL_FOG_COORD_SRC: {
455 GLuint out_0 = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0];
456 GLuint fog = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR];
457
458 fog &= ~R200_FOG_USE_MASK;
459 if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD || ctx->VertexProgram.Enabled) {
460 fog |= R200_FOG_USE_VTX_FOG;
461 out_0 |= R200_VTX_DISCRETE_FOG;
462 }
463 else {
464 fog |= R200_FOG_USE_SPEC_ALPHA;
465 out_0 &= ~R200_VTX_DISCRETE_FOG;
466 }
467
468 if ( fog != rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] ) {
469 R200_STATECHANGE( rmesa, ctx );
470 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog;
471 }
472
473 if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) {
474 R200_STATECHANGE( rmesa, vtx );
475 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0;
476 }
477
478 break;
479 }
480 default:
481 return;
482 }
483
484 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
485 R200_STATECHANGE( rmesa, fog );
486 rmesa->hw.fog.cmd[FOG_C] = c.i;
487 rmesa->hw.fog.cmd[FOG_D] = d.i;
488 }
489 }
490
491 /* =============================================================
492 * Culling
493 */
494
r200CullFace(struct gl_context * ctx,GLenum unused)495 static void r200CullFace( struct gl_context *ctx, GLenum unused )
496 {
497 r200ContextPtr rmesa = R200_CONTEXT(ctx);
498 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
499 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
500
501 s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
502 t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
503
504 if ( ctx->Polygon.CullFlag ) {
505 switch ( ctx->Polygon.CullFaceMode ) {
506 case GL_FRONT:
507 s &= ~R200_FFACE_SOLID;
508 t |= R200_CULL_FRONT;
509 break;
510 case GL_BACK:
511 s &= ~R200_BFACE_SOLID;
512 t |= R200_CULL_BACK;
513 break;
514 case GL_FRONT_AND_BACK:
515 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
516 t |= (R200_CULL_FRONT | R200_CULL_BACK);
517 break;
518 }
519 }
520
521 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
522 R200_STATECHANGE(rmesa, set );
523 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
524 }
525
526 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
527 R200_STATECHANGE(rmesa, tcl );
528 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
529 }
530 }
531
r200FrontFace(struct gl_context * ctx,GLenum mode)532 static void r200FrontFace( struct gl_context *ctx, GLenum mode )
533 {
534 r200ContextPtr rmesa = R200_CONTEXT(ctx);
535 int cull_face = (mode == GL_CW) ? R200_FFACE_CULL_CW : R200_FFACE_CULL_CCW;
536
537 R200_STATECHANGE( rmesa, set );
538 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
539
540 R200_STATECHANGE( rmesa, tcl );
541 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
542
543 /* Winding is inverted when rendering to FBO */
544 if (ctx->DrawBuffer && _mesa_is_user_fbo(ctx->DrawBuffer))
545 cull_face = (mode == GL_CCW) ? R200_FFACE_CULL_CW : R200_FFACE_CULL_CCW;
546 rmesa->hw.set.cmd[SET_SE_CNTL] |= cull_face;
547
548 if ( mode == GL_CCW )
549 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW;
550 }
551
552 /* =============================================================
553 * Point state
554 */
r200PointSize(struct gl_context * ctx,GLfloat size)555 static void r200PointSize( struct gl_context *ctx, GLfloat size )
556 {
557 r200ContextPtr rmesa = R200_CONTEXT(ctx);
558 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
559
560 radeon_print(RADEON_STATE, RADEON_TRACE,
561 "%s(%p) size: %f, fixed point result: %d.%d (%d/16)\n",
562 __func__, ctx, size,
563 ((GLuint)(ctx->Point.Size * 16.0))/16,
564 (((GLuint)(ctx->Point.Size * 16.0))&15)*100/16,
565 ((GLuint)(ctx->Point.Size * 16.0))&15);
566
567 R200_STATECHANGE( rmesa, cst );
568 R200_STATECHANGE( rmesa, ptp );
569 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff;
570 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0));
571 /* this is the size param of the point size calculation (point size reg value
572 is not used when calculation is active). */
573 fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size;
574 }
575
r200PointParameter(struct gl_context * ctx,GLenum pname,const GLfloat * params)576 static void r200PointParameter( struct gl_context *ctx, GLenum pname, const GLfloat *params)
577 {
578 r200ContextPtr rmesa = R200_CONTEXT(ctx);
579 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
580
581 switch (pname) {
582 case GL_POINT_SIZE_MIN:
583 /* Can clamp both in tcl and setup - just set both (as does fglrx) */
584 R200_STATECHANGE( rmesa, lin );
585 R200_STATECHANGE( rmesa, ptp );
586 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff;
587 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16;
588 fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize;
589 break;
590 case GL_POINT_SIZE_MAX:
591 R200_STATECHANGE( rmesa, cst );
592 R200_STATECHANGE( rmesa, ptp );
593 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff;
594 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16;
595 fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize;
596 break;
597 case GL_POINT_DISTANCE_ATTENUATION:
598 R200_STATECHANGE( rmesa, vtx );
599 R200_STATECHANGE( rmesa, spr );
600 R200_STATECHANGE( rmesa, ptp );
601 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
602 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &=
603 ~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE);
604 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
605 r200ValidateState looks like overkill */
606 if (ctx->Point.Params[0] != 1.0 ||
607 ctx->Point.Params[1] != 0.0 ||
608 ctx->Point.Params[2] != 0.0 ||
609 (ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) {
610 /* all we care for vp would be the ps_se_sel_state setting */
611 fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2];
612 fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1];
613 fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0];
614 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST;
615 if (ctx->Point.Params[1] == 0.0)
616 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO;
617 /* FIXME: setting this here doesn't look quite ok - we only want to do
618 that if we're actually drawing points probably */
619 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE;
620 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE;
621 }
622 else {
623 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
624 R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST;
625 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE;
626 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE;
627 }
628 break;
629 case GL_POINT_FADE_THRESHOLD_SIZE:
630 /* don't support multisampling, so doesn't matter. */
631 break;
632 /* can't do these but don't need them.
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 */
r200LineWidth(struct gl_context * ctx,GLfloat widthf)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
r200LineStipple(struct gl_context * ctx,GLint factor,GLushort pattern)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 */
r200ColorMask(struct gl_context * ctx,GLboolean r,GLboolean g,GLboolean b,GLboolean a)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 GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0)*0xFF,
691 GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1)*0xFF,
692 GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2)*0xFF,
693 GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3)*0xFF );
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
r200PolygonOffset(struct gl_context * ctx,GLfloat factor,GLfloat units,GLfloat clamp)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
r200PolygonMode(struct gl_context * ctx,GLenum face,GLenum mode)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 */
r200UpdateSpecular(struct gl_context * ctx)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 */
update_global_ambient(struct gl_context * ctx)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 */
update_light_colors(struct gl_context * ctx,GLuint p)866 static void update_light_colors( struct gl_context *ctx, GLuint p )
867 {
868 struct gl_light *l = &ctx->Light.Light[p];
869 struct gl_light_uniforms *lu = &ctx->Light.LightSource[p];
870
871 /* fprintf(stderr, "%s\n", __func__); */
872
873 if (l->Enabled) {
874 r200ContextPtr rmesa = R200_CONTEXT(ctx);
875 float *fcmd = (float *)R200_DB_STATE( lit[p] );
876
877 COPY_4V( &fcmd[LIT_AMBIENT_RED], lu->Ambient );
878 COPY_4V( &fcmd[LIT_DIFFUSE_RED], lu->Diffuse );
879 COPY_4V( &fcmd[LIT_SPECULAR_RED], lu->Specular );
880
881 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
882 }
883 }
884
r200ColorMaterial(struct gl_context * ctx,GLenum face,GLenum mode)885 static void r200ColorMaterial( struct gl_context *ctx, GLenum face, GLenum mode )
886 {
887 r200ContextPtr rmesa = R200_CONTEXT(ctx);
888 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
889 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
890 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
891 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
892 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
893 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
894 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) |
895 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
896 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT));
897
898 if (ctx->Light.ColorMaterialEnabled) {
899 GLuint mask = ctx->Light._ColorMaterialBitmask;
900
901 if (mask & MAT_BIT_FRONT_EMISSION) {
902 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
903 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
904 }
905 else
906 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
907 R200_FRONT_EMISSIVE_SOURCE_SHIFT);
908
909 if (mask & MAT_BIT_FRONT_AMBIENT) {
910 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
911 R200_FRONT_AMBIENT_SOURCE_SHIFT);
912 }
913 else
914 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
915 R200_FRONT_AMBIENT_SOURCE_SHIFT);
916
917 if (mask & MAT_BIT_FRONT_DIFFUSE) {
918 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
919 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
920 }
921 else
922 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
923 R200_FRONT_DIFFUSE_SOURCE_SHIFT);
924
925 if (mask & MAT_BIT_FRONT_SPECULAR) {
926 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
927 R200_FRONT_SPECULAR_SOURCE_SHIFT);
928 }
929 else {
930 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
931 R200_FRONT_SPECULAR_SOURCE_SHIFT);
932 }
933
934 if (mask & MAT_BIT_BACK_EMISSION) {
935 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
936 R200_BACK_EMISSIVE_SOURCE_SHIFT);
937 }
938
939 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
940 R200_BACK_EMISSIVE_SOURCE_SHIFT);
941
942 if (mask & MAT_BIT_BACK_AMBIENT) {
943 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
944 R200_BACK_AMBIENT_SOURCE_SHIFT);
945 }
946 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
947 R200_BACK_AMBIENT_SOURCE_SHIFT);
948
949 if (mask & MAT_BIT_BACK_DIFFUSE) {
950 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
951 R200_BACK_DIFFUSE_SOURCE_SHIFT);
952 }
953 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
954 R200_BACK_DIFFUSE_SOURCE_SHIFT);
955
956 if (mask & MAT_BIT_BACK_SPECULAR) {
957 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
958 R200_BACK_SPECULAR_SOURCE_SHIFT);
959 }
960 else {
961 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
962 R200_BACK_SPECULAR_SOURCE_SHIFT);
963 }
964 }
965 else {
966 /* Default to SOURCE_MATERIAL:
967 */
968 light_model_ctl1 |=
969 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
970 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
971 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
972 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
973 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
974 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) |
975 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
976 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT);
977 }
978
979 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
980 R200_STATECHANGE( rmesa, tcl );
981 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
982 }
983
984
985 }
986
r200UpdateMaterial(struct gl_context * ctx)987 void r200UpdateMaterial( struct gl_context *ctx )
988 {
989 r200ContextPtr rmesa = R200_CONTEXT(ctx);
990 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
991 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
992 GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] );
993 GLuint mask = ~0;
994
995 /* Might be possible and faster to update everything unconditionally? */
996 if (ctx->Light.ColorMaterialEnabled)
997 mask &= ~ctx->Light._ColorMaterialBitmask;
998
999 if (R200_DEBUG & RADEON_STATE)
1000 fprintf(stderr, "%s\n", __func__);
1001
1002 if (mask & MAT_BIT_FRONT_EMISSION) {
1003 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
1004 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
1005 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
1006 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
1007 }
1008 if (mask & MAT_BIT_FRONT_AMBIENT) {
1009 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
1010 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
1011 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
1012 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
1013 }
1014 if (mask & MAT_BIT_FRONT_DIFFUSE) {
1015 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
1016 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
1017 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
1018 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
1019 }
1020 if (mask & MAT_BIT_FRONT_SPECULAR) {
1021 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
1022 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
1023 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
1024 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
1025 }
1026 if (mask & MAT_BIT_FRONT_SHININESS) {
1027 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
1028 }
1029
1030 if (mask & MAT_BIT_BACK_EMISSION) {
1031 fcmd2[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_BACK_EMISSION][0];
1032 fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1];
1033 fcmd2[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_BACK_EMISSION][2];
1034 fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3];
1035 }
1036 if (mask & MAT_BIT_BACK_AMBIENT) {
1037 fcmd2[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_BACK_AMBIENT][0];
1038 fcmd2[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_BACK_AMBIENT][1];
1039 fcmd2[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_BACK_AMBIENT][2];
1040 fcmd2[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_BACK_AMBIENT][3];
1041 }
1042 if (mask & MAT_BIT_BACK_DIFFUSE) {
1043 fcmd2[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_BACK_DIFFUSE][0];
1044 fcmd2[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_BACK_DIFFUSE][1];
1045 fcmd2[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_BACK_DIFFUSE][2];
1046 fcmd2[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_BACK_DIFFUSE][3];
1047 }
1048 if (mask & MAT_BIT_BACK_SPECULAR) {
1049 fcmd2[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_BACK_SPECULAR][0];
1050 fcmd2[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_BACK_SPECULAR][1];
1051 fcmd2[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_BACK_SPECULAR][2];
1052 fcmd2[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_BACK_SPECULAR][3];
1053 }
1054 if (mask & MAT_BIT_BACK_SHININESS) {
1055 fcmd2[MTL_SHININESS] = mat[MAT_ATTRIB_BACK_SHININESS][0];
1056 }
1057
1058 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] );
1059 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] );
1060
1061 /* currently material changes cannot trigger a global ambient change, I believe this is correct
1062 update_global_ambient( ctx ); */
1063 }
1064
1065 /* _NEW_LIGHT
1066 * _NEW_MODELVIEW
1067 * _MESA_NEW_NEED_EYE_COORDS
1068 *
1069 * Uses derived state from mesa:
1070 * _VP_inf_norm
1071 * _h_inf_norm
1072 * _Position
1073 * _NormSpotDirection
1074 * _ModelViewInvScale
1075 * _NeedEyeCoords
1076 * _EyeZDir
1077 *
1078 * which are calculated in light.c and are correct for the current
1079 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1080 * and _MESA_NEW_NEED_EYE_COORDS.
1081 */
update_light(struct gl_context * ctx)1082 static void update_light( struct gl_context *ctx )
1083 {
1084 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1085
1086 /* Have to check these, or have an automatic shortcircuit mechanism
1087 * to remove noop statechanges. (Or just do a better job on the
1088 * front end).
1089 */
1090 {
1091 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
1092
1093 if (ctx->_NeedEyeCoords)
1094 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1095 else
1096 tmp |= R200_LIGHT_IN_MODELSPACE;
1097
1098 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1099 {
1100 R200_STATECHANGE( rmesa, tcl );
1101 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1102 }
1103 }
1104
1105 {
1106 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1107 fcmd[EYE_X] = ctx->_EyeZDir[0];
1108 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1109 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1110 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1111 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1112 }
1113
1114
1115
1116 if (ctx->Light.Enabled) {
1117 GLbitfield mask = ctx->Light._EnabledLights;
1118 while (mask) {
1119 const int p = u_bit_scan(&mask);
1120 struct gl_light *l = &ctx->Light.Light[p];
1121 struct gl_light_uniforms *lu = &ctx->Light.LightSource[p];
1122 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1123
1124 if (lu->EyePosition[3] == 0.0) {
1125 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1126 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1127 fcmd[LIT_POSITION_W] = 0;
1128 fcmd[LIT_DIRECTION_W] = 0;
1129 } else {
1130 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1131 fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0];
1132 fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1];
1133 fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2];
1134 fcmd[LIT_DIRECTION_W] = 0;
1135 }
1136
1137 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1138 }
1139 }
1140 }
1141
r200Lightfv(struct gl_context * ctx,GLenum light,GLenum pname,const GLfloat * params)1142 static void r200Lightfv( struct gl_context *ctx, GLenum light,
1143 GLenum pname, const GLfloat *params )
1144 {
1145 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1146 GLint p = light - GL_LIGHT0;
1147 struct gl_light_uniforms *lu = &ctx->Light.LightSource[p];
1148 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1149
1150
1151 switch (pname) {
1152 case GL_AMBIENT:
1153 case GL_DIFFUSE:
1154 case GL_SPECULAR:
1155 update_light_colors( ctx, p );
1156 break;
1157
1158 case GL_SPOT_DIRECTION:
1159 /* picked up in update_light */
1160 break;
1161
1162 case GL_POSITION: {
1163 /* positions picked up in update_light, but can do flag here */
1164 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1165 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1166
1167 R200_STATECHANGE(rmesa, tcl);
1168 if (lu->EyePosition[3] != 0.0F)
1169 rmesa->hw.tcl.cmd[idx] |= flag;
1170 else
1171 rmesa->hw.tcl.cmd[idx] &= ~flag;
1172 break;
1173 }
1174
1175 case GL_SPOT_EXPONENT:
1176 R200_STATECHANGE(rmesa, lit[p]);
1177 fcmd[LIT_SPOT_EXPONENT] = params[0];
1178 break;
1179
1180 case GL_SPOT_CUTOFF: {
1181 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1182 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1183
1184 R200_STATECHANGE(rmesa, lit[p]);
1185 fcmd[LIT_SPOT_CUTOFF] = lu->_CosCutoff;
1186
1187 R200_STATECHANGE(rmesa, tcl);
1188 if (lu->SpotCutoff != 180.0F)
1189 rmesa->hw.tcl.cmd[idx] |= flag;
1190 else
1191 rmesa->hw.tcl.cmd[idx] &= ~flag;
1192
1193 break;
1194 }
1195
1196 case GL_CONSTANT_ATTENUATION:
1197 R200_STATECHANGE(rmesa, lit[p]);
1198 fcmd[LIT_ATTEN_CONST] = params[0];
1199 if ( params[0] == 0.0 )
1200 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1201 else
1202 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1203 break;
1204 case GL_LINEAR_ATTENUATION:
1205 R200_STATECHANGE(rmesa, lit[p]);
1206 fcmd[LIT_ATTEN_LINEAR] = params[0];
1207 break;
1208 case GL_QUADRATIC_ATTENUATION:
1209 R200_STATECHANGE(rmesa, lit[p]);
1210 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1211 break;
1212 default:
1213 return;
1214 }
1215
1216 /* Set RANGE_ATTEN only when needed */
1217 switch (pname) {
1218 case GL_POSITION:
1219 case GL_CONSTANT_ATTENUATION:
1220 case GL_LINEAR_ATTENUATION:
1221 case GL_QUADRATIC_ATTENUATION: {
1222 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1223 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1224 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1225 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1226 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1227 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1228
1229 if ( lu->EyePosition[3] == 0.0F ||
1230 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1231 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1232 /* Disable attenuation */
1233 icmd[idx] &= ~atten_flag;
1234 } else {
1235 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1236 /* Enable only constant portion of attenuation calculation */
1237 icmd[idx] |= ( atten_flag | atten_const_flag );
1238 } else {
1239 /* Enable full attenuation calculation */
1240 icmd[idx] &= ~atten_const_flag;
1241 icmd[idx] |= atten_flag;
1242 }
1243 }
1244
1245 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1246 break;
1247 }
1248 default:
1249 break;
1250 }
1251 }
1252
r200UpdateLocalViewer(struct gl_context * ctx)1253 static void r200UpdateLocalViewer ( struct gl_context *ctx )
1254 {
1255 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1256 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1257 for these and only these modes). This means specular highlights may turn out
1258 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1259 is not set, though it seems to happen rarely and the effect seems quite
1260 subtle. May need TCL fallback to fix it completely, though I'm not sure
1261 how you'd identify the cases where the specular highlights indeed will
1262 be wrong. Don't know if fglrx does something special in that case.
1263 */
1264 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1265 R200_STATECHANGE( rmesa, tcl );
1266 if (ctx->Light.Model.LocalViewer ||
1267 ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
1268 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1269 else
1270 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1271 }
1272
r200LightModelfv(struct gl_context * ctx,GLenum pname,const GLfloat * param)1273 static void r200LightModelfv( struct gl_context *ctx, GLenum pname,
1274 const GLfloat *param )
1275 {
1276 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1277
1278 switch (pname) {
1279 case GL_LIGHT_MODEL_AMBIENT:
1280 update_global_ambient( ctx );
1281 break;
1282
1283 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1284 r200UpdateLocalViewer( ctx );
1285 break;
1286
1287 case GL_LIGHT_MODEL_TWO_SIDE:
1288 R200_STATECHANGE( rmesa, tcl );
1289 if (ctx->Light.Model.TwoSide)
1290 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1291 else
1292 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1293 if (rmesa->radeon.TclFallback) {
1294 r200ChooseRenderState( ctx );
1295 r200ChooseVertexState( ctx );
1296 }
1297 break;
1298
1299 case GL_LIGHT_MODEL_COLOR_CONTROL:
1300 r200UpdateSpecular(ctx);
1301 break;
1302
1303 default:
1304 break;
1305 }
1306 }
1307
r200ShadeModel(struct gl_context * ctx,GLenum mode)1308 static void r200ShadeModel( struct gl_context *ctx, GLenum mode )
1309 {
1310 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1311 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1312
1313 s &= ~(R200_DIFFUSE_SHADE_MASK |
1314 R200_ALPHA_SHADE_MASK |
1315 R200_SPECULAR_SHADE_MASK |
1316 R200_FOG_SHADE_MASK |
1317 R200_DISC_FOG_SHADE_MASK);
1318
1319 switch ( mode ) {
1320 case GL_FLAT:
1321 s |= (R200_DIFFUSE_SHADE_FLAT |
1322 R200_ALPHA_SHADE_FLAT |
1323 R200_SPECULAR_SHADE_FLAT |
1324 R200_FOG_SHADE_FLAT |
1325 R200_DISC_FOG_SHADE_FLAT);
1326 break;
1327 case GL_SMOOTH:
1328 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1329 R200_ALPHA_SHADE_GOURAUD |
1330 R200_SPECULAR_SHADE_GOURAUD |
1331 R200_FOG_SHADE_GOURAUD |
1332 R200_DISC_FOG_SHADE_GOURAUD);
1333 break;
1334 default:
1335 return;
1336 }
1337
1338 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1339 R200_STATECHANGE( rmesa, set );
1340 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1341 }
1342 }
1343
1344
1345 /* =============================================================
1346 * User clip planes
1347 */
1348
r200ClipPlane(struct gl_context * ctx,GLenum plane,const GLfloat * eq)1349 static void r200ClipPlane( struct gl_context *ctx, GLenum plane, const GLfloat *eq )
1350 {
1351 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1352 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1353 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1354
1355 R200_STATECHANGE( rmesa, ucp[p] );
1356 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1357 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1358 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1359 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1360 }
1361
r200UpdateClipPlanes(struct gl_context * ctx)1362 static void r200UpdateClipPlanes( struct gl_context *ctx )
1363 {
1364 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1365 GLbitfield mask = ctx->Transform.ClipPlanesEnabled;
1366
1367 while (mask) {
1368 const int p = u_bit_scan(&mask);
1369 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1370
1371 R200_STATECHANGE( rmesa, ucp[p] );
1372 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1373 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1374 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1375 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1376 }
1377 }
1378
1379
1380 /* =============================================================
1381 * Stencil
1382 */
1383
1384 static void
r200StencilFuncSeparate(struct gl_context * ctx,GLenum face,GLenum func,GLint ref,GLuint mask)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
r200StencilMaskSeparate(struct gl_context * ctx,GLenum face,GLuint mask)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
r200StencilOpSeparate(struct gl_context * ctx,GLenum face,GLenum fail,GLenum zfail,GLenum zpass)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 */
r200UpdateWindow(struct gl_context * ctx)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
r200_vtbl_update_scissor(struct gl_context * ctx)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
r200Viewport(struct gl_context * ctx)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
r200DepthRange(struct gl_context * ctx)1615 static void r200DepthRange(struct gl_context *ctx)
1616 {
1617 r200UpdateWindow( ctx );
1618 }
1619
1620 /* =============================================================
1621 * Miscellaneous
1622 */
1623
r200RenderMode(struct gl_context * ctx,GLenum mode)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
r200LogicOpCode(struct gl_context * ctx,enum gl_logicop_mode opcode)1630 static void r200LogicOpCode(struct gl_context *ctx, enum gl_logicop_mode opcode)
1631 {
1632 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1633
1634 assert((unsigned) opcode <= 15);
1635
1636 R200_STATECHANGE( rmesa, msk );
1637 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = opcode;
1638 }
1639
1640 /* =============================================================
1641 * State enable/disable
1642 */
1643
r200Enable(struct gl_context * ctx,GLenum cap,GLboolean state)1644 static void r200Enable( struct gl_context *ctx, GLenum cap, GLboolean state )
1645 {
1646 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1647 GLuint p, flag;
1648
1649 if ( R200_DEBUG & RADEON_STATE )
1650 fprintf( stderr, "%s( %s = %s )\n", __func__,
1651 _mesa_enum_to_string( cap ),
1652 state ? "GL_TRUE" : "GL_FALSE" );
1653
1654 switch ( cap ) {
1655 /* Fast track this one...
1656 */
1657 case GL_TEXTURE_1D:
1658 case GL_TEXTURE_2D:
1659 case GL_TEXTURE_3D:
1660 break;
1661
1662 case GL_ALPHA_TEST:
1663 R200_STATECHANGE( rmesa, ctx );
1664 if (state) {
1665 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1666 } else {
1667 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1668 }
1669 break;
1670
1671 case GL_BLEND:
1672 case GL_COLOR_LOGIC_OP:
1673 r200_set_blend_state( ctx );
1674 break;
1675
1676 case GL_CLIP_PLANE0:
1677 case GL_CLIP_PLANE1:
1678 case GL_CLIP_PLANE2:
1679 case GL_CLIP_PLANE3:
1680 case GL_CLIP_PLANE4:
1681 case GL_CLIP_PLANE5:
1682 p = cap-GL_CLIP_PLANE0;
1683 R200_STATECHANGE( rmesa, tcl );
1684 if (state) {
1685 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1686 r200ClipPlane( ctx, cap, NULL );
1687 }
1688 else {
1689 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1690 }
1691 break;
1692
1693 case GL_COLOR_MATERIAL:
1694 r200ColorMaterial( ctx, 0, 0 );
1695 r200UpdateMaterial( ctx );
1696 break;
1697
1698 case GL_CULL_FACE:
1699 r200CullFace( ctx, 0 );
1700 break;
1701
1702 case GL_DEPTH_TEST:
1703 R200_STATECHANGE(rmesa, ctx );
1704 if ( state ) {
1705 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1706 } else {
1707 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1708 }
1709 break;
1710
1711 case GL_DITHER:
1712 R200_STATECHANGE(rmesa, ctx );
1713 if ( state ) {
1714 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1715 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
1716 } else {
1717 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1718 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable;
1719 }
1720 break;
1721
1722 case GL_FOG:
1723 R200_STATECHANGE(rmesa, ctx );
1724 if ( state ) {
1725 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1726 r200Fogfv( ctx, GL_FOG_MODE, NULL );
1727 } else {
1728 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1729 R200_STATECHANGE(rmesa, tcl);
1730 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1731 }
1732 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1733 if (rmesa->radeon.TclFallback)
1734 r200ChooseVertexState( ctx );
1735 _mesa_allow_light_in_model( ctx, !state );
1736 break;
1737
1738 case GL_LIGHT0:
1739 case GL_LIGHT1:
1740 case GL_LIGHT2:
1741 case GL_LIGHT3:
1742 case GL_LIGHT4:
1743 case GL_LIGHT5:
1744 case GL_LIGHT6:
1745 case GL_LIGHT7:
1746 R200_STATECHANGE(rmesa, tcl);
1747 p = cap - GL_LIGHT0;
1748 if (p&1)
1749 flag = (R200_LIGHT_1_ENABLE |
1750 R200_LIGHT_1_ENABLE_AMBIENT |
1751 R200_LIGHT_1_ENABLE_SPECULAR);
1752 else
1753 flag = (R200_LIGHT_0_ENABLE |
1754 R200_LIGHT_0_ENABLE_AMBIENT |
1755 R200_LIGHT_0_ENABLE_SPECULAR);
1756
1757 if (state)
1758 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1759 else
1760 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1761
1762 /*
1763 */
1764 update_light_colors( ctx, p );
1765 break;
1766
1767 case GL_LIGHTING:
1768 r200UpdateSpecular(ctx);
1769 /* for reflection map fixup - might set recheck_texgen for all units too */
1770 rmesa->radeon.NewGLState |= _NEW_TEXTURE;
1771 break;
1772
1773 case GL_LINE_SMOOTH:
1774 R200_STATECHANGE( rmesa, ctx );
1775 if ( state ) {
1776 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1777 } else {
1778 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1779 }
1780 break;
1781
1782 case GL_LINE_STIPPLE:
1783 R200_STATECHANGE( rmesa, set );
1784 if ( state ) {
1785 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1786 } else {
1787 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1788 }
1789 break;
1790
1791 case GL_NORMALIZE:
1792 R200_STATECHANGE( rmesa, tcl );
1793 if ( state ) {
1794 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1795 } else {
1796 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1797 }
1798 break;
1799
1800 /* Pointsize registers on r200 only work for point sprites, and point smooth
1801 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1802 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1803 * is enough to satisfy conform.
1804 */
1805 case GL_POINT_SMOOTH:
1806 break;
1807
1808 /* These don't really do anything, as we don't use the 3vtx
1809 * primitives yet.
1810 */
1811 #if 0
1812 case GL_POLYGON_OFFSET_POINT:
1813 R200_STATECHANGE( rmesa, set );
1814 if ( state ) {
1815 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1816 } else {
1817 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1818 }
1819 break;
1820
1821 case GL_POLYGON_OFFSET_LINE:
1822 R200_STATECHANGE( rmesa, set );
1823 if ( state ) {
1824 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
1825 } else {
1826 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1827 }
1828 break;
1829 #endif
1830
1831 case GL_POINT_SPRITE_ARB:
1832 R200_STATECHANGE( rmesa, spr );
1833 if ( state ) {
1834 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_GEN_TEX_MASK &
1835 (ctx->Point.CoordReplace << R200_PS_GEN_TEX_0_SHIFT);
1836 } else {
1837 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
1838 }
1839 break;
1840
1841 case GL_POLYGON_OFFSET_FILL:
1842 R200_STATECHANGE( rmesa, set );
1843 if ( state ) {
1844 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
1845 } else {
1846 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1847 }
1848 break;
1849
1850 case GL_POLYGON_SMOOTH:
1851 R200_STATECHANGE( rmesa, ctx );
1852 if ( state ) {
1853 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
1854 } else {
1855 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
1856 }
1857 break;
1858
1859 case GL_POLYGON_STIPPLE:
1860 R200_STATECHANGE(rmesa, set );
1861 if ( state ) {
1862 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
1863 } else {
1864 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
1865 }
1866 break;
1867
1868 case GL_RESCALE_NORMAL_EXT: {
1869 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1870 R200_STATECHANGE( rmesa, tcl );
1871 if ( tmp ) {
1872 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1873 } else {
1874 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1875 }
1876 break;
1877 }
1878
1879 case GL_SCISSOR_TEST:
1880 radeon_firevertices(&rmesa->radeon);
1881 rmesa->radeon.state.scissor.enabled = state;
1882 radeonUpdateScissor( ctx );
1883 break;
1884
1885 case GL_STENCIL_TEST:
1886 {
1887 GLboolean hw_stencil = GL_FALSE;
1888 if (ctx->DrawBuffer) {
1889 struct radeon_renderbuffer *rrbStencil
1890 = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
1891 hw_stencil = (rrbStencil && rrbStencil->bo);
1892 }
1893
1894 if (hw_stencil) {
1895 R200_STATECHANGE( rmesa, ctx );
1896 if ( state ) {
1897 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
1898 } else {
1899 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
1900 }
1901 } else {
1902 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
1903 }
1904 }
1905 break;
1906
1907 case GL_TEXTURE_GEN_Q:
1908 case GL_TEXTURE_GEN_R:
1909 case GL_TEXTURE_GEN_S:
1910 case GL_TEXTURE_GEN_T:
1911 /* Picked up in r200UpdateTextureState.
1912 */
1913 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1914 break;
1915
1916 case GL_COLOR_SUM_EXT:
1917 r200UpdateSpecular ( ctx );
1918 break;
1919
1920 case GL_VERTEX_PROGRAM_ARB:
1921 if (!state) {
1922 GLuint i;
1923 rmesa->curr_vp_hw = NULL;
1924 R200_STATECHANGE( rmesa, vap );
1925 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
1926 /* mark all tcl atoms (tcl vector state got overwritten) dirty
1927 not sure about tcl scalar state - we need at least grd
1928 with vert progs too.
1929 ucp looks like it doesn't get overwritten (may even work
1930 with vp for pos-invariant progs if we're lucky) */
1931 R200_STATECHANGE( rmesa, mtl[0] );
1932 R200_STATECHANGE( rmesa, mtl[1] );
1933 R200_STATECHANGE( rmesa, fog );
1934 R200_STATECHANGE( rmesa, glt );
1935 R200_STATECHANGE( rmesa, eye );
1936 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
1937 R200_STATECHANGE( rmesa, mat[i] );
1938 }
1939 for (i = 0 ; i < 8; i++) {
1940 R200_STATECHANGE( rmesa, lit[i] );
1941 }
1942 R200_STATECHANGE( rmesa, tcl );
1943 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
1944 if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
1945 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
1946 }
1947 /* else {
1948 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
1949 }*/
1950 }
1951 /* ugly. Need to call everything which might change compsel. */
1952 r200UpdateSpecular( ctx );
1953 #if 0
1954 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
1955 but without it doom3 locks up at always the same places. Why? */
1956 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
1957 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
1958 r200UpdateTextureState( ctx );
1959 /* if we call r200UpdateTextureState we need the code below because we are calling it with
1960 non-current derived enabled values which may revert the state atoms for frag progs even when
1961 they already got disabled... ugh
1962 Should really figure out why we need to call r200UpdateTextureState in the first place */
1963 GLuint unit;
1964 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
1965 R200_STATECHANGE( rmesa, pix[unit] );
1966 R200_STATECHANGE( rmesa, tex[unit] );
1967 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
1968 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
1969 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
1970 /* need to guard this with drmSupportsFragmentShader? Should never get here if
1971 we don't announce ATI_fs, right? */
1972 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
1973 }
1974 R200_STATECHANGE( rmesa, cst );
1975 R200_STATECHANGE( rmesa, tf );
1976 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
1977 #endif
1978 }
1979 else {
1980 /* picked up later */
1981 }
1982 /* call functions which change hw state based on ARB_vp enabled or not. */
1983 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
1984 r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
1985 break;
1986
1987 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
1988 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
1989 break;
1990
1991 case GL_FRAGMENT_SHADER_ATI:
1992 if ( !state ) {
1993 /* restore normal tex env colors and make sure tex env combine will get updated
1994 mark env atoms dirty (as their data was overwritten by afs even
1995 if they didn't change) and restore tex coord routing */
1996 GLuint unit;
1997 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
1998 R200_STATECHANGE( rmesa, pix[unit] );
1999 R200_STATECHANGE( rmesa, tex[unit] );
2000 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2001 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2002 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2003 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2004 }
2005 R200_STATECHANGE( rmesa, cst );
2006 R200_STATECHANGE( rmesa, tf );
2007 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2008 }
2009 else {
2010 /* need to mark this dirty as pix/tf atoms have overwritten the data
2011 even if the data in the atoms didn't change */
2012 R200_STATECHANGE( rmesa, atf );
2013 R200_STATECHANGE( rmesa, afs[1] );
2014 /* everything else picked up in r200UpdateTextureState hopefully */
2015 }
2016 break;
2017 default:
2018 return;
2019 }
2020 }
2021
2022
r200LightingSpaceChange(struct gl_context * ctx)2023 void r200LightingSpaceChange( struct gl_context *ctx )
2024 {
2025 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2026 GLboolean tmp;
2027
2028 if (R200_DEBUG & RADEON_STATE)
2029 fprintf(stderr, "%s %d BEFORE %x\n", __func__, ctx->_NeedEyeCoords,
2030 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2031
2032 if (ctx->_NeedEyeCoords)
2033 tmp = ctx->Transform.RescaleNormals;
2034 else
2035 tmp = !ctx->Transform.RescaleNormals;
2036
2037 R200_STATECHANGE( rmesa, tcl );
2038 if ( tmp ) {
2039 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2040 } else {
2041 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2042 }
2043
2044 if (R200_DEBUG & RADEON_STATE)
2045 fprintf(stderr, "%s %d AFTER %x\n", __func__, ctx->_NeedEyeCoords,
2046 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2047 }
2048
2049 /* =============================================================
2050 * Deferred state management - matrices, textures, other?
2051 */
2052
2053
2054
2055
upload_matrix(r200ContextPtr rmesa,GLfloat * src,int idx)2056 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2057 {
2058 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2059 int i;
2060
2061
2062 for (i = 0 ; i < 4 ; i++) {
2063 *dest++ = src[i];
2064 *dest++ = src[i+4];
2065 *dest++ = src[i+8];
2066 *dest++ = src[i+12];
2067 }
2068
2069 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2070 }
2071
upload_matrix_t(r200ContextPtr rmesa,const GLfloat * src,int idx)2072 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2073 {
2074 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2075 memcpy(dest, src, 16*sizeof(float));
2076 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2077 }
2078
2079
update_texturematrix(struct gl_context * ctx)2080 static void update_texturematrix( struct gl_context *ctx )
2081 {
2082 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2083 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2084 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2085 int unit;
2086
2087 if (R200_DEBUG & RADEON_STATE)
2088 fprintf(stderr, "%s before COMPSEL: %x\n", __func__,
2089 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2090
2091 rmesa->TexMatEnabled = 0;
2092 rmesa->TexMatCompSel = 0;
2093
2094 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2095 if (!ctx->Texture.Unit[unit]._Current)
2096 continue;
2097
2098 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2099 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2100 R200_TEXMAT_0_ENABLE) << unit;
2101
2102 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2103
2104 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2105 /* Need to preconcatenate any active texgen
2106 * obj/eyeplane matrices:
2107 */
2108 _math_matrix_mul_matrix( &rmesa->tmpmat,
2109 ctx->TextureMatrixStack[unit].Top,
2110 &rmesa->TexGenMatrix[unit] );
2111 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2112 }
2113 else {
2114 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2115 R200_MTX_TEX0+unit );
2116 }
2117 }
2118 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2119 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2120 R200_MTX_TEX0+unit );
2121 }
2122 }
2123
2124 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2125 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2126 R200_STATECHANGE(rmesa, tcg);
2127 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2128 }
2129
2130 compsel &= ~R200_OUTPUT_TEX_MASK;
2131 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2132 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2133 R200_STATECHANGE(rmesa, vtx);
2134 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2135 }
2136 }
2137
r200ValidateBuffers(struct gl_context * ctx)2138 GLboolean r200ValidateBuffers(struct gl_context *ctx)
2139 {
2140 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2141 struct radeon_renderbuffer *rrb;
2142 struct radeon_dma_bo *dma_bo;
2143 int i, ret;
2144
2145 if (RADEON_DEBUG & RADEON_IOCTL)
2146 fprintf(stderr, "%s\n", __func__);
2147 radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
2148
2149 rrb = radeon_get_colorbuffer(&rmesa->radeon);
2150 /* color buffer */
2151 if (rrb && rrb->bo) {
2152 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2153 0, RADEON_GEM_DOMAIN_VRAM);
2154 }
2155
2156 /* depth buffer */
2157 rrb = radeon_get_depthbuffer(&rmesa->radeon);
2158 /* color buffer */
2159 if (rrb && rrb->bo) {
2160 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2161 0, RADEON_GEM_DOMAIN_VRAM);
2162 }
2163
2164 for (i = 0; i < ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits; ++i) {
2165 radeonTexObj *t;
2166
2167 if (!ctx->Texture.Unit[i]._Current)
2168 continue;
2169
2170 t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
2171 if (t->image_override && t->bo)
2172 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo,
2173 RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2174 else if (t->mt->bo)
2175 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo,
2176 RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2177 }
2178
2179 dma_bo = first_elem(&rmesa->radeon.dma.reserved);
2180 {
2181 ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, dma_bo->bo, RADEON_GEM_DOMAIN_GTT, 0);
2182 if (ret)
2183 return GL_FALSE;
2184 }
2185 return GL_TRUE;
2186 }
2187
r200ValidateState(struct gl_context * ctx)2188 GLboolean r200ValidateState( struct gl_context *ctx )
2189 {
2190 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2191 GLuint new_state = rmesa->radeon.NewGLState;
2192
2193 if (new_state & _NEW_BUFFERS) {
2194 _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer);
2195 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2196 _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
2197
2198 R200_STATECHANGE(rmesa, ctx);
2199 }
2200
2201 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) {
2202 r200UpdateTextureState( ctx );
2203 new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
2204 r200UpdateLocalViewer( ctx );
2205 }
2206
2207 /* we need to do a space check here */
2208 if (!r200ValidateBuffers(ctx))
2209 return GL_FALSE;
2210
2211 /* FIXME: don't really need most of these when vertex progs are enabled */
2212
2213 /* Need an event driven matrix update?
2214 */
2215 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2216 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2217
2218 /* Need these for lighting (shouldn't upload otherwise)
2219 */
2220 if (new_state & (_NEW_MODELVIEW)) {
2221 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2222 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2223 }
2224
2225 /* Does this need to be triggered on eg. modelview for
2226 * texgen-derived objplane/eyeplane matrices?
2227 */
2228 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2229 update_texturematrix( ctx );
2230 }
2231
2232 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2233 update_light( ctx );
2234 }
2235
2236 /* emit all active clip planes if projection matrix changes.
2237 */
2238 if (new_state & (_NEW_PROJECTION)) {
2239 if (ctx->Transform.ClipPlanesEnabled)
2240 r200UpdateClipPlanes( ctx );
2241 }
2242
2243 if (new_state & (_NEW_PROGRAM|
2244 _NEW_PROGRAM_CONSTANTS |
2245 /* need to test for pretty much anything due to possible parameter bindings */
2246 _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2247 _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2248 _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2249 if (_mesa_arb_vertex_program_enabled(ctx)) {
2250 r200SetupVertexProg( ctx );
2251 }
2252 else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2253 }
2254
2255 rmesa->radeon.NewGLState = 0;
2256 return GL_TRUE;
2257 }
2258
2259
r200InvalidateState(struct gl_context * ctx)2260 static void r200InvalidateState(struct gl_context *ctx)
2261 {
2262 GLuint new_state = ctx->NewState;
2263
2264 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2265
2266 if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
2267 _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
2268
2269 _swrast_InvalidateState( ctx, new_state );
2270 _swsetup_InvalidateState( ctx, new_state );
2271 _tnl_InvalidateState( ctx, new_state );
2272 R200_CONTEXT(ctx)->radeon.NewGLState |= new_state;
2273
2274 if (new_state & _NEW_PROGRAM)
2275 rmesa->curr_vp_hw = NULL;
2276 }
2277
2278 /* A hack. The r200 can actually cope just fine with materials
2279 * between begin/ends, so fix this.
2280 * Should map to inputs just like the generic vertex arrays for vertex progs.
2281 * In theory there could still be too many and we'd still need a fallback.
2282 */
check_material(struct gl_context * ctx)2283 static GLboolean check_material( struct gl_context *ctx )
2284 {
2285 TNLcontext *tnl = TNL_CONTEXT(ctx);
2286 GLint i;
2287
2288 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2289 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2290 i++)
2291 if (tnl->vb.AttribPtr[i] &&
2292 tnl->vb.AttribPtr[i]->stride)
2293 return GL_TRUE;
2294
2295 return GL_FALSE;
2296 }
2297
r200WrapRunPipeline(struct gl_context * ctx)2298 static void r200WrapRunPipeline( struct gl_context *ctx )
2299 {
2300 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2301 GLboolean has_material;
2302
2303 if (0)
2304 fprintf(stderr, "%s, newstate: %x\n", __func__, rmesa->radeon.NewGLState);
2305
2306 /* Validate state:
2307 */
2308 if (rmesa->radeon.NewGLState)
2309 if (!r200ValidateState( ctx ))
2310 FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
2311
2312 has_material = !_mesa_arb_vertex_program_enabled(ctx) &&
2313 ctx->Light.Enabled && check_material( ctx );
2314
2315 if (has_material) {
2316 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2317 }
2318
2319 /* Run the pipeline.
2320 */
2321 _tnl_run_pipeline( ctx );
2322
2323 if (has_material) {
2324 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2325 }
2326 }
2327
2328
r200PolygonStipple(struct gl_context * ctx,const GLubyte * mask)2329 static void r200PolygonStipple( struct gl_context *ctx, const GLubyte *mask )
2330 {
2331 r200ContextPtr r200 = R200_CONTEXT(ctx);
2332 GLint i;
2333
2334 radeon_firevertices(&r200->radeon);
2335
2336 radeon_print(RADEON_STATE, RADEON_TRACE,
2337 "%s(%p) first 32 bits are %x.\n",
2338 __func__,
2339 ctx,
2340 *(uint32_t*)mask);
2341
2342 R200_STATECHANGE(r200, stp);
2343
2344 /* Must flip pattern upside down.
2345 */
2346 for ( i = 31 ; i >= 0; i--) {
2347 r200->hw.stp.cmd[3 + i] = ((GLuint *) mask)[i];
2348 }
2349 }
2350 /* Initialize the driver's state functions.
2351 */
r200InitStateFuncs(radeonContextPtr radeon,struct dd_function_table * functions)2352 void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *functions )
2353 {
2354 functions->UpdateState = r200InvalidateState;
2355 functions->LightingSpaceChange = r200LightingSpaceChange;
2356
2357 functions->DrawBuffer = radeonDrawBuffer;
2358 functions->ReadBuffer = radeonReadBuffer;
2359
2360 functions->CopyPixels = _mesa_meta_CopyPixels;
2361 functions->DrawPixels = _mesa_meta_DrawPixels;
2362 functions->ReadPixels = radeonReadPixels;
2363
2364 functions->AlphaFunc = r200AlphaFunc;
2365 functions->BlendColor = r200BlendColor;
2366 functions->BlendEquationSeparate = r200BlendEquationSeparate;
2367 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2368 functions->ClipPlane = r200ClipPlane;
2369 functions->ColorMask = r200ColorMask;
2370 functions->CullFace = r200CullFace;
2371 functions->DepthFunc = r200DepthFunc;
2372 functions->DepthMask = r200DepthMask;
2373 functions->DepthRange = r200DepthRange;
2374 functions->Enable = r200Enable;
2375 functions->Fogfv = r200Fogfv;
2376 functions->FrontFace = r200FrontFace;
2377 functions->LightModelfv = r200LightModelfv;
2378 functions->Lightfv = r200Lightfv;
2379 functions->LineStipple = r200LineStipple;
2380 functions->LineWidth = r200LineWidth;
2381 functions->LogicOpcode = r200LogicOpCode;
2382 functions->PolygonMode = r200PolygonMode;
2383 functions->PolygonOffset = r200PolygonOffset;
2384 functions->PolygonStipple = r200PolygonStipple;
2385 functions->PointParameterfv = r200PointParameter;
2386 functions->PointSize = r200PointSize;
2387 functions->RenderMode = r200RenderMode;
2388 functions->Scissor = radeonScissor;
2389 functions->ShadeModel = r200ShadeModel;
2390 functions->StencilFuncSeparate = r200StencilFuncSeparate;
2391 functions->StencilMaskSeparate = r200StencilMaskSeparate;
2392 functions->StencilOpSeparate = r200StencilOpSeparate;
2393 functions->Viewport = r200Viewport;
2394 }
2395
2396
r200InitTnlFuncs(struct gl_context * ctx)2397 void r200InitTnlFuncs( struct gl_context *ctx )
2398 {
2399 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2400 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2401 }
2402