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