4de05c7697d94a43ec787f5150741dbea3d9968a
[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 rmesa->lastStamp = drawable->lastStamp;
1680 }
1681
1682
1683 /**
1684 * Called via glDrawBuffer.
1685 */
1686 static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
1687 {
1688 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1689
1690 if (RADEON_DEBUG & DEBUG_DRI)
1691 fprintf(stderr, "%s %s\n", __FUNCTION__,
1692 _mesa_lookup_enum_by_nr( mode ));
1693
1694 RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
1695
1696 /*
1697 * _ColorDrawBufferMask is easier to cope with than <mode>.
1698 * Check for software fallback, update cliprects.
1699 */
1700 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
1701 case BUFFER_BIT_FRONT_LEFT:
1702 case BUFFER_BIT_BACK_LEFT:
1703 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
1704 break;
1705 default:
1706 /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1707 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
1708 return;
1709 }
1710
1711 radeonSetCliprects( rmesa );
1712
1713 /* We'll set the drawing engine's offset/pitch parameters later
1714 * when we update other state.
1715 */
1716 }
1717
1718 static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
1719 {
1720 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1721 }
1722
1723
1724 /* =============================================================
1725 * State enable/disable
1726 */
1727
1728 static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
1729 {
1730 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1731 GLuint p, flag;
1732
1733 if ( RADEON_DEBUG & DEBUG_STATE )
1734 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1735 _mesa_lookup_enum_by_nr( cap ),
1736 state ? "GL_TRUE" : "GL_FALSE" );
1737
1738 switch ( cap ) {
1739 /* Fast track this one...
1740 */
1741 case GL_TEXTURE_1D:
1742 case GL_TEXTURE_2D:
1743 case GL_TEXTURE_3D:
1744 break;
1745
1746 case GL_ALPHA_TEST:
1747 RADEON_STATECHANGE( rmesa, ctx );
1748 if (state) {
1749 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE;
1750 } else {
1751 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE;
1752 }
1753 break;
1754
1755 case GL_BLEND:
1756 RADEON_STATECHANGE( rmesa, ctx );
1757 if (state) {
1758 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ALPHA_BLEND_ENABLE;
1759 } else {
1760 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE;
1761 }
1762 if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
1763 && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
1764 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
1765 } else {
1766 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
1767 }
1768
1769 /* Catch a possible fallback:
1770 */
1771 if (state) {
1772 ctx->Driver.BlendEquationSeparate( ctx,
1773 ctx->Color.BlendEquationRGB,
1774 ctx->Color.BlendEquationA );
1775 ctx->Driver.BlendFuncSeparate( ctx, ctx->Color.BlendSrcRGB,
1776 ctx->Color.BlendDstRGB,
1777 ctx->Color.BlendSrcA,
1778 ctx->Color.BlendDstA );
1779 }
1780 else {
1781 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE );
1782 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, GL_FALSE );
1783 }
1784 break;
1785
1786 case GL_CLIP_PLANE0:
1787 case GL_CLIP_PLANE1:
1788 case GL_CLIP_PLANE2:
1789 case GL_CLIP_PLANE3:
1790 case GL_CLIP_PLANE4:
1791 case GL_CLIP_PLANE5:
1792 p = cap-GL_CLIP_PLANE0;
1793 RADEON_STATECHANGE( rmesa, tcl );
1794 if (state) {
1795 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p);
1796 radeonClipPlane( ctx, cap, NULL );
1797 }
1798 else {
1799 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p);
1800 }
1801 break;
1802
1803 case GL_COLOR_MATERIAL:
1804 radeonColorMaterial( ctx, 0, 0 );
1805 radeonUpdateMaterial( ctx );
1806 break;
1807
1808 case GL_CULL_FACE:
1809 radeonCullFace( ctx, 0 );
1810 break;
1811
1812 case GL_DEPTH_TEST:
1813 RADEON_STATECHANGE(rmesa, ctx );
1814 if ( state ) {
1815 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_Z_ENABLE;
1816 } else {
1817 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE;
1818 }
1819 break;
1820
1821 case GL_DITHER:
1822 RADEON_STATECHANGE(rmesa, ctx );
1823 if ( state ) {
1824 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
1825 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
1826 } else {
1827 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE;
1828 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
1829 }
1830 break;
1831
1832 case GL_FOG:
1833 RADEON_STATECHANGE(rmesa, ctx );
1834 if ( state ) {
1835 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE;
1836 radeonFogfv( ctx, GL_FOG_MODE, NULL );
1837 } else {
1838 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE;
1839 RADEON_STATECHANGE(rmesa, tcl);
1840 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
1841 }
1842 radeonUpdateSpecular( ctx ); /* for PK_SPEC */
1843 _mesa_allow_light_in_model( ctx, !state );
1844 break;
1845
1846 case GL_LIGHT0:
1847 case GL_LIGHT1:
1848 case GL_LIGHT2:
1849 case GL_LIGHT3:
1850 case GL_LIGHT4:
1851 case GL_LIGHT5:
1852 case GL_LIGHT6:
1853 case GL_LIGHT7:
1854 RADEON_STATECHANGE(rmesa, tcl);
1855 p = cap - GL_LIGHT0;
1856 if (p&1)
1857 flag = (RADEON_LIGHT_1_ENABLE |
1858 RADEON_LIGHT_1_ENABLE_AMBIENT |
1859 RADEON_LIGHT_1_ENABLE_SPECULAR);
1860 else
1861 flag = (RADEON_LIGHT_0_ENABLE |
1862 RADEON_LIGHT_0_ENABLE_AMBIENT |
1863 RADEON_LIGHT_0_ENABLE_SPECULAR);
1864
1865 if (state)
1866 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1867 else
1868 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1869
1870 /*
1871 */
1872 update_light_colors( ctx, p );
1873 break;
1874
1875 case GL_LIGHTING:
1876 RADEON_STATECHANGE(rmesa, tcl);
1877 radeonUpdateSpecular(ctx);
1878 check_twoside_fallback( ctx );
1879 break;
1880
1881 case GL_LINE_SMOOTH:
1882 RADEON_STATECHANGE( rmesa, ctx );
1883 if ( state ) {
1884 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_LINE;
1885 } else {
1886 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE;
1887 }
1888 break;
1889
1890 case GL_LINE_STIPPLE:
1891 RADEON_STATECHANGE( rmesa, ctx );
1892 if ( state ) {
1893 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_PATTERN_ENABLE;
1894 } else {
1895 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE;
1896 }
1897 break;
1898
1899 case GL_COLOR_LOGIC_OP:
1900 RADEON_STATECHANGE( rmesa, ctx );
1901 if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
1902 && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
1903 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE;
1904 } else {
1905 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
1906 }
1907 break;
1908
1909 case GL_NORMALIZE:
1910 RADEON_STATECHANGE( rmesa, tcl );
1911 if ( state ) {
1912 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_NORMALIZE_NORMALS;
1913 } else {
1914 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS;
1915 }
1916 break;
1917
1918 case GL_POLYGON_OFFSET_POINT:
1919 RADEON_STATECHANGE( rmesa, set );
1920 if ( state ) {
1921 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_POINT;
1922 } else {
1923 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT;
1924 }
1925 break;
1926
1927 case GL_POLYGON_OFFSET_LINE:
1928 RADEON_STATECHANGE( rmesa, set );
1929 if ( state ) {
1930 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_LINE;
1931 } else {
1932 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE;
1933 }
1934 break;
1935
1936 case GL_POLYGON_OFFSET_FILL:
1937 RADEON_STATECHANGE( rmesa, set );
1938 if ( state ) {
1939 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_TRI;
1940 } else {
1941 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI;
1942 }
1943 break;
1944
1945 case GL_POLYGON_SMOOTH:
1946 RADEON_STATECHANGE( rmesa, ctx );
1947 if ( state ) {
1948 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_POLY;
1949 } else {
1950 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY;
1951 }
1952 break;
1953
1954 case GL_POLYGON_STIPPLE:
1955 RADEON_STATECHANGE(rmesa, ctx );
1956 if ( state ) {
1957 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_STIPPLE_ENABLE;
1958 } else {
1959 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE;
1960 }
1961 break;
1962
1963 case GL_RESCALE_NORMAL_EXT: {
1964 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1965 RADEON_STATECHANGE( rmesa, tcl );
1966 if ( tmp ) {
1967 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
1968 } else {
1969 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
1970 }
1971 break;
1972 }
1973
1974 case GL_SCISSOR_TEST:
1975 RADEON_FIREVERTICES( rmesa );
1976 rmesa->state.scissor.enabled = state;
1977 radeonUpdateScissor( ctx );
1978 break;
1979
1980 case GL_STENCIL_TEST:
1981 if ( rmesa->state.stencil.hwBuffer ) {
1982 RADEON_STATECHANGE( rmesa, ctx );
1983 if ( state ) {
1984 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE;
1985 } else {
1986 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
1987 }
1988 } else {
1989 FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
1990 }
1991 break;
1992
1993 case GL_TEXTURE_GEN_Q:
1994 case GL_TEXTURE_GEN_R:
1995 case GL_TEXTURE_GEN_S:
1996 case GL_TEXTURE_GEN_T:
1997 /* Picked up in radeonUpdateTextureState.
1998 */
1999 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
2000 break;
2001
2002 case GL_COLOR_SUM_EXT:
2003 radeonUpdateSpecular ( ctx );
2004 break;
2005
2006 default:
2007 return;
2008 }
2009 }
2010
2011
2012 static void radeonLightingSpaceChange( GLcontext *ctx )
2013 {
2014 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2015 GLboolean tmp;
2016 RADEON_STATECHANGE( rmesa, tcl );
2017
2018 if (RADEON_DEBUG & DEBUG_STATE)
2019 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2020 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
2021
2022 if (ctx->_NeedEyeCoords)
2023 tmp = ctx->Transform.RescaleNormals;
2024 else
2025 tmp = !ctx->Transform.RescaleNormals;
2026
2027 if ( tmp ) {
2028 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS;
2029 } else {
2030 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
2031 }
2032
2033 if (RADEON_DEBUG & DEBUG_STATE)
2034 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2035 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
2036 }
2037
2038 /* =============================================================
2039 * Deferred state management - matrices, textures, other?
2040 */
2041
2042
2043 void radeonUploadTexMatrix( radeonContextPtr rmesa,
2044 int unit, GLboolean swapcols )
2045 {
2046 /* Here's how this works: on r100, only 3 tex coords can be submitted, so the
2047 vector looks like this probably: (s t r|q 0) (not sure if the last coord
2048 is hardwired to 0, could be 1 too). Interestingly, it actually looks like
2049 texgen generates all 4 coords, at least tests with projtex indicated that.
2050 So: if we need the q coord in the end (solely determined by the texture
2051 target, i.e. 2d / 1d / texrect targets) we swap the third and 4th row.
2052 Additionally, if we don't have texgen but 4 tex coords submitted, we swap
2053 column 3 and 4 (for the 2d / 1d / texrect targets) since the the q coord
2054 will get submitted in the "wrong", i.e. 3rd, slot.
2055 If an app submits 3 coords for 2d targets, we assume it is saving on vertex
2056 size and using the texture matrix to swap the r and q coords around (ut2k3
2057 does exactly that), so we don't need the 3rd / 4th column swap - still need
2058 the 3rd / 4th row swap of course. This will potentially break for apps which
2059 use TexCoord3x just for fun. Additionally, it will never work if an app uses
2060 an "advanced" texture matrix and relies on all 4 texcoord inputs to generate
2061 the maximum needed 3. This seems impossible to do with hw tcl on r100, and
2062 incredibly hard to detect so we can't just fallback in such a case. Assume
2063 it never happens... - rs
2064 */
2065
2066 int idx = TEXMAT_0 + unit;
2067 float *dest = ((float *)RADEON_DB_STATE( mat[idx] )) + MAT_ELT_0;
2068 int i;
2069 struct gl_texture_unit tUnit = rmesa->glCtx->Texture.Unit[unit];
2070 GLfloat *src = rmesa->tmpmat[unit].m;
2071
2072 rmesa->TexMatColSwap &= ~(1 << unit);
2073 if ((tUnit._ReallyEnabled & (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT)) == 0) {
2074 if (swapcols) {
2075 rmesa->TexMatColSwap |= 1 << unit;
2076 /* attention some elems are swapped 2 times! */
2077 *dest++ = src[0];
2078 *dest++ = src[4];
2079 *dest++ = src[12];
2080 *dest++ = src[8];
2081 *dest++ = src[1];
2082 *dest++ = src[5];
2083 *dest++ = src[13];
2084 *dest++ = src[9];
2085 *dest++ = src[2];
2086 *dest++ = src[6];
2087 *dest++ = src[15];
2088 *dest++ = src[11];
2089 /* those last 4 are probably never used */
2090 *dest++ = src[3];
2091 *dest++ = src[7];
2092 *dest++ = src[14];
2093 *dest++ = src[10];
2094 }
2095 else {
2096 for (i = 0; i < 2; i++) {
2097 *dest++ = src[i];
2098 *dest++ = src[i+4];
2099 *dest++ = src[i+8];
2100 *dest++ = src[i+12];
2101 }
2102 for (i = 3; i >= 2; i--) {
2103 *dest++ = src[i];
2104 *dest++ = src[i+4];
2105 *dest++ = src[i+8];
2106 *dest++ = src[i+12];
2107 }
2108 }
2109 }
2110 else {
2111 for (i = 0 ; i < 4 ; i++) {
2112 *dest++ = src[i];
2113 *dest++ = src[i+4];
2114 *dest++ = src[i+8];
2115 *dest++ = src[i+12];
2116 }
2117 }
2118
2119 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2120 }
2121
2122
2123 static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
2124 {
2125 float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
2126 int i;
2127
2128
2129 for (i = 0 ; i < 4 ; i++) {
2130 *dest++ = src[i];
2131 *dest++ = src[i+4];
2132 *dest++ = src[i+8];
2133 *dest++ = src[i+12];
2134 }
2135
2136 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2137 }
2138
2139 static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
2140 {
2141 float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
2142 memcpy(dest, src, 16*sizeof(float));
2143 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2144 }
2145
2146
2147 static void update_texturematrix( GLcontext *ctx )
2148 {
2149 radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
2150 GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL];
2151 GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL];
2152 int unit;
2153 GLuint texMatEnabled = 0;
2154 rmesa->NeedTexMatrix = 0;
2155 rmesa->TexMatColSwap = 0;
2156
2157 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2158 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
2159 GLboolean needMatrix = GL_FALSE;
2160 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2161 needMatrix = GL_TRUE;
2162 texMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE |
2163 RADEON_TEXMAT_0_ENABLE) << unit;
2164
2165 if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
2166 /* Need to preconcatenate any active texgen
2167 * obj/eyeplane matrices:
2168 */
2169 _math_matrix_mul_matrix( &rmesa->tmpmat[unit],
2170 ctx->TextureMatrixStack[unit].Top,
2171 &rmesa->TexGenMatrix[unit] );
2172 }
2173 else {
2174 _math_matrix_copy( &rmesa->tmpmat[unit],
2175 ctx->TextureMatrixStack[unit].Top );
2176 }
2177 }
2178 else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
2179 _math_matrix_copy( &rmesa->tmpmat[unit], &rmesa->TexGenMatrix[unit] );
2180 needMatrix = GL_TRUE;
2181 }
2182 if (needMatrix) {
2183 rmesa->NeedTexMatrix |= 1 << unit;
2184 radeonUploadTexMatrix( rmesa, unit,
2185 !ctx->Texture.Unit[unit].TexGenEnabled );
2186 }
2187 }
2188 }
2189
2190 tpc = (texMatEnabled | rmesa->TexGenEnabled);
2191
2192 /* TCL_TEX_COMPUTED_x is TCL_TEX_INPUT_x | 0x8 */
2193 vs &= ~((RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
2194 (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
2195 (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
2196
2197 vs |= (((tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE) <<
2198 (RADEON_TCL_TEX_0_OUTPUT_SHIFT + 3)) |
2199 ((tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE) <<
2200 (RADEON_TCL_TEX_1_OUTPUT_SHIFT + 2)) |
2201 ((tpc & RADEON_TEXGEN_TEXMAT_2_ENABLE) <<
2202 (RADEON_TCL_TEX_2_OUTPUT_SHIFT + 1)));
2203
2204 if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] ||
2205 vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) {
2206
2207 RADEON_STATECHANGE(rmesa, tcl);
2208 rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc;
2209 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs;
2210 }
2211 }
2212
2213
2214 /**
2215 * Tell the card where to render (offset, pitch).
2216 * Effected by glDrawBuffer, etc
2217 */
2218 void
2219 radeonUpdateDrawBuffer(GLcontext *ctx)
2220 {
2221 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2222 struct gl_framebuffer *fb = ctx->DrawBuffer;
2223 driRenderbuffer *drb;
2224
2225 if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
2226 /* draw to front */
2227 drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2228 }
2229 else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) {
2230 /* draw to back */
2231 drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2232 }
2233 else {
2234 /* drawing to multiple buffers, or none */
2235 return;
2236 }
2237
2238 assert(drb);
2239 assert(drb->flippedPitch);
2240
2241 RADEON_STATECHANGE( rmesa, ctx );
2242
2243 /* Note: we used the (possibly) page-flipped values */
2244 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2245 = ((drb->flippedOffset + rmesa->radeonScreen->fbLocation)
2246 & RADEON_COLOROFFSET_MASK);
2247 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2248 if (rmesa->sarea->tiling_enabled) {
2249 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= RADEON_COLOR_TILE_ENABLE;
2250 }
2251 }
2252
2253
2254 void radeonValidateState( GLcontext *ctx )
2255 {
2256 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2257 GLuint new_state = rmesa->NewGLState;
2258
2259 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2260 radeonUpdateDrawBuffer(ctx);
2261 }
2262
2263 if (new_state & _NEW_TEXTURE) {
2264 radeonUpdateTextureState( ctx );
2265 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2266 }
2267
2268 /* Need an event driven matrix update?
2269 */
2270 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2271 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
2272
2273 /* Need these for lighting (shouldn't upload otherwise)
2274 */
2275 if (new_state & (_NEW_MODELVIEW)) {
2276 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL );
2277 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT );
2278 }
2279
2280 /* Does this need to be triggered on eg. modelview for
2281 * texgen-derived objplane/eyeplane matrices?
2282 */
2283 if (new_state & _NEW_TEXTURE_MATRIX) {
2284 update_texturematrix( ctx );
2285 }
2286
2287 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2288 update_light( ctx );
2289 }
2290
2291 /* emit all active clip planes if projection matrix changes.
2292 */
2293 if (new_state & (_NEW_PROJECTION)) {
2294 if (ctx->Transform.ClipPlanesEnabled)
2295 radeonUpdateClipPlanes( ctx );
2296 }
2297
2298
2299 rmesa->NewGLState = 0;
2300 }
2301
2302
2303 static void radeonInvalidateState( GLcontext *ctx, GLuint new_state )
2304 {
2305 _swrast_InvalidateState( ctx, new_state );
2306 _swsetup_InvalidateState( ctx, new_state );
2307 _vbo_InvalidateState( ctx, new_state );
2308 _tnl_InvalidateState( ctx, new_state );
2309 _ae_invalidate_state( ctx, new_state );
2310 RADEON_CONTEXT(ctx)->NewGLState |= new_state;
2311 }
2312
2313
2314 /* A hack. Need a faster way to find this out.
2315 */
2316 static GLboolean check_material( GLcontext *ctx )
2317 {
2318 TNLcontext *tnl = TNL_CONTEXT(ctx);
2319 GLint i;
2320
2321 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2322 i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2323 i++)
2324 if (tnl->vb.AttribPtr[i] &&
2325 tnl->vb.AttribPtr[i]->stride)
2326 return GL_TRUE;
2327
2328 return GL_FALSE;
2329 }
2330
2331
2332 static void radeonWrapRunPipeline( GLcontext *ctx )
2333 {
2334 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2335 GLboolean has_material;
2336
2337 if (0)
2338 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2339
2340 /* Validate state:
2341 */
2342 if (rmesa->NewGLState)
2343 radeonValidateState( ctx );
2344
2345 has_material = (ctx->Light.Enabled && check_material( ctx ));
2346
2347 if (has_material) {
2348 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE );
2349 }
2350
2351 /* Run the pipeline.
2352 */
2353 _tnl_run_pipeline( ctx );
2354
2355 if (has_material) {
2356 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE );
2357 }
2358 }
2359
2360
2361 /* Initialize the driver's state functions.
2362 * Many of the ctx->Driver functions might have been initialized to
2363 * software defaults in the earlier _mesa_init_driver_functions() call.
2364 */
2365 void radeonInitStateFuncs( GLcontext *ctx )
2366 {
2367 ctx->Driver.UpdateState = radeonInvalidateState;
2368 ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange;
2369
2370 ctx->Driver.DrawBuffer = radeonDrawBuffer;
2371 ctx->Driver.ReadBuffer = radeonReadBuffer;
2372
2373 ctx->Driver.AlphaFunc = radeonAlphaFunc;
2374 ctx->Driver.BlendEquationSeparate = radeonBlendEquationSeparate;
2375 ctx->Driver.BlendFuncSeparate = radeonBlendFuncSeparate;
2376 ctx->Driver.ClearColor = radeonClearColor;
2377 ctx->Driver.ClearDepth = radeonClearDepth;
2378 ctx->Driver.ClearIndex = NULL;
2379 ctx->Driver.ClearStencil = radeonClearStencil;
2380 ctx->Driver.ClipPlane = radeonClipPlane;
2381 ctx->Driver.ColorMask = radeonColorMask;
2382 ctx->Driver.CullFace = radeonCullFace;
2383 ctx->Driver.DepthFunc = radeonDepthFunc;
2384 ctx->Driver.DepthMask = radeonDepthMask;
2385 ctx->Driver.DepthRange = radeonDepthRange;
2386 ctx->Driver.Enable = radeonEnable;
2387 ctx->Driver.Fogfv = radeonFogfv;
2388 ctx->Driver.FrontFace = radeonFrontFace;
2389 ctx->Driver.Hint = NULL;
2390 ctx->Driver.IndexMask = NULL;
2391 ctx->Driver.LightModelfv = radeonLightModelfv;
2392 ctx->Driver.Lightfv = radeonLightfv;
2393 ctx->Driver.LineStipple = radeonLineStipple;
2394 ctx->Driver.LineWidth = radeonLineWidth;
2395 ctx->Driver.LogicOpcode = radeonLogicOpCode;
2396 ctx->Driver.PolygonMode = radeonPolygonMode;
2397 ctx->Driver.PolygonOffset = radeonPolygonOffset;
2398 ctx->Driver.PolygonStipple = radeonPolygonStipple;
2399 ctx->Driver.RenderMode = radeonRenderMode;
2400 ctx->Driver.Scissor = radeonScissor;
2401 ctx->Driver.ShadeModel = radeonShadeModel;
2402 ctx->Driver.StencilFuncSeparate = radeonStencilFuncSeparate;
2403 ctx->Driver.StencilMaskSeparate = radeonStencilMaskSeparate;
2404 ctx->Driver.StencilOpSeparate = radeonStencilOpSeparate;
2405 ctx->Driver.Viewport = radeonViewport;
2406
2407 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial;
2408 TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline;
2409 }