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