OSDN Git Service

f657abe6711e9d8e4e0294b69b4eb56d65076ff7
[android-x86/external-mesa.git] / src / mesa / drivers / dri / i810 / i810tex.c
1 /*
2  * GLX Hardware Device Driver for Intel i810
3  * Copyright (C) 1999 Keith Whitwell
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  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
21  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  */
24 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810tex.c,v 1.9 2002/10/30 12:51:33 alanh Exp $ */
25
26 #include "glheader.h"
27 #include "mtypes.h"
28 #include "imports.h"
29 #include "simple_list.h"
30 #include "enums.h"
31 #include "texstore.h"
32 #include "texformat.h"
33 #include "teximage.h"
34 #include "texmem.h"
35 #include "texobj.h"
36 #include "swrast/swrast.h"
37 #include "colormac.h"
38 #include "texobj.h"
39 #include "mm.h"
40
41 #include "i810screen.h"
42 #include "i810_dri.h"
43
44 #include "i810context.h"
45 #include "i810tex.h"
46 #include "i810state.h"
47 #include "i810ioctl.h"
48
49
50 /*
51  * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias.
52  */
53 static GLuint i810ComputeLodBias(GLfloat bias)
54 {
55    int b = (int) (bias * 16.0) + 12;
56    if (b > 63)
57       b = 63;
58    else if (b < -64)
59       b = -64;
60    return (GLuint) (b & MLC_LOD_BIAS_MASK);
61 }
62
63
64 static void i810SetTexWrapping(i810TextureObjectPtr tex,
65                                GLenum swrap, GLenum twrap)
66 {
67    tex->Setup[I810_TEXREG_MCS] &= ~(MCS_U_STATE_MASK| MCS_V_STATE_MASK);
68
69    switch( swrap ) {
70    case GL_REPEAT:
71       tex->Setup[I810_TEXREG_MCS] |= MCS_U_WRAP;
72       break;
73    case GL_CLAMP:
74    case GL_CLAMP_TO_EDGE:
75       tex->Setup[I810_TEXREG_MCS] |= MCS_U_CLAMP;
76       break;
77    case GL_MIRRORED_REPEAT:
78       tex->Setup[I810_TEXREG_MCS] |= MCS_U_MIRROR;
79       break;
80    default:
81       _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
82    }
83
84    switch( twrap ) {
85    case GL_REPEAT:
86       tex->Setup[I810_TEXREG_MCS] |= MCS_V_WRAP;
87       break;
88    case GL_CLAMP:
89    case GL_CLAMP_TO_EDGE:
90       tex->Setup[I810_TEXREG_MCS] |= MCS_V_CLAMP;
91       break;
92    case GL_MIRRORED_REPEAT:
93       tex->Setup[I810_TEXREG_MCS] |= MCS_V_MIRROR;
94       break;
95    default:
96       _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
97    }
98 }
99
100
101 static void i810SetTexFilter(i810ContextPtr imesa, 
102                              i810TextureObjectPtr t, 
103                              GLenum minf, GLenum magf,
104                              GLfloat bias)
105 {
106    t->Setup[I810_TEXREG_MF] &= ~(MF_MIN_MASK|
107                                  MF_MAG_MASK|
108                                  MF_MIP_MASK);
109    t->Setup[I810_TEXREG_MLC] &= ~(MLC_LOD_BIAS_MASK);
110
111    switch (minf) {
112    case GL_NEAREST:
113       t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_NONE;
114       break;
115    case GL_LINEAR:
116       t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_NONE;
117       break;
118    case GL_NEAREST_MIPMAP_NEAREST:
119       t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_NEAREST;
120       if (magf == GL_LINEAR) {
121          /*bias -= 0.5;*/  /* this doesn't work too good */
122       }
123       break;
124    case GL_LINEAR_MIPMAP_NEAREST:
125       t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_NEAREST;
126       break;
127    case GL_NEAREST_MIPMAP_LINEAR:
128       if (IS_I815(imesa)) 
129          t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_LINEAR;
130       else 
131          t->Setup[I810_TEXREG_MF] |= MF_MIN_NEAREST | MF_MIP_DITHER;
132       /*
133       if (magf == GL_LINEAR) {
134          bias -= 0.5;
135       }
136       */
137       bias -= 0.5; /* always biasing here looks better */
138       break;
139    case GL_LINEAR_MIPMAP_LINEAR:
140       if (IS_I815(imesa))
141          t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_LINEAR;
142       else 
143          t->Setup[I810_TEXREG_MF] |= MF_MIN_LINEAR | MF_MIP_DITHER;
144       break;
145    default:
146       return;
147    }
148
149    switch (magf) {
150    case GL_NEAREST: 
151       t->Setup[I810_TEXREG_MF] |= MF_MAG_NEAREST; 
152       break;
153    case GL_LINEAR: 
154       t->Setup[I810_TEXREG_MF] |= MF_MAG_LINEAR; 
155       break;
156    default: 
157       return;
158    }
159
160    t->Setup[I810_TEXREG_MLC] |= i810ComputeLodBias(bias);
161 }
162
163
164 static void
165 i810SetTexBorderColor( i810TextureObjectPtr t, GLubyte color[4] )
166 {
167    /* Need a fallback.
168     */
169 }
170
171
172 static i810TextureObjectPtr
173 i810AllocTexObj( GLcontext *ctx, struct gl_texture_object *texObj )
174 {
175    i810TextureObjectPtr t;
176    i810ContextPtr imesa = I810_CONTEXT(ctx);
177
178    t = CALLOC_STRUCT( i810_texture_object_t );
179    texObj->DriverData = t;
180    if ( t != NULL ) {
181       GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
182       /* Initialize non-image-dependent parts of the state:
183        */
184       t->base.tObj = texObj;
185       t->Setup[I810_TEXREG_MI0] = GFX_OP_MAP_INFO;
186       t->Setup[I810_TEXREG_MI1] = MI1_MAP_0; 
187       t->Setup[I810_TEXREG_MI2] = MI2_DIMENSIONS_ARE_LOG2;
188       t->Setup[I810_TEXREG_MLC] = (GFX_OP_MAP_LOD_CTL | 
189                                    MLC_MAP_0 |
190                                    /*MLC_DITHER_WEIGHT_FULL |*/
191                                    MLC_DITHER_WEIGHT_12 |
192                                    MLC_UPDATE_LOD_BIAS |
193                                    0x0);
194       t->Setup[I810_TEXREG_MCS] = (GFX_OP_MAP_COORD_SETS |
195                                    MCS_COORD_0 |
196                                    MCS_UPDATE_NORMALIZED |
197                                    MCS_NORMALIZED_COORDS |
198                                    MCS_UPDATE_V_STATE |
199                                    MCS_V_WRAP |
200                                    MCS_UPDATE_U_STATE |
201                                    MCS_U_WRAP);
202       t->Setup[I810_TEXREG_MF] = (GFX_OP_MAP_FILTER |
203                                   MF_MAP_0 |
204                                   MF_UPDATE_ANISOTROPIC |
205                                   MF_UPDATE_MIP_FILTER |
206                                   MF_UPDATE_MAG_FILTER |
207                                   MF_UPDATE_MIN_FILTER);
208       
209       make_empty_list( & t->base );
210
211       i810SetTexWrapping( t, texObj->WrapS, texObj->WrapT );
212       /*i830SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );*/
213       i810SetTexFilter( imesa, t, texObj->MinFilter, texObj->MagFilter, bias );
214       i810SetTexBorderColor( t, texObj->_BorderChan );
215    }
216
217    return t;
218 }
219
220
221 static void i810TexParameter( GLcontext *ctx, GLenum target,
222                               struct gl_texture_object *tObj,
223                               GLenum pname, const GLfloat *params )
224 {
225    i810ContextPtr imesa = I810_CONTEXT(ctx);
226    i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData;
227
228    if (!t)
229       return;
230
231    if ( target != GL_TEXTURE_2D )
232       return;
233
234    /* Can't do the update now as we don't know whether to flush
235     * vertices or not.  Setting imesa->new_state means that
236     * i810UpdateTextureState() will be called before any triangles are
237     * rendered.  If a statechange has occurred, it will be detected at
238     * that point, and buffered vertices flushed.  
239     */
240    switch (pname) {
241    case GL_TEXTURE_MIN_FILTER:
242    case GL_TEXTURE_MAG_FILTER:
243       {
244          GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
245          i810SetTexFilter( imesa, t, tObj->MinFilter, tObj->MagFilter, bias );
246       }
247       break;
248
249    case GL_TEXTURE_WRAP_S:
250    case GL_TEXTURE_WRAP_T:
251       i810SetTexWrapping( t, tObj->WrapS, tObj->WrapT );
252       break;
253   
254    case GL_TEXTURE_BORDER_COLOR:
255       i810SetTexBorderColor( t, tObj->_BorderChan );
256       break;
257
258    case GL_TEXTURE_BASE_LEVEL:
259    case GL_TEXTURE_MAX_LEVEL:
260    case GL_TEXTURE_MIN_LOD:
261    case GL_TEXTURE_MAX_LOD:
262       /* This isn't the most efficient solution but there doesn't appear to
263        * be a nice alternative for Radeon.  Since there's no LOD clamping,
264        * we just have to rely on loading the right subset of mipmap levels
265        * to simulate a clamped LOD.
266        */
267       I810_FIREVERTICES( I810_CONTEXT(ctx) );
268       driSwapOutTextureObject( (driTextureObject *) t );
269       break;
270
271    default:
272       return;
273    }
274
275    if (t == imesa->CurrentTexObj[0]) {
276       I810_STATECHANGE( imesa, I810_UPLOAD_TEX0 );
277    }
278
279    if (t == imesa->CurrentTexObj[1]) {
280       I810_STATECHANGE( imesa, I810_UPLOAD_TEX1 );
281    }
282 }
283
284
285 /**
286  * Setup hardware bits for new texture environment settings.
287  * 
288  * \todo
289  * Determine whether or not \c param can be used instead of
290  * \c texUnit->EnvColor in the \c GL_TEXTURE_ENV_COLOR case.
291  */
292 static void i810TexEnv( GLcontext *ctx, GLenum target, 
293                         GLenum pname, const GLfloat *param )
294 {
295    i810ContextPtr imesa = I810_CONTEXT( ctx );
296    const GLuint unit = ctx->Texture.CurrentUnit;
297    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
298
299    /* Only one env color.  Need a fallback if env colors are different
300     * and texture setup references env color in both units.  
301     */
302    switch (pname) {
303    case GL_TEXTURE_ENV_COLOR: {
304       GLubyte c[4];
305       GLuint envColor;
306
307       UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
308       envColor = PACK_COLOR_8888( c[3], c[0], c[1], c[2] );
309
310       if (imesa->Setup[I810_CTXREG_CF1] != envColor) {
311          I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
312          imesa->Setup[I810_CTXREG_CF1] = envColor;
313       }
314       break;
315    }
316
317    case GL_TEXTURE_ENV_MODE:
318       imesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */
319       break;
320
321    case GL_TEXTURE_LOD_BIAS: {
322       if ( texUnit->_Current != NULL ) {
323          const struct gl_texture_object *tObj = texUnit->_Current;
324          i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData;
325
326          t->Setup[I810_TEXREG_MLC] &= ~(MLC_LOD_BIAS_MASK);
327          t->Setup[I810_TEXREG_MLC] |= i810ComputeLodBias(*param);
328       }
329       break;
330    }
331
332    default:
333       break;
334    }
335
336
337
338
339 #if 0
340 static void i810TexImage1D( GLcontext *ctx, GLenum target, GLint level,
341                             GLint internalFormat,
342                             GLint width, GLint border,
343                             GLenum format, GLenum type, 
344                             const GLvoid *pixels,
345                             const struct gl_pixelstore_attrib *pack,
346                             struct gl_texture_object *texObj,
347                             struct gl_texture_image *texImage )
348 {
349    i810TextureObjectPtr t = (i810TextureObjectPtr) texObj->DriverData;
350    if (t) {
351       i810SwapOutTexObj( imesa, t );
352    }
353 }
354
355 static void i810TexSubImage1D( GLcontext *ctx, 
356                                GLenum target,
357                                GLint level,     
358                                GLint xoffset,
359                                GLsizei width,
360                                GLenum format, GLenum type,
361                                const GLvoid *pixels,
362                                const struct gl_pixelstore_attrib *pack,
363                                struct gl_texture_object *texObj,
364                                struct gl_texture_image *texImage )
365 {
366 }
367 #endif
368
369
370 static void i810TexImage2D( GLcontext *ctx, GLenum target, GLint level,
371                             GLint internalFormat,
372                             GLint width, GLint height, GLint border,
373                             GLenum format, GLenum type, const GLvoid *pixels,
374                             const struct gl_pixelstore_attrib *packing,
375                             struct gl_texture_object *texObj,
376                             struct gl_texture_image *texImage )
377 {
378    driTextureObject *t = (driTextureObject *) texObj->DriverData;
379    if (t) {
380       I810_FIREVERTICES( I810_CONTEXT(ctx) );
381       driSwapOutTextureObject( t );
382    }
383    else {
384       t = (driTextureObject *) i810AllocTexObj( ctx, texObj );
385       if (!t) {
386          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
387          return;
388       }
389    }
390    _mesa_store_teximage2d( ctx, target, level, internalFormat,
391                            width, height, border, format, type,
392                            pixels, packing, texObj, texImage );
393 }
394
395 static void i810TexSubImage2D( GLcontext *ctx, 
396                                GLenum target,
397                                GLint level,     
398                                GLint xoffset, GLint yoffset,
399                                GLsizei width, GLsizei height,
400                                GLenum format, GLenum type,
401                                const GLvoid *pixels,
402                                const struct gl_pixelstore_attrib *packing,
403                                struct gl_texture_object *texObj,
404                                struct gl_texture_image *texImage )
405 {
406    driTextureObject *t = (driTextureObject *)texObj->DriverData;
407    if (t) {
408      I810_FIREVERTICES( I810_CONTEXT(ctx) );
409      driSwapOutTextureObject( t );
410    }
411    _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, 
412                              height, format, type, pixels, packing, texObj,
413                              texImage);
414 }
415
416
417 static void i810BindTexture( GLcontext *ctx, GLenum target,
418                              struct gl_texture_object *tObj )
419 {
420    assert( (target != GL_TEXTURE_2D) || (tObj->DriverData != NULL) );
421 }
422
423
424 static void i810DeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
425 {
426    driTextureObject * t = (driTextureObject *) tObj->DriverData;
427    if (t) {
428       i810ContextPtr imesa = I810_CONTEXT( ctx );
429       if (imesa)
430          I810_FIREVERTICES( imesa );
431       driDestroyTextureObject( t );
432    }
433    /* Free mipmap images and the texture object itself */
434    _mesa_delete_texture_object(ctx, tObj);
435 }
436
437 /**
438  * Choose a Mesa texture format to match the requested format.
439  * 
440  * The i810 only supports 5 texture modes that are useful to Mesa.  That
441  * makes this routine pretty simple.
442  */
443 static const struct gl_texture_format *
444 i810ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
445                          GLenum format, GLenum type )
446 {
447    switch ( internalFormat ) {
448    case 4:
449    case GL_RGBA:
450    case GL_RGBA2:
451    case GL_RGBA4:
452    case GL_RGB5_A1:
453    case GL_RGBA8:
454    case GL_RGB10_A2:
455    case GL_RGBA12:
456    case GL_RGBA16:
457    case GL_COMPRESSED_RGBA:
458       if ( ((format == GL_BGRA) && (type == GL_UNSIGNED_SHORT_1_5_5_5_REV))
459            || ((format == GL_RGBA) && (type == GL_UNSIGNED_SHORT_5_5_5_1))
460            || (internalFormat == GL_RGB5_A1) ) {
461          return &_mesa_texformat_argb1555;
462       }
463       return &_mesa_texformat_argb4444;
464
465    case 3:
466    case GL_RGB:
467    case GL_COMPRESSED_RGB:
468    case GL_R3_G3_B2:
469    case GL_RGB4:
470    case GL_RGB5:
471    case GL_RGB8:
472    case GL_RGB10:
473    case GL_RGB12:
474    case GL_RGB16:
475       return &_mesa_texformat_rgb565;
476
477    case GL_ALPHA:
478    case GL_ALPHA4:
479    case GL_ALPHA8:
480    case GL_ALPHA12:
481    case GL_ALPHA16:
482    case GL_COMPRESSED_ALPHA:
483    case 1:
484    case GL_LUMINANCE:
485    case GL_LUMINANCE4:
486    case GL_LUMINANCE8:
487    case GL_LUMINANCE12:
488    case GL_LUMINANCE16:
489    case GL_COMPRESSED_LUMINANCE:
490    case 2:
491    case GL_LUMINANCE_ALPHA:
492    case GL_LUMINANCE4_ALPHA4:
493    case GL_LUMINANCE6_ALPHA2:
494    case GL_LUMINANCE8_ALPHA8:
495    case GL_LUMINANCE12_ALPHA4:
496    case GL_LUMINANCE12_ALPHA12:
497    case GL_LUMINANCE16_ALPHA16:
498    case GL_COMPRESSED_LUMINANCE_ALPHA:
499    case GL_INTENSITY:
500    case GL_INTENSITY4:
501    case GL_INTENSITY8:
502    case GL_INTENSITY12:
503    case GL_INTENSITY16:
504    case GL_COMPRESSED_INTENSITY:
505       return &_mesa_texformat_al88;
506
507    case GL_YCBCR_MESA:
508       if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
509           type == GL_UNSIGNED_BYTE)
510          return &_mesa_texformat_ycbcr;
511       else
512          return &_mesa_texformat_ycbcr_rev;
513
514    default:
515       fprintf(stderr, "unexpected texture format in %s\n", __FUNCTION__);
516       return NULL;
517    }
518
519    return NULL; /* never get here */
520 }
521
522 /**
523  * Allocate a new texture object.
524  * Called via ctx->Driver.NewTextureObject.
525  * Note: this function will be called during context creation to
526  * allocate the default texture objects.
527  * Note: we could use containment here to 'derive' the driver-specific
528  * texture object from the core mesa gl_texture_object.  Not done at this time.
529  */
530 static struct gl_texture_object *
531 i810NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
532 {
533    struct gl_texture_object *obj;
534    obj = _mesa_new_texture_object(ctx, name, target);
535    i810AllocTexObj( ctx, obj );
536    return obj;
537 }
538
539 void i810InitTextureFuncs( struct dd_function_table *functions )
540 {
541    functions->ChooseTextureFormat = i810ChooseTextureFormat;
542    functions->TexImage2D = i810TexImage2D;
543    functions->TexSubImage2D = i810TexSubImage2D;
544    functions->BindTexture = i810BindTexture;
545    functions->NewTextureObject = i810NewTextureObject;
546    functions->DeleteTexture = i810DeleteTexture;
547    functions->TexParameter = i810TexParameter;
548    functions->TexEnv = i810TexEnv;
549    functions->IsTextureResident = driIsTextureResident;
550 }