i915_texstate.c revision f6c2d1f94ffa8f87b22ed1ff5c465d0e9aa1489e
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
33#include "intel_mipmap_tree.h"
34#include "intel_tex.h"
35
36#include "i915_context.h"
37#include "i915_reg.h"
38
39
40static GLuint
41translate_texture_format(gl_format mesa_format, GLuint internal_format,
42			 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      if (DepthMode == GL_ALPHA)
86	 return (MAPSURF_32BIT | MT_32BIT_x8A24);
87      else if (DepthMode == GL_INTENSITY)
88	 return (MAPSURF_32BIT | MT_32BIT_x8I24);
89      else
90	 return (MAPSURF_32BIT | MT_32BIT_x8L24);
91   default:
92      fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format);
93      abort();
94      return 0;
95   }
96}
97
98
99
100
101/* The i915 (and related graphics cores) do not support GL_CLAMP.  The
102 * Intel drivers for "other operating systems" implement GL_CLAMP as
103 * GL_CLAMP_TO_EDGE, so the same is done here.
104 */
105static GLuint
106translate_wrap_mode(GLenum wrap)
107{
108   switch (wrap) {
109   case GL_REPEAT:
110      return TEXCOORDMODE_WRAP;
111   case GL_CLAMP:
112      return TEXCOORDMODE_CLAMP_EDGE;   /* not quite correct */
113   case GL_CLAMP_TO_EDGE:
114      return TEXCOORDMODE_CLAMP_EDGE;
115   case GL_CLAMP_TO_BORDER:
116      return TEXCOORDMODE_CLAMP_BORDER;
117   case GL_MIRRORED_REPEAT:
118      return TEXCOORDMODE_MIRROR;
119   default:
120      return TEXCOORDMODE_WRAP;
121   }
122}
123
124
125
126/* Recalculate all state from scratch.  Perhaps not the most
127 * efficient, but this has gotten complex enough that we need
128 * something which is understandable and reliable.
129 */
130static GLboolean
131i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
132{
133   GLcontext *ctx = &intel->ctx;
134   struct i915_context *i915 = i915_context(ctx);
135   struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit];
136   struct gl_texture_object *tObj = tUnit->_Current;
137   struct intel_texture_object *intelObj = intel_texture_object(tObj);
138   struct gl_texture_image *firstImage;
139   GLuint *state = i915->state.Tex[unit], format, pitch;
140   GLint lodbias, aniso = 0;
141   GLubyte border[4];
142   GLfloat maxlod;
143
144   memset(state, 0, sizeof(state));
145
146   /*We need to refcount these. */
147
148   if (i915->state.tex_buffer[unit] != NULL) {
149       dri_bo_unreference(i915->state.tex_buffer[unit]);
150       i915->state.tex_buffer[unit] = NULL;
151   }
152
153   if (!intelObj->imageOverride && !intel_finalize_mipmap_tree(intel, unit))
154      return GL_FALSE;
155
156   /* Get first image here, since intelObj->firstLevel will get set in
157    * the intel_finalize_mipmap_tree() call above.
158    */
159   firstImage = tObj->Image[0][intelObj->firstLevel];
160
161   if (intelObj->imageOverride) {
162      i915->state.tex_buffer[unit] = NULL;
163      i915->state.tex_offset[unit] = intelObj->textureOffset;
164
165      switch (intelObj->depthOverride) {
166      case 32:
167	 format = MAPSURF_32BIT | MT_32BIT_ARGB8888;
168	 break;
169      case 24:
170      default:
171	 format = MAPSURF_32BIT | MT_32BIT_XRGB8888;
172	 break;
173      case 16:
174	 format = MAPSURF_16BIT | MT_16BIT_RGB565;
175	 break;
176      }
177
178      pitch = intelObj->pitchOverride;
179   } else {
180      dri_bo_reference(intelObj->mt->region->buffer);
181      i915->state.tex_buffer[unit] = intelObj->mt->region->buffer;
182      i915->state.tex_offset[unit] = 0; /* Always the origin of the miptree */
183
184      format = translate_texture_format(firstImage->TexFormat,
185					firstImage->InternalFormat,
186					tObj->DepthMode);
187      pitch = intelObj->mt->pitch * intelObj->mt->cpp;
188   }
189
190   state[I915_TEXREG_MS3] =
191      (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) |
192       ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format);
193
194   if (intelObj->mt->region->tiling != I915_TILING_NONE) {
195      state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE;
196      if (intelObj->mt->region->tiling == I915_TILING_Y)
197	 state[I915_TEXREG_MS3] |= MS3_TILE_WALK;
198   }
199
200   /* We get one field with fraction bits for the maximum addressable
201    * (lowest resolution) LOD.  Use it to cover both MAX_LEVEL and
202    * MAX_LOD.
203    */
204   maxlod = MIN2(tObj->MaxLod, tObj->_MaxLevel - tObj->BaseLevel);
205   state[I915_TEXREG_MS4] =
206      ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
207       MS4_CUBE_FACE_ENA_MASK |
208       (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) |
209       ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
210
211
212   {
213      GLuint minFilt, mipFilt, magFilt;
214
215      switch (tObj->MinFilter) {
216      case GL_NEAREST:
217         minFilt = FILTER_NEAREST;
218         mipFilt = MIPFILTER_NONE;
219         break;
220      case GL_LINEAR:
221         minFilt = FILTER_LINEAR;
222         mipFilt = MIPFILTER_NONE;
223         break;
224      case GL_NEAREST_MIPMAP_NEAREST:
225         minFilt = FILTER_NEAREST;
226         mipFilt = MIPFILTER_NEAREST;
227         break;
228      case GL_LINEAR_MIPMAP_NEAREST:
229         minFilt = FILTER_LINEAR;
230         mipFilt = MIPFILTER_NEAREST;
231         break;
232      case GL_NEAREST_MIPMAP_LINEAR:
233         minFilt = FILTER_NEAREST;
234         mipFilt = MIPFILTER_LINEAR;
235         break;
236      case GL_LINEAR_MIPMAP_LINEAR:
237         minFilt = FILTER_LINEAR;
238         mipFilt = MIPFILTER_LINEAR;
239         break;
240      default:
241         return GL_FALSE;
242      }
243
244      if (tObj->MaxAnisotropy > 1.0) {
245         minFilt = FILTER_ANISOTROPIC;
246         magFilt = FILTER_ANISOTROPIC;
247         if (tObj->MaxAnisotropy > 2.0)
248            aniso = SS2_MAX_ANISO_4;
249         else
250            aniso = SS2_MAX_ANISO_2;
251      }
252      else {
253         switch (tObj->MagFilter) {
254         case GL_NEAREST:
255            magFilt = FILTER_NEAREST;
256            break;
257         case GL_LINEAR:
258            magFilt = FILTER_LINEAR;
259            break;
260         default:
261            return GL_FALSE;
262         }
263      }
264
265      lodbias = (int) ((tUnit->LodBias + tObj->LodBias) * 16.0);
266      if (lodbias < -256)
267          lodbias = -256;
268      if (lodbias > 255)
269          lodbias = 255;
270      state[I915_TEXREG_SS2] = ((lodbias << SS2_LOD_BIAS_SHIFT) &
271                                SS2_LOD_BIAS_MASK);
272
273      /* YUV conversion:
274       */
275      if (firstImage->TexFormat == MESA_FORMAT_YCBCR ||
276          firstImage->TexFormat == MESA_FORMAT_YCBCR_REV)
277         state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION;
278
279      /* Shadow:
280       */
281      if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
282          tObj->Target != GL_TEXTURE_3D) {
283         if (tObj->Target == GL_TEXTURE_1D)
284            return GL_FALSE;
285
286         state[I915_TEXREG_SS2] |=
287            (SS2_SHADOW_ENABLE |
288             intel_translate_shadow_compare_func(tObj->CompareFunc));
289
290         minFilt = FILTER_4X4_FLAT;
291         magFilt = FILTER_4X4_FLAT;
292      }
293
294      state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
295                                 (mipFilt << SS2_MIP_FILTER_SHIFT) |
296                                 (magFilt << SS2_MAG_FILTER_SHIFT) |
297                                 aniso);
298   }
299
300   {
301      GLenum ws = tObj->WrapS;
302      GLenum wt = tObj->WrapT;
303      GLenum wr = tObj->WrapR;
304
305      /* We program 1D textures as 2D textures, so the 2D texcoord could
306       * result in sampling border values if we don't set the T wrap to
307       * repeat.
308       */
309      if (tObj->Target == GL_TEXTURE_1D)
310	 wt = GL_REPEAT;
311
312      /* 3D textures don't seem to respect the border color.
313       * Fallback if there's ever a danger that they might refer to
314       * it.
315       *
316       * Effectively this means fallback on 3D clamp or
317       * clamp_to_border.
318       */
319      if (tObj->Target == GL_TEXTURE_3D &&
320          (tObj->MinFilter != GL_NEAREST ||
321           tObj->MagFilter != GL_NEAREST) &&
322          (ws == GL_CLAMP ||
323           wt == GL_CLAMP ||
324           wr == GL_CLAMP ||
325           ws == GL_CLAMP_TO_BORDER ||
326           wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER))
327         return GL_FALSE;
328
329      /* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not
330       * used) when using cube map texture coordinates
331       */
332      if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
333          (((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) ||
334           ((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE))))
335          return GL_FALSE;
336
337      state[I915_TEXREG_SS3] = ss3;     /* SS3_NORMALIZED_COORDS */
338
339      state[I915_TEXREG_SS3] |=
340         ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) |
341          (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) |
342          (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT));
343
344      state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
345      state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(tObj->MinLod, 0.0, 11.0), 4) <<
346				 SS3_MIN_LOD_SHIFT);
347
348   }
349
350   /* convert border color from float to ubyte */
351   CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->BorderColor.f[0]);
352   CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->BorderColor.f[1]);
353   CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->BorderColor.f[2]);
354   CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->BorderColor.f[3]);
355
356   if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) {
357      /* GL specs that border color for depth textures is taken from the
358       * R channel, while the hardware uses A.  Spam R into all the channels
359       * for safety.
360       */
361      state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[0],
362					       border[0],
363					       border[0],
364					       border[0]);
365   } else {
366      state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[3],
367					       border[0],
368					       border[1],
369					       border[2]);
370   }
371
372
373   I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
374   /* memcmp was already disabled, but definitely won't work as the
375    * region might now change and that wouldn't be detected:
376    */
377   I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
378
379
380#if 0
381   DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]);
382   DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]);
383   DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]);
384   DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]);
385   DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]);
386   DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]);
387#endif
388
389   return GL_TRUE;
390}
391
392
393
394
395void
396i915UpdateTextureState(struct intel_context *intel)
397{
398   GLboolean ok = GL_TRUE;
399   GLuint i;
400
401   for (i = 0; i < I915_TEX_UNITS && ok; i++) {
402      switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
403      case TEXTURE_1D_BIT:
404      case TEXTURE_2D_BIT:
405      case TEXTURE_CUBE_BIT:
406      case TEXTURE_3D_BIT:
407         ok = i915_update_tex_unit(intel, i, SS3_NORMALIZED_COORDS);
408         break;
409      case TEXTURE_RECT_BIT:
410         ok = i915_update_tex_unit(intel, i, 0);
411         break;
412      case 0:{
413            struct i915_context *i915 = i915_context(&intel->ctx);
414            if (i915->state.active & I915_UPLOAD_TEX(i))
415               I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), GL_FALSE);
416
417	    if (i915->state.tex_buffer[i] != NULL) {
418	       dri_bo_unreference(i915->state.tex_buffer[i]);
419	       i915->state.tex_buffer[i] = NULL;
420	    }
421
422            break;
423         }
424      default:
425         ok = GL_FALSE;
426         break;
427      }
428   }
429
430   FALLBACK(intel, I915_FALLBACK_TEXTURE, !ok);
431}
432