1 /**************************************************************************
2
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Keith Whitwell <keithw@vmware.com>
34 */
35
36 #include "main/glheader.h"
37 #include "main/imports.h"
38 #include "main/api_arrayelt.h"
39 #include "main/enums.h"
40 #include "main/light.h"
41 #include "main/framebuffer.h"
42 #include "main/fbobject.h"
43 #include "main/stencil.h"
44 #include "main/viewport.h"
45
46 #include "swrast/swrast.h"
47 #include "vbo/vbo.h"
48 #include "tnl/tnl.h"
49 #include "tnl/t_pipeline.h"
50 #include "swrast_setup/swrast_setup.h"
51 #include "drivers/common/meta.h"
52 #include "util/bitscan.h"
53
54 #include "radeon_common.h"
55 #include "radeon_mipmap_tree.h"
56 #include "r200_context.h"
57 #include "r200_ioctl.h"
58 #include "r200_state.h"
59 #include "r200_tcl.h"
60 #include "r200_tex.h"
61 #include "r200_swtcl.h"
62 #include "r200_vertprog.h"
63
64 #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_R_MODE_NV:
634 case GL_POINT_SPRITE_COORD_ORIGIN: */
635 default:
636 fprintf(stderr, "bad pname parameter in r200PointParameter\n");
637 return;
638 }
639 }
640
641 /* =============================================================
642 * Line state
643 */
r200LineWidth(struct gl_context * ctx,GLfloat widthf)644 static void r200LineWidth( struct gl_context *ctx, GLfloat widthf )
645 {
646 r200ContextPtr rmesa = R200_CONTEXT(ctx);
647
648 R200_STATECHANGE( rmesa, lin );
649 R200_STATECHANGE( rmesa, set );
650
651 /* Line width is stored in U6.4 format.
652 * Same min/max limits for AA, non-AA lines.
653 */
654 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
655 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)
656 (CLAMP(widthf, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth) * 16.0);
657
658 if ( widthf > 1.0 ) {
659 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE;
660 } else {
661 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
662 }
663 }
664
r200LineStipple(struct gl_context * ctx,GLint factor,GLushort pattern)665 static void r200LineStipple( struct gl_context *ctx, GLint factor, GLushort pattern )
666 {
667 r200ContextPtr rmesa = R200_CONTEXT(ctx);
668
669 R200_STATECHANGE( rmesa, lin );
670 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
671 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
672 }
673
674
675 /* =============================================================
676 * Masks
677 */
r200ColorMask(struct gl_context * ctx,GLboolean r,GLboolean g,GLboolean b,GLboolean a)678 static void r200ColorMask( struct gl_context *ctx,
679 GLboolean r, GLboolean g,
680 GLboolean b, GLboolean a )
681 {
682 r200ContextPtr rmesa = R200_CONTEXT(ctx);
683 GLuint mask;
684 struct radeon_renderbuffer *rrb;
685 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
686
687 rrb = radeon_get_colorbuffer(&rmesa->radeon);
688 if (!rrb)
689 return;
690 mask = radeonPackColor( rrb->cpp,
691 ctx->Color.ColorMask[0][RCOMP],
692 ctx->Color.ColorMask[0][GCOMP],
693 ctx->Color.ColorMask[0][BCOMP],
694 ctx->Color.ColorMask[0][ACOMP] );
695
696
697 if (!(r && g && b && a))
698 flag |= R200_PLANE_MASK_ENABLE;
699
700 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
701 R200_STATECHANGE( rmesa, ctx );
702 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
703 }
704
705 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
706 R200_STATECHANGE( rmesa, msk );
707 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
708 }
709 }
710
711
712 /* =============================================================
713 * Polygon state
714 */
715
r200PolygonOffset(struct gl_context * ctx,GLfloat factor,GLfloat units,GLfloat clamp)716 static void r200PolygonOffset( struct gl_context *ctx,
717 GLfloat factor, GLfloat units, GLfloat clamp )
718 {
719 r200ContextPtr rmesa = R200_CONTEXT(ctx);
720 const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
721 float_ui32_type constant = { units * depthScale };
722 float_ui32_type factoru = { factor };
723
724 /* factor *= 2; */
725 /* constant *= 2; */
726
727 /* fprintf(stderr, "%s f:%f u:%f\n", __func__, factor, constant); */
728
729 R200_STATECHANGE( rmesa, zbs );
730 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32;
731 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
732 }
733
r200PolygonMode(struct gl_context * ctx,GLenum face,GLenum mode)734 static void r200PolygonMode( struct gl_context *ctx, GLenum face, GLenum mode )
735 {
736 r200ContextPtr rmesa = R200_CONTEXT(ctx);
737 GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
738 ctx->Polygon.BackMode != GL_FILL);
739
740 /* Can't generally do unfilled via tcl, but some good special
741 * cases work.
742 */
743 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, unfilled);
744 if (rmesa->radeon.TclFallback) {
745 r200ChooseRenderState( ctx );
746 r200ChooseVertexState( ctx );
747 }
748 }
749
750
751 /* =============================================================
752 * Rendering attributes
753 *
754 * We really don't want to recalculate all this every time we bind a
755 * texture. These things shouldn't change all that often, so it makes
756 * sense to break them out of the core texture state update routines.
757 */
758
759 /* Examine lighting and texture state to determine if separate specular
760 * should be enabled.
761 */
r200UpdateSpecular(struct gl_context * ctx)762 static void r200UpdateSpecular( struct gl_context *ctx )
763 {
764 r200ContextPtr rmesa = R200_CONTEXT(ctx);
765 uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
766
767 R200_STATECHANGE( rmesa, tcl );
768 R200_STATECHANGE( rmesa, vtx );
769
770 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
771 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
772 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
773 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
774 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
775
776 p &= ~R200_SPECULAR_ENABLE;
777
778 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
779
780
781 if (ctx->Light.Enabled &&
782 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
783 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
784 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
785 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
786 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
787 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
788 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
789 p |= R200_SPECULAR_ENABLE;
790 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
791 ~R200_DIFFUSE_SPECULAR_COMBINE;
792 }
793 else if (ctx->Light.Enabled) {
794 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
795 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
796 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
797 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
798 } else if (ctx->Fog.ColorSumEnabled ) {
799 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
800 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
801 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
802 p |= R200_SPECULAR_ENABLE;
803 } else {
804 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
805 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
806 }
807
808 if (ctx->Fog.Enabled) {
809 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
810 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
811 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
812 }
813
814 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
815 R200_STATECHANGE( rmesa, ctx );
816 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
817 }
818
819 /* Update vertex/render formats
820 */
821 if (rmesa->radeon.TclFallback) {
822 r200ChooseRenderState( ctx );
823 r200ChooseVertexState( ctx );
824 }
825 }
826
827
828 /* =============================================================
829 * Materials
830 */
831
832
833 /* Update on colormaterial, material emmissive/ambient,
834 * lightmodel.globalambient
835 */
update_global_ambient(struct gl_context * ctx)836 static void update_global_ambient( struct gl_context *ctx )
837 {
838 r200ContextPtr rmesa = R200_CONTEXT(ctx);
839 float *fcmd = (float *)R200_DB_STATE( glt );
840
841 /* Need to do more if both emmissive & ambient are PREMULT:
842 * I believe this is not nessary when using source_material. This condition thus
843 * will never happen currently, and the function has no dependencies on materials now
844 */
845 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
846 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
847 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
848 {
849 COPY_3V( &fcmd[GLT_RED],
850 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
851 ACC_SCALE_3V( &fcmd[GLT_RED],
852 ctx->Light.Model.Ambient,
853 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
854 }
855 else
856 {
857 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
858 }
859
860 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
861 }
862
863 /* Update on change to
864 * - light[p].colors
865 * - light[p].enabled
866 */
update_light_colors(struct gl_context * ctx,GLuint p)867 static void update_light_colors( struct gl_context *ctx, GLuint p )
868 {
869 struct gl_light *l = &ctx->Light.Light[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], l->Ambient );
878 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
879 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->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 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1122
1123 if (l->EyePosition[3] == 0.0) {
1124 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1125 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1126 fcmd[LIT_POSITION_W] = 0;
1127 fcmd[LIT_DIRECTION_W] = 0;
1128 } else {
1129 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1130 fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0];
1131 fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1];
1132 fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2];
1133 fcmd[LIT_DIRECTION_W] = 0;
1134 }
1135
1136 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1137 }
1138 }
1139 }
1140
r200Lightfv(struct gl_context * ctx,GLenum light,GLenum pname,const GLfloat * params)1141 static void r200Lightfv( struct gl_context *ctx, GLenum light,
1142 GLenum pname, const GLfloat *params )
1143 {
1144 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1145 GLint p = light - GL_LIGHT0;
1146 struct gl_light *l = &ctx->Light.Light[p];
1147 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1148
1149
1150 switch (pname) {
1151 case GL_AMBIENT:
1152 case GL_DIFFUSE:
1153 case GL_SPECULAR:
1154 update_light_colors( ctx, p );
1155 break;
1156
1157 case GL_SPOT_DIRECTION:
1158 /* picked up in update_light */
1159 break;
1160
1161 case GL_POSITION: {
1162 /* positions picked up in update_light, but can do flag here */
1163 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1164 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1165
1166 R200_STATECHANGE(rmesa, tcl);
1167 if (l->EyePosition[3] != 0.0F)
1168 rmesa->hw.tcl.cmd[idx] |= flag;
1169 else
1170 rmesa->hw.tcl.cmd[idx] &= ~flag;
1171 break;
1172 }
1173
1174 case GL_SPOT_EXPONENT:
1175 R200_STATECHANGE(rmesa, lit[p]);
1176 fcmd[LIT_SPOT_EXPONENT] = params[0];
1177 break;
1178
1179 case GL_SPOT_CUTOFF: {
1180 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1181 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1182
1183 R200_STATECHANGE(rmesa, lit[p]);
1184 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1185
1186 R200_STATECHANGE(rmesa, tcl);
1187 if (l->SpotCutoff != 180.0F)
1188 rmesa->hw.tcl.cmd[idx] |= flag;
1189 else
1190 rmesa->hw.tcl.cmd[idx] &= ~flag;
1191
1192 break;
1193 }
1194
1195 case GL_CONSTANT_ATTENUATION:
1196 R200_STATECHANGE(rmesa, lit[p]);
1197 fcmd[LIT_ATTEN_CONST] = params[0];
1198 if ( params[0] == 0.0 )
1199 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1200 else
1201 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1202 break;
1203 case GL_LINEAR_ATTENUATION:
1204 R200_STATECHANGE(rmesa, lit[p]);
1205 fcmd[LIT_ATTEN_LINEAR] = params[0];
1206 break;
1207 case GL_QUADRATIC_ATTENUATION:
1208 R200_STATECHANGE(rmesa, lit[p]);
1209 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1210 break;
1211 default:
1212 return;
1213 }
1214
1215 /* Set RANGE_ATTEN only when needed */
1216 switch (pname) {
1217 case GL_POSITION:
1218 case GL_CONSTANT_ATTENUATION:
1219 case GL_LINEAR_ATTENUATION:
1220 case GL_QUADRATIC_ATTENUATION: {
1221 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1222 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1223 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1224 : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1225 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1226 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1227
1228 if ( l->EyePosition[3] == 0.0F ||
1229 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1230 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1231 /* Disable attenuation */
1232 icmd[idx] &= ~atten_flag;
1233 } else {
1234 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1235 /* Enable only constant portion of attenuation calculation */
1236 icmd[idx] |= ( atten_flag | atten_const_flag );
1237 } else {
1238 /* Enable full attenuation calculation */
1239 icmd[idx] &= ~atten_const_flag;
1240 icmd[idx] |= atten_flag;
1241 }
1242 }
1243
1244 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1245 break;
1246 }
1247 default:
1248 break;
1249 }
1250 }
1251
r200UpdateLocalViewer(struct gl_context * ctx)1252 static void r200UpdateLocalViewer ( struct gl_context *ctx )
1253 {
1254 /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1255 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1256 for these and only these modes). This means specular highlights may turn out
1257 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1258 is not set, though it seems to happen rarely and the effect seems quite
1259 subtle. May need TCL fallback to fix it completely, though I'm not sure
1260 how you'd identify the cases where the specular highlights indeed will
1261 be wrong. Don't know if fglrx does something special in that case.
1262 */
1263 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1264 R200_STATECHANGE( rmesa, tcl );
1265 if (ctx->Light.Model.LocalViewer ||
1266 ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
1267 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1268 else
1269 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1270 }
1271
r200LightModelfv(struct gl_context * ctx,GLenum pname,const GLfloat * param)1272 static void r200LightModelfv( struct gl_context *ctx, GLenum pname,
1273 const GLfloat *param )
1274 {
1275 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1276
1277 switch (pname) {
1278 case GL_LIGHT_MODEL_AMBIENT:
1279 update_global_ambient( ctx );
1280 break;
1281
1282 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1283 r200UpdateLocalViewer( ctx );
1284 break;
1285
1286 case GL_LIGHT_MODEL_TWO_SIDE:
1287 R200_STATECHANGE( rmesa, tcl );
1288 if (ctx->Light.Model.TwoSide)
1289 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1290 else
1291 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1292 if (rmesa->radeon.TclFallback) {
1293 r200ChooseRenderState( ctx );
1294 r200ChooseVertexState( ctx );
1295 }
1296 break;
1297
1298 case GL_LIGHT_MODEL_COLOR_CONTROL:
1299 r200UpdateSpecular(ctx);
1300 break;
1301
1302 default:
1303 break;
1304 }
1305 }
1306
r200ShadeModel(struct gl_context * ctx,GLenum mode)1307 static void r200ShadeModel( struct gl_context *ctx, GLenum mode )
1308 {
1309 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1310 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1311
1312 s &= ~(R200_DIFFUSE_SHADE_MASK |
1313 R200_ALPHA_SHADE_MASK |
1314 R200_SPECULAR_SHADE_MASK |
1315 R200_FOG_SHADE_MASK |
1316 R200_DISC_FOG_SHADE_MASK);
1317
1318 switch ( mode ) {
1319 case GL_FLAT:
1320 s |= (R200_DIFFUSE_SHADE_FLAT |
1321 R200_ALPHA_SHADE_FLAT |
1322 R200_SPECULAR_SHADE_FLAT |
1323 R200_FOG_SHADE_FLAT |
1324 R200_DISC_FOG_SHADE_FLAT);
1325 break;
1326 case GL_SMOOTH:
1327 s |= (R200_DIFFUSE_SHADE_GOURAUD |
1328 R200_ALPHA_SHADE_GOURAUD |
1329 R200_SPECULAR_SHADE_GOURAUD |
1330 R200_FOG_SHADE_GOURAUD |
1331 R200_DISC_FOG_SHADE_GOURAUD);
1332 break;
1333 default:
1334 return;
1335 }
1336
1337 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1338 R200_STATECHANGE( rmesa, set );
1339 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1340 }
1341 }
1342
1343
1344 /* =============================================================
1345 * User clip planes
1346 */
1347
r200ClipPlane(struct gl_context * ctx,GLenum plane,const GLfloat * eq)1348 static void r200ClipPlane( struct gl_context *ctx, GLenum plane, const GLfloat *eq )
1349 {
1350 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1351 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1352 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1353
1354 R200_STATECHANGE( rmesa, ucp[p] );
1355 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1356 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1357 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1358 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1359 }
1360
r200UpdateClipPlanes(struct gl_context * ctx)1361 static void r200UpdateClipPlanes( struct gl_context *ctx )
1362 {
1363 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1364 GLbitfield mask = ctx->Transform.ClipPlanesEnabled;
1365
1366 while (mask) {
1367 const int p = u_bit_scan(&mask);
1368 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1369
1370 R200_STATECHANGE( rmesa, ucp[p] );
1371 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1372 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1373 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1374 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1375 }
1376 }
1377
1378
1379 /* =============================================================
1380 * Stencil
1381 */
1382
1383 static void
r200StencilFuncSeparate(struct gl_context * ctx,GLenum face,GLenum func,GLint ref,GLuint mask)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
r200StencilMaskSeparate(struct gl_context * ctx,GLenum face,GLuint mask)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
r200StencilOpSeparate(struct gl_context * ctx,GLenum face,GLenum fail,GLenum zfail,GLenum zpass)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 */
r200UpdateWindow(struct gl_context * ctx)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 GLboolean render_to_fbo = (ctx->DrawBuffer ? _mesa_is_user_fbo(ctx->DrawBuffer) : 0);
1548 float scale[3], translate[3];
1549 GLfloat y_scale, y_bias;
1550
1551 if (render_to_fbo) {
1552 y_scale = 1.0;
1553 y_bias = 0;
1554 } else {
1555 y_scale = -1.0;
1556 y_bias = yoffset;
1557 }
1558
1559 _mesa_get_viewport_xform(ctx, 0, scale, translate);
1560 float_ui32_type sx = { scale[0] };
1561 float_ui32_type sy = { scale[1] * y_scale };
1562 float_ui32_type sz = { scale[2] };
1563 float_ui32_type tx = { translate[0] + xoffset };
1564 float_ui32_type ty = { (translate[1] * y_scale) + y_bias };
1565 float_ui32_type tz = { translate[2] };
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
r200_vtbl_update_scissor(struct gl_context * ctx)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
r200Viewport(struct gl_context * ctx)1603 static void r200Viewport(struct gl_context *ctx)
1604 {
1605 /* Don't pipeline viewport changes, conflict with window offset
1606 * setting below. Could apply deltas to rescue pipelined viewport
1607 * values, or keep the originals hanging around.
1608 */
1609 r200UpdateWindow( ctx );
1610
1611 radeon_viewport(ctx);
1612 }
1613
r200DepthRange(struct gl_context * ctx)1614 static void r200DepthRange(struct gl_context *ctx)
1615 {
1616 r200UpdateWindow( ctx );
1617 }
1618
1619 /* =============================================================
1620 * Miscellaneous
1621 */
1622
r200RenderMode(struct gl_context * ctx,GLenum mode)1623 static void r200RenderMode( struct gl_context *ctx, GLenum mode )
1624 {
1625 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1626 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1627 }
1628
1629
1630 static GLuint r200_rop_tab[] = {
1631 R200_ROP_CLEAR,
1632 R200_ROP_AND,
1633 R200_ROP_AND_REVERSE,
1634 R200_ROP_COPY,
1635 R200_ROP_AND_INVERTED,
1636 R200_ROP_NOOP,
1637 R200_ROP_XOR,
1638 R200_ROP_OR,
1639 R200_ROP_NOR,
1640 R200_ROP_EQUIV,
1641 R200_ROP_INVERT,
1642 R200_ROP_OR_REVERSE,
1643 R200_ROP_COPY_INVERTED,
1644 R200_ROP_OR_INVERTED,
1645 R200_ROP_NAND,
1646 R200_ROP_SET,
1647 };
1648
r200LogicOpCode(struct gl_context * ctx,GLenum opcode)1649 static void r200LogicOpCode( struct gl_context *ctx, GLenum opcode )
1650 {
1651 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1652 GLuint rop = (GLuint)opcode - GL_CLEAR;
1653
1654 assert( rop < 16 );
1655
1656 R200_STATECHANGE( rmesa, msk );
1657 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1658 }
1659
1660 /* =============================================================
1661 * State enable/disable
1662 */
1663
r200Enable(struct gl_context * ctx,GLenum cap,GLboolean state)1664 static void r200Enable( struct gl_context *ctx, GLenum cap, GLboolean state )
1665 {
1666 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1667 GLuint p, flag;
1668
1669 if ( R200_DEBUG & RADEON_STATE )
1670 fprintf( stderr, "%s( %s = %s )\n", __func__,
1671 _mesa_enum_to_string( cap ),
1672 state ? "GL_TRUE" : "GL_FALSE" );
1673
1674 switch ( cap ) {
1675 /* Fast track this one...
1676 */
1677 case GL_TEXTURE_1D:
1678 case GL_TEXTURE_2D:
1679 case GL_TEXTURE_3D:
1680 break;
1681
1682 case GL_ALPHA_TEST:
1683 R200_STATECHANGE( rmesa, ctx );
1684 if (state) {
1685 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1686 } else {
1687 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1688 }
1689 break;
1690
1691 case GL_BLEND:
1692 case GL_COLOR_LOGIC_OP:
1693 r200_set_blend_state( ctx );
1694 break;
1695
1696 case GL_CLIP_PLANE0:
1697 case GL_CLIP_PLANE1:
1698 case GL_CLIP_PLANE2:
1699 case GL_CLIP_PLANE3:
1700 case GL_CLIP_PLANE4:
1701 case GL_CLIP_PLANE5:
1702 p = cap-GL_CLIP_PLANE0;
1703 R200_STATECHANGE( rmesa, tcl );
1704 if (state) {
1705 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1706 r200ClipPlane( ctx, cap, NULL );
1707 }
1708 else {
1709 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1710 }
1711 break;
1712
1713 case GL_COLOR_MATERIAL:
1714 r200ColorMaterial( ctx, 0, 0 );
1715 r200UpdateMaterial( ctx );
1716 break;
1717
1718 case GL_CULL_FACE:
1719 r200CullFace( ctx, 0 );
1720 break;
1721
1722 case GL_DEPTH_TEST:
1723 R200_STATECHANGE(rmesa, ctx );
1724 if ( state ) {
1725 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE;
1726 } else {
1727 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1728 }
1729 break;
1730
1731 case GL_DITHER:
1732 R200_STATECHANGE(rmesa, ctx );
1733 if ( state ) {
1734 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
1735 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
1736 } else {
1737 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1738 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable;
1739 }
1740 break;
1741
1742 case GL_FOG:
1743 R200_STATECHANGE(rmesa, ctx );
1744 if ( state ) {
1745 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1746 r200Fogfv( ctx, GL_FOG_MODE, NULL );
1747 } else {
1748 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1749 R200_STATECHANGE(rmesa, tcl);
1750 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1751 }
1752 r200UpdateSpecular( ctx ); /* for PK_SPEC */
1753 if (rmesa->radeon.TclFallback)
1754 r200ChooseVertexState( ctx );
1755 _mesa_allow_light_in_model( ctx, !state );
1756 break;
1757
1758 case GL_LIGHT0:
1759 case GL_LIGHT1:
1760 case GL_LIGHT2:
1761 case GL_LIGHT3:
1762 case GL_LIGHT4:
1763 case GL_LIGHT5:
1764 case GL_LIGHT6:
1765 case GL_LIGHT7:
1766 R200_STATECHANGE(rmesa, tcl);
1767 p = cap - GL_LIGHT0;
1768 if (p&1)
1769 flag = (R200_LIGHT_1_ENABLE |
1770 R200_LIGHT_1_ENABLE_AMBIENT |
1771 R200_LIGHT_1_ENABLE_SPECULAR);
1772 else
1773 flag = (R200_LIGHT_0_ENABLE |
1774 R200_LIGHT_0_ENABLE_AMBIENT |
1775 R200_LIGHT_0_ENABLE_SPECULAR);
1776
1777 if (state)
1778 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1779 else
1780 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1781
1782 /*
1783 */
1784 update_light_colors( ctx, p );
1785 break;
1786
1787 case GL_LIGHTING:
1788 r200UpdateSpecular(ctx);
1789 /* for reflection map fixup - might set recheck_texgen for all units too */
1790 rmesa->radeon.NewGLState |= _NEW_TEXTURE;
1791 break;
1792
1793 case GL_LINE_SMOOTH:
1794 R200_STATECHANGE( rmesa, ctx );
1795 if ( state ) {
1796 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE;
1797 } else {
1798 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1799 }
1800 break;
1801
1802 case GL_LINE_STIPPLE:
1803 R200_STATECHANGE( rmesa, set );
1804 if ( state ) {
1805 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE;
1806 } else {
1807 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1808 }
1809 break;
1810
1811 case GL_NORMALIZE:
1812 R200_STATECHANGE( rmesa, tcl );
1813 if ( state ) {
1814 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS;
1815 } else {
1816 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1817 }
1818 break;
1819
1820 /* Pointsize registers on r200 only work for point sprites, and point smooth
1821 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1822 * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1823 * is enough to satisfy conform.
1824 */
1825 case GL_POINT_SMOOTH:
1826 break;
1827
1828 /* These don't really do anything, as we don't use the 3vtx
1829 * primitives yet.
1830 */
1831 #if 0
1832 case GL_POLYGON_OFFSET_POINT:
1833 R200_STATECHANGE( rmesa, set );
1834 if ( state ) {
1835 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT;
1836 } else {
1837 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1838 }
1839 break;
1840
1841 case GL_POLYGON_OFFSET_LINE:
1842 R200_STATECHANGE( rmesa, set );
1843 if ( state ) {
1844 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE;
1845 } else {
1846 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1847 }
1848 break;
1849 #endif
1850
1851 case GL_POINT_SPRITE_ARB:
1852 R200_STATECHANGE( rmesa, spr );
1853 if ( state ) {
1854 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_GEN_TEX_MASK &
1855 (ctx->Point.CoordReplace << R200_PS_GEN_TEX_0_SHIFT);
1856 } else {
1857 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
1858 }
1859 break;
1860
1861 case GL_POLYGON_OFFSET_FILL:
1862 R200_STATECHANGE( rmesa, set );
1863 if ( state ) {
1864 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI;
1865 } else {
1866 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1867 }
1868 break;
1869
1870 case GL_POLYGON_SMOOTH:
1871 R200_STATECHANGE( rmesa, ctx );
1872 if ( state ) {
1873 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY;
1874 } else {
1875 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
1876 }
1877 break;
1878
1879 case GL_POLYGON_STIPPLE:
1880 R200_STATECHANGE(rmesa, set );
1881 if ( state ) {
1882 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE;
1883 } else {
1884 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
1885 }
1886 break;
1887
1888 case GL_RESCALE_NORMAL_EXT: {
1889 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1890 R200_STATECHANGE( rmesa, tcl );
1891 if ( tmp ) {
1892 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
1893 } else {
1894 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1895 }
1896 break;
1897 }
1898
1899 case GL_SCISSOR_TEST:
1900 radeon_firevertices(&rmesa->radeon);
1901 rmesa->radeon.state.scissor.enabled = state;
1902 radeonUpdateScissor( ctx );
1903 break;
1904
1905 case GL_STENCIL_TEST:
1906 {
1907 GLboolean hw_stencil = GL_FALSE;
1908 if (ctx->DrawBuffer) {
1909 struct radeon_renderbuffer *rrbStencil
1910 = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
1911 hw_stencil = (rrbStencil && rrbStencil->bo);
1912 }
1913
1914 if (hw_stencil) {
1915 R200_STATECHANGE( rmesa, ctx );
1916 if ( state ) {
1917 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
1918 } else {
1919 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
1920 }
1921 } else {
1922 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
1923 }
1924 }
1925 break;
1926
1927 case GL_TEXTURE_GEN_Q:
1928 case GL_TEXTURE_GEN_R:
1929 case GL_TEXTURE_GEN_S:
1930 case GL_TEXTURE_GEN_T:
1931 /* Picked up in r200UpdateTextureState.
1932 */
1933 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1934 break;
1935
1936 case GL_COLOR_SUM_EXT:
1937 r200UpdateSpecular ( ctx );
1938 break;
1939
1940 case GL_VERTEX_PROGRAM_ARB:
1941 if (!state) {
1942 GLuint i;
1943 rmesa->curr_vp_hw = NULL;
1944 R200_STATECHANGE( rmesa, vap );
1945 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
1946 /* mark all tcl atoms (tcl vector state got overwritten) dirty
1947 not sure about tcl scalar state - we need at least grd
1948 with vert progs too.
1949 ucp looks like it doesn't get overwritten (may even work
1950 with vp for pos-invariant progs if we're lucky) */
1951 R200_STATECHANGE( rmesa, mtl[0] );
1952 R200_STATECHANGE( rmesa, mtl[1] );
1953 R200_STATECHANGE( rmesa, fog );
1954 R200_STATECHANGE( rmesa, glt );
1955 R200_STATECHANGE( rmesa, eye );
1956 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
1957 R200_STATECHANGE( rmesa, mat[i] );
1958 }
1959 for (i = 0 ; i < 8; i++) {
1960 R200_STATECHANGE( rmesa, lit[i] );
1961 }
1962 R200_STATECHANGE( rmesa, tcl );
1963 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
1964 if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
1965 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
1966 }
1967 /* else {
1968 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
1969 }*/
1970 }
1971 /* ugly. Need to call everything which might change compsel. */
1972 r200UpdateSpecular( ctx );
1973 #if 0
1974 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
1975 but without it doom3 locks up at always the same places. Why? */
1976 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
1977 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
1978 r200UpdateTextureState( ctx );
1979 /* if we call r200UpdateTextureState we need the code below because we are calling it with
1980 non-current derived enabled values which may revert the state atoms for frag progs even when
1981 they already got disabled... ugh
1982 Should really figure out why we need to call r200UpdateTextureState in the first place */
1983 GLuint unit;
1984 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
1985 R200_STATECHANGE( rmesa, pix[unit] );
1986 R200_STATECHANGE( rmesa, tex[unit] );
1987 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
1988 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
1989 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
1990 /* need to guard this with drmSupportsFragmentShader? Should never get here if
1991 we don't announce ATI_fs, right? */
1992 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
1993 }
1994 R200_STATECHANGE( rmesa, cst );
1995 R200_STATECHANGE( rmesa, tf );
1996 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
1997 #endif
1998 }
1999 else {
2000 /* picked up later */
2001 }
2002 /* call functions which change hw state based on ARB_vp enabled or not. */
2003 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2004 r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
2005 break;
2006
2007 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
2008 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2009 break;
2010
2011 case GL_FRAGMENT_SHADER_ATI:
2012 if ( !state ) {
2013 /* restore normal tex env colors and make sure tex env combine will get updated
2014 mark env atoms dirty (as their data was overwritten by afs even
2015 if they didn't change) and restore tex coord routing */
2016 GLuint unit;
2017 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2018 R200_STATECHANGE( rmesa, pix[unit] );
2019 R200_STATECHANGE( rmesa, tex[unit] );
2020 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2021 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2022 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2023 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2024 }
2025 R200_STATECHANGE( rmesa, cst );
2026 R200_STATECHANGE( rmesa, tf );
2027 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2028 }
2029 else {
2030 /* need to mark this dirty as pix/tf atoms have overwritten the data
2031 even if the data in the atoms didn't change */
2032 R200_STATECHANGE( rmesa, atf );
2033 R200_STATECHANGE( rmesa, afs[1] );
2034 /* everything else picked up in r200UpdateTextureState hopefully */
2035 }
2036 break;
2037 default:
2038 return;
2039 }
2040 }
2041
2042
r200LightingSpaceChange(struct gl_context * ctx)2043 void r200LightingSpaceChange( struct gl_context *ctx )
2044 {
2045 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2046 GLboolean tmp;
2047
2048 if (R200_DEBUG & RADEON_STATE)
2049 fprintf(stderr, "%s %d BEFORE %x\n", __func__, ctx->_NeedEyeCoords,
2050 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2051
2052 if (ctx->_NeedEyeCoords)
2053 tmp = ctx->Transform.RescaleNormals;
2054 else
2055 tmp = !ctx->Transform.RescaleNormals;
2056
2057 R200_STATECHANGE( rmesa, tcl );
2058 if ( tmp ) {
2059 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS;
2060 } else {
2061 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2062 }
2063
2064 if (R200_DEBUG & RADEON_STATE)
2065 fprintf(stderr, "%s %d AFTER %x\n", __func__, ctx->_NeedEyeCoords,
2066 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2067 }
2068
2069 /* =============================================================
2070 * Deferred state management - matrices, textures, other?
2071 */
2072
2073
2074
2075
upload_matrix(r200ContextPtr rmesa,GLfloat * src,int idx)2076 static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2077 {
2078 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2079 int i;
2080
2081
2082 for (i = 0 ; i < 4 ; i++) {
2083 *dest++ = src[i];
2084 *dest++ = src[i+4];
2085 *dest++ = src[i+8];
2086 *dest++ = src[i+12];
2087 }
2088
2089 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2090 }
2091
upload_matrix_t(r200ContextPtr rmesa,const GLfloat * src,int idx)2092 static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2093 {
2094 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2095 memcpy(dest, src, 16*sizeof(float));
2096 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2097 }
2098
2099
update_texturematrix(struct gl_context * ctx)2100 static void update_texturematrix( struct gl_context *ctx )
2101 {
2102 r200ContextPtr rmesa = R200_CONTEXT( ctx );
2103 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2104 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2105 int unit;
2106
2107 if (R200_DEBUG & RADEON_STATE)
2108 fprintf(stderr, "%s before COMPSEL: %x\n", __func__,
2109 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2110
2111 rmesa->TexMatEnabled = 0;
2112 rmesa->TexMatCompSel = 0;
2113
2114 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2115 if (!ctx->Texture.Unit[unit]._Current)
2116 continue;
2117
2118 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2119 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2120 R200_TEXMAT_0_ENABLE) << unit;
2121
2122 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2123
2124 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2125 /* Need to preconcatenate any active texgen
2126 * obj/eyeplane matrices:
2127 */
2128 _math_matrix_mul_matrix( &rmesa->tmpmat,
2129 ctx->TextureMatrixStack[unit].Top,
2130 &rmesa->TexGenMatrix[unit] );
2131 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2132 }
2133 else {
2134 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2135 R200_MTX_TEX0+unit );
2136 }
2137 }
2138 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2139 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2140 R200_MTX_TEX0+unit );
2141 }
2142 }
2143
2144 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2145 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2146 R200_STATECHANGE(rmesa, tcg);
2147 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2148 }
2149
2150 compsel &= ~R200_OUTPUT_TEX_MASK;
2151 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2152 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2153 R200_STATECHANGE(rmesa, vtx);
2154 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2155 }
2156 }
2157
r200ValidateBuffers(struct gl_context * ctx)2158 GLboolean r200ValidateBuffers(struct gl_context *ctx)
2159 {
2160 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2161 struct radeon_renderbuffer *rrb;
2162 struct radeon_dma_bo *dma_bo;
2163 int i, ret;
2164
2165 if (RADEON_DEBUG & RADEON_IOCTL)
2166 fprintf(stderr, "%s\n", __func__);
2167 radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
2168
2169 rrb = radeon_get_colorbuffer(&rmesa->radeon);
2170 /* color buffer */
2171 if (rrb && rrb->bo) {
2172 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2173 0, RADEON_GEM_DOMAIN_VRAM);
2174 }
2175
2176 /* depth buffer */
2177 rrb = radeon_get_depthbuffer(&rmesa->radeon);
2178 /* color buffer */
2179 if (rrb && rrb->bo) {
2180 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2181 0, RADEON_GEM_DOMAIN_VRAM);
2182 }
2183
2184 for (i = 0; i < ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits; ++i) {
2185 radeonTexObj *t;
2186
2187 if (!ctx->Texture.Unit[i]._Current)
2188 continue;
2189
2190 t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
2191 if (t->image_override && t->bo)
2192 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo,
2193 RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2194 else if (t->mt->bo)
2195 radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo,
2196 RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2197 }
2198
2199 dma_bo = first_elem(&rmesa->radeon.dma.reserved);
2200 {
2201 ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, dma_bo->bo, RADEON_GEM_DOMAIN_GTT, 0);
2202 if (ret)
2203 return GL_FALSE;
2204 }
2205 return GL_TRUE;
2206 }
2207
r200ValidateState(struct gl_context * ctx)2208 GLboolean r200ValidateState( struct gl_context *ctx )
2209 {
2210 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2211 GLuint new_state = rmesa->radeon.NewGLState;
2212
2213 if (new_state & _NEW_BUFFERS) {
2214 _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer);
2215 /* this updates the DrawBuffer's Width/Height if it's a FBO */
2216 _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
2217
2218 R200_STATECHANGE(rmesa, ctx);
2219 }
2220
2221 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) {
2222 r200UpdateTextureState( ctx );
2223 new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
2224 r200UpdateLocalViewer( ctx );
2225 }
2226
2227 /* we need to do a space check here */
2228 if (!r200ValidateBuffers(ctx))
2229 return GL_FALSE;
2230
2231 /* FIXME: don't really need most of these when vertex progs are enabled */
2232
2233 /* Need an event driven matrix update?
2234 */
2235 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2236 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2237
2238 /* Need these for lighting (shouldn't upload otherwise)
2239 */
2240 if (new_state & (_NEW_MODELVIEW)) {
2241 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2242 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2243 }
2244
2245 /* Does this need to be triggered on eg. modelview for
2246 * texgen-derived objplane/eyeplane matrices?
2247 */
2248 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2249 update_texturematrix( ctx );
2250 }
2251
2252 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2253 update_light( ctx );
2254 }
2255
2256 /* emit all active clip planes if projection matrix changes.
2257 */
2258 if (new_state & (_NEW_PROJECTION)) {
2259 if (ctx->Transform.ClipPlanesEnabled)
2260 r200UpdateClipPlanes( ctx );
2261 }
2262
2263 if (new_state & (_NEW_PROGRAM|
2264 _NEW_PROGRAM_CONSTANTS |
2265 /* need to test for pretty much anything due to possible parameter bindings */
2266 _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2267 _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2268 _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2269 if (ctx->VertexProgram._Enabled) {
2270 r200SetupVertexProg( ctx );
2271 }
2272 else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2273 }
2274
2275 rmesa->radeon.NewGLState = 0;
2276 return GL_TRUE;
2277 }
2278
2279
r200InvalidateState(struct gl_context * ctx,GLuint new_state)2280 static void r200InvalidateState( struct gl_context *ctx, GLuint new_state )
2281 {
2282 _swrast_InvalidateState( ctx, new_state );
2283 _swsetup_InvalidateState( ctx, new_state );
2284 _vbo_InvalidateState( ctx, new_state );
2285 _tnl_InvalidateState( ctx, new_state );
2286 _ae_invalidate_state( ctx, new_state );
2287 R200_CONTEXT(ctx)->radeon.NewGLState |= new_state;
2288 }
2289
2290 /* A hack. The r200 can actually cope just fine with materials
2291 * between begin/ends, so fix this.
2292 * Should map to inputs just like the generic vertex arrays for vertex progs.
2293 * In theory there could still be too many and we'd still need a fallback.
2294 */
check_material(struct gl_context * ctx)2295 static GLboolean check_material( struct gl_context *ctx )
2296 {
2297 TNLcontext *tnl = TNL_CONTEXT(ctx);
2298 GLint i;
2299
2300 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2301 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2302 i++)
2303 if (tnl->vb.AttribPtr[i] &&
2304 tnl->vb.AttribPtr[i]->stride)
2305 return GL_TRUE;
2306
2307 return GL_FALSE;
2308 }
2309
r200WrapRunPipeline(struct gl_context * ctx)2310 static void r200WrapRunPipeline( struct gl_context *ctx )
2311 {
2312 r200ContextPtr rmesa = R200_CONTEXT(ctx);
2313 GLboolean has_material;
2314
2315 if (0)
2316 fprintf(stderr, "%s, newstate: %x\n", __func__, rmesa->radeon.NewGLState);
2317
2318 /* Validate state:
2319 */
2320 if (rmesa->radeon.NewGLState)
2321 if (!r200ValidateState( ctx ))
2322 FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
2323
2324 has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx );
2325
2326 if (has_material) {
2327 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2328 }
2329
2330 /* Run the pipeline.
2331 */
2332 _tnl_run_pipeline( ctx );
2333
2334 if (has_material) {
2335 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2336 }
2337 }
2338
2339
r200PolygonStipple(struct gl_context * ctx,const GLubyte * mask)2340 static void r200PolygonStipple( struct gl_context *ctx, const GLubyte *mask )
2341 {
2342 r200ContextPtr r200 = R200_CONTEXT(ctx);
2343 GLint i;
2344
2345 radeon_firevertices(&r200->radeon);
2346
2347 radeon_print(RADEON_STATE, RADEON_TRACE,
2348 "%s(%p) first 32 bits are %x.\n",
2349 __func__,
2350 ctx,
2351 *(uint32_t*)mask);
2352
2353 R200_STATECHANGE(r200, stp);
2354
2355 /* Must flip pattern upside down.
2356 */
2357 for ( i = 31 ; i >= 0; i--) {
2358 r200->hw.stp.cmd[3 + i] = ((GLuint *) mask)[i];
2359 }
2360 }
2361 /* Initialize the driver's state functions.
2362 */
r200InitStateFuncs(radeonContextPtr radeon,struct dd_function_table * functions)2363 void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *functions )
2364 {
2365 functions->UpdateState = r200InvalidateState;
2366 functions->LightingSpaceChange = r200LightingSpaceChange;
2367
2368 functions->DrawBuffer = radeonDrawBuffer;
2369 functions->ReadBuffer = radeonReadBuffer;
2370
2371 functions->CopyPixels = _mesa_meta_CopyPixels;
2372 functions->DrawPixels = _mesa_meta_DrawPixels;
2373 functions->ReadPixels = radeonReadPixels;
2374
2375 functions->AlphaFunc = r200AlphaFunc;
2376 functions->BlendColor = r200BlendColor;
2377 functions->BlendEquationSeparate = r200BlendEquationSeparate;
2378 functions->BlendFuncSeparate = r200BlendFuncSeparate;
2379 functions->ClipPlane = r200ClipPlane;
2380 functions->ColorMask = r200ColorMask;
2381 functions->CullFace = r200CullFace;
2382 functions->DepthFunc = r200DepthFunc;
2383 functions->DepthMask = r200DepthMask;
2384 functions->DepthRange = r200DepthRange;
2385 functions->Enable = r200Enable;
2386 functions->Fogfv = r200Fogfv;
2387 functions->FrontFace = r200FrontFace;
2388 functions->LightModelfv = r200LightModelfv;
2389 functions->Lightfv = r200Lightfv;
2390 functions->LineStipple = r200LineStipple;
2391 functions->LineWidth = r200LineWidth;
2392 functions->LogicOpcode = r200LogicOpCode;
2393 functions->PolygonMode = r200PolygonMode;
2394 functions->PolygonOffset = r200PolygonOffset;
2395 functions->PolygonStipple = r200PolygonStipple;
2396 functions->PointParameterfv = r200PointParameter;
2397 functions->PointSize = r200PointSize;
2398 functions->RenderMode = r200RenderMode;
2399 functions->Scissor = radeonScissor;
2400 functions->ShadeModel = r200ShadeModel;
2401 functions->StencilFuncSeparate = r200StencilFuncSeparate;
2402 functions->StencilMaskSeparate = r200StencilMaskSeparate;
2403 functions->StencilOpSeparate = r200StencilOpSeparate;
2404 functions->Viewport = r200Viewport;
2405 }
2406
2407
r200InitTnlFuncs(struct gl_context * ctx)2408 void r200InitTnlFuncs( struct gl_context *ctx )
2409 {
2410 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2411 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2412 }
2413