mga driver, brought over by Jon Smirl
[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 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgastate.c,v 1.13 2002/10/30 12:51:36 alanh Exp $ */
28
29 #include <stdio.h>
30
31 #include "mtypes.h"
32 #include "dd.h"
33
34 #include "mm.h"
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 #include "mgabuffers.h"
44
45 #include "swrast/swrast.h"
46 #include "array_cache/acache.h"
47 #include "tnl/tnl.h"
48 #include "swrast_setup/swrast_setup.h"
49
50
51
52 /* Some outstanding problems with accelerating logic ops...
53 */
54 #if defined(ACCEL_ROP)
55 static GLuint mgarop_NoBLK[16] = {
56 DC_atype_rpl | 0x00000000, DC_atype_rstr | 0x00080000,
57 DC_atype_rstr | 0x00040000, DC_atype_rpl | 0x000c0000,
58 DC_atype_rstr | 0x00020000, DC_atype_rstr | 0x000a0000,
59 DC_atype_rstr | 0x00060000, DC_atype_rstr | 0x000e0000,
60 DC_atype_rstr | 0x00010000, DC_atype_rstr | 0x00090000,
61 DC_atype_rstr | 0x00050000, DC_atype_rstr | 0x000d0000,
62 DC_atype_rpl | 0x00030000, DC_atype_rstr | 0x000b0000,
63 DC_atype_rstr | 0x00070000, DC_atype_rpl | 0x000f0000
64 };
65 #endif
66
67
68 static void mgaUpdateStencil(const GLcontext *ctx)
69 {
70 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
71 GLuint stencil = 0, stencilctl = 0;
72
73 if (ctx->Stencil.Enabled)
74 {
75 stencil = ctx->Stencil.Ref[0] |
76 ( ctx->Stencil.ValueMask[0] << 8 ) |
77 ( ctx->Stencil.WriteMask[0] << 16 );
78
79 switch (ctx->Stencil.Function[0])
80 {
81 case GL_NEVER:
82 MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_snever);
83 break;
84 case GL_LESS:
85 MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_slt);
86 break;
87 case GL_LEQUAL:
88 MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_slte);
89 break;
90 case GL_GREATER:
91 MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sgt);
92 break;
93 case GL_GEQUAL:
94 MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sgte);
95 break;
96 case GL_NOTEQUAL:
97 MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sne);
98 break;
99 case GL_EQUAL:
100 MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_se);
101 break;
102 case GL_ALWAYS:
103 MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_salways);
104 default:
105 break;
106 }
107
108 switch (ctx->Stencil.FailFunc[0])
109 {
110 case GL_KEEP:
111 MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_keep);
112 break;
113 case GL_ZERO:
114 MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_zero);
115 break;
116 case GL_REPLACE:
117 MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_replace);
118 break;
119 case GL_INCR:
120 MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_incrsat);
121 break;
122 case GL_DECR:
123 MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_decrsat);
124 break;
125 case GL_INVERT:
126 MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_invert);
127 break;
128 default:
129 break;
130 }
131
132 switch (ctx->Stencil.ZFailFunc[0])
133 {
134 case GL_KEEP:
135 MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_keep);
136 break;
137 case GL_ZERO:
138 MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_zero);
139 break;
140 case GL_REPLACE:
141 MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_replace);
142 break;
143 case GL_INCR:
144 MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_incrsat);
145 break;
146 case GL_DECR:
147 MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_decrsat);
148 break;
149 case GL_INVERT:
150 MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_invert);
151 break;
152 default:
153 break;
154 }
155
156 switch (ctx->Stencil.ZPassFunc[0])
157 {
158 case GL_KEEP:
159 MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_keep);
160 break;
161 case GL_ZERO:
162 MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_zero);
163 break;
164 case GL_REPLACE:
165 MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_replace);
166 break;
167 case GL_INCR:
168 MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_incrsat);
169 break;
170 case GL_DECR:
171 MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_decrsat);
172 break;
173 case GL_INVERT:
174 MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_invert);
175 break;
176 default:
177 break;
178 }
179 }
180
181 mmesa->setup.stencil = stencil;
182 mmesa->setup.stencilctl = stencilctl;
183 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
184 }
185
186 static void mgaDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
187 GLuint mask)
188 {
189 FLUSH_BATCH( MGA_CONTEXT(ctx) );
190 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL;
191 }
192
193 static void mgaDDStencilMask(GLcontext *ctx, GLuint mask)
194 {
195 FLUSH_BATCH( MGA_CONTEXT(ctx) );
196 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL;
197 }
198
199 static void mgaDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
200 GLenum zpass)
201 {
202 FLUSH_BATCH( MGA_CONTEXT(ctx) );
203 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL;
204 }
205
206 static void mgaDDClearDepth(GLcontext *ctx, GLclampd d)
207 {
208 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
209
210 /* KW: should the ~ be there? */
211 switch (mmesa->setup.maccess & ~MA_zwidth_MASK) {
212 case MA_zwidth_16: mmesa->ClearDepth = d * 0x0000ffff; break;
213 case MA_zwidth_24: mmesa->ClearDepth = d * 0xffffff00; break;
214 case MA_zwidth_32: mmesa->ClearDepth = d * 0xffffffff; break;
215 default: return;
216 }
217 }
218
219 static void mgaUpdateZMode(const GLcontext *ctx)
220 {
221 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
222 int zmode = 0;
223
224 if (ctx->Depth.Test) {
225 switch(ctx->Depth.Func) {
226 case GL_NEVER:
227 /* can't do this in h/w, we'll use a s/w fallback */
228 zmode = DC_zmode_nozcmp;
229 break;
230 case GL_ALWAYS:
231 zmode = DC_zmode_nozcmp; break;
232 case GL_LESS:
233 zmode = DC_zmode_zlt; break;
234 case GL_LEQUAL:
235 zmode = DC_zmode_zlte; break;
236 case GL_EQUAL:
237 zmode = DC_zmode_ze; break;
238 case GL_GREATER:
239 zmode = DC_zmode_zgt; break;
240 case GL_GEQUAL:
241 zmode = DC_zmode_zgte; break;
242 case GL_NOTEQUAL:
243 zmode = DC_zmode_zne; break;
244 default:
245 break;
246 }
247
248 if (ctx->Depth.Mask)
249 zmode |= DC_atype_zi;
250 else
251 zmode |= DC_atype_i;
252 }
253 else {
254 zmode |= DC_zmode_nozcmp;
255 zmode |= DC_atype_i; /* don't write to zbuffer */
256 }
257
258 #if defined(ACCEL_ROP)
259 mmesa->setup.dwgctl &= DC_bop_MASK;
260 if (ctx->Color.ColorLogicOpEnabled)
261 zmode |= mgarop_NoBLK[(ctx->Color.LogicOp)&0xf];
262 else
263 zmode |= mgarop_NoBLK[GL_COPY & 0xf];
264 #endif
265
266 mmesa->setup.dwgctl &= DC_zmode_MASK & DC_atype_MASK;
267 mmesa->setup.dwgctl |= zmode;
268 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
269 }
270
271
272 static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
273 {
274 FLUSH_BATCH( MGA_CONTEXT(ctx) );
275 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
276 }
277
278
279 static void mgaDDBlendEquation(GLcontext *ctx, GLenum mode)
280 {
281 FLUSH_BATCH( MGA_CONTEXT(ctx) );
282 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
283
284 /* BlendEquation sets ColorLogicOpEnabled in an unexpected
285 * manner.
286 */
287 FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
288 (ctx->Color.ColorLogicOpEnabled &&
289 ctx->Color.LogicOp != GL_COPY));
290 }
291
292 static void mgaDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
293 {
294 FLUSH_BATCH( MGA_CONTEXT(ctx) );
295 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
296 }
297
298 static void mgaDDBlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB,
299 GLenum dfactorRGB, GLenum sfactorA,
300 GLenum dfactorA )
301 {
302 FLUSH_BATCH( MGA_CONTEXT(ctx) );
303 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
304 }
305
306
307
308 static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname,
309 const GLfloat *param)
310 {
311 if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
312 FLUSH_BATCH( MGA_CONTEXT(ctx) );
313 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE;
314 }
315 }
316
317
318 static void mgaDDShadeModel(GLcontext *ctx, GLenum mode)
319 {
320 FLUSH_BATCH( MGA_CONTEXT(ctx) );
321 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE;
322 }
323
324
325 static void mgaDDDepthFunc(GLcontext *ctx, GLenum func)
326 {
327 FLUSH_BATCH( MGA_CONTEXT(ctx) );
328 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH;
329 }
330
331 static void mgaDDDepthMask(GLcontext *ctx, GLboolean flag)
332 {
333 FLUSH_BATCH( MGA_CONTEXT(ctx) );
334 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH;
335 }
336
337 #if defined(ACCEL_ROP)
338 static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
339 {
340 FLUSH_BATCH( MGA_CONTEXT(ctx) );
341 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH;
342 }
343 #else
344 static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
345 {
346 FLUSH_BATCH( MGA_CONTEXT(ctx) );
347 FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
348 (ctx->Color.ColorLogicOpEnabled && opcode != GL_COPY) );
349 }
350 #endif
351
352
353
354 static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
355 {
356 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
357
358 if (pname == GL_FOG_COLOR) {
359 GLuint color = MGAPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F),
360 (GLubyte)(ctx->Fog.Color[1]*255.0F),
361 (GLubyte)(ctx->Fog.Color[2]*255.0F));
362
363 MGA_STATECHANGE(mmesa, MGA_UPLOAD_CONTEXT);
364 mmesa->setup.fogcolor = color;
365 }
366 }
367
368
369
370
371 /* =============================================================
372 * Alpha blending
373 */
374
375
376 static void mgaUpdateAlphaMode(GLcontext *ctx)
377 {
378 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
379 mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
380 int a = 0;
381
382 /* determine source of alpha for blending and testing */
383 if ( !ctx->Texture.Unit[0]._ReallyEnabled ) {
384 a |= AC_alphasel_diffused;
385 }
386 else {
387 /* G400: Regardless of texture env mode, we use the alpha from the
388 * texture unit (AC_alphasel_fromtex) since it will have already
389 * been modulated by the incoming fragment color, if needed.
390 * We don't want (AC_alphasel_modulate) since that'll effectively
391 * do the modulation twice.
392 */
393 if (MGA_IS_G400(mmesa)) {
394 a |= AC_alphasel_fromtex;
395 }
396 else {
397 /* G200 */
398 switch (ctx->Texture.Unit[0].EnvMode) {
399 case GL_DECAL:
400 a |= AC_alphasel_diffused;
401 case GL_REPLACE:
402 a |= AC_alphasel_fromtex;
403 break;
404 case GL_BLEND:
405 case GL_MODULATE:
406 a |= AC_alphasel_modulated;
407 break;
408 default:
409 break;
410 }
411 }
412 }
413
414
415 /* alpha test control.
416 */
417 if (ctx->Color.AlphaEnabled) {
418 GLubyte ref = ctx->Color.AlphaRef;
419 switch (ctx->Color.AlphaFunc) {
420 case GL_NEVER:
421 a |= AC_atmode_alt;
422 ref = 0;
423 break;
424 case GL_LESS:
425 a |= AC_atmode_alt;
426 break;
427 case GL_GEQUAL:
428 a |= AC_atmode_agte;
429 break;
430 case GL_LEQUAL:
431 a |= AC_atmode_alte;
432 break;
433 case GL_GREATER:
434 a |= AC_atmode_agt;
435 break;
436 case GL_NOTEQUAL:
437 a |= AC_atmode_ane;
438 break;
439 case GL_EQUAL:
440 a |= AC_atmode_ae;
441 break;
442 case GL_ALWAYS:
443 a |= AC_atmode_noacmp;
444 break;
445 default:
446 break;
447 }
448 a |= MGA_FIELD(AC_atref,ref);
449 }
450
451 /* blending control */
452 if (ctx->Color.BlendEnabled) {
453 switch (ctx->Color.BlendSrcRGB) {
454 case GL_ZERO:
455 a |= AC_src_zero; break;
456 case GL_SRC_ALPHA:
457 a |= AC_src_src_alpha; break;
458 case GL_ONE:
459 a |= AC_src_one; break;
460 case GL_DST_COLOR:
461 a |= AC_src_dst_color; break;
462 case GL_ONE_MINUS_DST_COLOR:
463 a |= AC_src_om_dst_color; break;
464 case GL_ONE_MINUS_SRC_ALPHA:
465 a |= AC_src_om_src_alpha; break;
466 case GL_DST_ALPHA:
467 if (mgaScreen->cpp == 4)
468 a |= AC_src_dst_alpha;
469 else
470 a |= AC_src_one;
471 break;
472 case GL_ONE_MINUS_DST_ALPHA:
473 if (mgaScreen->cpp == 4)
474 a |= AC_src_om_dst_alpha;
475 else
476 a |= AC_src_zero;
477 break;
478 case GL_SRC_ALPHA_SATURATE:
479 if (ctx->Visual.alphaBits > 0)
480 a |= AC_src_src_alpha_sat;
481 else
482 a |= AC_src_zero;
483 break;
484 default: /* never happens */
485 break;
486 }
487
488 switch (ctx->Color.BlendDstRGB) {
489 case GL_SRC_ALPHA:
490 a |= AC_dst_src_alpha; break;
491 case GL_ONE_MINUS_SRC_ALPHA:
492 a |= AC_dst_om_src_alpha; break;
493 case GL_ZERO:
494 a |= AC_dst_zero; break;
495 case GL_ONE:
496 a |= AC_dst_one; break;
497 case GL_SRC_COLOR:
498 a |= AC_dst_src_color; break;
499 case GL_ONE_MINUS_SRC_COLOR:
500 a |= AC_dst_om_src_color; break;
501 case GL_DST_ALPHA:
502 if (mgaScreen->cpp == 4)
503 a |= AC_dst_dst_alpha;
504 else
505 a |= AC_dst_one;
506 break;
507 case GL_ONE_MINUS_DST_ALPHA:
508 if (mgaScreen->cpp == 4)
509 a |= AC_dst_om_dst_alpha;
510 else
511 a |= AC_dst_zero;
512 break;
513 default: /* never happens */
514 break;
515 }
516 } else {
517 a |= AC_src_one|AC_dst_zero;
518 }
519
520 mmesa->setup.alphactrl = (AC_amode_alpha_channel |
521 AC_astipple_disable |
522 AC_aten_disable |
523 AC_atmode_noacmp |
524 a);
525
526 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
527 }
528
529
530
531 /* =============================================================
532 * Hardware clipping
533 */
534
535 void mgaUpdateClipping(const GLcontext *ctx)
536 {
537 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
538
539 if (mmesa->driDrawable)
540 {
541 int x1 = mmesa->driDrawable->x + ctx->Scissor.X;
542 int y1 = mmesa->driDrawable->y + mmesa->driDrawable->h
543 - (ctx->Scissor.Y + ctx->Scissor.Height);
544 int x2 = x1 + ctx->Scissor.Width - 1;
545 int y2 = y1 + ctx->Scissor.Height - 1;
546
547 if (x1 < 0) x1 = 0;
548 if (y1 < 0) y1 = 0;
549 if (x2 < 0) x2 = 0;
550 if (y2 < 0) y2 = 0;
551
552 mmesa->scissor_rect.x1 = x1;
553 mmesa->scissor_rect.y1 = y1;
554 mmesa->scissor_rect.x2 = x2;
555 mmesa->scissor_rect.y2 = y2;
556
557 if (MGA_DEBUG&DEBUG_VERBOSE_2D)
558 fprintf(stderr, "SET SCISSOR %d,%d-%d,%d\n",
559 mmesa->scissor_rect.x1,
560 mmesa->scissor_rect.y1,
561 mmesa->scissor_rect.x2,
562 mmesa->scissor_rect.y2);
563
564 mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
565 }
566 }
567
568
569 static void mgaDDScissor( GLcontext *ctx, GLint x, GLint y,
570 GLsizei w, GLsizei h )
571 {
572 FLUSH_BATCH( MGA_CONTEXT(ctx) );
573 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CLIP;
574 }
575
576
577 static void mgaDDClearColor(GLcontext *ctx,
578 const GLfloat color[4] )
579 {
580 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
581
582 mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp,
583 color[0], color[1],
584 color[2], color[3]);
585 }
586
587
588 /* =============================================================
589 * Culling
590 */
591
592 #define _CULL_DISABLE 0
593 #define _CULL_NEGATIVE ((1<<11)|(1<<5)|(1<<16))
594 #define _CULL_POSITIVE (1<<11)
595
596
597 void mgaUpdateCull( GLcontext *ctx )
598 {
599 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
600 GLuint mode = _CULL_DISABLE;
601
602 if (ctx->Polygon.CullFlag &&
603 mmesa->raster_primitive == GL_TRIANGLES &&
604 ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK)
605 {
606 mode = _CULL_NEGATIVE;
607 if (ctx->Polygon.CullFaceMode == GL_FRONT)
608 mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
609 if (ctx->Polygon.FrontFace != GL_CCW)
610 mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
611 if ((ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_2D_BIT) &&
612 (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_2D_BIT))
613 mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE); /* warp bug? */
614 }
615
616 mmesa->setup.wflag = mode;
617 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
618 }
619
620
621 static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum mode)
622 {
623 FLUSH_BATCH( MGA_CONTEXT(ctx) );
624 MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CULL;
625 }
626
627
628
629
630 /* =============================================================
631 * Color masks
632 */
633
634 static void mgaDDColorMask(GLcontext *ctx,
635 GLboolean r, GLboolean g,
636 GLboolean b, GLboolean a )
637 {
638 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
639 mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
640
641
642 GLuint mask = mgaPackColor(mgaScreen->cpp,
643 ctx->Color.ColorMask[RCOMP],
644 ctx->Color.ColorMask[GCOMP],
645 ctx->Color.ColorMask[BCOMP],
646 ctx->Color.ColorMask[ACOMP]);
647
648 if (mgaScreen->cpp == 2)
649 mask = mask | (mask << 16);
650
651 if (mmesa->setup.plnwt != mask) {
652 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
653 mmesa->setup.plnwt = mask;
654 }
655 }
656
657 /* =============================================================
658 * Polygon stipple
659 *
660 * The mga supports a subset of possible 4x4 stipples natively, GL
661 * wants 32x32. Fortunately stipple is usually a repeating pattern.
662 *
663 * Note: the fully opaque pattern (0xffff) has been disabled in order
664 * to work around a conformance issue.
665 */
666 static int mgaStipples[16] = {
667 0xffff1, /* See above note */
668 0xa5a5,
669 0x5a5a,
670 0xa0a0,
671 0x5050,
672 0x0a0a,
673 0x0505,
674 0x8020,
675 0x0401,
676 0x1040,
677 0x0208,
678 0x0802,
679 0x4010,
680 0x0104,
681 0x2080,
682 0x0000
683 };
684
685 static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
686 {
687 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
688 const GLubyte *m = mask;
689 GLubyte p[4];
690 int i,j,k;
691 int active = (ctx->Polygon.StippleFlag &&
692 mmesa->raster_primitive == GL_TRIANGLES);
693 GLuint stipple;
694
695 FLUSH_BATCH(mmesa);
696 mmesa->haveHwStipple = 0;
697
698 if (active) {
699 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
700 mmesa->setup.dwgctl &= ~(0xf<<20);
701 }
702
703 p[0] = mask[0] & 0xf; p[0] |= p[0] << 4;
704 p[1] = mask[4] & 0xf; p[1] |= p[1] << 4;
705 p[2] = mask[8] & 0xf; p[2] |= p[2] << 4;
706 p[3] = mask[12] & 0xf; p[3] |= p[3] << 4;
707
708 for (k = 0 ; k < 8 ; k++)
709 for (j = 0 ; j < 4; j++)
710 for (i = 0 ; i < 4 ; i++)
711 if (*m++ != p[j]) {
712 return;
713 }
714
715 stipple = ( ((p[0] & 0xf) << 0) |
716 ((p[1] & 0xf) << 4) |
717 ((p[2] & 0xf) << 8) |
718 ((p[3] & 0xf) << 12) );
719
720 for (i = 0 ; i < 16 ; i++)
721 if (mgaStipples[i] == stipple) {
722 mmesa->poly_stipple = i<<20;
723 mmesa->haveHwStipple = 1;
724 break;
725 }
726
727 if (active) {
728 mmesa->setup.dwgctl &= ~(0xf<<20);
729 mmesa->setup.dwgctl |= mmesa->poly_stipple;
730 }
731 }
732
733 /* =============================================================
734 */
735
736 static void mgaDDPrintDirty( const char *msg, GLuint state )
737 {
738 fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s%s\n",
739 msg,
740 (unsigned int) state,
741 (state & MGA_WAIT_AGE) ? "wait-age, " : "",
742 (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img, " : "",
743 (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img, " : "",
744 (state & MGA_UPLOAD_CONTEXT) ? "upload-ctx, " : "",
745 (state & MGA_UPLOAD_TEX0) ? "upload-tex0, " : "",
746 (state & MGA_UPLOAD_TEX1) ? "upload-tex1, " : "",
747 (state & MGA_UPLOAD_PIPE) ? "upload-pipe, " : ""
748 );
749 }
750
751 /* Push the state into the sarea and/or texture memory.
752 */
753 void mgaEmitHwStateLocked( mgaContextPtr mmesa )
754 {
755 MGASAREAPrivPtr sarea = mmesa->sarea;
756
757 if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
758 mgaDDPrintDirty( "mgaEmitHwStateLocked", mmesa->dirty );
759
760 if ((mmesa->dirty & MGA_UPLOAD_TEX0IMAGE) && mmesa->CurrentTexObj[0])
761 mgaUploadTexImages(mmesa, mmesa->CurrentTexObj[0]);
762
763 if ((mmesa->dirty & MGA_UPLOAD_TEX1IMAGE) && mmesa->CurrentTexObj[1])
764 mgaUploadTexImages(mmesa, mmesa->CurrentTexObj[1]);
765
766 if (mmesa->dirty & MGA_UPLOAD_CONTEXT) {
767 memcpy( &sarea->ContextState, &mmesa->setup, sizeof(mmesa->setup));
768 }
769
770 if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
771 memcpy(&sarea->TexState[0],
772 &mmesa->CurrentTexObj[0]->setup,
773 sizeof(sarea->TexState[0]));
774 }
775
776 if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
777 memcpy(&sarea->TexState[1],
778 &mmesa->CurrentTexObj[1]->setup,
779 sizeof(sarea->TexState[1]));
780 }
781
782 if (sarea->TexState[0].texctl2 !=
783 sarea->TexState[1].texctl2) {
784 memcpy(&sarea->TexState[1],
785 &sarea->TexState[0],
786 sizeof(sarea->TexState[0]));
787 mmesa->dirty |= MGA_UPLOAD_TEX1|MGA_UPLOAD_TEX0;
788 }
789
790 if (mmesa->dirty & MGA_UPLOAD_PIPE) {
791 /* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
792 mmesa->sarea->WarpPipe = mmesa->vertex_format;
793 mmesa->sarea->vertsize = mmesa->vertex_size;
794 }
795
796 mmesa->sarea->dirty |= mmesa->dirty;
797
798 mmesa->dirty &= (MGA_UPLOAD_CLIPRECTS|MGA_WAIT_AGE);
799
800 /* This is a bit of a hack but seems to be the best place to ensure
801 * that separate specular is disabled when not needed.
802 */
803 if (mmesa->glCtx->Texture.Unit[0]._ReallyEnabled == 0 ||
804 !mmesa->glCtx->Light.Enabled ||
805 mmesa->glCtx->Light.Model.ColorControl == GL_SINGLE_COLOR) {
806 sarea->TexState[0].texctl2 &= ~TMC_specen_enable;
807 sarea->TexState[1].texctl2 &= ~TMC_specen_enable;
808 }
809 }
810
811 /* Fallback to swrast for select and feedback.
812 */
813 static void mgaRenderMode( GLcontext *ctx, GLenum mode )
814 {
815 FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
816 }
817
818
819 /* =============================================================
820 */
821
822 void mgaCalcViewport( GLcontext *ctx )
823 {
824 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
825 const GLfloat *v = ctx->Viewport._WindowMap.m;
826 GLfloat *m = mmesa->hw_viewport;
827
828 /* See also mga_translate_vertex.
829 */
830 m[MAT_SX] = v[MAT_SX];
831 m[MAT_TX] = v[MAT_TX] + mmesa->drawX + SUBPIXEL_X;
832 m[MAT_SY] = - v[MAT_SY];
833 m[MAT_TY] = - v[MAT_TY] + mmesa->driDrawable->h + mmesa->drawY + SUBPIXEL_Y;
834 m[MAT_SZ] = v[MAT_SZ] * mmesa->depth_scale;
835 m[MAT_TZ] = v[MAT_TZ] * mmesa->depth_scale;
836
837 mmesa->SetupNewInputs = ~0;
838 }
839
840 static void mgaViewport( GLcontext *ctx,
841 GLint x, GLint y,
842 GLsizei width, GLsizei height )
843 {
844 mgaCalcViewport( ctx );
845 }
846
847 static void mgaDepthRange( GLcontext *ctx,
848 GLclampd nearval, GLclampd farval )
849 {
850 mgaCalcViewport( ctx );
851 }
852
853 /* =============================================================
854 */
855
856 static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
857 {
858 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
859
860 switch(cap) {
861 case GL_ALPHA_TEST:
862 FLUSH_BATCH( mmesa );
863 mmesa->new_state |= MGA_NEW_ALPHA;
864 break;
865 case GL_BLEND:
866 FLUSH_BATCH( mmesa );
867 mmesa->new_state |= MGA_NEW_ALPHA;
868
869 /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
870 */
871 FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
872 (ctx->Color.ColorLogicOpEnabled &&
873 ctx->Color.LogicOp != GL_COPY));
874 break;
875 case GL_DEPTH_TEST:
876 FLUSH_BATCH( mmesa );
877 mmesa->new_state |= MGA_NEW_DEPTH;
878 FALLBACK (ctx, MGA_FALLBACK_DEPTH,
879 ctx->Depth.Func == GL_NEVER && ctx->Depth.Test);
880 break;
881 case GL_SCISSOR_TEST:
882 FLUSH_BATCH( mmesa );
883 mmesa->scissor = state;
884 mmesa->new_state |= MGA_NEW_CLIP;
885 break;
886 case GL_FOG:
887 MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
888 if (ctx->Fog.Enabled)
889 mmesa->setup.maccess |= MA_fogen_enable;
890 else
891 mmesa->setup.maccess &= ~MA_fogen_enable;
892 break;
893 case GL_CULL_FACE:
894 FLUSH_BATCH( mmesa );
895 mmesa->new_state |= MGA_NEW_CULL;
896 break;
897 case GL_TEXTURE_1D:
898 case GL_TEXTURE_2D:
899 case GL_TEXTURE_3D:
900 FLUSH_BATCH( mmesa );
901 mmesa->new_state |= (MGA_NEW_TEXTURE|MGA_NEW_ALPHA);
902 break;
903 case GL_POLYGON_STIPPLE:
904 if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) {
905 FLUSH_BATCH(mmesa);
906 mmesa->dirty |= MGA_UPLOAD_CONTEXT;
907 mmesa->setup.dwgctl &= ~(0xf<<20);
908 if (state)
909 mmesa->setup.dwgctl |= mmesa->poly_stipple;
910 }
911 break;
912 case GL_COLOR_LOGIC_OP:
913 FLUSH_BATCH( mmesa );
914 #if !defined(ACCEL_ROP)
915 FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
916 (state && ctx->Color.LogicOp != GL_COPY));
917 #else
918 mmesa->new_state |= MGA_NEW_DEPTH;
919 #endif
920 break;
921 case GL_STENCIL_TEST:
922 FLUSH_BATCH( mmesa );
923 if (mmesa->hw_stencil)
924 mmesa->new_state |= MGA_NEW_STENCIL;
925 else
926 FALLBACK( ctx, MGA_FALLBACK_STENCIL, state );
927 default:
928 break;
929 }
930 }
931
932
933 /* =============================================================
934 */
935
936
937
938 /* =============================================================
939 */
940
941 static void mgaDDPrintState( const char *msg, GLuint state )
942 {
943 fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s\n",
944 msg,
945 state,
946 (state & MGA_NEW_DEPTH) ? "depth, " : "",
947 (state & MGA_NEW_ALPHA) ? "alpha, " : "",
948 (state & MGA_NEW_CLIP) ? "clip, " : "",
949 (state & MGA_NEW_CULL) ? "cull, " : "",
950 (state & MGA_NEW_TEXTURE) ? "texture, " : "",
951 (state & MGA_NEW_CONTEXT) ? "context, " : "");
952 }
953
954 void mgaDDUpdateHwState( GLcontext *ctx )
955 {
956 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
957 int new_state = mmesa->new_state;
958
959 if (new_state)
960 {
961 FLUSH_BATCH( mmesa );
962
963 mmesa->new_state = 0;
964
965 if (MESA_VERBOSE&VERBOSE_DRIVER)
966 mgaDDPrintState("UpdateHwState", new_state);
967
968 if (new_state & MGA_NEW_DEPTH)
969 mgaUpdateZMode(ctx);
970
971 if (new_state & MGA_NEW_ALPHA)
972 mgaUpdateAlphaMode(ctx);
973
974 if (new_state & MGA_NEW_CLIP)
975 mgaUpdateClipping(ctx);
976
977 if (new_state & MGA_NEW_STENCIL)
978 mgaUpdateStencil(ctx);
979
980 if (new_state & (MGA_NEW_WARP|MGA_NEW_CULL))
981 mgaUpdateCull(ctx);
982
983 if (new_state & (MGA_NEW_WARP|MGA_NEW_TEXTURE))
984 mgaUpdateTextureState(ctx);
985 }
986 }
987
988
989 static void mgaDDInvalidateState( GLcontext *ctx, GLuint new_state )
990 {
991 _swrast_InvalidateState( ctx, new_state );
992 _swsetup_InvalidateState( ctx, new_state );
993 _ac_InvalidateState( ctx, new_state );
994 _tnl_InvalidateState( ctx, new_state );
995 MGA_CONTEXT(ctx)->new_gl_state |= new_state;
996 }
997
998
999
1000 void mgaInitState( mgaContextPtr mmesa )
1001 {
1002 mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
1003 GLcontext *ctx = mmesa->glCtx;
1004
1005 if (ctx->Color._DrawDestMask == BACK_LEFT_BIT) {
1006 mmesa->draw_buffer = MGA_BACK;
1007 mmesa->read_buffer = MGA_BACK;
1008 mmesa->drawOffset = mmesa->mgaScreen->backOffset;
1009 mmesa->readOffset = mmesa->mgaScreen->backOffset;
1010 mmesa->setup.dstorg = mgaScreen->backOffset;
1011 } else {
1012 mmesa->draw_buffer = MGA_FRONT;
1013 mmesa->read_buffer = MGA_FRONT;
1014 mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
1015 mmesa->readOffset = mmesa->mgaScreen->frontOffset;
1016 mmesa->setup.dstorg = mgaScreen->frontOffset;
1017 }
1018
1019 mmesa->setup.maccess = (MA_memreset_disable |
1020 MA_fogen_disable |
1021 MA_tlutload_disable |
1022 MA_nodither_disable |
1023 MA_dit555_disable);
1024
1025 switch (mmesa->mgaScreen->cpp) {
1026 case 2:
1027 mmesa->setup.maccess |= MA_pwidth_16;
1028 break;
1029 case 4:
1030 mmesa->setup.maccess |= MA_pwidth_32;
1031 break;
1032 default:
1033 fprintf( stderr, "Error: unknown cpp %d, exiting...\n",
1034 mmesa->mgaScreen->cpp );
1035 exit( 1 );
1036 }
1037
1038 switch (mmesa->glCtx->Visual.depthBits) {
1039 case 16:
1040 mmesa->setup.maccess |= MA_zwidth_16;
1041 break;
1042 case 24:
1043 mmesa->setup.maccess |= MA_zwidth_24;
1044 break;
1045 case 32:
1046 mmesa->setup.maccess |= MA_pwidth_32;
1047 break;
1048 }
1049
1050 mmesa->setup.dwgctl = (DC_opcod_trap |
1051 DC_atype_i |
1052 DC_linear_xy |
1053 DC_zmode_nozcmp |
1054 DC_solid_disable |
1055 DC_arzero_disable |
1056 DC_sgnzero_disable |
1057 DC_shftzero_enable |
1058 (0xC << DC_bop_SHIFT) |
1059 (0x0 << DC_trans_SHIFT) |
1060 DC_bltmod_bmonolef |
1061 DC_pattern_disable |
1062 DC_transc_disable |
1063 DC_clipdis_disable);
1064
1065
1066 mmesa->setup.plnwt = ~0;
1067 mmesa->setup.alphactrl = ( AC_src_one |
1068 AC_dst_zero |
1069 AC_amode_FCOL |
1070 AC_astipple_disable |
1071 AC_aten_disable |
1072 AC_atmode_noacmp |
1073 AC_alphasel_fromtex );
1074
1075 mmesa->setup.fogcolor =
1076 MGAPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F),
1077 (GLubyte)(ctx->Fog.Color[1]*255.0F),
1078 (GLubyte)(ctx->Fog.Color[2]*255.0F));
1079
1080 mmesa->setup.wflag = 0;
1081 mmesa->setup.tdualstage0 = 0;
1082 mmesa->setup.tdualstage1 = 0;
1083 mmesa->setup.fcol = 0;
1084 mmesa->new_state = ~0;
1085 }
1086
1087
1088 void mgaDDInitStateFuncs( GLcontext *ctx )
1089 {
1090 ctx->Driver.UpdateState = mgaDDInvalidateState;
1091 ctx->Driver.Enable = mgaDDEnable;
1092 ctx->Driver.LightModelfv = mgaDDLightModelfv;
1093 ctx->Driver.AlphaFunc = mgaDDAlphaFunc;
1094 ctx->Driver.BlendEquation = mgaDDBlendEquation;
1095 ctx->Driver.BlendFunc = mgaDDBlendFunc;
1096 ctx->Driver.BlendFuncSeparate = mgaDDBlendFuncSeparate;
1097 ctx->Driver.DepthFunc = mgaDDDepthFunc;
1098 ctx->Driver.DepthMask = mgaDDDepthMask;
1099 ctx->Driver.Fogfv = mgaDDFogfv;
1100 ctx->Driver.Scissor = mgaDDScissor;
1101 ctx->Driver.ShadeModel = mgaDDShadeModel;
1102 ctx->Driver.CullFace = mgaDDCullFaceFrontFace;
1103 ctx->Driver.FrontFace = mgaDDCullFaceFrontFace;
1104 ctx->Driver.ColorMask = mgaDDColorMask;
1105
1106 ctx->Driver.DrawBuffer = mgaDDSetDrawBuffer;
1107 ctx->Driver.ReadBuffer = mgaDDSetReadBuffer;
1108 ctx->Driver.ClearColor = mgaDDClearColor;
1109 ctx->Driver.ClearDepth = mgaDDClearDepth;
1110 ctx->Driver.LogicOpcode = mgaDDLogicOp;
1111
1112 ctx->Driver.PolygonStipple = mgaDDPolygonStipple;
1113
1114 ctx->Driver.StencilFunc = mgaDDStencilFunc;
1115 ctx->Driver.StencilMask = mgaDDStencilMask;
1116 ctx->Driver.StencilOp = mgaDDStencilOp;
1117
1118 ctx->Driver.DepthRange = mgaDepthRange;
1119 ctx->Driver.Viewport = mgaViewport;
1120 ctx->Driver.RenderMode = mgaRenderMode;
1121
1122 ctx->Driver.ClearIndex = 0;
1123 ctx->Driver.IndexMask = 0;
1124
1125 /* Swrast hooks for imaging extensions:
1126 */
1127 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
1128 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
1129 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
1130 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
1131 }