i965/vs: Allocate storage for "auto" variables just like temps.
[mesa.git] / src / mesa / drivers / dri / mga / mgastate.c
1 /*
2 * Copyright 2000-2001 VA Linux Systems, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keith@tungstengraphics.com>
26 */
27
28
29 #include "main/mtypes.h"
30 #include "main/colormac.h"
31 #include "main/dd.h"
32 #include "main/mm.h"
33 #include "main/state.h"
34
35 #include "mgacontext.h"
36 #include "mgadd.h"
37 #include "mgastate.h"
38 #include "mgatex.h"
39 #include "mgavb.h"
40 #include "mgatris.h"
41 #include "mgaioctl.h"
42 #include "mgaregs.h"
43
44 #include "swrast/swrast.h"
45 #include "vbo/vbo.h"
46 #include "tnl/tnl.h"
47 #include "tnl/t_context.h"
48 #include "tnl/t_pipeline.h"
49 #include "swrast_setup/swrast_setup.h"
50
51 #include "xmlpool.h"
52 #include "drirenderbuffer.h"
53
54
55 static void updateSpecularLighting( struct gl_context *ctx );
56
57 static const GLuint mgarop_NoBLK[16] = {
58 DC_atype_rpl | 0x00000000, DC_atype_rstr | 0x00080000,
59 DC_atype_rstr | 0x00040000, DC_atype_rpl | 0x000c0000,
60 DC_atype_rstr | 0x00020000, DC_atype_rstr | 0x000a0000,
61 DC_atype_rstr | 0x00060000, DC_atype_rstr | 0x000e0000,
62 DC_atype_rstr | 0x00010000, DC_atype_rstr | 0x00090000,
63 DC_atype_rstr | 0x00050000, DC_atype_rstr | 0x000d0000,
64 DC_atype_rpl | 0x00030000, DC_atype_rstr | 0x000b0000,
65 DC_atype_rstr | 0x00070000, DC_atype_rpl | 0x000f0000
66 };
67
68 /* =============================================================
69 * Alpha blending
70 */
71
72 static void mgaDDAlphaFunc(struct gl_context *ctx, GLenum func, GLfloat ref)
73 {
74 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
75 GLubyte refByte;
76 GLuint a;
77
78 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
79
80 switch ( func ) {
81 case GL_NEVER:
82 a = AC_atmode_alt;
83 refByte = 0;
84 break;
85 case GL_LESS:
86 a = AC_atmode_alt;
87 break;
88 case GL_GEQUAL:
89 a = AC_atmode_agte;
90 break;
91 case GL_LEQUAL:
92 a = AC_atmode_alte;
93 break;
94 case GL_GREATER:
95 a = AC_atmode_agt;
96 break;
97 case GL_NOTEQUAL:
98 a = AC_atmode_ane;
99 break;
100 case GL_EQUAL:
101 a = AC_atmode_ae;
102 break;
103 case GL_ALWAYS:
104 a = AC_atmode_noacmp;
105 break;
106 default:
107 a = 0;
108 break;
109 }
110
111 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
112 mmesa->hw.alpha_func = a | MGA_FIELD( AC_atref, refByte );
113 }
114
115 static void updateBlendLogicOp(struct gl_context *ctx)
116 {
117 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
118 GLboolean logicOp = _mesa_rgba_logicop_enabled(ctx);
119
120 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
121
122 mmesa->hw.blend_func_enable =
123 (ctx->Color.BlendEnabled && !logicOp) ? ~0 : 0;
124
125 FALLBACK( ctx, MGA_FALLBACK_BLEND,
126 ctx->Color.BlendEnabled && !logicOp &&
127 mmesa->hw.blend_func == (AC_src_src_alpha_sat | AC_dst_zero) );
128 }
129
130 static void mgaDDBlendEquationSeparate(struct gl_context *ctx,
131 GLenum modeRGB, GLenum modeA)
132 {
133 assert( modeRGB == modeA );
134 updateBlendLogicOp( ctx );
135 }
136
137 static void mgaDDBlendFuncSeparate( struct gl_context *ctx, GLenum sfactorRGB,
138 GLenum dfactorRGB, GLenum sfactorA,
139 GLenum dfactorA )
140 {
141 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
142 GLuint src;
143 GLuint dst;
144
145 switch (ctx->Color.Blend[0].SrcRGB) {
146 case GL_ZERO:
147 src = AC_src_zero; break;
148 case GL_SRC_ALPHA:
149 src = AC_src_src_alpha; break;
150 case GL_ONE:
151 default: /* never happens */
152 src = AC_src_one; break;
153 case GL_DST_COLOR:
154 src = AC_src_dst_color; break;
155 case GL_ONE_MINUS_DST_COLOR:
156 src = AC_src_om_dst_color; break;
157 case GL_ONE_MINUS_SRC_ALPHA:
158 src = AC_src_om_src_alpha; break;
159 case GL_DST_ALPHA:
160 src = (ctx->Visual.alphaBits > 0)
161 ? AC_src_dst_alpha : AC_src_one;
162 break;
163 case GL_ONE_MINUS_DST_ALPHA:
164 src = (ctx->Visual.alphaBits > 0)
165 ? AC_src_om_dst_alpha : AC_src_zero;
166 break;
167 case GL_SRC_ALPHA_SATURATE:
168 src = (ctx->Visual.alphaBits > 0)
169 ? AC_src_src_alpha_sat : AC_src_zero;
170 break;
171 }
172
173 switch (ctx->Color.Blend[0].DstRGB) {
174 case GL_SRC_ALPHA:
175 dst = AC_dst_src_alpha; break;
176 case GL_ONE_MINUS_SRC_ALPHA:
177 dst = AC_dst_om_src_alpha; break;
178 default: /* never happens */
179 case GL_ZERO:
180 dst = AC_dst_zero; break;
181 case GL_ONE:
182 dst = AC_dst_one; break;
183 case GL_SRC_COLOR:
184 dst = AC_dst_src_color; break;
185 case GL_ONE_MINUS_SRC_COLOR:
186 dst = AC_dst_om_src_color; break;
187 case GL_DST_ALPHA:
188 dst = (ctx->Visual.alphaBits > 0)
189 ? AC_dst_dst_alpha : AC_dst_one;
190 break;
191 case GL_ONE_MINUS_DST_ALPHA:
192 dst = (ctx->Visual.alphaBits > 0)
193 ? AC_dst_om_dst_alpha : AC_dst_zero;
194 break;
195 }
196
197 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
198 mmesa->hw.blend_func = (src | dst);
199
200 FALLBACK( ctx, MGA_FALLBACK_BLEND,
201 ctx->Color.BlendEnabled && !_mesa_rgba_logicop_enabled(ctx) &&
202 mmesa->hw.blend_func == (AC_src_src_alpha_sat | AC_dst_zero) );
203 }
204
205 /* =============================================================
206 * Depth testing
207 */
208
209 static void mgaDDDepthFunc(struct gl_context *ctx, GLenum func)
210 {
211 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
212 int zmode;
213
214 switch (func) {
215 case GL_NEVER:
216 /* can't do this in h/w, we'll use a s/w fallback */
217 FALLBACK (ctx, MGA_FALLBACK_DEPTH, ctx->Depth.Test);
218
219 /* FALLTHROUGH */
220 case GL_ALWAYS:
221 zmode = DC_zmode_nozcmp; break;
222 case GL_LESS:
223 zmode = DC_zmode_zlt; break;
224 case GL_LEQUAL:
225 zmode = DC_zmode_zlte; break;
226 case GL_EQUAL:
227 zmode = DC_zmode_ze; break;
228 case GL_GREATER:
229 zmode = DC_zmode_zgt; break;
230 case GL_GEQUAL:
231 zmode = DC_zmode_zgte; break;
232 case GL_NOTEQUAL:
233 zmode = DC_zmode_zne; break;
234 default:
235 zmode = 0; break;
236 }
237
238 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
239 mmesa->hw.zmode &= DC_zmode_MASK;
240 mmesa->hw.zmode |= zmode;
241 }
242
243 static void mgaDDDepthMask(struct gl_context *ctx, GLboolean flag)
244 {
245 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
246
247
248 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
249 mmesa->hw.zmode &= DC_atype_MASK;
250 mmesa->hw.zmode |= (flag) ? DC_atype_zi : DC_atype_i;
251 }
252
253
254 static void mgaDDClearDepth(struct gl_context *ctx, GLclampd d)
255 {
256 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
257
258 /* Select the Z depth. The ~ is used because the _MASK values in the
259 * MGA driver are used to mask OFF the selected bits. In this case,
260 * we want to mask off everything except the MA_zwidth bits.
261 */
262 switch (mmesa->setup.maccess & ~MA_zwidth_MASK) {
263 case MA_zwidth_16: mmesa->ClearDepth = d * 0x0000ffff; break;
264 case MA_zwidth_24: mmesa->ClearDepth = d * 0xffffff00; break;
265 case MA_zwidth_32: mmesa->ClearDepth = d * 0xffffffff; break;
266 default: return;
267 }
268 }
269
270
271 /* =============================================================
272 * Fog
273 */
274
275
276 static void mgaDDFogfv(struct gl_context *ctx, GLenum pname, const GLfloat *param)
277 {
278 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
279
280 if (pname == GL_FOG_COLOR) {
281 GLuint color = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F),
282 (GLubyte)(ctx->Fog.Color[1]*255.0F),
283 (GLubyte)(ctx->Fog.Color[2]*255.0F));
284
285 MGA_STATECHANGE(mmesa, MGA_UPLOAD_CONTEXT);
286 mmesa->setup.fogcolor = color;
287 }
288 }
289
290
291 /* =============================================================
292 * Scissoring
293 */
294
295
296 void mgaUpdateClipping(const struct gl_context *ctx)
297 {
298 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
299
300 if (mmesa->driDrawable)
301 {
302 int x1 = mmesa->driDrawable->x + ctx->Scissor.X;
303 int y1 = mmesa->driDrawable->y + mmesa->driDrawable->h
304 - (ctx->Scissor.Y + ctx->Scissor.Height);
305 int x2 = x1 + ctx->Scissor.Width;
306 int y2 = y1 + ctx->Scissor.Height;
307
308 if (x1 < 0) x1 = 0;
309 if (y1 < 0) y1 = 0;
310 if (x2 < 0) x2 = 0;
311 if (y2 < 0) y2 = 0;
312
313 mmesa->scissor_rect.x1 = x1;
314 mmesa->scissor_rect.y1 = y1;
315 mmesa->scissor_rect.x2 = x2;
316 mmesa->scissor_rect.y2 = y2;
317
318 mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
319 }
320 }
321
322
323 static void mgaDDScissor( struct gl_context *ctx, GLint x, GLint y,
324 GLsizei w, GLsizei h )
325 {
326 if ( ctx->Scissor.Enabled ) {
327 FLUSH_BATCH( MGA_CONTEXT(ctx) ); /* don't pipeline cliprect changes */
328 mgaUpdateClipping( ctx );
329 }
330 }
331
332
333 /* =============================================================
334 * Culling
335 */
336
337
338 #define _CULL_DISABLE 0
339 #define _CULL_NEGATIVE ((1<<11)|(1<<5)|(1<<16))
340 #define _CULL_POSITIVE (1<<11)
341
342 static void mgaDDCullFaceFrontFace(struct gl_context *ctx, GLenum unused)
343 {
344 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
345
346 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
347 if (ctx->Polygon.CullFlag &&
348 ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK)
349 {
350 mmesa->hw.cull = _CULL_NEGATIVE;
351
352 if (ctx->Polygon.CullFaceMode == GL_FRONT)
353 mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
354
355 if (ctx->Polygon.FrontFace != GL_CCW)
356 mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
357
358 mmesa->hw.cull_dualtex = mmesa->hw.cull ^
359 (_CULL_POSITIVE ^ _CULL_NEGATIVE); /* warp bug? */
360 }
361 else {
362 mmesa->hw.cull = _CULL_DISABLE;
363 mmesa->hw.cull_dualtex = _CULL_DISABLE;
364 }
365 }
366
367
368 /* =============================================================
369 * Masks
370 */
371
372 static void mgaDDColorMask(struct gl_context *ctx,
373 GLboolean r, GLboolean g,
374 GLboolean b, GLboolean a )
375 {
376 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
377 mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
378 GLuint mask = mgaPackColor(mgaScreen->cpp,
379 ctx->Color.ColorMask[0][RCOMP],
380 ctx->Color.ColorMask[0][GCOMP],
381 ctx->Color.ColorMask[0][BCOMP],
382 ctx->Color.ColorMask[0][ACOMP]);
383
384 if (mgaScreen->cpp == 2)
385 mask = mask | (mask << 16);
386
387 if (mmesa->setup.plnwt != mask) {
388 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
389 mmesa->setup.plnwt = mask;
390 }
391 }
392
393
394 /* =============================================================
395 * Polygon state
396 */
397
398 static int mgaStipples[16] = {
399 0xffff,
400 0xa5a5,
401 0x5a5a,
402 0xa0a0,
403 0x5050,
404 0x0a0a,
405 0x0505,
406 0x8020,
407 0x0401,
408 0x1040,
409 0x0208,
410 0x0802,
411 0x4010,
412 0x0104,
413 0x2080,
414 0x0000
415 };
416
417 /**
418 * The MGA supports a subset of possible 4x4 stipples natively, GL
419 * wants 32x32. Fortunately stipple is usually a repeating pattern.
420 *
421 * \param ctx GL rendering context to be affected
422 * \param mask Pointer to the 32x32 stipple mask
423 */
424
425 static void mgaDDPolygonStipple( struct gl_context *ctx, const GLubyte *mask )
426 {
427 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
428 const GLubyte *m = mask;
429 GLubyte p[4];
430 int i,j,k;
431 int active = (ctx->Polygon.StippleFlag &&
432 mmesa->raster_primitive == GL_TRIANGLES);
433 GLuint stipple;
434
435 FLUSH_BATCH(mmesa);
436 mmesa->haveHwStipple = 0;
437
438 if (active) {
439 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
440 mmesa->setup.dwgctl &= ~(0xf<<20);
441 }
442
443 p[0] = mask[0] & 0xf; p[0] |= p[0] << 4;
444 p[1] = mask[4] & 0xf; p[1] |= p[1] << 4;
445 p[2] = mask[8] & 0xf; p[2] |= p[2] << 4;
446 p[3] = mask[12] & 0xf; p[3] |= p[3] << 4;
447
448 for (k = 0 ; k < 8 ; k++)
449 for (j = 0 ; j < 4; j++)
450 for (i = 0 ; i < 4 ; i++)
451 if (*m++ != p[j]) {
452 return;
453 }
454
455 stipple = ( ((p[0] & 0xf) << 0) |
456 ((p[1] & 0xf) << 4) |
457 ((p[2] & 0xf) << 8) |
458 ((p[3] & 0xf) << 12) );
459
460 for (i = 0 ; i < 16 ; i++)
461 if (mgaStipples[i] == stipple) {
462 mmesa->poly_stipple = i<<20;
463 mmesa->haveHwStipple = 1;
464 break;
465 }
466
467 if (active) {
468 mmesa->setup.dwgctl &= ~(0xf<<20);
469 mmesa->setup.dwgctl |= mmesa->poly_stipple;
470 }
471 }
472
473
474 /* =============================================================
475 * Rendering attributes
476 *
477 * We really don't want to recalculate all this every time we bind a
478 * texture. These things shouldn't change all that often, so it makes
479 * sense to break them out of the core texture state update routines.
480 */
481
482 static void updateSpecularLighting( struct gl_context *ctx )
483 {
484 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
485 unsigned int specen;
486
487 specen = _mesa_need_secondary_color(ctx) ? TMC_specen_enable : 0;
488
489 if ( specen != mmesa->hw.specen ) {
490 mmesa->hw.specen = specen;
491 mmesa->dirty |= MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1;
492 }
493 }
494
495
496 /* =============================================================
497 * Materials
498 */
499
500
501 static void mgaDDLightModelfv(struct gl_context *ctx, GLenum pname,
502 const GLfloat *param)
503 {
504 if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
505 FLUSH_BATCH( MGA_CONTEXT(ctx) );
506 updateSpecularLighting( ctx );
507 }
508 }
509
510
511 /* =============================================================
512 * Stencil
513 */
514
515
516 static void
517 mgaDDStencilFuncSeparate(struct gl_context *ctx, GLenum face, GLenum func, GLint ref,
518 GLuint mask)
519 {
520 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
521 GLuint stencil;
522 GLuint stencilctl;
523
524 stencil = MGA_FIELD( S_sref, ref ) | MGA_FIELD( S_smsk, mask );
525 switch (func)
526 {
527 case GL_NEVER:
528 stencilctl = SC_smode_snever;
529 break;
530 case GL_LESS:
531 stencilctl = SC_smode_slt;
532 break;
533 case GL_LEQUAL:
534 stencilctl = SC_smode_slte;
535 break;
536 case GL_GREATER:
537 stencilctl = SC_smode_sgt;
538 break;
539 case GL_GEQUAL:
540 stencilctl = SC_smode_sgte;
541 break;
542 case GL_NOTEQUAL:
543 stencilctl = SC_smode_sne;
544 break;
545 case GL_EQUAL:
546 stencilctl = SC_smode_se;
547 break;
548 case GL_ALWAYS:
549 default:
550 stencilctl = SC_smode_salways;
551 break;
552 }
553
554 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
555 mmesa->hw.stencil &= (S_sref_MASK & S_smsk_MASK);
556 mmesa->hw.stencil |= stencil;
557 mmesa->hw.stencilctl &= SC_smode_MASK;
558 mmesa->hw.stencilctl |= stencilctl;
559 }
560
561 static void
562 mgaDDStencilMaskSeparate(struct gl_context *ctx, GLenum face, GLuint mask)
563 {
564 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
565
566 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
567 mmesa->hw.stencil &= S_swtmsk_MASK;
568 mmesa->hw.stencil |= MGA_FIELD( S_swtmsk, mask );
569 }
570
571 static void
572 mgaDDStencilOpSeparate(struct gl_context *ctx, GLenum face, GLenum fail, GLenum zfail,
573 GLenum zpass)
574 {
575 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
576 GLuint stencilctl;
577
578 stencilctl = 0;
579 switch (ctx->Stencil.FailFunc[0])
580 {
581 case GL_KEEP:
582 stencilctl |= SC_sfailop_keep;
583 break;
584 case GL_ZERO:
585 stencilctl |= SC_sfailop_zero;
586 break;
587 case GL_REPLACE:
588 stencilctl |= SC_sfailop_replace;
589 break;
590 case GL_INCR:
591 stencilctl |= SC_sfailop_incrsat;
592 break;
593 case GL_DECR:
594 stencilctl |= SC_sfailop_decrsat;
595 break;
596 case GL_INCR_WRAP:
597 stencilctl |= SC_sfailop_incr;
598 break;
599 case GL_DECR_WRAP:
600 stencilctl |= SC_sfailop_decr;
601 break;
602 case GL_INVERT:
603 stencilctl |= SC_sfailop_invert;
604 break;
605 default:
606 break;
607 }
608
609 switch (ctx->Stencil.ZFailFunc[0])
610 {
611 case GL_KEEP:
612 stencilctl |= SC_szfailop_keep;
613 break;
614 case GL_ZERO:
615 stencilctl |= SC_szfailop_zero;
616 break;
617 case GL_REPLACE:
618 stencilctl |= SC_szfailop_replace;
619 break;
620 case GL_INCR:
621 stencilctl |= SC_szfailop_incrsat;
622 break;
623 case GL_DECR:
624 stencilctl |= SC_szfailop_decrsat;
625 break;
626 case GL_INCR_WRAP:
627 stencilctl |= SC_szfailop_incr;
628 break;
629 case GL_DECR_WRAP:
630 stencilctl |= SC_szfailop_decr;
631 break;
632 case GL_INVERT:
633 stencilctl |= SC_szfailop_invert;
634 break;
635 default:
636 break;
637 }
638
639 switch (ctx->Stencil.ZPassFunc[0])
640 {
641 case GL_KEEP:
642 stencilctl |= SC_szpassop_keep;
643 break;
644 case GL_ZERO:
645 stencilctl |= SC_szpassop_zero;
646 break;
647 case GL_REPLACE:
648 stencilctl |= SC_szpassop_replace;
649 break;
650 case GL_INCR:
651 stencilctl |= SC_szpassop_incrsat;
652 break;
653 case GL_DECR:
654 stencilctl |= SC_szpassop_decrsat;
655 break;
656 case GL_INCR_WRAP:
657 stencilctl |= SC_szpassop_incr;
658 break;
659 case GL_DECR_WRAP:
660 stencilctl |= SC_szpassop_decr;
661 break;
662 case GL_INVERT:
663 stencilctl |= SC_szpassop_invert;
664 break;
665 default:
666 break;
667 }
668
669 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
670 mmesa->hw.stencilctl &= (SC_sfailop_MASK & SC_szfailop_MASK
671 & SC_szpassop_MASK);
672 mmesa->hw.stencilctl |= stencilctl;
673 }
674
675
676 /* =============================================================
677 * Window position and viewport transformation
678 */
679
680 void mgaCalcViewport( struct gl_context *ctx )
681 {
682 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
683 const GLfloat *v = ctx->Viewport._WindowMap.m;
684 GLfloat *m = mmesa->hw_viewport;
685
686 /* See also mga_translate_vertex.
687 */
688 m[MAT_SX] = v[MAT_SX];
689 m[MAT_TX] = v[MAT_TX] + mmesa->drawX + SUBPIXEL_X;
690 m[MAT_SY] = - v[MAT_SY];
691 m[MAT_TY] = - v[MAT_TY] + mmesa->driDrawable->h + mmesa->drawY + SUBPIXEL_Y;
692 m[MAT_SZ] = v[MAT_SZ] * mmesa->depth_scale;
693 m[MAT_TZ] = v[MAT_TZ] * mmesa->depth_scale;
694
695 mmesa->SetupNewInputs = ~0;
696 }
697
698 static void mgaViewport( struct gl_context *ctx,
699 GLint x, GLint y,
700 GLsizei width, GLsizei height )
701 {
702 mgaCalcViewport( ctx );
703 }
704
705 static void mgaDepthRange( struct gl_context *ctx,
706 GLclampd nearval, GLclampd farval )
707 {
708 mgaCalcViewport( ctx );
709 }
710
711
712 /* =============================================================
713 * Miscellaneous
714 */
715
716 static void mgaDDClearColor(struct gl_context *ctx,
717 const GLfloat color[4] )
718 {
719 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
720 GLubyte c[4];
721 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
722 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
723 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
724 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
725
726 mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp,
727 c[0], c[1], c[2], c[3]);
728 }
729
730
731 /* Fallback to swrast for select and feedback.
732 */
733 static void mgaRenderMode( struct gl_context *ctx, GLenum mode )
734 {
735 FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
736 }
737
738
739 static void mgaDDLogicOp( struct gl_context *ctx, GLenum opcode )
740 {
741 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
742
743 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
744 mmesa->hw.rop = mgarop_NoBLK[ opcode & 0x0f ];
745 }
746
747
748 static void mga_set_cliprects(mgaContextPtr mmesa)
749 {
750 __DRIdrawable *driDrawable = mmesa->driDrawable;
751
752 if ((mmesa->draw_buffer != MGA_FRONT)
753 || (driDrawable->numBackClipRects == 0)) {
754 if (driDrawable->numClipRects == 0) {
755 static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
756 mmesa->numClipRects = 1;
757 mmesa->pClipRects = &zeroareacliprect;
758 } else {
759 mmesa->numClipRects = driDrawable->numClipRects;
760 mmesa->pClipRects = driDrawable->pClipRects;
761 }
762 mmesa->drawX = driDrawable->x;
763 mmesa->drawY = driDrawable->y;
764 } else {
765 mmesa->numClipRects = driDrawable->numBackClipRects;
766 mmesa->pClipRects = driDrawable->pBackClipRects;
767 mmesa->drawX = driDrawable->backX;
768 mmesa->drawY = driDrawable->backY;
769 }
770
771 mmesa->setup.dstorg = mmesa->drawOffset;
772 mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
773 }
774
775
776 void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers )
777 {
778 __DRIdrawable *const driDrawable = mmesa->driDrawable;
779 __DRIdrawable *const driReadable = mmesa->driReadable;
780
781 mmesa->dirty_cliprects = 0;
782
783 driUpdateFramebufferSize(mmesa->glCtx, driDrawable);
784 if (driDrawable != driReadable) {
785 driUpdateFramebufferSize(mmesa->glCtx, driReadable);
786 }
787
788 mga_set_cliprects(mmesa);
789
790 mgaUpdateClipping( mmesa->glCtx );
791 mgaCalcViewport( mmesa->glCtx );
792 }
793
794
795 static void mgaDDDrawBuffer(struct gl_context *ctx, GLenum mode )
796 {
797 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
798
799 FLUSH_BATCH( mmesa );
800
801 if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
802 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
803 FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
804 return;
805 }
806
807 switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
808 case BUFFER_FRONT_LEFT:
809 mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset;
810 mmesa->draw_buffer = MGA_FRONT;
811 break;
812 case BUFFER_BACK_LEFT:
813 mmesa->setup.dstorg = mmesa->mgaScreen->backOffset;
814 mmesa->draw_buffer = MGA_BACK;
815 break;
816 default:
817 FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
818 return;
819 }
820
821 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
822 mga_set_cliprects(mmesa);
823 FALLBACK(ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE);
824 }
825
826
827 static void mgaDDReadBuffer(struct gl_context *ctx, GLenum mode )
828 {
829 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
830 }
831
832
833 /* =============================================================
834 * State enable/disable
835 */
836
837
838 static void mgaDDEnable(struct gl_context *ctx, GLenum cap, GLboolean state)
839 {
840 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
841
842 switch(cap) {
843 case GL_DITHER:
844 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
845 if (!ctx->Color.DitherFlag)
846 mmesa->setup.maccess |= MA_nodither_enable;
847 else
848 mmesa->setup.maccess &= ~MA_nodither_enable;
849 break;
850 case GL_LIGHTING:
851 case GL_COLOR_SUM_EXT:
852 FLUSH_BATCH( mmesa );
853 updateSpecularLighting( ctx );
854 break;
855 case GL_ALPHA_TEST:
856 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
857 mmesa->hw.alpha_func_enable = (state) ? ~0 : 0;
858 break;
859 case GL_DEPTH_TEST:
860 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
861 FALLBACK (ctx, MGA_FALLBACK_DEPTH,
862 ctx->Depth.Func == GL_NEVER && ctx->Depth.Test);
863 break;
864
865 case GL_SCISSOR_TEST:
866 FLUSH_BATCH( mmesa );
867 mmesa->scissor = state;
868 mgaUpdateClipping( ctx );
869 break;
870
871 case GL_FOG:
872 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
873 if (ctx->Fog.Enabled)
874 mmesa->setup.maccess |= MA_fogen_enable;
875 else
876 mmesa->setup.maccess &= ~MA_fogen_enable;
877 break;
878 case GL_CULL_FACE:
879 mgaDDCullFaceFrontFace( ctx, 0 );
880 break;
881 case GL_TEXTURE_1D:
882 case GL_TEXTURE_2D:
883 case GL_TEXTURE_3D:
884 break;
885 case GL_POLYGON_STIPPLE:
886 if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) {
887 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
888 mmesa->setup.dwgctl &= ~(0xf<<20);
889 if (state)
890 mmesa->setup.dwgctl |= mmesa->poly_stipple;
891 }
892 break;
893
894 case GL_BLEND:
895 case GL_COLOR_LOGIC_OP:
896 updateBlendLogicOp( ctx );
897 break;
898
899 case GL_STENCIL_TEST:
900 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
901 if (mmesa->hw_stencil) {
902 mmesa->hw.stencil_enable = ( state ) ? ~0 : 0;
903 }
904 else {
905 FALLBACK( ctx, MGA_FALLBACK_STENCIL, state );
906 }
907 default:
908 break;
909 }
910 }
911
912
913 /* =============================================================
914 */
915
916 static void mgaDDPrintDirty( const char *msg, GLuint state )
917 {
918 fprintf(stderr, "%s (0x%03x): %s%s%s%s%s%s%s\n",
919 msg,
920 (unsigned int) state,
921 (state & MGA_WAIT_AGE) ? "wait-age " : "",
922 (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img " : "",
923 (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img " : "",
924 (state & MGA_UPLOAD_CONTEXT) ? "upload-ctx " : "",
925 (state & MGA_UPLOAD_TEX0) ? "upload-tex0 " : "",
926 (state & MGA_UPLOAD_TEX1) ? "upload-tex1 " : "",
927 (state & MGA_UPLOAD_PIPE) ? "upload-pipe " : ""
928 );
929 }
930
931 /* Push the state into the sarea and/or texture memory.
932 */
933 void mgaEmitHwStateLocked( mgaContextPtr mmesa )
934 {
935 drm_mga_sarea_t *sarea = mmesa->sarea;
936 struct gl_context * ctx = mmesa->glCtx;
937
938 if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
939 mgaDDPrintDirty( __FUNCTION__, mmesa->dirty );
940
941 if (mmesa->dirty & MGA_UPLOAD_CONTEXT) {
942 mmesa->setup.wflag = _CULL_DISABLE;
943 if (mmesa->raster_primitive == GL_TRIANGLES) {
944 if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT &&
945 ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) {
946 mmesa->setup.wflag = mmesa->hw.cull_dualtex;
947 }
948 else {
949 mmesa->setup.wflag = mmesa->hw.cull;
950 }
951 }
952
953 mmesa->setup.stencil = mmesa->hw.stencil
954 & mmesa->hw.stencil_enable;
955 mmesa->setup.stencilctl = mmesa->hw.stencilctl
956 & mmesa->hw.stencil_enable;
957
958 /* If depth testing is not enabled, then use the no Z-compare / no
959 * Z-write mode. Otherwise, use whatever is set in hw.zmode.
960 */
961 mmesa->setup.dwgctl &= (DC_zmode_MASK & DC_atype_MASK);
962 mmesa->setup.dwgctl |= (ctx->Depth.Test)
963 ? mmesa->hw.zmode : (DC_zmode_nozcmp | DC_atype_i);
964
965 mmesa->setup.dwgctl &= DC_bop_MASK;
966 mmesa->setup.dwgctl |= _mesa_rgba_logicop_enabled(ctx)
967 ? mmesa->hw.rop : mgarop_NoBLK[ GL_COPY & 0x0f ];
968
969 mmesa->setup.alphactrl &= AC_src_MASK & AC_dst_MASK & AC_atmode_MASK
970 & AC_atref_MASK & AC_alphasel_MASK;
971 mmesa->setup.alphactrl |=
972 (mmesa->hw.alpha_func & mmesa->hw.alpha_func_enable) |
973 (mmesa->hw.blend_func & mmesa->hw.blend_func_enable) |
974 ((AC_src_one | AC_dst_zero) & ~mmesa->hw.blend_func_enable) |
975 mmesa->hw.alpha_sel;
976
977 memcpy( &sarea->context_state, &mmesa->setup, sizeof(mmesa->setup));
978 }
979
980 if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
981 memcpy(&sarea->tex_state[0],
982 &mmesa->CurrentTexObj[0]->setup,
983 sizeof(sarea->tex_state[0]));
984 }
985
986 if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
987 memcpy(&sarea->tex_state[1],
988 &mmesa->CurrentTexObj[1]->setup,
989 sizeof(sarea->tex_state[1]));
990 }
991
992 if (mmesa->dirty & (MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1)) {
993 sarea->tex_state[0].texctl2 &= ~TMC_specen_enable;
994 sarea->tex_state[1].texctl2 &= ~TMC_specen_enable;
995 sarea->tex_state[0].texctl2 |= mmesa->hw.specen;
996 sarea->tex_state[1].texctl2 |= mmesa->hw.specen;
997 }
998
999 if (mmesa->dirty & MGA_UPLOAD_PIPE) {
1000 /* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
1001 mmesa->sarea->warp_pipe = mmesa->vertex_format;
1002 mmesa->sarea->vertsize = mmesa->vertex_size;
1003 }
1004
1005 mmesa->sarea->dirty |= mmesa->dirty;
1006 mmesa->dirty &= MGA_UPLOAD_CLIPRECTS;
1007 }
1008
1009 /* =============================================================
1010 */
1011
1012
1013 static void mgaDDValidateState( struct gl_context *ctx )
1014 {
1015 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
1016
1017 FLUSH_BATCH( mmesa );
1018
1019 if (mmesa->NewGLState & _NEW_TEXTURE) {
1020 mgaUpdateTextureState(ctx);
1021 }
1022
1023 if (!mmesa->Fallback) {
1024 if (mmesa->NewGLState & _MGA_NEW_RASTERSETUP) {
1025 mgaChooseVertexState( ctx );
1026 }
1027
1028 if (mmesa->NewGLState & _MGA_NEW_RENDERSTATE) {
1029 mgaChooseRenderState( ctx );
1030 }
1031 }
1032
1033 mmesa->NewGLState = 0;
1034 }
1035
1036
1037 static void mgaDDInvalidateState( struct gl_context *ctx, GLuint new_state )
1038 {
1039 _swrast_InvalidateState( ctx, new_state );
1040 _swsetup_InvalidateState( ctx, new_state );
1041 _vbo_InvalidateState( ctx, new_state );
1042 _tnl_InvalidateState( ctx, new_state );
1043 MGA_CONTEXT(ctx)->NewGLState |= new_state;
1044 }
1045
1046
1047 static void mgaRunPipeline( struct gl_context *ctx )
1048 {
1049 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
1050
1051 if (mmesa->NewGLState) {
1052 mgaDDValidateState( ctx );
1053 }
1054
1055 if (mmesa->dirty) {
1056 mgaEmitHwStateLocked( mmesa );
1057 }
1058
1059 _tnl_run_pipeline( ctx );
1060 }
1061
1062
1063 void mgaInitState( mgaContextPtr mmesa )
1064 {
1065 mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
1066 struct gl_context *ctx = mmesa->glCtx;
1067
1068 if (ctx->Visual.doubleBufferMode) {
1069 /* use back buffer by default */
1070 mmesa->draw_buffer = MGA_BACK;
1071 mmesa->drawOffset = mmesa->mgaScreen->backOffset;
1072 mmesa->readOffset = mmesa->mgaScreen->backOffset;
1073 mmesa->setup.dstorg = mgaScreen->backOffset;
1074 } else {
1075 /* use front buffer by default */
1076 mmesa->draw_buffer = MGA_FRONT;
1077 mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
1078 mmesa->readOffset = mmesa->mgaScreen->frontOffset;
1079 mmesa->setup.dstorg = mgaScreen->frontOffset;
1080 }
1081
1082 mmesa->setup.maccess = (MA_memreset_disable |
1083 MA_fogen_disable |
1084 MA_tlutload_disable |
1085 MA_nodither_disable |
1086 MA_dit555_disable);
1087 if (driQueryOptioni (&mmesa->optionCache, "color_reduction") !=
1088 DRI_CONF_COLOR_REDUCTION_DITHER)
1089 mmesa->setup.maccess |= MA_nodither_enable;
1090
1091 switch (mmesa->mgaScreen->cpp) {
1092 case 2:
1093 mmesa->setup.maccess |= MA_pwidth_16;
1094 break;
1095 case 4:
1096 mmesa->setup.maccess |= MA_pwidth_32;
1097 break;
1098 default:
1099 fprintf( stderr, "Error: unknown cpp %d, exiting...\n",
1100 mmesa->mgaScreen->cpp );
1101 exit( 1 );
1102 }
1103
1104 switch (mmesa->glCtx->Visual.depthBits) {
1105 case 16:
1106 mmesa->setup.maccess |= MA_zwidth_16;
1107 break;
1108 case 24:
1109 mmesa->setup.maccess |= MA_zwidth_24;
1110 break;
1111 case 32:
1112 mmesa->setup.maccess |= MA_zwidth_32;
1113 break;
1114 }
1115
1116 mmesa->hw.blend_func = AC_src_one | AC_dst_zero;
1117 mmesa->hw.blend_func_enable = 0;
1118 mmesa->hw.alpha_func = AC_atmode_noacmp | MGA_FIELD( AC_atref, 0x00 );
1119 mmesa->hw.alpha_func_enable = 0;
1120 mmesa->hw.rop = mgarop_NoBLK[ GL_COPY & 0x0f ];
1121 mmesa->hw.zmode = DC_zmode_zlt | DC_atype_zi;
1122 mmesa->hw.stencil = MGA_FIELD( S_sref, 0x00) | MGA_FIELD( S_smsk, 0xff ) |
1123 MGA_FIELD( S_swtmsk, 0xff );
1124 mmesa->hw.stencilctl = SC_smode_salways | SC_sfailop_keep
1125 | SC_szfailop_keep | SC_szpassop_keep;
1126 mmesa->hw.stencil_enable = 0;
1127 mmesa->hw.cull = _CULL_DISABLE;
1128 mmesa->hw.cull_dualtex = _CULL_DISABLE;
1129 mmesa->hw.specen = 0;
1130 mmesa->hw.alpha_sel = AC_alphasel_diffused;
1131
1132 mmesa->setup.dwgctl = (DC_opcod_trap |
1133 DC_linear_xy |
1134 DC_solid_disable |
1135 DC_arzero_disable |
1136 DC_sgnzero_disable |
1137 DC_shftzero_enable |
1138 MGA_FIELD( DC_bop, 0xC ) |
1139 MGA_FIELD( DC_trans, 0x0 ) |
1140 DC_bltmod_bmonolef |
1141 DC_pattern_disable |
1142 DC_transc_disable |
1143 DC_clipdis_disable);
1144
1145 mmesa->setup.plnwt = ~0;
1146 mmesa->setup.alphactrl = (AC_amode_alpha_channel |
1147 AC_astipple_disable |
1148 AC_aten_disable);
1149
1150 mmesa->setup.fogcolor = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F),
1151 (GLubyte)(ctx->Fog.Color[1]*255.0F),
1152 (GLubyte)(ctx->Fog.Color[2]*255.0F));
1153
1154 mmesa->setup.wflag = 0;
1155 mmesa->setup.tdualstage0 = 0;
1156 mmesa->setup.tdualstage1 = 0;
1157 mmesa->setup.fcol = 0;
1158 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
1159
1160 mmesa->envcolor[0] = 0;
1161 mmesa->envcolor[1] = 0;
1162 }
1163
1164
1165 void mgaDDInitStateFuncs( struct gl_context *ctx )
1166 {
1167 ctx->Driver.UpdateState = mgaDDInvalidateState;
1168 ctx->Driver.Enable = mgaDDEnable;
1169 ctx->Driver.LightModelfv = mgaDDLightModelfv;
1170 ctx->Driver.AlphaFunc = mgaDDAlphaFunc;
1171 ctx->Driver.BlendEquationSeparate = mgaDDBlendEquationSeparate;
1172 ctx->Driver.BlendFuncSeparate = mgaDDBlendFuncSeparate;
1173 ctx->Driver.DepthFunc = mgaDDDepthFunc;
1174 ctx->Driver.DepthMask = mgaDDDepthMask;
1175 ctx->Driver.Fogfv = mgaDDFogfv;
1176 ctx->Driver.Scissor = mgaDDScissor;
1177 ctx->Driver.CullFace = mgaDDCullFaceFrontFace;
1178 ctx->Driver.FrontFace = mgaDDCullFaceFrontFace;
1179 ctx->Driver.ColorMask = mgaDDColorMask;
1180
1181 ctx->Driver.DrawBuffer = mgaDDDrawBuffer;
1182 ctx->Driver.ReadBuffer = mgaDDReadBuffer;
1183 ctx->Driver.ClearColor = mgaDDClearColor;
1184 ctx->Driver.ClearDepth = mgaDDClearDepth;
1185 ctx->Driver.LogicOpcode = mgaDDLogicOp;
1186
1187 ctx->Driver.PolygonStipple = mgaDDPolygonStipple;
1188
1189 ctx->Driver.StencilFuncSeparate = mgaDDStencilFuncSeparate;
1190 ctx->Driver.StencilMaskSeparate = mgaDDStencilMaskSeparate;
1191 ctx->Driver.StencilOpSeparate = mgaDDStencilOpSeparate;
1192
1193 ctx->Driver.DepthRange = mgaDepthRange;
1194 ctx->Driver.Viewport = mgaViewport;
1195 ctx->Driver.RenderMode = mgaRenderMode;
1196
1197 TNL_CONTEXT(ctx)->Driver.RunPipeline = mgaRunPipeline;
1198 }