i915_texstate.c revision a9fc8ba756dd25a07dc19058fe60f65bda82a055
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 "glheader.h" 29#include "macros.h" 30#include "mtypes.h" 31#include "simple_list.h" 32#include "enums.h" 33#include "texformat.h" 34#include "texstore.h" 35 36#include "mm.h" 37 38#include "intel_screen.h" 39#include "intel_ioctl.h" 40#include "intel_tex.h" 41 42#include "i915_context.h" 43#include "i915_reg.h" 44 45static GLint initial_offsets[6][2] = { {0,0}, 46 {0,2}, 47 {1,0}, 48 {1,2}, 49 {1,1}, 50 {1,3} }; 51 52 53static GLint step_offsets[6][2] = { {0,2}, 54 {0,2}, 55 {-1,2}, 56 {-1,2}, 57 {-1,1}, 58 {-1,1} }; 59 60 61#define I915_TEX_UNIT_ENABLED(unit) (1<<unit) 62 63static void i915LayoutTextureImages( i915ContextPtr i915, 64 struct gl_texture_object *tObj ) 65{ 66 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; 67 i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; 68 GLint firstLevel, lastLevel, numLevels; 69 GLint i, total_height, pitch; 70 71 /* Compute which mipmap levels we really want to send to the hardware. 72 */ 73 driCalculateTextureFirstLastLevel( (driTextureObject *) t ); 74 75 /* Figure out the amount of memory required to hold all the mipmap 76 * levels. Choose the smallest pitch to accomodate the largest 77 * mipmap: 78 */ 79 firstLevel = t->intel.base.firstLevel; 80 lastLevel = t->intel.base.lastLevel; 81 numLevels = lastLevel - firstLevel + 1; 82 83 84 85 /* All images must be loaded at this pitch. Count the number of 86 * lines required: 87 */ 88 switch (tObj->Target) { 89 case GL_TEXTURE_CUBE_MAP: { 90 const GLuint dim = tObj->Image[0][firstLevel]->Width; 91 GLuint face; 92 93 pitch = dim * t->intel.texelBytes; 94 pitch *= 2; /* double pitch for cube layouts */ 95 pitch = (pitch + 3) & ~3; 96 97 total_height = dim * 4; 98 99 for ( face = 0 ; face < 6 ; face++) { 100 GLuint x = initial_offsets[face][0] * dim; 101 GLuint y = initial_offsets[face][1] * dim; 102 GLuint d = dim; 103 104 t->intel.base.dirty_images[face] = ~0; 105 106 assert(tObj->Image[face][firstLevel]->Width == dim); 107 assert(tObj->Image[face][firstLevel]->Height == dim); 108 109 for (i = 0; i < numLevels; i++) { 110 t->intel.image[face][i].image = tObj->Image[face][firstLevel + i]; 111 if (!t->intel.image[face][i].image) { 112 fprintf(stderr, "no image %d %d\n", face, i); 113 break; /* can't happen */ 114 } 115 116 t->intel.image[face][i].offset = 117 y * pitch + x * t->intel.texelBytes; 118 t->intel.image[face][i].internalFormat = baseImage->_BaseFormat; 119 120 d >>= 1; 121 x += step_offsets[face][0] * d; 122 y += step_offsets[face][1] * d; 123 } 124 } 125 break; 126 } 127 case GL_TEXTURE_3D: { 128 GLuint virtual_height; 129 GLuint tmp_numLevels = numLevels; 130 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; 131 pitch = (pitch + 3) & ~3; 132 t->intel.base.dirty_images[0] = ~0; 133 134 /* Calculate the size of a single slice. Hardware demands a 135 * minimum of 8 mipmaps, some of which might ultimately not be 136 * used: 137 */ 138 if (tmp_numLevels < 9) 139 tmp_numLevels = 9; 140 141 virtual_height = tObj->Image[0][firstLevel]->Height; 142 143 for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) { 144 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; 145 if (t->intel.image[0][i].image) { 146 t->intel.image[0][i].offset = total_height * pitch; 147 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; 148 } 149 150 total_height += MAX2(2, virtual_height); 151 virtual_height >>= 1; 152 } 153 154 t->intel.depth_pitch = total_height * pitch; 155 156 /* Multiply slice size by texture depth for total size. It's 157 * remarkable how wasteful of memory all the i8x0 texture 158 * layouts are. 159 */ 160 total_height *= t->intel.image[0][0].image->Depth; 161 break; 162 } 163 default: 164 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; 165 pitch = (pitch + 3) & ~3; 166 t->intel.base.dirty_images[0] = ~0; 167 168 for ( total_height = i = 0 ; i < numLevels ; i++ ) { 169 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; 170 if (!t->intel.image[0][i].image) 171 break; 172 173 t->intel.image[0][i].offset = total_height * pitch; 174 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; 175 if (t->intel.image[0][i].image->IsCompressed) 176 { 177 if (t->intel.image[0][i].image->Height > 4) 178 total_height += t->intel.image[0][i].image->Height/4; 179 else 180 total_height += 1; 181 } 182 else 183 total_height += MAX2(2, t->intel.image[0][i].image->Height); 184 } 185 break; 186 } 187 188 t->intel.Pitch = pitch; 189 t->intel.base.totalSize = total_height*pitch; 190 t->intel.max_level = numLevels-1; 191} 192 193 194static void i945LayoutTextureImages( i915ContextPtr i915, 195 struct gl_texture_object *tObj ) 196{ 197 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; 198 i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; 199 GLint firstLevel, lastLevel, numLevels; 200 GLint i, total_height, pitch, sz, max_offset = 0, offset; 201 202 203 /* Compute which mipmap levels we really want to send to the hardware. 204 */ 205 driCalculateTextureFirstLastLevel( (driTextureObject *) t ); 206 207 /* Figure out the amount of memory required to hold all the mipmap 208 * levels. Choose the smallest pitch to accomodate the largest 209 * mipmap: 210 */ 211 firstLevel = t->intel.base.firstLevel; 212 lastLevel = t->intel.base.lastLevel; 213 numLevels = lastLevel - firstLevel + 1; 214 215 216 217 /* All images must be loaded at this pitch. Count the number of 218 * lines required: 219 */ 220 switch (tObj->Target) { 221 case GL_TEXTURE_CUBE_MAP: { 222 const GLuint dim = tObj->Image[0][firstLevel]->Width; 223 GLuint face; 224 225 /* Depending on the size of the largest images, pitch can be 226 * determined either by the old-style packing of cubemap faces, 227 * or the final row of 4x4, 2x2 and 1x1 faces below this. 228 */ 229 if (dim > 32) { 230 pitch = dim * t->intel.texelBytes; 231 pitch *= 2; /* double pitch for cube layouts */ 232 pitch = (pitch + 3) & ~3; 233 } 234 else { 235 pitch = 14 * 8 * t->intel.texelBytes; /* determined by row of 236 * little maps at 237 * bottom */ 238 } 239 240 total_height = dim * 4 + 4; 241 242 for ( face = 0 ; face < 6 ; face++) { 243 GLuint x = initial_offsets[face][0] * dim; 244 GLuint y = initial_offsets[face][1] * dim; 245 GLuint d = dim; 246 247 if (dim == 4 && face >= 4) { 248 y = total_height - 4; 249 x = (face - 4) * 8; 250 } 251 else if (dim < 4) { 252 y = total_height - 4; 253 x = face * 8; 254 } 255 256 t->intel.base.dirty_images[face] = ~0; 257 258 assert(tObj->Image[face][firstLevel]->Width == dim); 259 assert(tObj->Image[face][firstLevel]->Height == dim); 260 261 for (i = 0; i < numLevels; i++) { 262 263 264 t->intel.image[face][i].image = tObj->Image[face][firstLevel + i]; 265 assert(t->intel.image[face][i].image); 266 267 t->intel.image[face][i].offset = 268 y * pitch + x * t->intel.texelBytes; 269 t->intel.image[face][i].internalFormat = baseImage->_BaseFormat; 270 271 d >>= 1; 272 273 switch (d) { 274 case 4: 275 switch (face) { 276 case FACE_POS_X: 277 case FACE_NEG_X: 278 x += step_offsets[face][0] * d; 279 y += step_offsets[face][1] * d; 280 break; 281 case FACE_POS_Y: 282 case FACE_NEG_Y: 283 y += 12; 284 x -= 8; 285 break; 286 case FACE_POS_Z: 287 case FACE_NEG_Z: 288 y = total_height - 4; 289 x = (face - 4) * 8; 290 break; 291 } 292 293 case 2: 294 y = total_height - 4; 295 x = 16 + face * 8; 296 break; 297 298 case 1: 299 x += 48; 300 break; 301 302 default: 303 x += step_offsets[face][0] * d; 304 y += step_offsets[face][1] * d; 305 break; 306 } 307 } 308 } 309 max_offset = total_height * pitch; 310 break; 311 } 312 case GL_TEXTURE_3D: { 313 GLuint depth_packing = 0, depth_pack_pitch; 314 GLuint tmp_numLevels = numLevels; 315 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; 316 pitch = (pitch + 3) & ~3; 317 depth_pack_pitch = pitch; 318 319 t->intel.base.dirty_images[0] = ~0; 320 321 322 for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) { 323 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; 324 if (!t->intel.image[0][i].image) 325 break; 326 327 328 t->intel.image[0][i].offset = total_height * pitch; 329 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; 330 331 332 333 total_height += MAX2(2, t->intel.image[0][i].image->Height) * 334 MAX2((t->intel.image[0][i].image->Depth >> depth_packing), 1); 335 336 /* When alignment dominates, can't increase depth packing? 337 * Or does pitch grow??? What are the alignment constraints, 338 * anyway? 339 */ 340 if (depth_pack_pitch > 4) { 341 depth_packing++; 342 depth_pack_pitch <<= 2; 343 } 344 } 345 346 max_offset = total_height * pitch; 347 break; 348 } 349 default: 350 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; 351 pitch = (pitch + 3) & ~3; 352 t->intel.base.dirty_images[0] = ~0; 353 max_offset = 0; 354 355 for ( offset = i = 0 ; i < numLevels ; i++ ) { 356 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; 357 if (!t->intel.image[0][i].image) 358 break; 359 360 t->intel.image[0][i].offset = offset; 361 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; 362 363 if (t->intel.image[0][i].image->IsCompressed) 364 sz = MAX2(1, t->intel.image[0][i].image->Height/4) * pitch; 365 else 366 sz = MAX2(2, t->intel.image[0][i].image->Height) * pitch; 367 368 /* Because the images are packed better, the final offset 369 * might not be the maximal one: 370 */ 371 max_offset = MAX2(max_offset, offset + sz); 372 373 /* LPT change: step right after second mipmap. 374 */ 375 if (i == 1) 376 offset += pitch / 2; 377 else 378 offset += sz; 379 380 } 381 break; 382 } 383 384 t->intel.Pitch = pitch; 385 t->intel.base.totalSize = max_offset; 386 t->intel.max_level = numLevels-1; 387} 388 389 390 391 392static void i915SetTexImages( i915ContextPtr i915, 393 struct gl_texture_object *tObj ) 394{ 395 GLuint textureFormat; 396 i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; 397 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; 398 GLint ss2 = 0; 399 400 switch( baseImage->TexFormat->MesaFormat ) { 401 case MESA_FORMAT_L8: 402 t->intel.texelBytes = 1; 403 textureFormat = MAPSURF_8BIT | MT_8BIT_L8; 404 break; 405 406 case MESA_FORMAT_I8: 407 t->intel.texelBytes = 1; 408 textureFormat = MAPSURF_8BIT | MT_8BIT_I8; 409 break; 410 411 case MESA_FORMAT_A8: 412 t->intel.texelBytes = 1; 413 textureFormat = MAPSURF_8BIT | MT_8BIT_A8; 414 break; 415 416 case MESA_FORMAT_AL88: 417 t->intel.texelBytes = 2; 418 textureFormat = MAPSURF_16BIT | MT_16BIT_AY88; 419 break; 420 421 case MESA_FORMAT_RGB565: 422 t->intel.texelBytes = 2; 423 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565; 424 break; 425 426 case MESA_FORMAT_ARGB1555: 427 t->intel.texelBytes = 2; 428 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555; 429 break; 430 431 case MESA_FORMAT_ARGB4444: 432 t->intel.texelBytes = 2; 433 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444; 434 break; 435 436 case MESA_FORMAT_ARGB8888: 437 t->intel.texelBytes = 4; 438 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888; 439 break; 440 441 case MESA_FORMAT_YCBCR_REV: 442 t->intel.texelBytes = 2; 443 textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL); 444 ss2 |= SS2_COLORSPACE_CONVERSION; 445 break; 446 447 case MESA_FORMAT_YCBCR: 448 t->intel.texelBytes = 2; 449 textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY); 450 ss2 |= SS2_COLORSPACE_CONVERSION; 451 break; 452 453 case MESA_FORMAT_RGB_FXT1: 454 case MESA_FORMAT_RGBA_FXT1: 455 t->intel.texelBytes = 2; 456 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); 457 break; 458 459 case MESA_FORMAT_DEPTH_COMPONENT16: 460 t->intel.texelBytes = 2; 461 textureFormat = (MAPSURF_16BIT | MT_16BIT_L16); 462 break; 463 464 case MESA_FORMAT_RGBA_DXT1: 465 case MESA_FORMAT_RGB_DXT1: 466 /* 467 * DXTn pitches are Width/4 * blocksize in bytes 468 * for DXT1: blocksize=8 so Width/4*8 = Width * 2 469 * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4 470 */ 471 t->intel.texelBytes = 2; 472 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); 473 break; 474 475 case MESA_FORMAT_RGBA_DXT3: 476 t->intel.texelBytes = 4; 477 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); 478 break; 479 480 case MESA_FORMAT_RGBA_DXT5: 481 t->intel.texelBytes = 4; 482 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); 483 break; 484 485#if 0 486 case MESA_FORMAT_DEPTH_COMPONENT_X8Z24: 487 t->intel.texelBytes = 4; 488 textureFormat = (MAPSURF_32BIT | MT_32BIT_xL824); 489 break; 490#endif 491 492 default: 493 fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, 494 baseImage->TexFormat->MesaFormat); 495 abort(); 496 } 497 498 499 if (i915->intel.intelScreen->deviceID == PCI_CHIP_I945_G) 500 i945LayoutTextureImages( i915, tObj ); 501 else 502 i915LayoutTextureImages( i915, tObj ); 503 504 t->Setup[I915_TEXREG_MS3] = 505 (((tObj->Image[0][t->intel.base.firstLevel]->Height - 1) << MS3_HEIGHT_SHIFT) | 506 ((tObj->Image[0][t->intel.base.firstLevel]->Width - 1) << MS3_WIDTH_SHIFT) | 507 textureFormat | 508 MS3_USE_FENCE_REGS); 509 510 t->Setup[I915_TEXREG_MS4] = 511 ((((t->intel.Pitch / 4) - 1) << MS4_PITCH_SHIFT) | 512 MS4_CUBE_FACE_ENA_MASK | 513 (((t->intel.max_level * 4)) << MS4_MAX_LOD_SHIFT) | 514 ((tObj->Image[0][t->intel.base.firstLevel]->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); 515 516 t->Setup[I915_TEXREG_SS2] &= ~(SS2_COLORSPACE_CONVERSION); 517 t->Setup[I915_TEXREG_SS2] |= ss2; 518 519 t->intel.dirty = I915_UPLOAD_TEX_ALL; 520 521} 522 523 524/* The i915 (and related graphics cores) do not support GL_CLAMP. The 525 * Intel drivers for "other operating systems" implement GL_CLAMP as 526 * GL_CLAMP_TO_EDGE, so the same is done here. 527 */ 528static GLuint translate_wrap_mode( GLenum wrap ) 529{ 530 switch( wrap ) { 531 case GL_REPEAT: return TEXCOORDMODE_WRAP; 532 case GL_CLAMP: return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */ 533 case GL_CLAMP_TO_EDGE: return TEXCOORDMODE_CLAMP_EDGE; 534 case GL_CLAMP_TO_BORDER: return TEXCOORDMODE_CLAMP_BORDER; 535 case GL_MIRRORED_REPEAT: return TEXCOORDMODE_MIRROR; 536 default: return TEXCOORDMODE_WRAP; 537 } 538} 539 540 541/** 542 */ 543static void i915ImportTexObjState( struct gl_texture_object *texObj ) 544{ 545 i915TextureObjectPtr t = (i915TextureObjectPtr)texObj->DriverData; 546 int minFilt = 0, mipFilt = 0, magFilt = 0, shadow = 0; 547 548 if(INTEL_DEBUG&DEBUG_DRI) 549 fprintf(stderr, "%s\n", __FUNCTION__); 550 551 switch (texObj->MinFilter) { 552 case GL_NEAREST: 553 minFilt = FILTER_NEAREST; 554 mipFilt = MIPFILTER_NONE; 555 break; 556 case GL_LINEAR: 557 minFilt = FILTER_LINEAR; 558 mipFilt = MIPFILTER_NONE; 559 break; 560 case GL_NEAREST_MIPMAP_NEAREST: 561 minFilt = FILTER_NEAREST; 562 mipFilt = MIPFILTER_NEAREST; 563 break; 564 case GL_LINEAR_MIPMAP_NEAREST: 565 minFilt = FILTER_LINEAR; 566 mipFilt = MIPFILTER_NEAREST; 567 break; 568 case GL_NEAREST_MIPMAP_LINEAR: 569 minFilt = FILTER_NEAREST; 570 mipFilt = MIPFILTER_LINEAR; 571 break; 572 case GL_LINEAR_MIPMAP_LINEAR: 573 minFilt = FILTER_LINEAR; 574 mipFilt = MIPFILTER_LINEAR; 575 break; 576 default: 577 break; 578 } 579 580 if ( texObj->MaxAnisotropy > 1.0 ) { 581 minFilt = FILTER_ANISOTROPIC; 582 magFilt = FILTER_ANISOTROPIC; 583 } 584 else { 585 switch (texObj->MagFilter) { 586 case GL_NEAREST: 587 magFilt = FILTER_NEAREST; 588 break; 589 case GL_LINEAR: 590 magFilt = FILTER_LINEAR; 591 break; 592 default: 593 break; 594 } 595 } 596 597 if (texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && 598 texObj->Target != GL_TEXTURE_3D) { 599 600 shadow = SS2_SHADOW_ENABLE; 601 shadow |= intel_translate_compare_func( texObj->CompareFunc ); 602 603 minFilt = FILTER_4X4_FLAT; 604 magFilt = FILTER_4X4_FLAT; 605 } 606 607 608 t->Setup[I915_TEXREG_SS2] &= ~(SS2_MIN_FILTER_MASK | 609 SS2_MIP_FILTER_MASK | 610 SS2_MAG_FILTER_MASK | 611 SS2_SHADOW_ENABLE | 612 SS2_SHADOW_FUNC_MASK); 613 t->Setup[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | 614 (mipFilt << SS2_MIP_FILTER_SHIFT) | 615 (magFilt << SS2_MAG_FILTER_SHIFT) | 616 shadow); 617 618 { 619 GLuint ss3 = t->Setup[I915_TEXREG_SS3] & ~(SS3_TCX_ADDR_MODE_MASK | 620 SS3_TCY_ADDR_MODE_MASK | 621 SS3_TCZ_ADDR_MODE_MASK); 622 GLenum ws = texObj->WrapS; 623 GLenum wt = texObj->WrapT; 624 GLenum wr = texObj->WrapR; 625 626 t->refs_border_color = 0; 627 628 if (texObj->Target == GL_TEXTURE_3D && 629 (texObj->MinFilter != GL_NEAREST || 630 texObj->MagFilter != GL_NEAREST)) { 631 632 /* Try to mimic GL_CLAMP functionality a little better - 633 * switch to CLAMP_TO_BORDER whenever a non-NEAREST filter is 634 * in use. Only do this for 3D textures at the moment -- 635 * doing it universally would fix the conform texbc.c 636 * failure, though. 637 */ 638 if (ws == GL_CLAMP) ws = GL_CLAMP_TO_BORDER; 639 if (wt == GL_CLAMP) wt = GL_CLAMP_TO_BORDER; 640 if (wr == GL_CLAMP) wr = GL_CLAMP_TO_BORDER; 641 642 /* 3D textures don't seem to respect the border color. 643 * Fallback if there's ever a danger that they might refer to 644 * it. 645 */ 646 if (ws == GL_CLAMP_TO_BORDER) t->refs_border_color = 1; 647 if (wt == GL_CLAMP_TO_BORDER) t->refs_border_color = 1; 648 if (wr == GL_CLAMP_TO_BORDER) t->refs_border_color = 1; 649 } 650 651 ss3 |= translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT; 652 ss3 |= translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT; 653 ss3 |= translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT; 654 655 if (ss3 != t->Setup[I915_TEXREG_SS3]) { 656 t->intel.dirty = I915_UPLOAD_TEX_ALL; 657 t->Setup[I915_TEXREG_SS3] = ss3; 658 } 659 } 660 661 { 662 const GLubyte *color = texObj->_BorderChan; 663 664 t->Setup[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(color[0],color[1], 665 color[2],color[3]); 666 } 667} 668 669 670 671static void i915_import_tex_unit( i915ContextPtr i915, 672 i915TextureObjectPtr t, 673 GLuint unit ) 674{ 675 GLuint state[I915_TEX_SETUP_SIZE]; 676 677 if(INTEL_DEBUG&DEBUG_TEXTURE) 678 fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit); 679 680 if (i915->intel.CurrentTexObj[unit]) 681 i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit); 682 683 i915->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t; 684 t->intel.base.bound |= (1 << unit); 685 686 if (t->intel.dirty & I915_UPLOAD_TEX(unit)) { 687 i915ImportTexObjState( t->intel.base.tObj ); 688 t->intel.dirty &= ~I915_UPLOAD_TEX(unit); 689 } 690 691 state[I915_TEXREG_MS2] = t->intel.TextureOffset; 692 state[I915_TEXREG_MS3] = t->Setup[I915_TEXREG_MS3]; 693 state[I915_TEXREG_MS4] = t->Setup[I915_TEXREG_MS4]; 694 695 state[I915_TEXREG_SS2] = (i915->state.Tex[unit][I915_TEXREG_SS2] & 696 SS2_LOD_BIAS_MASK); 697 state[I915_TEXREG_SS2] |= (t->Setup[I915_TEXREG_SS2] & ~SS2_LOD_BIAS_MASK); 698 699 state[I915_TEXREG_SS3] = (i915->state.Tex[unit][I915_TEXREG_SS3] & 700 SS3_NORMALIZED_COORDS); 701 state[I915_TEXREG_SS3] |= (t->Setup[I915_TEXREG_SS3] & 702 ~(SS3_NORMALIZED_COORDS| 703 SS3_TEXTUREMAP_INDEX_MASK)); 704 705 state[I915_TEXREG_SS3] |= (unit<<SS3_TEXTUREMAP_INDEX_SHIFT); 706 707 state[I915_TEXREG_SS4] = t->Setup[I915_TEXREG_SS4]; 708 709 710 if (memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) { 711 I915_STATECHANGE( i915, I915_UPLOAD_TEX(unit) ); 712 memcpy(i915->state.Tex[unit], state, sizeof(state)); 713 } 714} 715 716 717 718static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit ) 719{ 720 i915ContextPtr i915 = I915_CONTEXT(ctx); 721 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; 722 struct gl_texture_object *tObj = texUnit->_Current; 723 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData; 724 725 if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, unit); 726 727 if (!(i915->state.active & I915_UPLOAD_TEX(unit))) { 728 I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE); 729 } 730 731 /* Fallback if there's a texture border */ 732 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) { 733 return GL_FALSE; 734 } 735 736 737 /* Update state if this is a different texture object to last 738 * time. 739 */ 740 if (i915->intel.CurrentTexObj[unit] != &t->intel || 741 (t->intel.dirty & I915_UPLOAD_TEX(unit))) { 742 i915_import_tex_unit( i915, t, unit); 743 i915->tex_program.translated = 0; 744 } 745 746 return GL_TRUE; 747} 748 749static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit ) 750{ 751 i915ContextPtr i915 = I915_CONTEXT(ctx); 752 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; 753 struct gl_texture_object *tObj = texUnit->_Current; 754 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData; 755 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3]; 756 757 ss3 &= ~SS3_NORMALIZED_COORDS; 758 759 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) { 760 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); 761 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3; 762 } 763 764 /* Upload teximages (not pipelined) 765 */ 766 if (t->intel.base.dirty_images[0]) { 767 i915SetTexImages( i915, tObj ); 768 if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) { 769 return GL_FALSE; 770 } 771 } 772 773 return GL_TRUE; 774} 775 776 777static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit ) 778{ 779 i915ContextPtr i915 = I915_CONTEXT(ctx); 780 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; 781 struct gl_texture_object *tObj = texUnit->_Current; 782 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData; 783 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3]; 784 785 ss3 |= SS3_NORMALIZED_COORDS; 786 787 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) { 788 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); 789 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3; 790 } 791 792 /* Upload teximages (not pipelined) 793 */ 794 if (t->intel.base.dirty_images[0]) { 795 i915SetTexImages( i915, tObj ); 796 if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) { 797 return GL_FALSE; 798 } 799 } 800 801 return GL_TRUE; 802} 803 804static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit ) 805{ 806 i915ContextPtr i915 = I915_CONTEXT(ctx); 807 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; 808 struct gl_texture_object *tObj = texUnit->_Current; 809 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData; 810 GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3]; 811 GLuint face; 812 813 ss3 |= SS3_NORMALIZED_COORDS; 814 815 if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) { 816 I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); 817 i915->state.Tex[unit][I915_TEXREG_SS3] = ss3; 818 } 819 820 /* Upload teximages (not pipelined) 821 */ 822 if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] || 823 t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] || 824 t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) { 825 i915SetTexImages( i915, tObj ); 826 } 827 828 /* upload (per face) */ 829 for (face = 0; face < 6; face++) { 830 if (t->intel.base.dirty_images[face]) { 831 if (!intelUploadTexImages( &i915->intel, &t->intel, face )) { 832 return GL_FALSE; 833 } 834 } 835 } 836 837 838 return GL_TRUE; 839} 840 841static GLboolean enable_tex_3d( GLcontext *ctx, GLuint unit ) 842{ 843 struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; 844 i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData; 845 846 /* 3D textures on I915 seem to get bogus border colors, hence this 847 * fallback: 848 */ 849 if (t->refs_border_color) 850 return GL_FALSE; 851 852 return GL_TRUE; 853} 854 855 856 857 858static GLboolean disable_tex( GLcontext *ctx, GLuint unit ) 859{ 860 i915ContextPtr i915 = I915_CONTEXT(ctx); 861 862 if (i915->state.active & I915_UPLOAD_TEX(unit)) { 863 I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_FALSE); 864 } 865 866 /* The old texture is no longer bound to this texture unit. 867 * Mark it as such. 868 */ 869 if ( i915->intel.CurrentTexObj[unit] != NULL ) { 870 i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0); 871 i915->intel.CurrentTexObj[unit] = NULL; 872 } 873 874 return GL_TRUE; 875} 876 877static GLboolean i915UpdateTexUnit( GLcontext *ctx, GLuint unit ) 878{ 879 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; 880 881 if (texUnit->_ReallyEnabled && 882 INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024) 883 return GL_FALSE; 884 885 switch (texUnit->_ReallyEnabled) { 886 case TEXTURE_1D_BIT: 887 case TEXTURE_2D_BIT: 888 return (enable_tex_2d( ctx, unit ) && 889 enable_tex_common( ctx, unit )); 890 case TEXTURE_RECT_BIT: 891 return (enable_tex_rect( ctx, unit ) && 892 enable_tex_common( ctx, unit )); 893 case TEXTURE_CUBE_BIT: 894 return (enable_tex_cube( ctx, unit ) && 895 enable_tex_common( ctx, unit )); 896 case TEXTURE_3D_BIT: 897 return (enable_tex_2d( ctx, unit ) && 898 enable_tex_common( ctx, unit ) && 899 enable_tex_3d( ctx, unit)); 900 case 0: 901 return disable_tex( ctx, unit ); 902 default: 903 return GL_FALSE; 904 } 905} 906 907 908void i915UpdateTextureState( intelContextPtr intel ) 909{ 910 GLcontext *ctx = &intel->ctx; 911 GLboolean ok = GL_TRUE; 912 GLuint i; 913 914 for (i = 0 ; i < I915_TEX_UNITS && ok ; i++) { 915 ok = i915UpdateTexUnit( ctx, i ); 916 } 917 918 FALLBACK( intel, I915_FALLBACK_TEXTURE, !ok ); 919} 920 921 922 923