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