Tizen 2.0 Release
[profile/ivi/osmesa.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 }