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