e19202fa44324a956c894e6b58d67c32a6397c84
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_state.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.8 2002/12/16 16:18:58 dawes Exp $ */
2 /**************************************************************************
3
4 Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California.
5
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /*
31 * Authors:
32 * Gareth Hughes <gareth@valinux.com>
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "api_arrayelt.h"
39 #include "enums.h"
40 #include "light.h"
41 #include "state.h"
42 #include "context.h"
43 #include "framebuffer.h"
44
45 #include "vbo/vbo.h"
46 #include "tnl/tnl.h"
47 #include "tnl/t_pipeline.h"
48 #include "swrast_setup/swrast_setup.h"
49
50 #include "radeon_context.h"
51 #include "radeon_ioctl.h"
52 #include "radeon_state.h"
53 #include "radeon_tcl.h"
54 #include "radeon_tex.h"
55 #include "radeon_swtcl.h"
56 #include "drirenderbuffer.h"
57
58 static void radeonUpdateSpecular( GLcontext *ctx );
59
60 /* =============================================================
61 * Alpha blending
62 */
63
64 static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
65 {
66 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
67 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
68 GLubyte refByte;
69
70 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
71
72 RADEON_STATECHANGE( rmesa, ctx );
73
74 pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | RADEON_REF_ALPHA_MASK);
75 pp_misc |= (refByte & RADEON_REF_ALPHA_MASK);
76
77 switch ( func ) {
78 case GL_NEVER:
79 pp_misc |= RADEON_ALPHA_TEST_FAIL;
80 break;
81 case GL_LESS:
82 pp_misc |= RADEON_ALPHA_TEST_LESS;
83 break;
84 case GL_EQUAL:
85 pp_misc |= RADEON_ALPHA_TEST_EQUAL;
86 break;
87 case GL_LEQUAL:
88 pp_misc |= RADEON_ALPHA_TEST_LEQUAL;
89 break;
90 case GL_GREATER:
91 pp_misc |= RADEON_ALPHA_TEST_GREATER;
92 break;
93 case GL_NOTEQUAL:
94 pp_misc |= RADEON_ALPHA_TEST_NEQUAL;
95 break;
96 case GL_GEQUAL:
97 pp_misc |= RADEON_ALPHA_TEST_GEQUAL;
98 break;
99 case GL_ALWAYS:
100 pp_misc |= RADEON_ALPHA_TEST_PASS;
101 break;
102 }
103
104 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
105 }
106
107 static void radeonBlendEquationSeparate( GLcontext *ctx,
108 GLenum modeRGB, GLenum modeA )
109 {
110 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
111 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK;
112 GLboolean fallback = GL_FALSE;
113
114 assert( modeRGB == modeA );
115
116 switch ( modeRGB ) {
117 case GL_FUNC_ADD:
118 case GL_LOGIC_OP:
119 b |= RADEON_COMB_FCN_ADD_CLAMP;
120 break;
121
122 case GL_FUNC_SUBTRACT:
123 b |= RADEON_COMB_FCN_SUB_CLAMP;
124 break;
125
126 default:
127 if (ctx->Color.BlendEnabled)
128 fallback = GL_TRUE;
129 else
130 b |= RADEON_COMB_FCN_ADD_CLAMP;
131 break;
132 }
133
134 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, fallback );
135 if ( !fallback ) {
136 RADEON_STATECHANGE( rmesa, ctx );
137 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
138 if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
139 && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
140 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
141 } else {
142 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
143 }
144 }
145 }
146
147 static void radeonBlendFuncSeparate( GLcontext *ctx,
148 GLenum sfactorRGB, GLenum dfactorRGB,
149 GLenum sfactorA, GLenum dfactorA )
150 {
151 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
152 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] &
153 ~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK);
154 GLboolean fallback = GL_FALSE;
155
156 switch ( ctx->Color.BlendSrcRGB ) {
157 case GL_ZERO:
158 b |= RADEON_SRC_BLEND_GL_ZERO;
159 break;
160 case GL_ONE:
161 b |= RADEON_SRC_BLEND_GL_ONE;
162 break;
163 case GL_DST_COLOR:
164 b |= RADEON_SRC_BLEND_GL_DST_COLOR;
165 break;
166 case GL_ONE_MINUS_DST_COLOR:
167 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR;
168 break;
169 case GL_SRC_COLOR:
170 b |= RADEON_SRC_BLEND_GL_SRC_COLOR;
171 break;
172 case GL_ONE_MINUS_SRC_COLOR:
173 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR;
174 break;
175 case GL_SRC_ALPHA:
176 b |= RADEON_SRC_BLEND_GL_SRC_ALPHA;
177 break;
178 case GL_ONE_MINUS_SRC_ALPHA:
179 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
180 break;
181 case GL_DST_ALPHA:
182 b |= RADEON_SRC_BLEND_GL_DST_ALPHA;
183 break;
184 case GL_ONE_MINUS_DST_ALPHA:
185 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
186 break;
187 case GL_SRC_ALPHA_SATURATE:
188 b |= RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
189 break;
190 case GL_CONSTANT_COLOR:
191 case GL_ONE_MINUS_CONSTANT_COLOR:
192 case GL_CONSTANT_ALPHA:
193 case GL_ONE_MINUS_CONSTANT_ALPHA:
194 if (ctx->Color.BlendEnabled)
195 fallback = GL_TRUE;
196 else
197 b |= RADEON_SRC_BLEND_GL_ONE;
198 break;
199 default:
200 break;
201 }
202
203 switch ( ctx->Color.BlendDstRGB ) {
204 case GL_ZERO:
205 b |= RADEON_DST_BLEND_GL_ZERO;
206 break;
207 case GL_ONE:
208 b |= RADEON_DST_BLEND_GL_ONE;
209 break;
210 case GL_SRC_COLOR:
211 b |= RADEON_DST_BLEND_GL_SRC_COLOR;
212 break;
213 case GL_ONE_MINUS_SRC_COLOR:
214 b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR;
215 break;
216 case GL_SRC_ALPHA:
217 b |= RADEON_DST_BLEND_GL_SRC_ALPHA;
218 break;
219 case GL_ONE_MINUS_SRC_ALPHA:
220 b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA;
221 break;
222 case GL_DST_COLOR:
223 b |= RADEON_DST_BLEND_GL_DST_COLOR;
224 break;
225 case GL_ONE_MINUS_DST_COLOR:
226 b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR;
227 break;
228 case GL_DST_ALPHA:
229 b |= RADEON_DST_BLEND_GL_DST_ALPHA;
230 break;
231 case GL_ONE_MINUS_DST_ALPHA:
232 b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA;
233 break;
234 case GL_CONSTANT_COLOR:
235 case GL_ONE_MINUS_CONSTANT_COLOR:
236 case GL_CONSTANT_ALPHA:
237 case GL_ONE_MINUS_CONSTANT_ALPHA:
238 if (ctx->Color.BlendEnabled)
239 fallback = GL_TRUE;
240 else
241 b |= RADEON_DST_BLEND_GL_ZERO;
242 break;
243 default:
244 break;
245 }
246
247 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, fallback );
248 if ( !fallback ) {
249 RADEON_STATECHANGE( rmesa, ctx );
250 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
251 }
252 }
253
254
255 /* =============================================================
256 * Depth testing
257 */
258
259 static void radeonDepthFunc( GLcontext *ctx, GLenum func )
260 {
261 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
262
263 RADEON_STATECHANGE( rmesa, ctx );
264 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK;
265
266 switch ( ctx->Depth.Func ) {
267 case GL_NEVER:
268 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEVER;
269 break;
270 case GL_LESS:
271 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LESS;
272 break;
273 case GL_EQUAL:
274 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_EQUAL;
275 break;
276 case GL_LEQUAL:
277 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LEQUAL;
278 break;
279 case GL_GREATER:
280 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GREATER;
281 break;
282 case GL_NOTEQUAL:
283 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEQUAL;
284 break;
285 case GL_GEQUAL:
286 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GEQUAL;
287 break;
288 case GL_ALWAYS:
289 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_ALWAYS;
290 break;
291 }
292 }
293
294
295 static void radeonDepthMask( GLcontext *ctx, GLboolean flag )
296 {
297 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
298 RADEON_STATECHANGE( rmesa, ctx );
299
300 if ( ctx->Depth.Mask ) {
301 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_WRITE_ENABLE;
302 } else {
303 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_WRITE_ENABLE;
304 }
305 }
306
307 static void radeonClearDepth( GLcontext *ctx, GLclampd d )
308 {
309 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
310 GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
311 RADEON_DEPTH_FORMAT_MASK);
312
313 switch ( format ) {
314 case RADEON_DEPTH_FORMAT_16BIT_INT_Z:
315 rmesa->state.depth.clear = d * 0x0000ffff;
316 break;
317 case RADEON_DEPTH_FORMAT_24BIT_INT_Z:
318 rmesa->state.depth.clear = d * 0x00ffffff;
319 break;
320 }
321 }
322
323
324 /* =============================================================
325 * Fog
326 */
327
328
329 static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
330 {
331 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
332 union { int i; float f; } c, d;
333 GLchan col[4];
334
335 switch (pname) {
336 case GL_FOG_MODE:
337 if (!ctx->Fog.Enabled)
338 return;
339 RADEON_STATECHANGE(rmesa, tcl);
340 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
341 switch (ctx->Fog.Mode) {
342 case GL_LINEAR:
343 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR;
344 break;
345 case GL_EXP:
346 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP;
347 break;
348 case GL_EXP2:
349 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2;
350 break;
351 default:
352 return;
353 }
354 /* fallthrough */
355 case GL_FOG_DENSITY:
356 case GL_FOG_START:
357 case GL_FOG_END:
358 if (!ctx->Fog.Enabled)
359 return;
360 c.i = rmesa->hw.fog.cmd[FOG_C];
361 d.i = rmesa->hw.fog.cmd[FOG_D];
362 switch (ctx->Fog.Mode) {
363 case GL_EXP:
364 c.f = 0.0;
365 /* While this is the opposite sign from the DDK, it makes the fog test
366 * pass, and matches r200.
367 */
368 d.f = -ctx->Fog.Density;
369 break;
370 case GL_EXP2:
371 c.f = 0.0;
372 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
373 break;
374 case GL_LINEAR:
375 if (ctx->Fog.Start == ctx->Fog.End) {
376 c.f = 1.0F;
377 d.f = 1.0F;
378 } else {
379 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
380 /* While this is the opposite sign from the DDK, it makes the fog
381 * test pass, and matches r200.
382 */
383 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
384 }
385 break;
386 default:
387 break;
388 }
389 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
390 RADEON_STATECHANGE( rmesa, fog );
391 rmesa->hw.fog.cmd[FOG_C] = c.i;
392 rmesa->hw.fog.cmd[FOG_D] = d.i;
393 }
394 break;
395 case GL_FOG_COLOR:
396 RADEON_STATECHANGE( rmesa, ctx );
397 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
398 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~RADEON_FOG_COLOR_MASK;
399 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |=
400 radeonPackColor( 4, col[0], col[1], col[2], 0 );
401 break;
402 case GL_FOG_COORD_SRC:
403 radeonUpdateSpecular( ctx );
404 break;
405 default:
406 return;
407 }
408 }
409
410
411 /* =============================================================
412 * Scissoring
413 */
414
415
416 static GLboolean intersect_rect( drm_clip_rect_t *out,
417 drm_clip_rect_t *a,
418 drm_clip_rect_t *b )
419 {
420 *out = *a;
421 if ( b->x1 > out->x1 ) out->x1 = b->x1;
422 if ( b->y1 > out->y1 ) out->y1 = b->y1;
423 if ( b->x2 < out->x2 ) out->x2 = b->x2;
424 if ( b->y2 < out->y2 ) out->y2 = b->y2;
425 if ( out->x1 >= out->x2 ) return GL_FALSE;
426 if ( out->y1 >= out->y2 ) return GL_FALSE;
427 return GL_TRUE;
428 }
429
430
431 void radeonRecalcScissorRects( radeonContextPtr rmesa )
432 {
433 drm_clip_rect_t *out;
434 int i;
435
436 /* Grow cliprect store?
437 */
438 if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
439 while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
440 rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
441 rmesa->state.scissor.numAllocedClipRects *= 2;
442 }
443
444 if (rmesa->state.scissor.pClipRects)
445 FREE(rmesa->state.scissor.pClipRects);
446
447 rmesa->state.scissor.pClipRects =
448 MALLOC( rmesa->state.scissor.numAllocedClipRects *
449 sizeof(drm_clip_rect_t) );
450
451 if ( rmesa->state.scissor.pClipRects == NULL ) {
452 rmesa->state.scissor.numAllocedClipRects = 0;
453 return;
454 }
455 }
456
457 out = rmesa->state.scissor.pClipRects;
458 rmesa->state.scissor.numClipRects = 0;
459
460 for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
461 if ( intersect_rect( out,
462 &rmesa->pClipRects[i],
463 &rmesa->state.scissor.rect ) ) {
464 rmesa->state.scissor.numClipRects++;
465 out++;
466 }
467 }
468 }
469
470
471 static void radeonUpdateScissor( GLcontext *ctx )
472 {
473 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
474
475 if ( rmesa->dri.drawable ) {
476 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
477
478 int x = ctx->Scissor.X;
479 int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
480 int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
481 int h = dPriv->h - ctx->Scissor.Y - 1;
482
483 rmesa->state.scissor.rect.x1 = x + dPriv->x;
484 rmesa->state.scissor.rect.y1 = y + dPriv->y;
485 rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
486 rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
487
488 radeonRecalcScissorRects( rmesa );
489 }
490 }
491
492
493 static void radeonScissor( GLcontext *ctx,
494 GLint x, GLint y, GLsizei w, GLsizei h )
495 {
496 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
497
498 if ( ctx->Scissor.Enabled ) {
499 RADEON_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
500 radeonUpdateScissor( ctx );
501 }
502
503 }
504
505
506 /* =============================================================
507 * Culling
508 */
509
510 static void radeonCullFace( GLcontext *ctx, GLenum unused )
511 {
512 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
513 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
514 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
515
516 s |= RADEON_FFACE_SOLID | RADEON_BFACE_SOLID;
517 t &= ~(RADEON_CULL_FRONT | RADEON_CULL_BACK);
518
519 if ( ctx->Polygon.CullFlag ) {
520 switch ( ctx->Polygon.CullFaceMode ) {
521 case GL_FRONT:
522 s &= ~RADEON_FFACE_SOLID;
523 t |= RADEON_CULL_FRONT;
524 break;
525 case GL_BACK:
526 s &= ~RADEON_BFACE_SOLID;
527 t |= RADEON_CULL_BACK;
528 break;
529 case GL_FRONT_AND_BACK:
530 s &= ~(RADEON_FFACE_SOLID | RADEON_BFACE_SOLID);
531 t |= (RADEON_CULL_FRONT | RADEON_CULL_BACK);
532 break;
533 }
534 }
535
536 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
537 RADEON_STATECHANGE(rmesa, set );
538 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
539 }
540
541 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
542 RADEON_STATECHANGE(rmesa, tcl );
543 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
544 }
545 }
546
547 static void radeonFrontFace( GLcontext *ctx, GLenum mode )
548 {
549 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
550
551 RADEON_STATECHANGE( rmesa, set );
552 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK;
553
554 RADEON_STATECHANGE( rmesa, tcl );
555 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_CULL_FRONT_IS_CCW;
556
557 switch ( mode ) {
558 case GL_CW:
559 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CW;
560 break;
561 case GL_CCW:
562 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CCW;
563 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_CULL_FRONT_IS_CCW;
564 break;
565 }
566 }
567
568
569 /* =============================================================
570 * Line state
571 */
572 static void radeonLineWidth( GLcontext *ctx, GLfloat widthf )
573 {
574 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
575
576 RADEON_STATECHANGE( rmesa, lin );
577 RADEON_STATECHANGE( rmesa, set );
578
579 /* Line width is stored in U6.4 format.
580 */
581 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (GLuint)(widthf * 16.0);
582 if ( widthf > 1.0 ) {
583 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_WIDELINE_ENABLE;
584 } else {
585 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_WIDELINE_ENABLE;
586 }
587 }
588
589 static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
590 {
591 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
592
593 RADEON_STATECHANGE( rmesa, lin );
594 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
595 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
596 }
597
598
599 /* =============================================================
600 * Masks
601 */
602 static void radeonColorMask( GLcontext *ctx,
603 GLboolean r, GLboolean g,
604 GLboolean b, GLboolean a )
605 {
606 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
607 GLuint mask = radeonPackColor( rmesa->radeonScreen->cpp,
608 ctx->Color.ColorMask[RCOMP],
609 ctx->Color.ColorMask[GCOMP],
610 ctx->Color.ColorMask[BCOMP],
611 ctx->Color.ColorMask[ACOMP] );
612
613 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
614 RADEON_STATECHANGE( rmesa, msk );
615 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
616 }
617 }
618
619
620 /* =============================================================
621 * Polygon state
622 */
623
624 static void radeonPolygonOffset( GLcontext *ctx,
625 GLfloat factor, GLfloat units )
626 {
627 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
628 float_ui32_type constant = { units * rmesa->state.depth.scale };
629 float_ui32_type factoru = { factor };
630
631 RADEON_STATECHANGE( rmesa, zbs );
632 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32;
633 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
634 }
635
636 static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
637 {
638 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
639 GLuint i;
640 drm_radeon_stipple_t stipple;
641
642 /* Must flip pattern upside down.
643 */
644 for ( i = 0 ; i < 32 ; i++ ) {
645 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
646 }
647
648 /* TODO: push this into cmd mechanism
649 */
650 RADEON_FIREVERTICES( rmesa );
651 LOCK_HARDWARE( rmesa );
652
653 /* FIXME: Use window x,y offsets into stipple RAM.
654 */
655 stipple.mask = rmesa->state.stipple.mask;
656 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
657 &stipple, sizeof(drm_radeon_stipple_t) );
658 UNLOCK_HARDWARE( rmesa );
659 }
660
661 static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
662 {
663 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
664 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
665
666 /* Can't generally do unfilled via tcl, but some good special
667 * cases work.
668 */
669 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag);
670 if (rmesa->TclFallback) {
671 radeonChooseRenderState( ctx );
672 radeonChooseVertexState( ctx );
673 }
674 }
675
676
677 /* =============================================================
678 * Rendering attributes
679 *
680 * We really don't want to recalculate all this every time we bind a
681 * texture. These things shouldn't change all that often, so it makes
682 * sense to break them out of the core texture state update routines.
683 */
684
685 /* Examine lighting and texture state to determine if separate specular
686 * should be enabled.
687 */
688 static void radeonUpdateSpecular( GLcontext *ctx )
689 {
690 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
691 u_int32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
692 GLuint flag = 0;
693
694 RADEON_STATECHANGE( rmesa, tcl );
695
696 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
697 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
698 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC;
699 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_DIFFUSE;
700 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE;
701
702 p &= ~RADEON_SPECULAR_ENABLE;
703
704 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_DIFFUSE_SPECULAR_COMBINE;
705
706
707 if (ctx->Light.Enabled &&
708 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
709 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
710 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
711 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
712 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
713 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
714 p |= RADEON_SPECULAR_ENABLE;
715 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &=
716 ~RADEON_DIFFUSE_SPECULAR_COMBINE;
717 }
718 else if (ctx->Light.Enabled) {
719 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
720 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
721 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
722 } else if (ctx->Fog.ColorSumEnabled ) {
723 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
724 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
725 p |= RADEON_SPECULAR_ENABLE;
726 } else {
727 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
728 }
729
730 if (ctx->Fog.Enabled) {
731 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
732 if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH) {
733 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
734 /* Bizzare: have to leave lighting enabled to get fog. */
735 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
736 }
737 else {
738 /* cannot do tcl fog factor calculation with fog coord source
739 * (send precomputed factors). Cannot use precomputed fog
740 * factors together with tcl spec light (need tcl fallback) */
741 flag = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &
742 RADEON_TCL_COMPUTE_SPECULAR) != 0;
743 }
744 }
745
746 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_FOGCOORDSPEC, flag);
747
748 if (NEED_SECONDARY_COLOR(ctx)) {
749 assert( (p & RADEON_SPECULAR_ENABLE) != 0 );
750 } else {
751 assert( (p & RADEON_SPECULAR_ENABLE) == 0 );
752 }
753
754 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
755 RADEON_STATECHANGE( rmesa, ctx );
756 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
757 }
758
759 /* Update vertex/render formats
760 */
761 if (rmesa->TclFallback) {
762 radeonChooseRenderState( ctx );
763 radeonChooseVertexState( ctx );
764 }
765 }
766
767
768 /* =============================================================
769 * Materials
770 */
771
772
773 /* Update on colormaterial, material emmissive/ambient,
774 * lightmodel.globalambient
775 */
776 static void update_global_ambient( GLcontext *ctx )
777 {
778 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
779 float *fcmd = (float *)RADEON_DB_STATE( glt );
780
781 /* Need to do more if both emmissive & ambient are PREMULT:
782 * Hope this is not needed for MULT
783 */
784 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &
785 ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
786 (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0)
787 {
788 COPY_3V( &fcmd[GLT_RED],
789 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
790 ACC_SCALE_3V( &fcmd[GLT_RED],
791 ctx->Light.Model.Ambient,
792 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
793 }
794 else
795 {
796 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
797 }
798
799 RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
800 }
801
802 /* Update on change to
803 * - light[p].colors
804 * - light[p].enabled
805 */
806 static void update_light_colors( GLcontext *ctx, GLuint p )
807 {
808 struct gl_light *l = &ctx->Light.Light[p];
809
810 /* fprintf(stderr, "%s\n", __FUNCTION__); */
811
812 if (l->Enabled) {
813 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
814 float *fcmd = (float *)RADEON_DB_STATE( lit[p] );
815
816 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
817 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
818 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
819
820 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
821 }
822 }
823
824 /* Also fallback for asym colormaterial mode in twoside lighting...
825 */
826 static void check_twoside_fallback( GLcontext *ctx )
827 {
828 GLboolean fallback = GL_FALSE;
829 GLint i;
830
831 if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
832 if (ctx->Light.ColorMaterialEnabled &&
833 (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
834 ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
835 fallback = GL_TRUE;
836 else {
837 for (i = MAT_ATTRIB_FRONT_AMBIENT; i < MAT_ATTRIB_FRONT_INDEXES; i+=2)
838 if (memcmp( ctx->Light.Material.Attrib[i],
839 ctx->Light.Material.Attrib[i+1],
840 sizeof(GLfloat)*4) != 0) {
841 fallback = GL_TRUE;
842 break;
843 }
844 }
845 }
846
847 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
848 }
849
850
851 static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
852 {
853 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
854 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
855
856 light_model_ctl1 &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
857 (3 << RADEON_AMBIENT_SOURCE_SHIFT) |
858 (3 << RADEON_DIFFUSE_SOURCE_SHIFT) |
859 (3 << RADEON_SPECULAR_SOURCE_SHIFT));
860
861 if (ctx->Light.ColorMaterialEnabled) {
862 GLuint mask = ctx->Light.ColorMaterialBitmask;
863
864 if (mask & MAT_BIT_FRONT_EMISSION) {
865 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
866 RADEON_EMISSIVE_SOURCE_SHIFT);
867 }
868 else {
869 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
870 RADEON_EMISSIVE_SOURCE_SHIFT);
871 }
872
873 if (mask & MAT_BIT_FRONT_AMBIENT) {
874 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
875 RADEON_AMBIENT_SOURCE_SHIFT);
876 }
877 else {
878 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
879 RADEON_AMBIENT_SOURCE_SHIFT);
880 }
881
882 if (mask & MAT_BIT_FRONT_DIFFUSE) {
883 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
884 RADEON_DIFFUSE_SOURCE_SHIFT);
885 }
886 else {
887 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
888 RADEON_DIFFUSE_SOURCE_SHIFT);
889 }
890
891 if (mask & MAT_BIT_FRONT_SPECULAR) {
892 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
893 RADEON_SPECULAR_SOURCE_SHIFT);
894 }
895 else {
896 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
897 RADEON_SPECULAR_SOURCE_SHIFT);
898 }
899 }
900 else {
901 /* Default to MULT:
902 */
903 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << RADEON_EMISSIVE_SOURCE_SHIFT) |
904 (RADEON_LM_SOURCE_STATE_MULT << RADEON_AMBIENT_SOURCE_SHIFT) |
905 (RADEON_LM_SOURCE_STATE_MULT << RADEON_DIFFUSE_SOURCE_SHIFT) |
906 (RADEON_LM_SOURCE_STATE_MULT << RADEON_SPECULAR_SOURCE_SHIFT);
907 }
908
909 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) {
910 RADEON_STATECHANGE( rmesa, tcl );
911 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1;
912 }
913 }
914
915 void radeonUpdateMaterial( GLcontext *ctx )
916 {
917 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
918 GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
919 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl );
920 GLuint mask = ~0;
921
922 if (ctx->Light.ColorMaterialEnabled)
923 mask &= ~ctx->Light.ColorMaterialBitmask;
924
925 if (RADEON_DEBUG & DEBUG_STATE)
926 fprintf(stderr, "%s\n", __FUNCTION__);
927
928
929 if (mask & MAT_BIT_FRONT_EMISSION) {
930 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
931 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
932 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2];
933 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
934 }
935 if (mask & MAT_BIT_FRONT_AMBIENT) {
936 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
937 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
938 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
939 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
940 }
941 if (mask & MAT_BIT_FRONT_DIFFUSE) {
942 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
943 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
944 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
945 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
946 }
947 if (mask & MAT_BIT_FRONT_SPECULAR) {
948 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
949 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
950 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
951 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
952 }
953 if (mask & MAT_BIT_FRONT_SHININESS) {
954 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0];
955 }
956
957 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl );
958
959 check_twoside_fallback( ctx );
960 /* update_global_ambient( ctx );*/
961 }
962
963 /* _NEW_LIGHT
964 * _NEW_MODELVIEW
965 * _MESA_NEW_NEED_EYE_COORDS
966 *
967 * Uses derived state from mesa:
968 * _VP_inf_norm
969 * _h_inf_norm
970 * _Position
971 * _NormDirection
972 * _ModelViewInvScale
973 * _NeedEyeCoords
974 * _EyeZDir
975 *
976 * which are calculated in light.c and are correct for the current
977 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
978 * and _MESA_NEW_NEED_EYE_COORDS.
979 */
980 static void update_light( GLcontext *ctx )
981 {
982 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
983
984 /* Have to check these, or have an automatic shortcircuit mechanism
985 * to remove noop statechanges. (Or just do a better job on the
986 * front end).
987 */
988 {
989 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
990
991 if (ctx->_NeedEyeCoords)
992 tmp &= ~RADEON_LIGHT_IN_MODELSPACE;
993 else
994 tmp |= RADEON_LIGHT_IN_MODELSPACE;
995
996
997 /* Leave this test disabled: (unexplained q3 lockup) (even with
998 new packets)
999 */
1000 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL])
1001 {
1002 RADEON_STATECHANGE( rmesa, tcl );
1003 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp;
1004 }
1005 }
1006
1007 {
1008 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye );
1009 fcmd[EYE_X] = ctx->_EyeZDir[0];
1010 fcmd[EYE_Y] = ctx->_EyeZDir[1];
1011 fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1012 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1013 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1014 }
1015
1016
1017
1018 if (ctx->Light.Enabled) {
1019 GLint p;
1020 for (p = 0 ; p < MAX_LIGHTS; p++) {
1021 if (ctx->Light.Light[p].Enabled) {
1022 struct gl_light *l = &ctx->Light.Light[p];
1023 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] );
1024
1025 if (l->EyePosition[3] == 0.0) {
1026 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1027 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1028 fcmd[LIT_POSITION_W] = 0;
1029 fcmd[LIT_DIRECTION_W] = 0;
1030 } else {
1031 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1032 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1033 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1034 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1035 fcmd[LIT_DIRECTION_W] = 0;
1036 }
1037
1038 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1039 }
1040 }
1041 }
1042 }
1043
1044 static void radeonLightfv( GLcontext *ctx, GLenum light,
1045 GLenum pname, const GLfloat *params )
1046 {
1047 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1048 GLint p = light - GL_LIGHT0;
1049 struct gl_light *l = &ctx->Light.Light[p];
1050 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1051
1052
1053 switch (pname) {
1054 case GL_AMBIENT:
1055 case GL_DIFFUSE:
1056 case GL_SPECULAR:
1057 update_light_colors( ctx, p );
1058 break;
1059
1060 case GL_SPOT_DIRECTION:
1061 /* picked up in update_light */
1062 break;
1063
1064 case GL_POSITION: {
1065 /* positions picked up in update_light, but can do flag here */
1066 GLuint flag;
1067 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1068
1069 /* FIXME: Set RANGE_ATTEN only when needed */
1070 if (p&1)
1071 flag = RADEON_LIGHT_1_IS_LOCAL;
1072 else
1073 flag = RADEON_LIGHT_0_IS_LOCAL;
1074
1075 RADEON_STATECHANGE(rmesa, tcl);
1076 if (l->EyePosition[3] != 0.0F)
1077 rmesa->hw.tcl.cmd[idx] |= flag;
1078 else
1079 rmesa->hw.tcl.cmd[idx] &= ~flag;
1080 break;
1081 }
1082
1083 case GL_SPOT_EXPONENT:
1084 RADEON_STATECHANGE(rmesa, lit[p]);
1085 fcmd[LIT_SPOT_EXPONENT] = params[0];
1086 break;
1087
1088 case GL_SPOT_CUTOFF: {
1089 GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT;
1090 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1091
1092 RADEON_STATECHANGE(rmesa, lit[p]);
1093 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1094
1095 RADEON_STATECHANGE(rmesa, tcl);
1096 if (l->SpotCutoff != 180.0F)
1097 rmesa->hw.tcl.cmd[idx] |= flag;
1098 else
1099 rmesa->hw.tcl.cmd[idx] &= ~flag;
1100
1101 break;
1102 }
1103
1104 case GL_CONSTANT_ATTENUATION:
1105 RADEON_STATECHANGE(rmesa, lit[p]);
1106 fcmd[LIT_ATTEN_CONST] = params[0];
1107 if ( params[0] == 0.0 )
1108 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1109 else
1110 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1111 break;
1112 case GL_LINEAR_ATTENUATION:
1113 RADEON_STATECHANGE(rmesa, lit[p]);
1114 fcmd[LIT_ATTEN_LINEAR] = params[0];
1115 break;
1116 case GL_QUADRATIC_ATTENUATION:
1117 RADEON_STATECHANGE(rmesa, lit[p]);
1118 fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1119 break;
1120 default:
1121 return;
1122 }
1123
1124 /* Set RANGE_ATTEN only when needed */
1125 switch (pname) {
1126 case GL_POSITION:
1127 case GL_CONSTANT_ATTENUATION:
1128 case GL_LINEAR_ATTENUATION:
1129 case GL_QUADRATIC_ATTENUATION:
1130 {
1131 GLuint *icmd = (GLuint *)RADEON_DB_STATE( tcl );
1132 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1133 GLuint atten_flag = ( p&1 ) ? RADEON_LIGHT_1_ENABLE_RANGE_ATTEN
1134 : RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
1135 GLuint atten_const_flag = ( p&1 ) ? RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN
1136 : RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN;
1137
1138 if ( l->EyePosition[3] == 0.0F ||
1139 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1140 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1141 /* Disable attenuation */
1142 icmd[idx] &= ~atten_flag;
1143 } else {
1144 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1145 /* Enable only constant portion of attenuation calculation */
1146 icmd[idx] |= ( atten_flag | atten_const_flag );
1147 } else {
1148 /* Enable full attenuation calculation */
1149 icmd[idx] &= ~atten_const_flag;
1150 icmd[idx] |= atten_flag;
1151 }
1152 }
1153
1154 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1155 break;
1156 }
1157 default:
1158 break;
1159 }
1160 }
1161
1162
1163
1164
1165 static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
1166 const GLfloat *param )
1167 {
1168 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1169
1170 switch (pname) {
1171 case GL_LIGHT_MODEL_AMBIENT:
1172 update_global_ambient( ctx );
1173 break;
1174
1175 case GL_LIGHT_MODEL_LOCAL_VIEWER:
1176 RADEON_STATECHANGE( rmesa, tcl );
1177 if (ctx->Light.Model.LocalViewer)
1178 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER;
1179 else
1180 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER;
1181 break;
1182
1183 case GL_LIGHT_MODEL_TWO_SIDE:
1184 RADEON_STATECHANGE( rmesa, tcl );
1185 if (ctx->Light.Model.TwoSide)
1186 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE;
1187 else
1188 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE;
1189
1190 check_twoside_fallback( ctx );
1191
1192 if (rmesa->TclFallback) {
1193 radeonChooseRenderState( ctx );
1194 radeonChooseVertexState( ctx );
1195 }
1196 break;
1197
1198 case GL_LIGHT_MODEL_COLOR_CONTROL:
1199 radeonUpdateSpecular(ctx);
1200 break;
1201
1202 default:
1203 break;
1204 }
1205 }
1206
1207 static void radeonShadeModel( GLcontext *ctx, GLenum mode )
1208 {
1209 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1210 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1211
1212 s &= ~(RADEON_DIFFUSE_SHADE_MASK |
1213 RADEON_ALPHA_SHADE_MASK |
1214 RADEON_SPECULAR_SHADE_MASK |
1215 RADEON_FOG_SHADE_MASK);
1216
1217 switch ( mode ) {
1218 case GL_FLAT:
1219 s |= (RADEON_DIFFUSE_SHADE_FLAT |
1220 RADEON_ALPHA_SHADE_FLAT |
1221 RADEON_SPECULAR_SHADE_FLAT |
1222 RADEON_FOG_SHADE_FLAT);
1223 break;
1224 case GL_SMOOTH:
1225 s |= (RADEON_DIFFUSE_SHADE_GOURAUD |
1226 RADEON_ALPHA_SHADE_GOURAUD |
1227 RADEON_SPECULAR_SHADE_GOURAUD |
1228 RADEON_FOG_SHADE_GOURAUD);
1229 break;
1230 default:
1231 return;
1232 }
1233
1234 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1235 RADEON_STATECHANGE( rmesa, set );
1236 rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1237 }
1238 }
1239
1240
1241 /* =============================================================
1242 * User clip planes
1243 */
1244
1245 static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1246 {
1247 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1248 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1249 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1250
1251 RADEON_STATECHANGE( rmesa, ucp[p] );
1252 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1253 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1254 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1255 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1256 }
1257
1258 static void radeonUpdateClipPlanes( GLcontext *ctx )
1259 {
1260 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1261 GLuint p;
1262
1263 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1264 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1265 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1266
1267 RADEON_STATECHANGE( rmesa, ucp[p] );
1268 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1269 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1270 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1271 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1272 }
1273 }
1274 }
1275
1276
1277 /* =============================================================
1278 * Stencil
1279 */
1280
1281 static void
1282 radeonStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
1283 GLint ref, GLuint mask )
1284 {
1285 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1286 GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << RADEON_STENCIL_REF_SHIFT) |
1287 ((ctx->Stencil.ValueMask[0] & 0xff) << RADEON_STENCIL_MASK_SHIFT));
1288
1289 RADEON_STATECHANGE( rmesa, ctx );
1290 RADEON_STATECHANGE( rmesa, msk );
1291
1292 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_STENCIL_TEST_MASK;
1293 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(RADEON_STENCIL_REF_MASK|
1294 RADEON_STENCIL_VALUE_MASK);
1295
1296 switch ( ctx->Stencil.Function[0] ) {
1297 case GL_NEVER:
1298 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER;
1299 break;
1300 case GL_LESS:
1301 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS;
1302 break;
1303 case GL_EQUAL:
1304 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL;
1305 break;
1306 case GL_LEQUAL:
1307 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL;
1308 break;
1309 case GL_GREATER:
1310 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER;
1311 break;
1312 case GL_NOTEQUAL:
1313 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL;
1314 break;
1315 case GL_GEQUAL:
1316 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL;
1317 break;
1318 case GL_ALWAYS:
1319 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS;
1320 break;
1321 }
1322
1323 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1324 }
1325
1326 static void
1327 radeonStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
1328 {
1329 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1330
1331 RADEON_STATECHANGE( rmesa, msk );
1332 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK;
1333 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1334 ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT);
1335 }
1336
1337 static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
1338 GLenum zfail, GLenum zpass )
1339 {
1340 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1341
1342 /* radeon 7200 have stencil bug, DEC and INC_WRAP will actually both do DEC_WRAP,
1343 and DEC_WRAP (and INVERT) will do INVERT. No way to get correct INC_WRAP and DEC,
1344 but DEC_WRAP can be fixed by using DEC and INC_WRAP at least use INC. */
1345
1346 GLuint tempRADEON_STENCIL_FAIL_DEC_WRAP;
1347 GLuint tempRADEON_STENCIL_FAIL_INC_WRAP;
1348 GLuint tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
1349 GLuint tempRADEON_STENCIL_ZFAIL_INC_WRAP;
1350 GLuint tempRADEON_STENCIL_ZPASS_DEC_WRAP;
1351 GLuint tempRADEON_STENCIL_ZPASS_INC_WRAP;
1352
1353 if (rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_BROKEN_STENCIL) {
1354 tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC;
1355 tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC;
1356 tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC;
1357 tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC;
1358 tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC;
1359 tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC;
1360 }
1361 else {
1362 tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC_WRAP;
1363 tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC_WRAP;
1364 tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC_WRAP;
1365 tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC_WRAP;
1366 tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC_WRAP;
1367 tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC_WRAP;
1368 }
1369
1370 RADEON_STATECHANGE( rmesa, ctx );
1371 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK |
1372 RADEON_STENCIL_ZFAIL_MASK |
1373 RADEON_STENCIL_ZPASS_MASK);
1374
1375 switch ( ctx->Stencil.FailFunc[0] ) {
1376 case GL_KEEP:
1377 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP;
1378 break;
1379 case GL_ZERO:
1380 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO;
1381 break;
1382 case GL_REPLACE:
1383 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE;
1384 break;
1385 case GL_INCR:
1386 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC;
1387 break;
1388 case GL_DECR:
1389 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC;
1390 break;
1391 case GL_INCR_WRAP:
1392 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_INC_WRAP;
1393 break;
1394 case GL_DECR_WRAP:
1395 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_DEC_WRAP;
1396 break;
1397 case GL_INVERT:
1398 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT;
1399 break;
1400 }
1401
1402 switch ( ctx->Stencil.ZFailFunc[0] ) {
1403 case GL_KEEP:
1404 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP;
1405 break;
1406 case GL_ZERO:
1407 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO;
1408 break;
1409 case GL_REPLACE:
1410 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE;
1411 break;
1412 case GL_INCR:
1413 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC;
1414 break;
1415 case GL_DECR:
1416 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC;
1417 break;
1418 case GL_INCR_WRAP:
1419 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_INC_WRAP;
1420 break;
1421 case GL_DECR_WRAP:
1422 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
1423 break;
1424 case GL_INVERT:
1425 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT;
1426 break;
1427 }
1428
1429 switch ( ctx->Stencil.ZPassFunc[0] ) {
1430 case GL_KEEP:
1431 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP;
1432 break;
1433 case GL_ZERO:
1434 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO;
1435 break;
1436 case GL_REPLACE:
1437 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE;
1438 break;
1439 case GL_INCR:
1440 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC;
1441 break;
1442 case GL_DECR:
1443 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC;
1444 break;
1445 case GL_INCR_WRAP:
1446 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_INC_WRAP;
1447 break;
1448 case GL_DECR_WRAP:
1449 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_DEC_WRAP;
1450 break;
1451 case GL_INVERT:
1452 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT;
1453 break;
1454 }
1455 }
1456
1457 static void radeonClearStencil( GLcontext *ctx, GLint s )
1458 {
1459 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1460
1461 rmesa->state.stencil.clear =
1462 ((GLuint) (ctx->Stencil.Clear & 0xff) |
1463 (0xff << RADEON_STENCIL_MASK_SHIFT) |
1464 ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT));
1465 }
1466
1467
1468 /* =============================================================
1469 * Window position and viewport transformation
1470 */
1471
1472 /*
1473 * To correctly position primitives:
1474 */
1475 #define SUBPIXEL_X 0.125
1476 #define SUBPIXEL_Y 0.125
1477
1478
1479 /**
1480 * Called when window size or position changes or viewport or depth range
1481 * state is changed. We update the hardware viewport state here.
1482 */
1483 void radeonUpdateWindow( GLcontext *ctx )
1484 {
1485 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1486 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1487 GLfloat xoffset = (GLfloat)dPriv->x;
1488 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1489 const GLfloat *v = ctx->Viewport._WindowMap.m;
1490
1491 float_ui32_type sx = { v[MAT_SX] };
1492 float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
1493 float_ui32_type sy = { - v[MAT_SY] };
1494 float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
1495 float_ui32_type sz = { v[MAT_SZ] * rmesa->state.depth.scale };
1496 float_ui32_type tz = { v[MAT_TZ] * rmesa->state.depth.scale };
1497
1498 RADEON_FIREVERTICES( rmesa );
1499 RADEON_STATECHANGE( rmesa, vpt );
1500
1501 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32;
1502 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1503 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32;
1504 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1505 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32;
1506 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1507 }
1508
1509
1510 static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
1511 GLsizei width, GLsizei height )
1512 {
1513 /* Don't pipeline viewport changes, conflict with window offset
1514 * setting below. Could apply deltas to rescue pipelined viewport
1515 * values, or keep the originals hanging around.
1516 */
1517 radeonUpdateWindow( ctx );
1518 }
1519
1520 static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
1521 GLclampd farval )
1522 {
1523 radeonUpdateWindow( ctx );
1524 }
1525
1526 void radeonUpdateViewportOffset( GLcontext *ctx )
1527 {
1528 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1529 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1530 GLfloat xoffset = (GLfloat)dPriv->x;
1531 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1532 const GLfloat *v = ctx->Viewport._WindowMap.m;
1533
1534 float_ui32_type tx;
1535 float_ui32_type ty;
1536
1537 tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X;
1538 ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1539
1540 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
1541 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
1542 {
1543 /* Note: this should also modify whatever data the context reset
1544 * code uses...
1545 */
1546 RADEON_STATECHANGE( rmesa, vpt );
1547 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1548 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1549
1550 /* update polygon stipple x/y screen offset */
1551 {
1552 GLuint stx, sty;
1553 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1554
1555 m &= ~(RADEON_STIPPLE_X_OFFSET_MASK |
1556 RADEON_STIPPLE_Y_OFFSET_MASK);
1557
1558 /* add magic offsets, then invert */
1559 stx = 31 - ((rmesa->dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK);
1560 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1561 & RADEON_STIPPLE_COORD_MASK);
1562
1563 m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) |
1564 (sty << RADEON_STIPPLE_Y_OFFSET_SHIFT));
1565
1566 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1567 RADEON_STATECHANGE( rmesa, msc );
1568 rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1569 }
1570 }
1571 }
1572
1573 radeonUpdateScissor( ctx );
1574 }
1575
1576
1577
1578 /* =============================================================
1579 * Miscellaneous
1580 */
1581
1582 static void radeonClearColor( GLcontext *ctx, const GLfloat color[4] )
1583 {
1584 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1585 GLubyte c[4];
1586 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
1587 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
1588 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
1589 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
1590 rmesa->state.color.clear = radeonPackColor( rmesa->radeonScreen->cpp,
1591 c[0], c[1], c[2], c[3] );
1592 }
1593
1594
1595 static void radeonRenderMode( GLcontext *ctx, GLenum mode )
1596 {
1597 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1598 FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1599 }
1600
1601
1602 static GLuint radeon_rop_tab[] = {
1603 RADEON_ROP_CLEAR,
1604 RADEON_ROP_AND,
1605 RADEON_ROP_AND_REVERSE,
1606 RADEON_ROP_COPY,
1607 RADEON_ROP_AND_INVERTED,
1608 RADEON_ROP_NOOP,
1609 RADEON_ROP_XOR,
1610 RADEON_ROP_OR,
1611 RADEON_ROP_NOR,
1612 RADEON_ROP_EQUIV,
1613 RADEON_ROP_INVERT,
1614 RADEON_ROP_OR_REVERSE,
1615 RADEON_ROP_COPY_INVERTED,
1616 RADEON_ROP_OR_INVERTED,
1617 RADEON_ROP_NAND,
1618 RADEON_ROP_SET,
1619 };
1620
1621 static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
1622 {
1623 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1624 GLuint rop = (GLuint)opcode - GL_CLEAR;
1625
1626 ASSERT( rop < 16 );
1627
1628 RADEON_STATECHANGE( rmesa, msk );
1629 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop];
1630 }
1631
1632
1633 /**
1634 * Set up the cliprects for either front or back-buffer drawing.
1635 */
1636 void radeonSetCliprects( radeonContextPtr rmesa )
1637 {
1638 __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
1639 __DRIdrawablePrivate *const readable = rmesa->dri.readable;
1640 GLframebuffer *const draw_fb = (GLframebuffer*) drawable->driverPrivate;
1641 GLframebuffer *const read_fb = (GLframebuffer*) readable->driverPrivate;
1642
1643 if (draw_fb->_ColorDrawBufferMask[0]
1644 == BUFFER_BIT_BACK_LEFT) {
1645 /* Can't ignore 2d windows if we are page flipping.
1646 */
1647 if ( drawable->numBackClipRects == 0 || rmesa->doPageFlip ) {
1648 rmesa->numClipRects = drawable->numClipRects;
1649 rmesa->pClipRects = drawable->pClipRects;
1650 }
1651 else {
1652 rmesa->numClipRects = drawable->numBackClipRects;
1653 rmesa->pClipRects = drawable->pBackClipRects;
1654 }
1655 }
1656 else {
1657 /* front buffer (or none, or multiple buffers */
1658 rmesa->numClipRects = drawable->numClipRects;
1659 rmesa->pClipRects = drawable->pClipRects;
1660 }
1661
1662 if ((draw_fb->Width != drawable->w) || (draw_fb->Height != drawable->h)) {
1663 _mesa_resize_framebuffer(rmesa->glCtx, draw_fb,
1664 drawable->w, drawable->h);
1665 draw_fb->Initialized = GL_TRUE;
1666 }
1667
1668 if (drawable != readable) {
1669 if ((read_fb->Width != readable->w) || (read_fb->Height != readable->h)) {
1670 _mesa_resize_framebuffer(rmesa->glCtx, read_fb,
1671 readable->w, readable->h);
1672 read_fb->Initialized = GL_TRUE;
1673 }
1674 }
1675
1676 if (rmesa->state.scissor.enabled)
1677 radeonRecalcScissorRects( rmesa );
1678 }
1679
1680
1681 /**
1682 * Called via glDrawBuffer.
1683 */
1684 static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
1685 {
1686 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1687
1688 if (RADEON_DEBUG & DEBUG_DRI)
1689 fprintf(stderr, "%s %s\n", __FUNCTION__,
1690 _mesa_lookup_enum_by_nr( mode ));
1691
1692 RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1693
1694 /*
1695 * _ColorDrawBufferMask is easier to cope with than <mode>.
1696 * Check for software fallback, update cliprects.
1697 */
1698 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
1699 case BUFFER_BIT_FRONT_LEFT:
1700 case BUFFER_BIT_BACK_LEFT:
1701 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
1702 break;
1703 default:
1704 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1705 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
1706 return;
1707 }
1708
1709 radeonSetCliprects( rmesa );
1710
1711 /* We'll set the drawing engine's offset/pitch parameters later
1712 * when we update other state.
1713 */
1714 }
1715
1716 static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
1717 {
1718 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1719 }
1720
1721
1722 /* =============================================================
1723 * State enable/disable
1724 */
1725
1726 static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
1727 {
1728 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1729 GLuint p, flag;
1730
1731 if ( RADEON_DEBUG & DEBUG_STATE )
1732 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1733 _mesa_lookup_enum_by_nr( cap ),
1734 state ? "GL_TRUE" : "GL_FALSE" );
1735
1736 switch ( cap ) {
1737 /* Fast track this one...
1738 */
1739 case GL_TEXTURE_1D:
1740 case GL_TEXTURE_2D:
1741 case GL_TEXTURE_3D:
1742 break;
1743
1744 case GL_ALPHA_TEST:
1745 RADEON_STATECHANGE( rmesa, ctx );
1746 if (state) {
1747 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE;
1748 } else {
1749 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE;
1750 }
1751 break;
1752
1753 case GL_BLEND:
1754 RADEON_STATECHANGE( rmesa, ctx );
1755 if (state) {
1756 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ALPHA_BLEND_ENABLE;
1757 } else {
1758 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE;
1759 }
1760 if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
1761 && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
1762 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
1763 } else {
1764 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
1765 }
1766
1767 /* Catch a possible fallback:
1768 */
1769 if (state) {
1770 ctx->Driver.BlendEquationSeparate( ctx,
1771 ctx->Color.BlendEquationRGB,
1772 ctx->Color.BlendEquationA );
1773 ctx->Driver.BlendFuncSeparate( ctx, ctx->Color.BlendSrcRGB,
1774 ctx->Color.BlendDstRGB,
1775 ctx->Color.BlendSrcA,
1776 ctx->Color.BlendDstA );
1777 }
1778 else {
1779 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE );
1780 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, GL_FALSE );
1781 }
1782 break;
1783
1784 case GL_CLIP_PLANE0:
1785 case GL_CLIP_PLANE1:
1786 case GL_CLIP_PLANE2:
1787 case GL_CLIP_PLANE3:
1788 case GL_CLIP_PLANE4:
1789 case GL_CLIP_PLANE5:
1790 p = cap-GL_CLIP_PLANE0;
1791 RADEON_STATECHANGE( rmesa, tcl );
1792 if (state) {
1793 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p);
1794 radeonClipPlane( ctx, cap, NULL );
1795 }
1796 else {
1797 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p);
1798 }
1799 break;
1800
1801 case GL_COLOR_MATERIAL:
1802 radeonColorMaterial( ctx, 0, 0 );
1803 radeonUpdateMaterial( ctx );
1804 break;
1805
1806 case GL_CULL_FACE:
1807 radeonCullFace( ctx, 0 );
1808 break;
1809
1810 case GL_DEPTH_TEST:
1811 RADEON_STATECHANGE(rmesa, ctx );
1812 if ( state ) {
1813 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_Z_ENABLE;
1814 } else {
1815 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE;
1816 }
1817 break;
1818
1819 case GL_DITHER:
1820 RADEON_STATECHANGE(rmesa, ctx );
1821 if ( state ) {
1822 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
1823 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
1824 } else {
1825 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE;
1826 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
1827 }
1828 break;
1829
1830 case GL_FOG:
1831 RADEON_STATECHANGE(rmesa, ctx );
1832 if ( state ) {
1833 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE;
1834 radeonFogfv( ctx, GL_FOG_MODE, NULL );
1835 } else {
1836 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE;
1837 RADEON_STATECHANGE(rmesa, tcl);
1838 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
1839 }
1840 radeonUpdateSpecular( ctx ); /* for PK_SPEC */
1841 _mesa_allow_light_in_model( ctx, !state );
1842 break;
1843
1844 case GL_LIGHT0:
1845 case GL_LIGHT1:
1846 case GL_LIGHT2:
1847 case GL_LIGHT3:
1848 case GL_LIGHT4:
1849 case GL_LIGHT5:
1850 case GL_LIGHT6:
1851 case GL_LIGHT7:
1852 RADEON_STATECHANGE(rmesa, tcl);
1853 p = cap - GL_LIGHT0;
1854 if (p&1)
1855 flag = (RADEON_LIGHT_1_ENABLE |
1856 RADEON_LIGHT_1_ENABLE_AMBIENT |
1857 RADEON_LIGHT_1_ENABLE_SPECULAR);
1858 else
1859 flag = (RADEON_LIGHT_0_ENABLE |
1860 RADEON_LIGHT_0_ENABLE_AMBIENT |
1861 RADEON_LIGHT_0_ENABLE_SPECULAR);
1862
1863 if (state)
1864 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1865 else
1866 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1867
1868 /*
1869 */
1870 update_light_colors( ctx, p );
1871 break;
1872
1873 case GL_LIGHTING:
1874 RADEON_STATECHANGE(rmesa, tcl);
1875 radeonUpdateSpecular(ctx);
1876 check_twoside_fallback( ctx );
1877 break;
1878
1879 case GL_LINE_SMOOTH:
1880 RADEON_STATECHANGE( rmesa, ctx );
1881 if ( state ) {
1882 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_LINE;
1883 } else {
1884 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE;
1885 }
1886 break;
1887
1888 case GL_LINE_STIPPLE:
1889 RADEON_STATECHANGE( rmesa, ctx );
1890 if ( state ) {
1891 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_PATTERN_ENABLE;
1892 } else {
1893 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE;
1894 }
1895 break;
1896
1897 case GL_COLOR_LOGIC_OP:
1898 RADEON_STATECHANGE( rmesa, ctx );
1899 if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
1900 && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
1901 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
1902 } else {
1903 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
1904 }
1905 break;
1906
1907 case GL_NORMALIZE:
1908 RADEON_STATECHANGE( rmesa, tcl );
1909 if ( state ) {
1910 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_NORMALIZE_NORMALS;
1911 } else {
1912 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS;
1913 }
1914 break;
1915
1916 case GL_POLYGON_OFFSET_POINT:
1917 RADEON_STATECHANGE( rmesa, set );
1918 if ( state ) {
1919 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_POINT;
1920 } else {
1921 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT;
1922 }
1923 break;
1924
1925 case GL_POLYGON_OFFSET_LINE:
1926 RADEON_STATECHANGE( rmesa, set );
1927 if ( state ) {
1928 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_LINE;
1929 } else {
1930 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE;
1931 }
1932 break;
1933
1934 case GL_POLYGON_OFFSET_FILL:
1935 RADEON_STATECHANGE( rmesa, set );
1936 if ( state ) {
1937 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_TRI;
1938 } else {
1939 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI;
1940 }
1941 break;
1942
1943 case GL_POLYGON_SMOOTH:
1944 RADEON_STATECHANGE( rmesa, ctx );
1945 if ( state ) {
1946 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_POLY;
1947 } else {
1948 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY;
1949 }
1950 break;
1951
1952 case GL_POLYGON_STIPPLE:
1953 RADEON_STATECHANGE(rmesa, ctx );
1954 if ( state ) {
1955 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_STIPPLE_ENABLE;
1956 } else {
1957 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE;
1958 }
1959 break;
1960
1961 case GL_RESCALE_NORMAL_EXT: {
1962 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1963 RADEON_STATECHANGE( rmesa, tcl );
1964 if ( tmp ) {
1965 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
1966 } else {
1967 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
1968 }
1969 break;
1970 }
1971
1972 case GL_SCISSOR_TEST:
1973 RADEON_FIREVERTICES( rmesa );
1974 rmesa->state.scissor.enabled = state;
1975 radeonUpdateScissor( ctx );
1976 break;
1977
1978 case GL_STENCIL_TEST:
1979 if ( rmesa->state.stencil.hwBuffer ) {
1980 RADEON_STATECHANGE( rmesa, ctx );
1981 if ( state ) {
1982 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE;
1983 } else {
1984 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
1985 }
1986 } else {
1987 FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
1988 }
1989 break;
1990
1991 case GL_TEXTURE_GEN_Q:
1992 case GL_TEXTURE_GEN_R:
1993 case GL_TEXTURE_GEN_S:
1994 case GL_TEXTURE_GEN_T:
1995 /* Picked up in radeonUpdateTextureState.
1996 */
1997 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1998 break;
1999
2000 case GL_COLOR_SUM_EXT:
2001 radeonUpdateSpecular ( ctx );
2002 break;
2003
2004 default:
2005 return;
2006 }
2007 }
2008
2009
2010 static void radeonLightingSpaceChange( GLcontext *ctx )
2011 {
2012 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2013 GLboolean tmp;
2014 RADEON_STATECHANGE( rmesa, tcl );
2015
2016 if (RADEON_DEBUG & DEBUG_STATE)
2017 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2018 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
2019
2020 if (ctx->_NeedEyeCoords)
2021 tmp = ctx->Transform.RescaleNormals;
2022 else
2023 tmp = !ctx->Transform.RescaleNormals;
2024
2025 if ( tmp ) {
2026 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
2027 } else {
2028 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
2029 }
2030
2031 if (RADEON_DEBUG & DEBUG_STATE)
2032 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2033 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
2034 }
2035
2036 /* =============================================================
2037 * Deferred state management - matrices, textures, other?
2038 */
2039
2040
2041 void radeonUploadTexMatrix( radeonContextPtr rmesa,
2042 int unit, GLboolean swapcols )
2043 {
2044 /* Here's how this works: on r100, only 3 tex coords can be submitted, so the
2045 vector looks like this probably: (s t r|q 0) (not sure if the last coord
2046 is hardwired to 0, could be 1 too). Interestingly, it actually looks like
2047 texgen generates all 4 coords, at least tests with projtex indicated that.
2048 So: if we need the q coord in the end (solely determined by the texture
2049 target, i.e. 2d / 1d / texrect targets) we swap the third and 4th row.
2050 Additionally, if we don't have texgen but 4 tex coords submitted, we swap
2051 column 3 and 4 (for the 2d / 1d / texrect targets) since the the q coord
2052 will get submitted in the "wrong", i.e. 3rd, slot.
2053 If an app submits 3 coords for 2d targets, we assume it is saving on vertex
2054 size and using the texture matrix to swap the r and q coords around (ut2k3
2055 does exactly that), so we don't need the 3rd / 4th column swap - still need
2056 the 3rd / 4th row swap of course. This will potentially break for apps which
2057 use TexCoord3x just for fun. Additionally, it will never work if an app uses
2058 an "advanced" texture matrix and relies on all 4 texcoord inputs to generate
2059 the maximum needed 3. This seems impossible to do with hw tcl on r100, and
2060 incredibly hard to detect so we can't just fallback in such a case. Assume
2061 it never happens... - rs
2062 */
2063
2064 int idx = TEXMAT_0 + unit;
2065 float *dest = ((float *)RADEON_DB_STATE( mat[idx] )) + MAT_ELT_0;
2066 int i;
2067 struct gl_texture_unit tUnit = rmesa->glCtx->Texture.Unit[unit];
2068 GLfloat *src = rmesa->tmpmat[unit].m;
2069
2070 rmesa->TexMatColSwap &= ~(1 << unit);
2071 if ((tUnit._ReallyEnabled & (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT)) == 0) {
2072 if (swapcols) {
2073 rmesa->TexMatColSwap |= 1 << unit;
2074 /* attention some elems are swapped 2 times! */
2075 *dest++ = src[0];
2076 *dest++ = src[4];
2077 *dest++ = src[12];
2078 *dest++ = src[8];
2079 *dest++ = src[1];
2080 *dest++ = src[5];
2081 *dest++ = src[13];
2082 *dest++ = src[9];
2083 *dest++ = src[2];
2084 *dest++ = src[6];
2085 *dest++ = src[15];
2086 *dest++ = src[11];
2087 /* those last 4 are probably never used */
2088 *dest++ = src[3];
2089 *dest++ = src[7];
2090 *dest++ = src[14];
2091 *dest++ = src[10];
2092 }
2093 else {
2094 for (i = 0; i < 2; i++) {
2095 *dest++ = src[i];
2096 *dest++ = src[i+4];
2097 *dest++ = src[i+8];
2098 *dest++ = src[i+12];
2099 }
2100 for (i = 3; i >= 2; i--) {
2101 *dest++ = src[i];
2102 *dest++ = src[i+4];
2103 *dest++ = src[i+8];
2104 *dest++ = src[i+12];
2105 }
2106 }
2107 }
2108 else {
2109 for (i = 0 ; i < 4 ; i++) {
2110 *dest++ = src[i];
2111 *dest++ = src[i+4];
2112 *dest++ = src[i+8];
2113 *dest++ = src[i+12];
2114 }
2115 }
2116
2117 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2118 }
2119
2120
2121 static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
2122 {
2123 float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
2124 int i;
2125
2126
2127 for (i = 0 ; i < 4 ; i++) {
2128 *dest++ = src[i];
2129 *dest++ = src[i+4];
2130 *dest++ = src[i+8];
2131 *dest++ = src[i+12];
2132 }
2133
2134 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2135 }
2136
2137 static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
2138 {
2139 float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
2140 memcpy(dest, src, 16*sizeof(float));
2141 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2142 }
2143
2144
2145 static void update_texturematrix( GLcontext *ctx )
2146 {
2147 radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
2148 GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL];
2149 GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL];
2150 int unit;
2151 GLuint texMatEnabled = 0;
2152 rmesa->NeedTexMatrix = 0;
2153 rmesa->TexMatColSwap = 0;
2154
2155 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2156 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
2157 GLboolean needMatrix = GL_FALSE;
2158 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2159 needMatrix = GL_TRUE;
2160 texMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE |
2161 RADEON_TEXMAT_0_ENABLE) << unit;
2162
2163 if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
2164 /* Need to preconcatenate any active texgen
2165 * obj/eyeplane matrices:
2166 */
2167 _math_matrix_mul_matrix( &rmesa->tmpmat[unit],
2168 ctx->TextureMatrixStack[unit].Top,
2169 &rmesa->TexGenMatrix[unit] );
2170 }
2171 else {
2172 _math_matrix_copy( &rmesa->tmpmat[unit],
2173 ctx->TextureMatrixStack[unit].Top );
2174 }
2175 }
2176 else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
2177 _math_matrix_copy( &rmesa->tmpmat[unit], &rmesa->TexGenMatrix[unit] );
2178 needMatrix = GL_TRUE;
2179 }
2180 if (needMatrix) {
2181 rmesa->NeedTexMatrix |= 1 << unit;
2182 radeonUploadTexMatrix( rmesa, unit,
2183 !ctx->Texture.Unit[unit].TexGenEnabled );
2184 }
2185 }
2186 }
2187
2188 tpc = (texMatEnabled | rmesa->TexGenEnabled);
2189
2190 /* TCL_TEX_COMPUTED_x is TCL_TEX_INPUT_x | 0x8 */
2191 vs &= ~((RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
2192 (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
2193 (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
2194
2195 vs |= (((tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE) <<
2196 (RADEON_TCL_TEX_0_OUTPUT_SHIFT + 3)) |
2197 ((tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE) <<
2198 (RADEON_TCL_TEX_1_OUTPUT_SHIFT + 2)) |
2199 ((tpc & RADEON_TEXGEN_TEXMAT_2_ENABLE) <<
2200 (RADEON_TCL_TEX_2_OUTPUT_SHIFT + 1)));
2201
2202 if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] ||
2203 vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) {
2204
2205 RADEON_STATECHANGE(rmesa, tcl);
2206 rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc;
2207 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs;
2208 }
2209 }
2210
2211
2212 /**
2213 * Tell the card where to render (offset, pitch).
2214 * Effected by glDrawBuffer, etc
2215 */
2216 void
2217 radeonUpdateDrawBuffer(GLcontext *ctx)
2218 {
2219 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2220 struct gl_framebuffer *fb = ctx->DrawBuffer;
2221 driRenderbuffer *drb;
2222
2223 if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
2224 /* draw to front */
2225 drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2226 }
2227 else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) {
2228 /* draw to back */
2229 drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2230 }
2231 else {
2232 /* drawing to multiple buffers, or none */
2233 return;
2234 }
2235
2236 assert(drb);
2237 assert(drb->flippedPitch);
2238
2239 RADEON_STATECHANGE( rmesa, ctx );
2240
2241 /* Note: we used the (possibly) page-flipped values */
2242 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2243 = ((drb->flippedOffset + rmesa->radeonScreen->fbLocation)
2244 & RADEON_COLOROFFSET_MASK);
2245 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2246 if (rmesa->sarea->tiling_enabled) {
2247 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= RADEON_COLOR_TILE_ENABLE;
2248 }
2249 }
2250
2251
2252 void radeonValidateState( GLcontext *ctx )
2253 {
2254 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2255 GLuint new_state = rmesa->NewGLState;
2256
2257 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2258 radeonUpdateDrawBuffer(ctx);
2259 }
2260
2261 if (new_state & _NEW_TEXTURE) {
2262 radeonUpdateTextureState( ctx );
2263 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2264 }
2265
2266 /* Need an event driven matrix update?
2267 */
2268 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2269 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
2270
2271 /* Need these for lighting (shouldn't upload otherwise)
2272 */
2273 if (new_state & (_NEW_MODELVIEW)) {
2274 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL );
2275 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT );
2276 }
2277
2278 /* Does this need to be triggered on eg. modelview for
2279 * texgen-derived objplane/eyeplane matrices?
2280 */
2281 if (new_state & _NEW_TEXTURE_MATRIX) {
2282 update_texturematrix( ctx );
2283 }
2284
2285 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2286 update_light( ctx );
2287 }
2288
2289 /* emit all active clip planes if projection matrix changes.
2290 */
2291 if (new_state & (_NEW_PROJECTION)) {
2292 if (ctx->Transform.ClipPlanesEnabled)
2293 radeonUpdateClipPlanes( ctx );
2294 }
2295
2296
2297 rmesa->NewGLState = 0;
2298 }
2299
2300
2301 static void radeonInvalidateState( GLcontext *ctx, GLuint new_state )
2302 {
2303 _swrast_InvalidateState( ctx, new_state );
2304 _swsetup_InvalidateState( ctx, new_state );
2305 _vbo_InvalidateState( ctx, new_state );
2306 _tnl_InvalidateState( ctx, new_state );
2307 _ae_invalidate_state( ctx, new_state );
2308 RADEON_CONTEXT(ctx)->NewGLState |= new_state;
2309 }
2310
2311
2312 /* A hack. Need a faster way to find this out.
2313 */
2314 static GLboolean check_material( GLcontext *ctx )
2315 {
2316 TNLcontext *tnl = TNL_CONTEXT(ctx);
2317 GLint i;
2318
2319 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2320 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2321 i++)
2322 if (tnl->vb.AttribPtr[i] &&
2323 tnl->vb.AttribPtr[i]->stride)
2324 return GL_TRUE;
2325
2326 return GL_FALSE;
2327 }
2328
2329
2330 static void radeonWrapRunPipeline( GLcontext *ctx )
2331 {
2332 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2333 GLboolean has_material;
2334
2335 if (0)
2336 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2337
2338 /* Validate state:
2339 */
2340 if (rmesa->NewGLState)
2341 radeonValidateState( ctx );
2342
2343 has_material = (ctx->Light.Enabled && check_material( ctx ));
2344
2345 if (has_material) {
2346 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE );
2347 }
2348
2349 /* Run the pipeline.
2350 */
2351 _tnl_run_pipeline( ctx );
2352
2353 if (has_material) {
2354 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE );
2355 }
2356 }
2357
2358
2359 /* Initialize the driver's state functions.
2360 * Many of the ctx->Driver functions might have been initialized to
2361 * software defaults in the earlier _mesa_init_driver_functions() call.
2362 */
2363 void radeonInitStateFuncs( GLcontext *ctx )
2364 {
2365 ctx->Driver.UpdateState = radeonInvalidateState;
2366 ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange;
2367
2368 ctx->Driver.DrawBuffer = radeonDrawBuffer;
2369 ctx->Driver.ReadBuffer = radeonReadBuffer;
2370
2371 ctx->Driver.AlphaFunc = radeonAlphaFunc;
2372 ctx->Driver.BlendEquationSeparate = radeonBlendEquationSeparate;
2373 ctx->Driver.BlendFuncSeparate = radeonBlendFuncSeparate;
2374 ctx->Driver.ClearColor = radeonClearColor;
2375 ctx->Driver.ClearDepth = radeonClearDepth;
2376 ctx->Driver.ClearIndex = NULL;
2377 ctx->Driver.ClearStencil = radeonClearStencil;
2378 ctx->Driver.ClipPlane = radeonClipPlane;
2379 ctx->Driver.ColorMask = radeonColorMask;
2380 ctx->Driver.CullFace = radeonCullFace;
2381 ctx->Driver.DepthFunc = radeonDepthFunc;
2382 ctx->Driver.DepthMask = radeonDepthMask;
2383 ctx->Driver.DepthRange = radeonDepthRange;
2384 ctx->Driver.Enable = radeonEnable;
2385 ctx->Driver.Fogfv = radeonFogfv;
2386 ctx->Driver.FrontFace = radeonFrontFace;
2387 ctx->Driver.Hint = NULL;
2388 ctx->Driver.IndexMask = NULL;
2389 ctx->Driver.LightModelfv = radeonLightModelfv;
2390 ctx->Driver.Lightfv = radeonLightfv;
2391 ctx->Driver.LineStipple = radeonLineStipple;
2392 ctx->Driver.LineWidth = radeonLineWidth;
2393 ctx->Driver.LogicOpcode = radeonLogicOpCode;
2394 ctx->Driver.PolygonMode = radeonPolygonMode;
2395 ctx->Driver.PolygonOffset = radeonPolygonOffset;
2396 ctx->Driver.PolygonStipple = radeonPolygonStipple;
2397 ctx->Driver.RenderMode = radeonRenderMode;
2398 ctx->Driver.Scissor = radeonScissor;
2399 ctx->Driver.ShadeModel = radeonShadeModel;
2400 ctx->Driver.StencilFuncSeparate = radeonStencilFuncSeparate;
2401 ctx->Driver.StencilMaskSeparate = radeonStencilMaskSeparate;
2402 ctx->Driver.StencilOpSeparate = radeonStencilOpSeparate;
2403 ctx->Driver.Viewport = radeonViewport;
2404
2405 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial;
2406 TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline;
2407 }