Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / mga / mga_texstate.c
1 /*
2  * Copyright 2000-2001 VA Linux Systems, Inc.
3  * (c) Copyright IBM Corporation 2002
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * on the rights to use, copy, modify, merge, publish, distribute, sub
10  * license, and/or sell copies of the Software, and to permit persons to whom
11  * the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
20  * VA LINUX SYSTEMS, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23  * USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Ian Romanick <idr@us.ibm.com>
27  *    Keith Whitwell <keithw@tungstengraphics.com>
28  */
29
30 #include "main/context.h"
31 #include "main/enums.h"
32 #include "main/macros.h"
33 #include "main/mm.h"
34 #include "main/imports.h"
35 #include "main/simple_list.h"
36
37 #include "mgacontext.h"
38 #include "mgatex.h"
39 #include "mgaregs.h"
40 #include "mgatris.h"
41 #include "mgaioctl.h"
42
43 #define MGA_USE_TABLE_FOR_FORMAT
44 #ifdef MGA_USE_TABLE_FOR_FORMAT
45 #define TMC_nr_tformat (MESA_FORMAT_YCBCR_REV + 1)
46 static const unsigned TMC_tformat[ TMC_nr_tformat ] =
47 {
48     [MESA_FORMAT_ARGB8888] = TMC_tformat_tw32,
49     [MESA_FORMAT_RGB565]   = TMC_tformat_tw16,
50     [MESA_FORMAT_ARGB4444] = TMC_tformat_tw12,
51     [MESA_FORMAT_ARGB1555] = TMC_tformat_tw15,
52     [MESA_FORMAT_AL88]     = TMC_tformat_tw8al,
53     [MESA_FORMAT_I8]       = TMC_tformat_tw8a,
54     [MESA_FORMAT_CI8]      = TMC_tformat_tw8 ,
55     [MESA_FORMAT_YCBCR]     = TMC_tformat_tw422uyvy,
56     [MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422,
57 };
58 #endif
59
60 static void
61 mgaSetTexImages( mgaContextPtr mmesa,
62                  const struct gl_texture_object * tObj )
63 {
64     mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
65     struct gl_texture_image *baseImage = tObj->Image[0][ tObj->BaseLevel ];
66     GLint totalSize;
67     GLint width, height;
68     GLint i;
69     GLint numLevels;
70     GLint log2Width, log2Height;
71     GLuint txformat = 0;
72     GLint ofs;
73
74     /* Set the hardware texture format
75      */
76 #ifndef MGA_USE_TABLE_FOR_FORMAT
77     switch (baseImage->TexFormat->MesaFormat) {
78
79         case MESA_FORMAT_ARGB8888: txformat = TMC_tformat_tw32; break;
80         case MESA_FORMAT_RGB565:   txformat = TMC_tformat_tw16; break;
81         case MESA_FORMAT_ARGB4444: txformat = TMC_tformat_tw12; break;
82         case MESA_FORMAT_ARGB1555: txformat = TMC_tformat_tw15; break;
83         case MESA_FORMAT_AL88:     txformat = TMC_tformat_tw8al; break;
84         case MESA_FORMAT_I8:       txformat = TMC_tformat_tw8a; break;
85         case MESA_FORMAT_CI8:      txformat = TMC_tformat_tw8;  break;
86         case MESA_FORMAT_YCBCR:    txformat  = TMC_tformat_tw422uyvy; break;
87         case MESA_FORMAT_YCBCR_REV: txformat = TMC_tformat_tw422; break;
88
89         default:
90         _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
91         return;
92     }
93 #else
94     if ( (baseImage->TexFormat >= TMC_nr_tformat)
95          || (TMC_tformat[ baseImage->TexFormat ] == 0) )
96     {
97         _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
98         return;
99     }
100
101     txformat = TMC_tformat[ baseImage->TexFormat ];
102
103 #endif /* MGA_USE_TABLE_FOR_FORMAT */
104
105    driCalculateTextureFirstLastLevel( (driTextureObject *) t );
106    if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
107       log2Width = 0;
108       log2Height = 0;
109    } else {
110       log2Width  = tObj->Image[0][t->base.firstLevel]->WidthLog2;
111       log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
112    }
113
114    width = tObj->Image[0][t->base.firstLevel]->Width;
115    height = tObj->Image[0][t->base.firstLevel]->Height;
116
117    numLevels = MIN2( t->base.lastLevel - t->base.firstLevel + 1,
118                      MGA_IS_G200(mmesa) ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS);
119
120
121    totalSize = 0;
122    for ( i = 0 ; i < numLevels ; i++ ) {
123       const struct gl_texture_image * const texImage = 
124           tObj->Image[0][ i + t->base.firstLevel ];
125       int size;
126
127       if (texImage == NULL)
128          break;
129
130       size = texImage->Width * texImage->Height *
131          _mesa_get_format_bytes(baseImage->TexFormat);
132
133       t->offsets[i] = totalSize;
134       t->base.dirty_images[0] |= (1<<i);
135
136       /* All mipmaps must be 32-byte aligned */
137       totalSize += (size + 31) & ~31;
138
139       /* Since G400 calculates the offsets in hardware
140        * it can't handle more than one < 32 byte mipmap.
141        *
142        * Further testing has indicated that it can't
143        * handle any < 32 byte mipmaps.
144        */
145       if (MGA_IS_G400( mmesa ) && size <= 32) {
146          i++;
147          break;
148       }
149    }
150
151    /* save these values */
152    numLevels = i;
153    t->base.lastLevel = t->base.firstLevel + numLevels - 1;
154    t->base.totalSize = totalSize;
155
156    /* setup hardware register values */
157    t->setup.texctl &= (TMC_tformat_MASK & TMC_tpitch_MASK 
158                        & TMC_tpitchext_MASK);
159    t->setup.texctl |= txformat;
160
161
162    /* Set the texture width.  In order to support non-power of 2 textures and
163     * textures larger than 1024 texels wide, "linear" pitch must be used.  For
164     * the linear pitch, if the width is 2048, a value of zero is used.
165     */
166
167    t->setup.texctl |= TMC_tpitchlin_enable;
168    t->setup.texctl |= MGA_FIELD( TMC_tpitchext, width & (2048 - 1) );
169
170
171    /* G400 specifies the number of mip levels in a strange way.  Since there
172     * are up to 11 levels, it requires 4 bits.  Three of the bits are at the
173     * high end of TEXFILTER.  The other bit is in the middle.  Weird.
174     */
175    numLevels--;
176    t->setup.texfilter &= TF_mapnb_MASK & TF_mapnbhigh_MASK & TF_reserved_MASK;
177    t->setup.texfilter |= MGA_FIELD( TF_mapnb, numLevels & 0x7 );
178    t->setup.texfilter |= MGA_FIELD( TF_mapnbhigh, (numLevels >> 3) & 0x1 );
179
180    /* warp texture registers */
181    ofs = MGA_IS_G200(mmesa) ? 28 : 11;
182
183    t->setup.texwidth = (MGA_FIELD(TW_twmask, width - 1) |
184                         MGA_FIELD(TW_rfw, (10 - log2Width - 8) & 63 ) |
185                         MGA_FIELD(TW_tw, (log2Width + ofs ) | 0x40 ));
186
187    t->setup.texheight = (MGA_FIELD(TH_thmask, height - 1) |
188                          MGA_FIELD(TH_rfh, (10 - log2Height - 8) & 63 ) |
189                          MGA_FIELD(TH_th, (log2Height + ofs ) | 0x40 ));
190
191    mgaUploadTexImages( mmesa, t );
192 }
193
194
195 /* ================================================================
196  * Texture unit state management
197  */
198
199 static void mgaUpdateTextureEnvG200( struct gl_context *ctx, GLuint unit )
200 {
201    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
202    struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
203    mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
204    GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
205
206    if (tObj != ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX] &&
207        tObj != ctx->Texture.Unit[0].CurrentTex[TEXTURE_RECT_INDEX])
208       return;
209
210
211    t->setup.texctl &= ~TMC_tmodulate_enable;
212    t->setup.texctl2 &= ~(TMC_decalblend_enable |
213                          TMC_idecal_enable |
214                          TMC_decaldis_enable);
215
216    switch (ctx->Texture.Unit[0].EnvMode) {
217    case GL_REPLACE:
218       if (format == GL_ALPHA)
219          t->setup.texctl2 |= TMC_idecal_enable;
220
221       if (format == GL_RGB || format == GL_LUMINANCE)
222          mmesa->hw.alpha_sel = AC_alphasel_diffused;
223       else
224          mmesa->hw.alpha_sel = AC_alphasel_fromtex;
225       break;
226
227    case GL_MODULATE:
228       t->setup.texctl |= TMC_tmodulate_enable;
229
230       if (format == GL_ALPHA)
231          t->setup.texctl2 |= (TMC_idecal_enable |
232                               TMC_decaldis_enable);
233
234       if (format == GL_RGB || format == GL_LUMINANCE)
235          mmesa->hw.alpha_sel = AC_alphasel_diffused;
236       else
237          mmesa->hw.alpha_sel = AC_alphasel_modulated;
238       break;
239
240    case GL_DECAL:
241       if (format == GL_RGB || format == GL_RGBA)
242          t->setup.texctl2 |= TMC_decalblend_enable;
243       else
244          t->setup.texctl2 |= TMC_idecal_enable;
245
246       mmesa->hw.alpha_sel = AC_alphasel_diffused;
247       break;
248
249    case GL_BLEND:
250       if (format == GL_ALPHA) {
251          t->setup.texctl2 |= TMC_idecal_enable;
252          mmesa->hw.alpha_sel = AC_alphasel_modulated;
253       } else {
254          t->texenv_fallback = GL_TRUE;
255       }
256       break;
257
258    default:
259       break;
260    }
261 }
262
263
264 #define MGA_REPLACE             0
265 #define MGA_MODULATE            1
266 #define MGA_DECAL               2
267 #define MGA_ADD                 3
268 #define MGA_MAX_COMBFUNC        4
269
270 static const GLuint g400_color_combine[][MGA_MAX_COMBFUNC] =
271 {
272    /* Unit 0:
273     */
274    {
275       /* GL_REPLACE
276        * Cv = Cs
277        * Av = Af
278        */
279       (TD0_color_sel_arg1 |
280        TD0_alpha_arg2_diffuse |
281        TD0_alpha_sel_arg2),
282       
283       /* GL_MODULATE
284        * Cv = Cf Cs
285        * Av = Af
286        */
287       (TD0_color_arg2_diffuse |
288        TD0_color_sel_mul |
289        TD0_alpha_arg2_diffuse |
290        TD0_alpha_sel_arg2),
291       
292       /* GL_DECAL
293        * Cv = Cs
294        * Av = Af
295        */
296       (TD0_color_sel_arg1 |
297        TD0_alpha_arg2_diffuse |
298        TD0_alpha_sel_arg2),
299       
300       /* GL_ADD
301        * Cv = Cf + Cs
302        * Av = Af
303        */
304       (TD0_color_arg2_diffuse |
305        TD0_color_add_add |
306        TD0_color_sel_add |
307        TD0_alpha_arg2_diffuse |
308        TD0_alpha_sel_arg2),
309    },
310    
311    /* Unit 1:
312     */
313    {
314       /* GL_REPLACE
315        * Cv = Cs
316        * Av = Ap
317        */
318       (TD0_color_sel_arg1 |
319        TD0_alpha_arg2_prevstage |
320        TD0_alpha_sel_arg2),
321       
322       /* GL_MODULATE
323        * Cv = Cp Cs
324        * Av = Ap
325        */
326       (TD0_color_arg2_prevstage |
327        TD0_color_sel_mul |
328        TD0_alpha_arg2_prevstage |
329        TD0_alpha_sel_arg2),
330
331       /* GL_DECAL
332        * Cv = Cs
333        * Av = Ap
334        */
335       (TD0_color_sel_arg1 |
336        TD0_alpha_arg2_prevstage |
337        TD0_alpha_sel_arg2),
338       
339       /* GL_ADD
340        * Cv = Cp + Cs
341        * Av = Ap
342        */
343       (TD0_color_arg2_prevstage |
344        TD0_color_add_add |
345        TD0_color_sel_add |
346        TD0_alpha_arg2_prevstage |
347        TD0_alpha_sel_arg2),
348    },
349 };
350
351 static const GLuint g400_color_alpha_combine[][MGA_MAX_COMBFUNC] =
352 {
353    /* Unit 0:
354     */
355    {
356       /* GL_REPLACE
357        * Cv = Cs
358        * Av = As
359        */
360       (TD0_color_sel_arg1 |
361        TD0_alpha_sel_arg1),
362       
363       /* GL_MODULATE
364        * Cv = Cf Cs
365        * Av = Af As
366        */
367       (TD0_color_arg2_diffuse |
368        TD0_color_sel_mul |
369        TD0_alpha_arg2_diffuse |
370        TD0_alpha_sel_mul),
371       
372       /* GL_DECAL
373        * tmp = Cf ( 1 - As )
374        * Cv = tmp + Cs As
375        * Av = Af
376        */
377       (TD0_color_arg2_diffuse |
378        TD0_color_alpha_currtex |
379        TD0_color_alpha1inv_enable |
380        TD0_color_arg1mul_alpha1 |
381        TD0_color_blend_enable |
382        TD0_color_arg1add_mulout |
383        TD0_color_arg2add_mulout |
384        TD0_color_add_add |
385        TD0_color_sel_add |
386        TD0_alpha_arg2_diffuse |
387        TD0_alpha_sel_arg2),
388
389       /* GL_ADD
390        * Cv = Cf + Cs
391        * Av = Af As
392        */
393       (TD0_color_arg2_diffuse |
394        TD0_color_add_add |
395        TD0_color_sel_add |
396        TD0_alpha_arg2_diffuse |
397        TD0_alpha_sel_mul),
398    },
399    
400    /* Unit 1:
401     */
402    {
403       /* GL_REPLACE
404        * Cv = Cs
405        * Av = As
406        */
407       (TD0_color_sel_arg1 |
408        TD0_alpha_sel_arg1),
409       
410       /* GL_MODULATE
411        * Cv = Cp Cs
412        * Av = Ap As
413        */
414       (TD0_color_arg2_prevstage |
415        TD0_color_sel_mul |
416        TD0_alpha_arg2_prevstage |
417        TD0_alpha_sel_mul),
418
419       /* GL_DECAL
420        * tmp = Cp ( 1 - As )
421        * Cv = tmp + Cs As
422        * Av = Ap
423        */
424       (TD0_color_arg2_prevstage |
425        TD0_color_alpha_currtex |
426        TD0_color_alpha1inv_enable |
427        TD0_color_arg1mul_alpha1 |
428        TD0_color_blend_enable |
429        TD0_color_arg1add_mulout |
430        TD0_color_arg2add_mulout |
431        TD0_color_add_add |
432        TD0_color_sel_add |
433        TD0_alpha_arg2_prevstage |
434        TD0_alpha_sel_arg2),
435       
436       /* GL_ADD
437        * Cv = Cp + Cs
438        * Av = Ap As
439        */
440       (TD0_color_arg2_prevstage |
441        TD0_color_add_add |
442        TD0_color_sel_add |
443        TD0_alpha_arg2_prevstage |
444        TD0_alpha_sel_mul),
445    },
446 };
447
448 static const GLuint g400_alpha_combine[][MGA_MAX_COMBFUNC] =
449 {
450    /* Unit 0:
451     */
452    {
453       /* GL_REPLACE
454        * Cv = Cf
455        * Av = As
456        */
457       (TD0_color_arg2_diffuse |
458        TD0_color_sel_arg2 |
459        TD0_alpha_sel_arg1),
460       
461       /* GL_MODULATE
462        * Cv = Cf
463        * Av = Af As
464        */
465       (TD0_color_arg2_diffuse |
466        TD0_color_sel_arg2 |
467        TD0_alpha_arg2_diffuse |
468        TD0_alpha_sel_mul),
469
470       /* GL_DECAL (undefined)
471        * Cv = Cf
472        * Av = Af
473        */
474       (TD0_color_arg2_diffuse |
475        TD0_color_sel_arg2 |
476        TD0_alpha_arg2_diffuse |
477        TD0_alpha_sel_arg2),
478
479       /* GL_ADD
480        * Cv = Cf
481        * Av = Af As
482        */
483       (TD0_color_arg2_diffuse |
484        TD0_color_sel_arg2 |
485        TD0_alpha_arg2_diffuse |
486        TD0_alpha_sel_mul),
487    },
488
489    /* Unit 1:
490     */
491    {
492       /* GL_REPLACE
493        * Cv = Cp
494        * Av = As
495        */
496       (TD0_color_arg2_prevstage |
497        TD0_color_sel_arg2 |
498        TD0_alpha_sel_arg1),
499       
500       /* GL_MODULATE
501        * Cv = Cp
502        * Av = Ap As
503        */
504       (TD0_color_arg2_prevstage |
505        TD0_color_sel_arg2 |
506        TD0_alpha_arg2_prevstage |
507        TD0_alpha_sel_mul),
508
509       /* GL_DECAL (undefined)
510        * Cv = Cp
511        * Av = Ap
512        */
513       (TD0_color_arg2_prevstage |
514        TD0_color_sel_arg2 |
515        TD0_alpha_arg2_prevstage |
516        TD0_alpha_sel_arg2),
517
518       /* GL_ADD
519        * Cv = Cp
520        * Av = Ap As
521        */
522       (TD0_color_arg2_prevstage |
523        TD0_color_sel_arg2 |
524        TD0_alpha_arg2_prevstage |
525        TD0_alpha_sel_mul),
526    },
527 };
528
529 static GLboolean mgaUpdateTextureEnvBlend( struct gl_context *ctx, int unit )
530 {
531    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
532    const int source = mmesa->tmu_source[unit];
533    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
534    const struct gl_texture_object *tObj = texUnit->_Current;
535    GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
536    GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
537
538    *reg = 0;
539
540    if (format == GL_ALPHA) {
541       /* Cv = Cf */
542       *reg |= (TD0_color_arg2_diffuse |
543                TD0_color_sel_arg2);
544       /* Av = Af As */
545       *reg |= (TD0_alpha_arg2_diffuse |
546                TD0_alpha_sel_mul);
547       return GL_TRUE;
548    }
549
550    /* C1 = Cf ( 1 - Cs ) */
551    *reg |= (TD0_color_arg1_inv_enable |
552             TD0_color_arg2_diffuse |
553             TD0_color_sel_mul);
554
555    if (format == GL_RGB || format == GL_LUMINANCE) {
556       /* A1 = Af */
557       *reg |= (TD0_alpha_arg2_diffuse |
558                TD0_alpha_sel_arg2);
559    } else
560    if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) {
561       /* A1 = Af As */
562       *reg |= (TD0_alpha_arg2_diffuse |
563                TD0_alpha_sel_mul);
564    } else
565    if (format == GL_INTENSITY) {
566       /* A1 = Af ( 1 - As ) */
567       *reg |= (TD0_alpha_arg1_inv_enable |
568                TD0_alpha_arg2_diffuse |
569                TD0_alpha_sel_mul);
570    }
571    
572    if (RGB_ZERO(mmesa->envcolor[source]) &&
573        (format != GL_INTENSITY || ALPHA_ZERO(mmesa->envcolor[source])))
574       return GL_TRUE; /* all done */
575
576    if (ctx->Texture._EnabledUnits == 0x03)
577       return GL_FALSE; /* need both units */
578
579    mmesa->force_dualtex = GL_TRUE;
580    reg = &mmesa->setup.tdualstage1;
581    *reg = 0;
582
583    if (RGB_ZERO(mmesa->envcolor[source])) {
584       /* Cv = C1 */
585       *reg |= (TD0_color_arg2_prevstage |
586                TD0_color_sel_arg2);
587    } else
588    if (RGB_ONE(mmesa->envcolor[source])) {
589       /* Cv = C1 + Cs */
590       *reg |= (TD0_color_arg2_prevstage |
591                TD0_color_add_add |
592                TD0_color_sel_add);
593    } else
594    if (RGBA_EQUAL(mmesa->envcolor[source])) {
595       /* Cv = C1 + Cc Cs */
596       *reg |= (TD0_color_arg2_prevstage |
597                TD0_color_alpha_fcol |
598                TD0_color_arg2mul_alpha2 |
599                TD0_color_arg1add_mulout |
600                TD0_color_add_add |
601                TD0_color_sel_add);
602
603       mmesa->setup.fcol = mmesa->envcolor[source];
604    } else {
605       return GL_FALSE;
606    }
607
608    if (format != GL_INTENSITY || ALPHA_ZERO(mmesa->envcolor[source])) {
609       /* Av = A1 */
610       *reg |= (TD0_alpha_arg2_prevstage |
611                TD0_alpha_sel_arg2);
612    } else
613    if (ALPHA_ONE(mmesa->envcolor[source])) {
614       /* Av = A1 + As */
615       *reg |= (TD0_alpha_arg2_prevstage |
616                TD0_alpha_add_enable |
617                TD0_alpha_sel_add);
618    } else {
619       return GL_FALSE;
620    }
621
622    return GL_TRUE;
623 }
624
625 static void mgaUpdateTextureEnvG400( struct gl_context *ctx, GLuint unit )
626 {
627    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
628    const int source = mmesa->tmu_source[unit];
629    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
630    const struct gl_texture_object *tObj = texUnit->_Current;
631    GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
632    mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
633    GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
634
635    if (tObj != ctx->Texture.Unit[source].CurrentTex[TEXTURE_2D_INDEX] &&
636        tObj != ctx->Texture.Unit[source].CurrentTex[TEXTURE_RECT_INDEX])
637       return;
638
639    switch (ctx->Texture.Unit[source].EnvMode) {
640    case GL_REPLACE:
641       if (format == GL_ALPHA) {
642          *reg = g400_alpha_combine[unit][MGA_REPLACE];
643       } else if (format == GL_RGB || format == GL_LUMINANCE) {
644          *reg = g400_color_combine[unit][MGA_REPLACE];
645       } else {
646          *reg = g400_color_alpha_combine[unit][MGA_REPLACE];
647       }
648       break;
649
650    case GL_MODULATE:
651       if (format == GL_ALPHA) {
652          *reg = g400_alpha_combine[unit][MGA_MODULATE];
653       } else if (format == GL_RGB || format == GL_LUMINANCE) {
654          *reg = g400_color_combine[unit][MGA_MODULATE];
655       } else {
656          *reg = g400_color_alpha_combine[unit][MGA_MODULATE];
657       }
658       break;
659
660    case GL_DECAL:
661       if (format == GL_RGB) {
662          *reg = g400_color_combine[unit][MGA_DECAL];
663       } else if (format == GL_RGBA) {
664          *reg = g400_color_alpha_combine[unit][MGA_DECAL];
665          if (ctx->Texture._EnabledUnits != 0x03) {
666             /* Linear blending mode needs dual texturing enabled */
667             *(reg+1) = (TD0_color_arg2_prevstage |
668                         TD0_color_sel_arg2 |
669                         TD0_alpha_arg2_prevstage |
670                         TD0_alpha_sel_arg2);
671             mmesa->force_dualtex = GL_TRUE;
672          }
673       } else {
674          /* Undefined */
675          *reg = g400_alpha_combine[unit][MGA_DECAL];
676       }
677       break;
678
679    case GL_ADD:
680       if (format == GL_ALPHA) {
681          *reg = g400_alpha_combine[unit][MGA_ADD];
682       } else if (format == GL_RGB || format == GL_LUMINANCE) {
683          *reg = g400_color_combine[unit][MGA_ADD];
684       } else if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) {
685          *reg = g400_color_alpha_combine[unit][MGA_ADD];
686       } else if (format == GL_INTENSITY) {
687          /* Cv = Cf + Cs
688           * Av = Af + As
689           */
690          if (unit == 0) {
691             *reg = (TD0_color_arg2_diffuse |
692                     TD0_color_add_add |
693                     TD0_color_sel_add |
694                     TD0_alpha_arg2_diffuse |
695                     TD0_alpha_add_enable |
696                     TD0_alpha_sel_add);
697          } else {
698             *reg = (TD0_color_arg2_prevstage |
699                     TD0_color_add_add |
700                     TD0_color_sel_add |
701                     TD0_alpha_arg2_prevstage |
702                     TD0_alpha_add_enable |
703                     TD0_alpha_sel_add);
704          }
705       }
706       break;
707
708    case GL_BLEND:
709       if (!mgaUpdateTextureEnvBlend(ctx, unit))
710          t->texenv_fallback = GL_TRUE;
711       break;
712
713    case GL_COMBINE:
714       if (!mgaUpdateTextureEnvCombine(ctx, unit))
715          t->texenv_fallback = GL_TRUE;
716       break;
717    default:
718       break;
719    }
720 }
721
722 static void disable_tex( struct gl_context *ctx, int unit )
723 {
724    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
725
726    /* Texture unit disabled */
727
728    if ( mmesa->CurrentTexObj[unit] != NULL ) {
729       /* The old texture is no longer bound to this texture unit.
730        * Mark it as such.
731        */
732
733       mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
734       mmesa->CurrentTexObj[unit] = NULL;
735    }
736
737    if ( unit != 0 && !mmesa->force_dualtex ) {
738       mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
739    }
740
741    if ( ctx->Texture._EnabledUnits == 0 ) {
742       mmesa->setup.dwgctl &= DC_opcod_MASK;
743       mmesa->setup.dwgctl |= DC_opcod_trap;
744       mmesa->hw.alpha_sel = AC_alphasel_diffused;
745    }
746
747    mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
748 }
749
750 static GLboolean enable_tex( struct gl_context *ctx, int unit )
751 {
752    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
753    const int source = mmesa->tmu_source[unit];
754    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
755    const struct gl_texture_object *tObj = texUnit->_Current;
756    mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
757
758    /* Upload teximages (not pipelined)
759     */
760    if (t->base.dirty_images[0]) {
761       FLUSH_BATCH( mmesa );
762       mgaSetTexImages( mmesa, tObj );
763       if ( t->base.memBlock == NULL ) {
764          return GL_FALSE;
765       }
766    }
767
768    return GL_TRUE;
769 }
770
771 static GLboolean update_tex_common( struct gl_context *ctx, int unit )
772 {
773    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
774    const int source = mmesa->tmu_source[unit];
775    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
776    struct gl_texture_object     *tObj = texUnit->_Current;
777    mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
778
779    /* Fallback if there's a texture border */
780    if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
781       return GL_FALSE;
782    }
783
784
785    /* Update state if this is a different texture object to last
786     * time.
787     */
788    if ( mmesa->CurrentTexObj[unit] != t ) {
789       if ( mmesa->CurrentTexObj[unit] != NULL ) {
790          /* The old texture is no longer bound to this texture unit.
791           * Mark it as such.
792           */
793
794          mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
795       }
796
797       mmesa->CurrentTexObj[unit] = t;
798       t->base.bound |= (1UL << unit);
799
800       driUpdateTextureLRU( (driTextureObject *) t ); /* done too often */
801    }
802
803    /* register setup */
804    if ( unit == 1 ) {
805       mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
806    }
807
808    t->texenv_fallback = GL_FALSE;
809
810    /* Set this before mgaUpdateTextureEnvG400() since
811     * GL_ARB_texture_env_crossbar may have to disable texturing.
812     */
813    mmesa->setup.dwgctl &= DC_opcod_MASK;
814    mmesa->setup.dwgctl |= DC_opcod_texture_trap;
815
816    /* FIXME: The Radeon has some cached state so that it can avoid calling
817     * FIXME: UpdateTextureEnv in some cases.  Is that possible here?
818     */
819    if (MGA_IS_G400(mmesa)) {
820       /* G400: Regardless of texture env mode, we use the alpha from the
821        * texture unit (AC_alphasel_fromtex) since it will have already
822        * been modulated by the incoming fragment color, if needed.
823        * We don't want (AC_alphasel_modulate) since that'll effectively
824        * do the modulation twice.
825        */
826       mmesa->hw.alpha_sel = AC_alphasel_fromtex;
827
828       mgaUpdateTextureEnvG400( ctx, unit );
829    } else {
830       mgaUpdateTextureEnvG200( ctx, unit );
831    }
832
833    t->setup.texctl2 &= TMC_dualtex_MASK;
834    if (ctx->Texture._EnabledUnits == 0x03 || mmesa->force_dualtex) {
835       t->setup.texctl2 |= TMC_dualtex_enable;
836    }
837
838    mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
839
840    FALLBACK( ctx, MGA_FALLBACK_BORDER_MODE, t->border_fallback );
841    return !t->border_fallback && !t->texenv_fallback;
842 }
843
844
845 static GLboolean updateTextureUnit( struct gl_context *ctx, int unit )
846 {
847    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
848    const int source = mmesa->tmu_source[unit];
849    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
850
851
852    if ( texUnit->_ReallyEnabled == TEXTURE_2D_BIT ||
853         texUnit->_ReallyEnabled == TEXTURE_RECT_BIT ) {
854       return(enable_tex( ctx, unit ) &&
855              update_tex_common( ctx, unit ));
856    }
857    else if ( texUnit->_ReallyEnabled ) {
858       return GL_FALSE;
859    }
860    else {
861       disable_tex( ctx, unit );
862       return GL_TRUE;
863    }
864 }
865
866 /* The G400 is now programmed quite differently wrt texture environment.
867  */
868 void mgaUpdateTextureState( struct gl_context *ctx )
869 {
870    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
871    GLboolean ok;
872    unsigned  i;
873
874    mmesa->force_dualtex = GL_FALSE;
875    mmesa->fcol_used = GL_FALSE;
876
877    /* This works around a quirk with the MGA hardware.  If only OpenGL 
878     * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used.  The
879     * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
880     */
881
882    mmesa->tmu_source[0] = 0;
883    mmesa->tmu_source[1] = 1;
884
885    if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) {
886       /* only texture 1 enabled */
887       mmesa->tmu_source[0] = 1;
888       mmesa->tmu_source[1] = 0;
889    }
890
891    for ( i = 0, ok = GL_TRUE 
892          ; (i < ctx->Const.MaxTextureUnits) && ok
893          ; i++ ) {
894       ok = updateTextureUnit( ctx, i );
895    }
896
897    FALLBACK( ctx, MGA_FALLBACK_TEXTURE, !ok );
898 }