i830_texstate.c revision 39cc0ee3eaf0d0cae70d91ae33961053782662c8
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/colormac.h" 31#include "main/macros.h" 32 33#include "intel_mipmap_tree.h" 34#include "intel_tex.h" 35 36#include "i830_context.h" 37#include "i830_reg.h" 38#include "intel_chipset.h" 39 40 41static GLuint 42translate_texture_format(GLuint mesa_format, GLuint internal_format) 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_I8; /* Kludge! */ 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_RGBA_DXT1: 71 case MESA_FORMAT_RGB_DXT1: 72 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); 73 case MESA_FORMAT_RGBA_DXT3: 74 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); 75 case MESA_FORMAT_RGBA_DXT5: 76 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); 77 default: 78 fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format); 79 abort(); 80 return 0; 81 } 82} 83 84 85 86 87/* The i915 (and related graphics cores) do not support GL_CLAMP. The 88 * Intel drivers for "other operating systems" implement GL_CLAMP as 89 * GL_CLAMP_TO_EDGE, so the same is done here. 90 */ 91static GLuint 92translate_wrap_mode(GLenum wrap) 93{ 94 switch (wrap) { 95 case GL_REPEAT: 96 return TEXCOORDMODE_WRAP; 97 case GL_CLAMP: 98 case GL_CLAMP_TO_EDGE: 99 return TEXCOORDMODE_CLAMP; /* not really correct */ 100 case GL_CLAMP_TO_BORDER: 101 return TEXCOORDMODE_CLAMP_BORDER; 102 case GL_MIRRORED_REPEAT: 103 return TEXCOORDMODE_MIRROR; 104 default: 105 return TEXCOORDMODE_WRAP; 106 } 107} 108 109 110/* Recalculate all state from scratch. Perhaps not the most 111 * efficient, but this has gotten complex enough that we need 112 * something which is understandable and reliable. 113 */ 114static GLboolean 115i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) 116{ 117 struct gl_context *ctx = &intel->ctx; 118 struct i830_context *i830 = i830_context(ctx); 119 struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; 120 struct gl_texture_object *tObj = tUnit->_Current; 121 struct intel_texture_object *intelObj = intel_texture_object(tObj); 122 struct gl_texture_image *firstImage; 123 GLuint *state = i830->state.Tex[unit], format, pitch; 124 GLint lodbias; 125 GLubyte border[4]; 126 GLuint dst_x, dst_y; 127 128 memset(state, 0, sizeof(state)); 129 130 /*We need to refcount these. */ 131 132 if (i830->state.tex_buffer[unit] != NULL) { 133 drm_intel_bo_unreference(i830->state.tex_buffer[unit]); 134 i830->state.tex_buffer[unit] = NULL; 135 } 136 137 if (!intel_finalize_mipmap_tree(intel, unit)) 138 return GL_FALSE; 139 140 /* Get first image here, since intelObj->firstLevel will get set in 141 * the intel_finalize_mipmap_tree() call above. 142 */ 143 firstImage = tObj->Image[0][intelObj->firstLevel]; 144 145 intel_miptree_get_image_offset(intelObj->mt, intelObj->firstLevel, 0, 0, 146 &dst_x, &dst_y); 147 148 drm_intel_bo_reference(intelObj->mt->region->buffer); 149 i830->state.tex_buffer[unit] = intelObj->mt->region->buffer; 150 pitch = intelObj->mt->region->pitch * intelObj->mt->cpp; 151 152 /* XXX: This calculation is probably broken for tiled images with 153 * a non-page-aligned offset. 154 */ 155 i830->state.tex_offset[unit] = dst_x * intelObj->mt->cpp + dst_y * pitch; 156 157 format = translate_texture_format(firstImage->TexFormat, 158 firstImage->InternalFormat); 159 160 state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 161 (LOAD_TEXTURE_MAP0 << unit) | 4); 162 163 state[I830_TEXREG_TM0S1] = 164 (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) | 165 ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format); 166 167 if (intelObj->mt->region->tiling != I915_TILING_NONE) { 168 state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE; 169 if (intelObj->mt->region->tiling == I915_TILING_Y) 170 state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK; 171 } 172 173 state[I830_TEXREG_TM0S2] = 174 ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK); 175 176 { 177 if (tObj->Target == GL_TEXTURE_CUBE_MAP) 178 state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) | 179 CUBE_NEGX_ENABLE | 180 CUBE_POSX_ENABLE | 181 CUBE_NEGY_ENABLE | 182 CUBE_POSY_ENABLE | 183 CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE); 184 else 185 state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit)); 186 } 187 188 189 190 191 { 192 GLuint minFilt, mipFilt, magFilt; 193 float maxlod; 194 uint32_t minlod_fixed, maxlod_fixed; 195 196 switch (tObj->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 (tObj->MaxAnisotropy > 1.0) { 226 minFilt = FILTER_ANISOTROPIC; 227 magFilt = FILTER_ANISOTROPIC; 228 } 229 else { 230 switch (tObj->MagFilter) { 231 case GL_NEAREST: 232 magFilt = FILTER_NEAREST; 233 break; 234 case GL_LINEAR: 235 magFilt = FILTER_LINEAR; 236 break; 237 default: 238 return GL_FALSE; 239 } 240 } 241 242 lodbias = (int) ((tUnit->LodBias + tObj->LodBias) * 16.0); 243 if (lodbias < -64) 244 lodbias = -64; 245 if (lodbias > 63) 246 lodbias = 63; 247 248 state[I830_TEXREG_TM0S3] = ((lodbias << TM0S3_LOD_BIAS_SHIFT) & 249 TM0S3_LOD_BIAS_MASK); 250#if 0 251 /* YUV conversion: 252 */ 253 if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR || 254 firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV) 255 state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION; 256#endif 257 258 /* We get one field with fraction bits for the maximum 259 * addressable (smallest resolution) LOD. Use it to cover both 260 * MAX_LEVEL and MAX_LOD. 261 */ 262 minlod_fixed = U_FIXED(CLAMP(tObj->MinLod, 0.0, 11), 4); 263 maxlod = MIN2(tObj->MaxLod, tObj->_MaxLevel - tObj->BaseLevel); 264 if (intel->intelScreen->deviceID == PCI_CHIP_I855_GM || 265 intel->intelScreen->deviceID == PCI_CHIP_I865_G) { 266 maxlod_fixed = U_FIXED(CLAMP(maxlod, 0.0, 11.75), 2); 267 maxlod_fixed = MAX2(maxlod_fixed, (minlod_fixed + 3) >> 2); 268 state[I830_TEXREG_TM0S3] |= maxlod_fixed << TM0S3_MIN_MIP_SHIFT; 269 state[I830_TEXREG_TM0S2] |= TM0S2_LOD_PRECLAMP; 270 } else { 271 maxlod_fixed = U_FIXED(CLAMP(maxlod, 0.0, 11), 0); 272 maxlod_fixed = MAX2(maxlod_fixed, (minlod_fixed + 15) >> 4); 273 state[I830_TEXREG_TM0S3] |= maxlod_fixed << TM0S3_MIN_MIP_SHIFT_830; 274 } 275 state[I830_TEXREG_TM0S3] |= minlod_fixed << TM0S3_MAX_MIP_SHIFT; 276 state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) | 277 (mipFilt << TM0S3_MIP_FILTER_SHIFT) | 278 (magFilt << TM0S3_MAG_FILTER_SHIFT)); 279 } 280 281 { 282 GLenum ws = tObj->WrapS; 283 GLenum wt = tObj->WrapT; 284 285 286 /* 3D textures not available on i830 287 */ 288 if (tObj->Target == GL_TEXTURE_3D) 289 return GL_FALSE; 290 291 state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD | 292 MAP_UNIT(unit) | 293 ENABLE_TEXCOORD_PARAMS | 294 ss3 | 295 ENABLE_ADDR_V_CNTL | 296 TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt)) 297 | ENABLE_ADDR_U_CNTL | 298 TEXCOORD_ADDR_U_MODE(translate_wrap_mode 299 (ws))); 300 } 301 302 /* convert border color from float to ubyte */ 303 CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->BorderColor.f[0]); 304 CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->BorderColor.f[1]); 305 CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->BorderColor.f[2]); 306 CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->BorderColor.f[3]); 307 308 state[I830_TEXREG_TM0S4] = PACK_COLOR_8888(border[3], 309 border[0], 310 border[1], 311 border[2]); 312 313 I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE); 314 /* memcmp was already disabled, but definitely won't work as the 315 * region might now change and that wouldn't be detected: 316 */ 317 I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); 318 return GL_TRUE; 319} 320 321 322 323 324void 325i830UpdateTextureState(struct intel_context *intel) 326{ 327 struct i830_context *i830 = i830_context(&intel->ctx); 328 GLboolean ok = GL_TRUE; 329 GLuint i; 330 331 for (i = 0; i < I830_TEX_UNITS && ok; i++) { 332 switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) { 333 case TEXTURE_1D_BIT: 334 case TEXTURE_2D_BIT: 335 case TEXTURE_CUBE_BIT: 336 ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_NORMAL); 337 break; 338 case TEXTURE_RECT_BIT: 339 ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_IN_TEXELUNITS); 340 break; 341 case 0:{ 342 struct i830_context *i830 = i830_context(&intel->ctx); 343 if (i830->state.active & I830_UPLOAD_TEX(i)) 344 I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), GL_FALSE); 345 346 if (i830->state.tex_buffer[i] != NULL) { 347 drm_intel_bo_unreference(i830->state.tex_buffer[i]); 348 i830->state.tex_buffer[i] = NULL; 349 } 350 break; 351 } 352 case TEXTURE_3D_BIT: 353 default: 354 ok = GL_FALSE; 355 break; 356 } 357 } 358 359 FALLBACK(intel, I830_FALLBACK_TEXTURE, !ok); 360 361 if (ok) 362 i830EmitTextureBlend(i830); 363} 364