Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / mach64 / mach64_texstate.c
1 /* -*- mode: c; c-basic-offset: 3 -*- */
2 /*
3  * Copyright 2000 Gareth Hughes
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  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
20  * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 /*
26  * Authors:
27  *      Gareth Hughes <gareth@valinux.com>
28  *      Leif Delgass <ldelgass@retinalburn.net>
29  *      José Fonseca <j_r_fonseca@yahoo.co.uk>
30  */
31
32 #include "main/glheader.h"
33 #include "main/imports.h"
34 #include "main/context.h"
35 #include "main/macros.h"
36
37 #include "mach64_context.h"
38 #include "mach64_ioctl.h"
39 #include "mach64_tris.h"
40 #include "mach64_tex.h"
41
42 static void mach64SetTexImages( mach64ContextPtr mmesa,
43                               const struct gl_texture_object *tObj )
44 {
45    mach64TexObjPtr t = (mach64TexObjPtr) tObj->DriverData;
46    struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
47    int totalSize;
48
49    assert(t);
50    assert(baseImage);
51
52    if ( MACH64_DEBUG & DEBUG_VERBOSE_API )
53       fprintf( stderr, "%s( %p )\n", __FUNCTION__, tObj );
54
55    switch (baseImage->TexFormat) {
56    case MESA_FORMAT_ARGB8888:
57       t->textureFormat = MACH64_DATATYPE_ARGB8888;
58       break;
59    case MESA_FORMAT_ARGB4444:
60       t->textureFormat = MACH64_DATATYPE_ARGB4444;
61       break;
62    case MESA_FORMAT_RGB565:
63       t->textureFormat = MACH64_DATATYPE_RGB565;
64       break;
65    case MESA_FORMAT_ARGB1555:
66       t->textureFormat = MACH64_DATATYPE_ARGB1555;
67       break;
68    case MESA_FORMAT_RGB332:
69       t->textureFormat = MACH64_DATATYPE_RGB332;
70       break;
71    case MESA_FORMAT_RGB888:
72       t->textureFormat = MACH64_DATATYPE_RGB8;
73       break;
74    case MESA_FORMAT_CI8:
75       t->textureFormat = MACH64_DATATYPE_CI8;
76       break;
77    case MESA_FORMAT_YCBCR:
78       t->textureFormat = MACH64_DATATYPE_YVYU422;
79       break;
80    case MESA_FORMAT_YCBCR_REV:
81       t->textureFormat = MACH64_DATATYPE_VYUY422;
82       break;
83    default:
84       _mesa_problem(mmesa->glCtx, "Bad texture format in %s", __FUNCTION__);
85    };
86
87    totalSize = ( baseImage->Height *
88                  baseImage->Width *
89                  _mesa_get_format_bytes(baseImage->TexFormat) );
90
91    totalSize = (totalSize + 31) & ~31;
92
93    t->base.totalSize = totalSize;
94    t->base.firstLevel = tObj->BaseLevel;
95    t->base.lastLevel = tObj->BaseLevel;
96
97    /* Set the texture format */
98    if ( ( baseImage->_BaseFormat == GL_RGBA ) ||
99         ( baseImage->_BaseFormat == GL_ALPHA ) ||
100         ( baseImage->_BaseFormat == GL_LUMINANCE_ALPHA ) ) {
101       t->hasAlpha = 1;
102    } else {
103       t->hasAlpha = 0;
104    }
105
106    t->widthLog2 = baseImage->WidthLog2;
107    t->heightLog2 = baseImage->HeightLog2;
108    t->maxLog2 = baseImage->MaxLog2;
109 }
110
111 static void mach64UpdateTextureEnv( struct gl_context *ctx, int unit )
112 {
113    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
114    GLint source = mmesa->tmu_source[unit];
115    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
116    const struct gl_texture_object *tObj = texUnit->_Current;
117    const GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
118    GLuint s = mmesa->setup.scale_3d_cntl;
119
120    if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
121       fprintf( stderr, "%s( %p, %d )\n",
122                __FUNCTION__, ctx, unit );
123    }
124
125 /*                 REPLACE  MODULATE   DECAL              GL_BLEND
126  *
127  * ALPHA           C = Cf   C = Cf     undef              C = Cf
128  *                 A = At   A = AfAt                      A = AfAt
129  *
130  * LUMINANCE       C = Ct   C = CfCt   undef              C = Cf(1-Ct)+CcCt 
131  *                 A = Af   A = Af                        A = Af
132  *
133  * LUMINANCE_ALPHA C = Ct   C = CfCt   undef              C = Cf(1-Ct)+CcCt
134  *                 A = At   A = AfAt                      A = AfAt
135  *
136  * INTENSITY       C = Ct   C = CfCt   undef              C = Cf(1-Ct)+CcCt
137  *                 A = At   A = AfAt                      A = Af(1-At)+AcAt
138  *
139  * RGB             C = Ct   C = CfCt   C = Ct             C = Cf(1-Ct)+CcCt
140  *                 A = Af   A = Af     A = Af             A = Af
141  *
142  * RGBA            C = Ct   C = CfCt   C = Cf(1-At)+CtAt  C = Cf(1-Ct)+CcCt
143  *                 A = At   A = AfAt   A = Af             A = AfAt 
144  */
145
146
147    if ( unit == 0 ) {
148       s &= ~MACH64_TEX_LIGHT_FCN_MASK;
149
150       /* Set the texture environment state 
151        * Need to verify these are working correctly, but the
152        * texenv Mesa demo seems to work.
153        */
154       switch ( texUnit->EnvMode ) {
155       case GL_REPLACE:
156          switch ( format ) {
157          case GL_ALPHA:
158          case GL_LUMINANCE_ALPHA:
159          case GL_INTENSITY:
160             /* Not compliant - can't get At */
161             FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
162             s |= MACH64_TEX_LIGHT_FCN_MODULATE;
163             break;
164          default:
165             s |= MACH64_TEX_LIGHT_FCN_REPLACE;
166          }
167          break;
168       case GL_MODULATE:
169          switch ( format ) {
170          case GL_ALPHA:
171             FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
172             s |= MACH64_TEX_LIGHT_FCN_MODULATE;
173             break;
174          case GL_RGB:
175          case GL_LUMINANCE:
176             /* These should be compliant */
177             s |= MACH64_TEX_LIGHT_FCN_MODULATE;
178             break;
179          case GL_LUMINANCE_ALPHA:
180          case GL_INTENSITY:
181             FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
182             s |= MACH64_TEX_LIGHT_FCN_MODULATE;
183             break;
184          case GL_RGBA:
185             /* Should fallback when blending enabled for complete compliance */
186             s |= MACH64_TEX_LIGHT_FCN_MODULATE;
187             break;
188          default:
189             s |= MACH64_TEX_LIGHT_FCN_MODULATE;
190          }
191          break;
192       case GL_DECAL:
193          switch ( format ) {
194          case GL_RGBA: 
195             s |= MACH64_TEX_LIGHT_FCN_ALPHA_DECAL;
196             break;
197          case GL_RGB:
198             s |= MACH64_TEX_LIGHT_FCN_REPLACE;
199             break;
200          case GL_ALPHA:
201          case GL_LUMINANCE_ALPHA:
202             /* undefined - disable texturing, pass fragment unmodified  */
203             /* Also, pass fragment alpha instead of texture alpha */
204             s &= ~MACH64_TEX_MAP_AEN;
205             s |= MACH64_TEXTURE_DISABLE;
206             s |= MACH64_TEX_LIGHT_FCN_MODULATE;
207             break;
208          case GL_LUMINANCE:
209          case GL_INTENSITY:
210             /* undefined - disable texturing, pass fragment unmodified  */
211             s |= MACH64_TEXTURE_DISABLE;
212             s |= MACH64_TEX_LIGHT_FCN_MODULATE;
213             break;
214          default:
215             s |= MACH64_TEX_LIGHT_FCN_MODULATE;
216          }
217          break;
218       case GL_BLEND:
219          /* GL_BLEND not supported by RagePRO, use software */
220          FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
221          s |= MACH64_TEX_LIGHT_FCN_MODULATE;
222          break;
223       case GL_ADD:
224       case GL_COMBINE:
225          FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
226          s |= MACH64_TEX_LIGHT_FCN_MODULATE;
227          break;
228       default:
229          s |= MACH64_TEX_LIGHT_FCN_MODULATE;
230       }
231
232       if ( mmesa->setup.scale_3d_cntl != s ) {
233          mmesa->setup.scale_3d_cntl = s;
234          mmesa->dirty |= MACH64_UPLOAD_SCALE_3D_CNTL;
235       }
236
237    } else {
238       /* blend = 0, modulate = 1 - initialize to blend */
239       mmesa->setup.tex_cntl &= ~MACH64_COMP_COMBINE_MODULATE;
240       /* Set the texture composite function for multitexturing*/
241       switch ( texUnit->EnvMode ) {
242       case GL_BLEND:
243          /* GL_BLEND not supported by RagePRO, use software */
244          FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
245          mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
246          break;
247       case GL_MODULATE:
248          /* Should fallback when blending enabled for complete compliance */
249          mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
250          break;
251       case GL_REPLACE:
252          switch ( format ) {
253          case GL_ALPHA:
254             mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
255             break;
256          default: /* not supported by RagePRO */
257             FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
258             mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
259          }
260          break;
261       case GL_DECAL:
262          switch ( format ) {
263          case GL_ALPHA:
264          case GL_LUMINANCE:
265          case GL_LUMINANCE_ALPHA:
266          case GL_INTENSITY:
267             /* undefined, disable compositing and pass fragment unmodified */
268             mmesa->setup.tex_cntl &= ~MACH64_TEXTURE_COMPOSITE;
269             break;
270          default: /* not supported by RagePRO */
271             FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
272             mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
273          }
274          break;
275       case GL_ADD:
276       case GL_COMBINE:
277          FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
278          mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
279          break;
280       default:
281          mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
282       }
283    }
284 }
285
286
287 static void mach64UpdateTextureUnit( struct gl_context *ctx, int unit )
288 {
289    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
290    int source = mmesa->tmu_source[unit];
291    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
292    const struct gl_texture_object *tObj = ctx->Texture.Unit[source]._Current;
293    mach64TexObjPtr t = tObj->DriverData;
294    GLuint d = mmesa->setup.dp_pix_width;
295    GLuint s = mmesa->setup.scale_3d_cntl;
296
297    assert(unit == 0 || unit == 1);  /* only two tex units */
298
299    if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
300       fprintf( stderr, "%s( %p, %d ) enabled=0x%x 0x%x\n",
301                __FUNCTION__, ctx, unit, ctx->Texture.Unit[0]._ReallyEnabled,
302                ctx->Texture.Unit[1]._ReallyEnabled);
303    }
304
305    if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) {
306
307       assert(t);  /* should have driver tex data by now */
308
309       /* Fallback if there's a texture border */
310       if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
311          FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
312          return;
313       }
314
315       /* Upload teximages */
316       if (t->base.dirty_images[0]) {
317          mach64SetTexImages( mmesa, tObj );
318          mmesa->dirty |= (MACH64_UPLOAD_TEX0IMAGE << unit);
319       }
320
321       /* Bind to the given texture unit */
322       mmesa->CurrentTexObj[unit] = t;
323       t->base.bound |= (1 << unit);
324
325       if ( t->base.memBlock )
326          driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
327
328       /* register setup */
329       if ( unit == 0 ) {
330          d &= ~MACH64_SCALE_PIX_WIDTH_MASK;
331          d |= (t->textureFormat << 28);
332    
333          s &= ~(MACH64_TEXTURE_DISABLE |
334                 MACH64_TEX_CACHE_SPLIT |
335                 MACH64_TEX_BLEND_FCN_MASK |
336                 MACH64_TEX_MAP_AEN);
337    
338          if ( mmesa->multitex ) {
339             s |= MACH64_TEX_BLEND_FCN_TRILINEAR | MACH64_TEX_CACHE_SPLIT;
340          } else if ( t->BilinearMin ) {
341             s |= MACH64_TEX_BLEND_FCN_LINEAR;
342          } else {
343             s |= MACH64_TEX_BLEND_FCN_NEAREST;
344          }
345          if ( t->BilinearMag ) {
346             s |=  MACH64_BILINEAR_TEX_EN;
347          } else {
348             s &= ~MACH64_BILINEAR_TEX_EN;
349          }
350    
351          if ( t->hasAlpha ) {
352             s |= MACH64_TEX_MAP_AEN;
353          }
354    
355          mmesa->setup.tex_cntl &= ~(MACH64_TEXTURE_CLAMP_S |
356                                     MACH64_TEXTURE_CLAMP_T |
357                                     MACH64_SECONDARY_STW);
358    
359          if ( t->ClampS ) {
360             mmesa->setup.tex_cntl |= MACH64_TEXTURE_CLAMP_S;
361          }
362          if ( t->ClampT ) {
363             mmesa->setup.tex_cntl |= MACH64_TEXTURE_CLAMP_T;
364          }
365    
366          mmesa->setup.tex_size_pitch |= ((t->widthLog2  << 0) |
367                                          (t->maxLog2    << 4) |
368                                          (t->heightLog2 << 8));
369       } else {
370          
371          /* Enable texture mapping mode */
372          s &= ~MACH64_TEXTURE_DISABLE;
373    
374          d &= ~MACH64_COMPOSITE_PIX_WIDTH_MASK;
375          d |= (t->textureFormat << 4);
376    
377          mmesa->setup.tex_cntl &= ~(MACH64_COMP_ALPHA |
378                                     MACH64_SEC_TEX_CLAMP_S |
379                                     MACH64_SEC_TEX_CLAMP_T);
380          mmesa->setup.tex_cntl |= (MACH64_TEXTURE_COMPOSITE |
381                                    MACH64_SECONDARY_STW);
382    
383          if ( t->BilinearMin ) {
384             mmesa->setup.tex_cntl |= MACH64_COMP_BLEND_BILINEAR;
385          } else {
386             mmesa->setup.tex_cntl &= ~MACH64_COMP_BLEND_BILINEAR;
387          }
388          if ( t->BilinearMag ) {
389             mmesa->setup.tex_cntl |=  MACH64_COMP_FILTER_BILINEAR;
390          } else {
391             mmesa->setup.tex_cntl &= ~MACH64_COMP_FILTER_BILINEAR;
392          }
393          
394          if ( t->hasAlpha ) {
395             mmesa->setup.tex_cntl |= MACH64_COMP_ALPHA;
396          }
397          if ( t->ClampS ) {
398             mmesa->setup.tex_cntl |= MACH64_SEC_TEX_CLAMP_S;
399          }
400          if ( t->ClampT ) {
401             mmesa->setup.tex_cntl |= MACH64_SEC_TEX_CLAMP_T;
402          }
403    
404          mmesa->setup.tex_size_pitch |= ((t->widthLog2  << 16) |
405                                          (t->maxLog2    << 20) |
406                                          (t->heightLog2 << 24));
407       }
408    
409       if ( mmesa->setup.scale_3d_cntl != s ) {
410          mmesa->setup.scale_3d_cntl = s;
411          mmesa->dirty |= MACH64_UPLOAD_SCALE_3D_CNTL;
412       }
413    
414       if ( mmesa->setup.dp_pix_width != d ) {
415          mmesa->setup.dp_pix_width = d;
416          mmesa->dirty |= MACH64_UPLOAD_DP_PIX_WIDTH;
417       }  
418    }
419    else if (texUnit->_ReallyEnabled) {
420       /* 3D or cube map texture enabled - fallback */
421       FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
422    }
423    else {
424       /* texture unit disabled */
425    }
426 }
427
428
429 /* Update the hardware texture state */
430 void mach64UpdateTextureState( struct gl_context *ctx )
431 {
432    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
433
434    if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
435       fprintf( stderr, "%s( %p ) en=0x%x 0x%x\n",
436                __FUNCTION__, ctx, ctx->Texture.Unit[0]._ReallyEnabled,
437                ctx->Texture.Unit[1]._ReallyEnabled);
438    }
439
440    /* Clear any texturing fallbacks */
441    FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_FALSE );
442
443    /* Unbind any currently bound textures */
444    if ( mmesa->CurrentTexObj[0] ) mmesa->CurrentTexObj[0]->base.bound = 0;
445    if ( mmesa->CurrentTexObj[1] ) mmesa->CurrentTexObj[1]->base.bound = 0;
446    mmesa->CurrentTexObj[0] = NULL;
447    mmesa->CurrentTexObj[1] = NULL;
448
449    /* Disable all texturing until it is known to be good */
450    mmesa->setup.scale_3d_cntl  |=  MACH64_TEXTURE_DISABLE;
451    mmesa->setup.scale_3d_cntl  &= ~MACH64_TEX_MAP_AEN;
452    mmesa->setup.tex_cntl       &= ~MACH64_TEXTURE_COMPOSITE;
453
454    mmesa->setup.tex_size_pitch = 0x00000000;
455
456    mmesa->tmu_source[0] = 0;
457    mmesa->tmu_source[1] = 1;
458    mmesa->multitex = 0;
459
460    if (ctx->Texture._EnabledUnits & 0x2) {
461        /* unit 1 enabled */
462        if (ctx->Texture._EnabledUnits & 0x1) {
463           /* units 0 and 1 enabled */
464           mmesa->multitex = 1;
465           mach64UpdateTextureUnit( ctx, 0 );
466           mach64UpdateTextureEnv( ctx, 0 );
467           mach64UpdateTextureUnit( ctx, 1 );
468           mach64UpdateTextureEnv( ctx, 1 );
469        } else {
470           mmesa->tmu_source[0] = 1;
471           mmesa->tmu_source[1] = 0;
472           mach64UpdateTextureUnit( ctx, 0 );
473           mach64UpdateTextureEnv( ctx, 0 );
474        }
475    } else if (ctx->Texture._EnabledUnits & 0x1) {
476       /* only unit 0 enabled */ 
477       mach64UpdateTextureUnit( ctx, 0 );
478       mach64UpdateTextureEnv( ctx, 0 );
479    }
480
481    mmesa->dirty |= (MACH64_UPLOAD_SCALE_3D_CNTL |
482                     MACH64_UPLOAD_TEXTURE);
483 }
484
485
486 /* Due to the way we must program texture state into the Rage Pro,
487  * we must leave these calculations to the absolute last minute.
488  */
489 void mach64EmitTexStateLocked( mach64ContextPtr mmesa,
490                                mach64TexObjPtr t0,
491                                mach64TexObjPtr t1 )
492 {
493    drm_mach64_sarea_t *sarea = mmesa->sarea;
494    drm_mach64_context_regs_t *regs = &(mmesa->setup);
495
496    /* for multitex, both textures must be local or AGP */
497    if ( t0 && t1 )
498       assert(t0->heap == t1->heap);
499
500    if ( t0 ) {
501       if (t0->heap == MACH64_CARD_HEAP) {
502 #if ENABLE_PERF_BOXES
503          mmesa->c_texsrc_card++;
504 #endif
505          mmesa->setup.tex_cntl &= ~MACH64_TEX_SRC_AGP;
506       } else {
507 #if ENABLE_PERF_BOXES
508          mmesa->c_texsrc_agp++;
509 #endif
510          mmesa->setup.tex_cntl |= MACH64_TEX_SRC_AGP;
511       }
512       mmesa->setup.tex_offset = t0->bufAddr;
513    }
514
515    if ( t1 ) {
516       mmesa->setup.secondary_tex_off = t1->bufAddr;
517    }
518
519    memcpy( &sarea->context_state.tex_size_pitch, &regs->tex_size_pitch,
520            MACH64_NR_TEXTURE_REGS * sizeof(GLuint) );
521 }
522