Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / i915 / i915_texstate.c
1 /**************************************************************************
2  * 
3  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  * 
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  * 
26  **************************************************************************/
27
28 #include "main/mtypes.h"
29 #include "main/enums.h"
30 #include "main/macros.h"
31 #include "main/colormac.h"
32 #include "main/samplerobj.h"
33
34 #include "intel_mipmap_tree.h"
35 #include "intel_tex.h"
36
37 #include "i915_context.h"
38 #include "i915_reg.h"
39
40
41 static GLuint
42 translate_texture_format(gl_format mesa_format, GLenum DepthMode)
43 {
44    switch (mesa_format) {
45    case MESA_FORMAT_L8:
46       return MAPSURF_8BIT | MT_8BIT_L8;
47    case MESA_FORMAT_I8:
48       return MAPSURF_8BIT | MT_8BIT_I8;
49    case MESA_FORMAT_A8:
50       return MAPSURF_8BIT | MT_8BIT_A8;
51    case MESA_FORMAT_AL88:
52       return MAPSURF_16BIT | MT_16BIT_AY88;
53    case MESA_FORMAT_RGB565:
54       return MAPSURF_16BIT | MT_16BIT_RGB565;
55    case MESA_FORMAT_ARGB1555:
56       return MAPSURF_16BIT | MT_16BIT_ARGB1555;
57    case MESA_FORMAT_ARGB4444:
58       return MAPSURF_16BIT | MT_16BIT_ARGB4444;
59    case MESA_FORMAT_ARGB8888:
60       return MAPSURF_32BIT | MT_32BIT_ARGB8888;
61    case MESA_FORMAT_XRGB8888:
62       return MAPSURF_32BIT | MT_32BIT_XRGB8888;
63    case MESA_FORMAT_YCBCR_REV:
64       return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
65    case MESA_FORMAT_YCBCR:
66       return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
67    case MESA_FORMAT_RGB_FXT1:
68    case MESA_FORMAT_RGBA_FXT1:
69       return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
70    case MESA_FORMAT_Z16:
71       if (DepthMode == GL_ALPHA)
72           return (MAPSURF_16BIT | MT_16BIT_A16);
73       else if (DepthMode == GL_INTENSITY)
74           return (MAPSURF_16BIT | MT_16BIT_I16);
75       else
76           return (MAPSURF_16BIT | MT_16BIT_L16);
77    case MESA_FORMAT_RGBA_DXT1:
78    case MESA_FORMAT_RGB_DXT1:
79       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
80    case MESA_FORMAT_RGBA_DXT3:
81       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
82    case MESA_FORMAT_RGBA_DXT5:
83       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
84    case MESA_FORMAT_S8_Z24:
85    case MESA_FORMAT_X8_Z24:
86       if (DepthMode == GL_ALPHA)
87          return (MAPSURF_32BIT | MT_32BIT_x8A24);
88       else if (DepthMode == GL_INTENSITY)
89          return (MAPSURF_32BIT | MT_32BIT_x8I24);
90       else
91          return (MAPSURF_32BIT | MT_32BIT_x8L24);
92    default:
93       fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format);
94       abort();
95       return 0;
96    }
97 }
98
99
100
101
102 /* The i915 (and related graphics cores) do not support GL_CLAMP.  The
103  * Intel drivers for "other operating systems" implement GL_CLAMP as
104  * GL_CLAMP_TO_EDGE, so the same is done here.
105  */
106 static GLuint
107 translate_wrap_mode(GLenum wrap)
108 {
109    switch (wrap) {
110    case GL_REPEAT:
111       return TEXCOORDMODE_WRAP;
112    case GL_CLAMP:
113       return TEXCOORDMODE_CLAMP_EDGE;   /* not quite correct */
114    case GL_CLAMP_TO_EDGE:
115       return TEXCOORDMODE_CLAMP_EDGE;
116    case GL_CLAMP_TO_BORDER:
117       return TEXCOORDMODE_CLAMP_BORDER;
118    case GL_MIRRORED_REPEAT:
119       return TEXCOORDMODE_MIRROR;
120    default:
121       return TEXCOORDMODE_WRAP;
122    }
123 }
124
125
126
127 /* Recalculate all state from scratch.  Perhaps not the most
128  * efficient, but this has gotten complex enough that we need
129  * something which is understandable and reliable.
130  */
131 static GLboolean
132 i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
133 {
134    struct gl_context *ctx = &intel->ctx;
135    struct i915_context *i915 = i915_context(ctx);
136    struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit];
137    struct gl_texture_object *tObj = tUnit->_Current;
138    struct intel_texture_object *intelObj = intel_texture_object(tObj);
139    struct gl_texture_image *firstImage;
140    struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
141    GLuint *state = i915->state.Tex[unit], format, pitch;
142    GLint lodbias, aniso = 0;
143    GLubyte border[4];
144    GLfloat maxlod;
145
146    memset(state, 0, sizeof(state));
147
148    /*We need to refcount these. */
149
150    if (i915->state.tex_buffer[unit] != NULL) {
151        drm_intel_bo_unreference(i915->state.tex_buffer[unit]);
152        i915->state.tex_buffer[unit] = NULL;
153    }
154
155    if (!intel_finalize_mipmap_tree(intel, unit))
156       return GL_FALSE;
157
158    /* Get first image here, since intelObj->firstLevel will get set in
159     * the intel_finalize_mipmap_tree() call above.
160     */
161    firstImage = tObj->Image[0][tObj->BaseLevel];
162
163    drm_intel_bo_reference(intelObj->mt->region->buffer);
164    i915->state.tex_buffer[unit] = intelObj->mt->region->buffer;
165    i915->state.tex_offset[unit] = 0; /* Always the origin of the miptree */
166
167    format = translate_texture_format(firstImage->TexFormat,
168                                      sampler->DepthMode);
169    pitch = intelObj->mt->region->pitch * intelObj->mt->cpp;
170
171    state[I915_TEXREG_MS3] =
172       (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) |
173        ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format);
174
175    if (intelObj->mt->region->tiling != I915_TILING_NONE) {
176       state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE;
177       if (intelObj->mt->region->tiling == I915_TILING_Y)
178          state[I915_TEXREG_MS3] |= MS3_TILE_WALK;
179    }
180
181    /* We get one field with fraction bits for the maximum addressable
182     * (lowest resolution) LOD.  Use it to cover both MAX_LEVEL and
183     * MAX_LOD.
184     */
185    maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel);
186    state[I915_TEXREG_MS4] =
187       ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
188        MS4_CUBE_FACE_ENA_MASK |
189        (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) |
190        ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
191
192
193    {
194       GLuint minFilt, mipFilt, magFilt;
195
196       switch (sampler->MinFilter) {
197       case GL_NEAREST:
198          minFilt = FILTER_NEAREST;
199          mipFilt = MIPFILTER_NONE;
200          break;
201       case GL_LINEAR:
202          minFilt = FILTER_LINEAR;
203          mipFilt = MIPFILTER_NONE;
204          break;
205       case GL_NEAREST_MIPMAP_NEAREST:
206          minFilt = FILTER_NEAREST;
207          mipFilt = MIPFILTER_NEAREST;
208          break;
209       case GL_LINEAR_MIPMAP_NEAREST:
210          minFilt = FILTER_LINEAR;
211          mipFilt = MIPFILTER_NEAREST;
212          break;
213       case GL_NEAREST_MIPMAP_LINEAR:
214          minFilt = FILTER_NEAREST;
215          mipFilt = MIPFILTER_LINEAR;
216          break;
217       case GL_LINEAR_MIPMAP_LINEAR:
218          minFilt = FILTER_LINEAR;
219          mipFilt = MIPFILTER_LINEAR;
220          break;
221       default:
222          return GL_FALSE;
223       }
224
225       if (sampler->MaxAnisotropy > 1.0) {
226          minFilt = FILTER_ANISOTROPIC;
227          magFilt = FILTER_ANISOTROPIC;
228          if (sampler->MaxAnisotropy > 2.0)
229             aniso = SS2_MAX_ANISO_4;
230          else
231             aniso = SS2_MAX_ANISO_2;
232       }
233       else {
234          switch (sampler->MagFilter) {
235          case GL_NEAREST:
236             magFilt = FILTER_NEAREST;
237             break;
238          case GL_LINEAR:
239             magFilt = FILTER_LINEAR;
240             break;
241          default:
242             return GL_FALSE;
243          }
244       }
245
246       lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0);
247       if (lodbias < -256)
248           lodbias = -256;
249       if (lodbias > 255)
250           lodbias = 255;
251       state[I915_TEXREG_SS2] = ((lodbias << SS2_LOD_BIAS_SHIFT) & 
252                                 SS2_LOD_BIAS_MASK);
253
254       /* YUV conversion:
255        */
256       if (firstImage->TexFormat == MESA_FORMAT_YCBCR ||
257           firstImage->TexFormat == MESA_FORMAT_YCBCR_REV)
258          state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION;
259
260       /* Shadow:
261        */
262       if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
263           tObj->Target != GL_TEXTURE_3D) {
264          if (tObj->Target == GL_TEXTURE_1D) 
265             return GL_FALSE;
266
267          state[I915_TEXREG_SS2] |=
268             (SS2_SHADOW_ENABLE |
269              intel_translate_shadow_compare_func(sampler->CompareFunc));
270
271          minFilt = FILTER_4X4_FLAT;
272          magFilt = FILTER_4X4_FLAT;
273       }
274
275       state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
276                                  (mipFilt << SS2_MIP_FILTER_SHIFT) |
277                                  (magFilt << SS2_MAG_FILTER_SHIFT) |
278                                  aniso);
279    }
280
281    {
282       GLenum ws = sampler->WrapS;
283       GLenum wt = sampler->WrapT;
284       GLenum wr = sampler->WrapR;
285       float minlod;
286
287       /* We program 1D textures as 2D textures, so the 2D texcoord could
288        * result in sampling border values if we don't set the T wrap to
289        * repeat.
290        */
291       if (tObj->Target == GL_TEXTURE_1D)
292          wt = GL_REPEAT;
293
294       /* 3D textures don't seem to respect the border color.
295        * Fallback if there's ever a danger that they might refer to
296        * it.  
297        * 
298        * Effectively this means fallback on 3D clamp or
299        * clamp_to_border.
300        */
301       if (tObj->Target == GL_TEXTURE_3D &&
302           (sampler->MinFilter != GL_NEAREST ||
303            sampler->MagFilter != GL_NEAREST) &&
304           (ws == GL_CLAMP ||
305            wt == GL_CLAMP ||
306            wr == GL_CLAMP ||
307            ws == GL_CLAMP_TO_BORDER ||
308            wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER))
309          return GL_FALSE;
310
311       /* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not 
312        * used) when using cube map texture coordinates
313        */
314       if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
315           (((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) ||
316            ((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE))))
317           return GL_FALSE;
318
319       state[I915_TEXREG_SS3] = ss3;     /* SS3_NORMALIZED_COORDS */
320
321       state[I915_TEXREG_SS3] |=
322          ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) |
323           (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) |
324           (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT));
325
326       minlod = MIN2(sampler->MinLod, tObj->_MaxLevel - tObj->BaseLevel);
327       state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
328       state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(minlod, 0.0, 11.0), 4) <<
329                                  SS3_MIN_LOD_SHIFT);
330
331    }
332
333    /* convert border color from float to ubyte */
334    CLAMPED_FLOAT_TO_UBYTE(border[0], sampler->BorderColor.f[0]);
335    CLAMPED_FLOAT_TO_UBYTE(border[1], sampler->BorderColor.f[1]);
336    CLAMPED_FLOAT_TO_UBYTE(border[2], sampler->BorderColor.f[2]);
337    CLAMPED_FLOAT_TO_UBYTE(border[3], sampler->BorderColor.f[3]);
338
339    if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) {
340       /* GL specs that border color for depth textures is taken from the
341        * R channel, while the hardware uses A.  Spam R into all the channels
342        * for safety.
343        */
344       state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[0],
345                                                border[0],
346                                                border[0],
347                                                border[0]);
348    } else {
349       state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[3],
350                                                border[0],
351                                                border[1],
352                                                border[2]);
353    }
354
355
356    I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
357    /* memcmp was already disabled, but definitely won't work as the
358     * region might now change and that wouldn't be detected:
359     */
360    I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
361
362
363 #if 0
364    DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]);
365    DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]);
366    DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]);
367    DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]);
368    DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]);
369    DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]);
370 #endif
371
372    return GL_TRUE;
373 }
374
375
376
377
378 void
379 i915UpdateTextureState(struct intel_context *intel)
380 {
381    GLboolean ok = GL_TRUE;
382    GLuint i;
383
384    for (i = 0; i < I915_TEX_UNITS && ok; i++) {
385       switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
386       case TEXTURE_1D_BIT:
387       case TEXTURE_2D_BIT:
388       case TEXTURE_CUBE_BIT:
389       case TEXTURE_3D_BIT:
390          ok = i915_update_tex_unit(intel, i, SS3_NORMALIZED_COORDS);
391          break;
392       case TEXTURE_RECT_BIT:
393          ok = i915_update_tex_unit(intel, i, 0);
394          break;
395       case 0:{
396             struct i915_context *i915 = i915_context(&intel->ctx);
397             if (i915->state.active & I915_UPLOAD_TEX(i))
398                I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), GL_FALSE);
399
400             if (i915->state.tex_buffer[i] != NULL) {
401                drm_intel_bo_unreference(i915->state.tex_buffer[i]);
402                i915->state.tex_buffer[i] = NULL;
403             }
404
405             break;
406          }
407       default:
408          ok = GL_FALSE;
409          break;
410       }
411    }
412
413    FALLBACK(intel, I915_FALLBACK_TEXTURE, !ok);
414 }