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