1/************************************************************************** 2 * 3 * Copyright 2003 VMware, Inc. 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 VMWARE 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 41static GLuint 42translate_texture_format(mesa_format mesa_format, GLenum DepthMode) 43{ 44 switch (mesa_format) { 45 case MESA_FORMAT_L_UNORM8: 46 return MAPSURF_8BIT | MT_8BIT_L8; 47 case MESA_FORMAT_I_UNORM8: 48 return MAPSURF_8BIT | MT_8BIT_I8; 49 case MESA_FORMAT_A_UNORM8: 50 return MAPSURF_8BIT | MT_8BIT_A8; 51 case MESA_FORMAT_L8A8_UNORM: 52 return MAPSURF_16BIT | MT_16BIT_AY88; 53 case MESA_FORMAT_B5G6R5_UNORM: 54 return MAPSURF_16BIT | MT_16BIT_RGB565; 55 case MESA_FORMAT_B5G5R5A1_UNORM: 56 return MAPSURF_16BIT | MT_16BIT_ARGB1555; 57 case MESA_FORMAT_B4G4R4A4_UNORM: 58 return MAPSURF_16BIT | MT_16BIT_ARGB4444; 59 case MESA_FORMAT_B8G8R8A8_SRGB: 60 case MESA_FORMAT_B8G8R8A8_UNORM: 61 return MAPSURF_32BIT | MT_32BIT_ARGB8888; 62 case MESA_FORMAT_B8G8R8X8_UNORM: 63 return MAPSURF_32BIT | MT_32BIT_XRGB8888; 64 case MESA_FORMAT_R8G8B8A8_UNORM: 65 return MAPSURF_32BIT | MT_32BIT_ABGR8888; 66 case MESA_FORMAT_YCBCR_REV: 67 return (MAPSURF_422 | MT_422_YCRCB_NORMAL); 68 case MESA_FORMAT_YCBCR: 69 return (MAPSURF_422 | MT_422_YCRCB_SWAPY); 70 case MESA_FORMAT_RGB_FXT1: 71 case MESA_FORMAT_RGBA_FXT1: 72 return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); 73 case MESA_FORMAT_Z_UNORM16: 74 if (DepthMode == GL_ALPHA) 75 return (MAPSURF_16BIT | MT_16BIT_A16); 76 else if (DepthMode == GL_INTENSITY) 77 return (MAPSURF_16BIT | MT_16BIT_I16); 78 else 79 return (MAPSURF_16BIT | MT_16BIT_L16); 80 case MESA_FORMAT_RGBA_DXT1: 81 case MESA_FORMAT_RGB_DXT1: 82 case MESA_FORMAT_SRGB_DXT1: 83 case MESA_FORMAT_SRGBA_DXT1: 84 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); 85 case MESA_FORMAT_RGBA_DXT3: 86 case MESA_FORMAT_SRGBA_DXT3: 87 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); 88 case MESA_FORMAT_RGBA_DXT5: 89 case MESA_FORMAT_SRGBA_DXT5: 90 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); 91 case MESA_FORMAT_Z24_UNORM_S8_UINT: 92 case MESA_FORMAT_Z24_UNORM_X8_UINT: 93 if (DepthMode == GL_ALPHA) 94 return (MAPSURF_32BIT | MT_32BIT_x8A24); 95 else if (DepthMode == GL_INTENSITY) 96 return (MAPSURF_32BIT | MT_32BIT_x8I24); 97 else 98 return (MAPSURF_32BIT | MT_32BIT_x8L24); 99 default: 100 fprintf(stderr, "%s: bad image format %s\n", __func__, 101 _mesa_get_format_name(mesa_format)); 102 abort(); 103 return 0; 104 } 105} 106 107 108 109 110/* The i915 (and related graphics cores) do not support GL_CLAMP. The 111 * Intel drivers for "other operating systems" implement GL_CLAMP as 112 * GL_CLAMP_TO_EDGE, so the same is done here. 113 */ 114static GLuint 115translate_wrap_mode(GLenum wrap) 116{ 117 switch (wrap) { 118 case GL_REPEAT: 119 return TEXCOORDMODE_WRAP; 120 case GL_CLAMP: 121 return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */ 122 case GL_CLAMP_TO_EDGE: 123 return TEXCOORDMODE_CLAMP_EDGE; 124 case GL_CLAMP_TO_BORDER: 125 return TEXCOORDMODE_CLAMP_BORDER; 126 case GL_MIRRORED_REPEAT: 127 return TEXCOORDMODE_MIRROR; 128 default: 129 return TEXCOORDMODE_WRAP; 130 } 131} 132 133 134 135/* Recalculate all state from scratch. Perhaps not the most 136 * efficient, but this has gotten complex enough that we need 137 * something which is understandable and reliable. 138 */ 139static bool 140i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) 141{ 142 struct gl_context *ctx = &intel->ctx; 143 struct i915_context *i915 = i915_context(ctx); 144 struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; 145 struct gl_texture_object *tObj = tUnit->_Current; 146 struct intel_texture_object *intelObj = intel_texture_object(tObj); 147 struct gl_texture_image *firstImage; 148 struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); 149 GLuint *state = i915->state.Tex[unit], format; 150 GLint lodbias, aniso = 0; 151 GLubyte border[4]; 152 GLfloat maxlod; 153 154 memset(state, 0, sizeof(*state)); 155 156 /*We need to refcount these. */ 157 158 if (i915->state.tex_buffer[unit] != NULL) { 159 drm_intel_bo_unreference(i915->state.tex_buffer[unit]); 160 i915->state.tex_buffer[unit] = NULL; 161 } 162 163 if (!intel_finalize_mipmap_tree(intel, unit)) 164 return false; 165 166 /* Get first image here, since intelObj->firstLevel will get set in 167 * the intel_finalize_mipmap_tree() call above. 168 */ 169 firstImage = tObj->Image[0][tObj->BaseLevel]; 170 171 drm_intel_bo_reference(intelObj->mt->region->bo); 172 i915->state.tex_buffer[unit] = intelObj->mt->region->bo; 173 i915->state.tex_offset[unit] = intelObj->mt->offset; 174 175 format = translate_texture_format(firstImage->TexFormat, 176 tObj->DepthMode); 177 178 state[I915_TEXREG_MS3] = 179 (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) | 180 ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format); 181 182 if (intelObj->mt->region->tiling != I915_TILING_NONE) { 183 state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE; 184 if (intelObj->mt->region->tiling == I915_TILING_Y) 185 state[I915_TEXREG_MS3] |= MS3_TILE_WALK; 186 } 187 188 /* We get one field with fraction bits for the maximum addressable 189 * (lowest resolution) LOD. Use it to cover both MAX_LEVEL and 190 * MAX_LOD. 191 */ 192 maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel); 193 state[I915_TEXREG_MS4] = 194 ((((intelObj->mt->region->pitch / 4) - 1) << MS4_PITCH_SHIFT) | 195 MS4_CUBE_FACE_ENA_MASK | 196 (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) | 197 ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); 198 199 200 { 201 GLuint minFilt, mipFilt, magFilt; 202 203 switch (sampler->MinFilter) { 204 case GL_NEAREST: 205 minFilt = FILTER_NEAREST; 206 mipFilt = MIPFILTER_NONE; 207 break; 208 case GL_LINEAR: 209 minFilt = FILTER_LINEAR; 210 mipFilt = MIPFILTER_NONE; 211 break; 212 case GL_NEAREST_MIPMAP_NEAREST: 213 minFilt = FILTER_NEAREST; 214 mipFilt = MIPFILTER_NEAREST; 215 break; 216 case GL_LINEAR_MIPMAP_NEAREST: 217 minFilt = FILTER_LINEAR; 218 mipFilt = MIPFILTER_NEAREST; 219 break; 220 case GL_NEAREST_MIPMAP_LINEAR: 221 minFilt = FILTER_NEAREST; 222 mipFilt = MIPFILTER_LINEAR; 223 break; 224 case GL_LINEAR_MIPMAP_LINEAR: 225 minFilt = FILTER_LINEAR; 226 mipFilt = MIPFILTER_LINEAR; 227 break; 228 default: 229 return false; 230 } 231 232 if (sampler->MaxAnisotropy > 1.0) { 233 minFilt = FILTER_ANISOTROPIC; 234 magFilt = FILTER_ANISOTROPIC; 235 if (sampler->MaxAnisotropy > 2.0) 236 aniso = SS2_MAX_ANISO_4; 237 else 238 aniso = SS2_MAX_ANISO_2; 239 } 240 else { 241 switch (sampler->MagFilter) { 242 case GL_NEAREST: 243 magFilt = FILTER_NEAREST; 244 break; 245 case GL_LINEAR: 246 magFilt = FILTER_LINEAR; 247 break; 248 default: 249 return false; 250 } 251 } 252 253 lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0); 254 if (lodbias < -256) 255 lodbias = -256; 256 if (lodbias > 255) 257 lodbias = 255; 258 state[I915_TEXREG_SS2] = ((lodbias << SS2_LOD_BIAS_SHIFT) & 259 SS2_LOD_BIAS_MASK); 260 261 /* YUV conversion: 262 */ 263 if (firstImage->TexFormat == MESA_FORMAT_YCBCR || 264 firstImage->TexFormat == MESA_FORMAT_YCBCR_REV) 265 state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION; 266 267 /* Shadow: 268 */ 269 if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && 270 tObj->Target != GL_TEXTURE_3D) { 271 if (tObj->Target == GL_TEXTURE_1D) 272 return false; 273 274 state[I915_TEXREG_SS2] |= 275 (SS2_SHADOW_ENABLE | 276 intel_translate_shadow_compare_func(sampler->CompareFunc)); 277 278 minFilt = FILTER_4X4_FLAT; 279 magFilt = FILTER_4X4_FLAT; 280 } 281 282 state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | 283 (mipFilt << SS2_MIP_FILTER_SHIFT) | 284 (magFilt << SS2_MAG_FILTER_SHIFT) | 285 aniso); 286 } 287 288 { 289 GLenum ws = sampler->WrapS; 290 GLenum wt = sampler->WrapT; 291 GLenum wr = sampler->WrapR; 292 float minlod; 293 294 /* We program 1D textures as 2D textures, so the 2D texcoord could 295 * result in sampling border values if we don't set the T wrap to 296 * repeat. 297 */ 298 if (tObj->Target == GL_TEXTURE_1D) 299 wt = GL_REPEAT; 300 301 /* 3D textures don't seem to respect the border color. 302 * Fallback if there's ever a danger that they might refer to 303 * it. 304 * 305 * Effectively this means fallback on 3D clamp or 306 * clamp_to_border. 307 */ 308 if (tObj->Target == GL_TEXTURE_3D && 309 (sampler->MinFilter != GL_NEAREST || 310 sampler->MagFilter != GL_NEAREST) && 311 (ws == GL_CLAMP || 312 wt == GL_CLAMP || 313 wr == GL_CLAMP || 314 ws == GL_CLAMP_TO_BORDER || 315 wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER)) 316 return false; 317 318 /* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not 319 * used) when using cube map texture coordinates 320 */ 321 if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB && 322 (((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) || 323 ((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE)))) 324 return false; 325 326 /* 327 * According to 3DSTATE_MAP_STATE at page of 104 in Bspec 328 * Vol3d 3D Instructions: 329 * [DevGDG and DevAlv]: Must be a power of 2 for cube maps. 330 * [DevLPT, DevCST and DevBLB]: If not a power of 2, cube maps 331 * must have all faces enabled. 332 * 333 * But, as I tested on pineview(DevBLB derived), the rendering is 334 * bad(you will find the color isn't samplered right in some 335 * fragments). After checking, it seems that the texture layout is 336 * wrong: making the width and height align of 4(although this 337 * doesn't make much sense) will fix this issue and also broke some 338 * others. Well, Bspec mentioned nothing about the layout alignment 339 * and layout for NPOT cube map. I guess the Bspec just assume it's 340 * a POT cube map. 341 * 342 * Thus, I guess we need do this for other platforms as well. 343 */ 344 if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB && 345 !_mesa_is_pow_two(firstImage->Height)) 346 return false; 347 348 state[I915_TEXREG_SS3] = ss3; /* SS3_NORMALIZED_COORDS */ 349 350 state[I915_TEXREG_SS3] |= 351 ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) | 352 (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) | 353 (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT)); 354 355 minlod = MIN2(sampler->MinLod, tObj->_MaxLevel - tObj->BaseLevel); 356 state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); 357 state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(minlod, 0.0, 11.0), 4) << 358 SS3_MIN_LOD_SHIFT); 359 360 } 361 362 if (sampler->sRGBDecode == GL_DECODE_EXT && 363 (_mesa_get_srgb_format_linear(firstImage->TexFormat) != 364 firstImage->TexFormat)) { 365 state[I915_TEXREG_SS2] |= SS2_REVERSE_GAMMA_ENABLE; 366 } 367 368 /* convert border color from float to ubyte */ 369 CLAMPED_FLOAT_TO_UBYTE(border[0], sampler->BorderColor.f[0]); 370 CLAMPED_FLOAT_TO_UBYTE(border[1], sampler->BorderColor.f[1]); 371 CLAMPED_FLOAT_TO_UBYTE(border[2], sampler->BorderColor.f[2]); 372 CLAMPED_FLOAT_TO_UBYTE(border[3], sampler->BorderColor.f[3]); 373 374 if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) { 375 /* GL specs that border color for depth textures is taken from the 376 * R channel, while the hardware uses A. Spam R into all the channels 377 * for safety. 378 */ 379 state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[0], 380 border[0], 381 border[0], 382 border[0]); 383 } else { 384 state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[3], 385 border[0], 386 border[1], 387 border[2]); 388 } 389 390 391 I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), true); 392 /* memcmp was already disabled, but definitely won't work as the 393 * region might now change and that wouldn't be detected: 394 */ 395 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); 396 397 398#if 0 399 DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]); 400 DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]); 401 DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]); 402 DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]); 403 DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]); 404 DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]); 405#endif 406 407 return true; 408} 409 410 411 412 413void 414i915UpdateTextureState(struct intel_context *intel) 415{ 416 bool ok = true; 417 GLuint i; 418 419 for (i = 0; i < I915_TEX_UNITS && ok; i++) { 420 if (intel->ctx.Texture.Unit[i]._Current) { 421 switch (intel->ctx.Texture.Unit[i]._Current->Target) { 422 case GL_TEXTURE_1D: 423 case GL_TEXTURE_2D: 424 case GL_TEXTURE_CUBE_MAP: 425 case GL_TEXTURE_3D: 426 ok = i915_update_tex_unit(intel, i, SS3_NORMALIZED_COORDS); 427 break; 428 case GL_TEXTURE_RECTANGLE: 429 ok = i915_update_tex_unit(intel, i, 0); 430 break; 431 default: 432 ok = false; 433 break; 434 } 435 } else { 436 struct i915_context *i915 = i915_context(&intel->ctx); 437 if (i915->state.active & I915_UPLOAD_TEX(i)) 438 I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), false); 439 440 if (i915->state.tex_buffer[i] != NULL) { 441 drm_intel_bo_unreference(i915->state.tex_buffer[i]); 442 i915->state.tex_buffer[i] = NULL; 443 } 444 } 445 } 446 447 FALLBACK(intel, I915_FALLBACK_TEXTURE, !ok); 448} 449