1/************************************************************************** 2 * 3 * Copyright 2006 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 * Authors: 29 * Keith Whitwell <keithw@vmware.com> 30 * Michel Dänzer <daenzer@vmware.com> 31 */ 32 33#include "pipe/p_context.h" 34#include "pipe/p_defines.h" 35#include "pipe/p_state.h" 36#include "util/format/u_format.h" 37#include "util/u_inlines.h" 38#include "util/u_math.h" 39#include "util/u_memory.h" 40#include "util/u_rect.h" 41 42#include "i915_context.h" 43#include "i915_debug.h" 44#include "i915_resource.h" 45#include "i915_screen.h" 46#include "i915_winsys.h" 47 48#define DEBUG_TEXTURES 0 49 50/* 51 * Helper function and arrays 52 */ 53 54/** 55 * Initial offset for Cube map. 56 */ 57static const int initial_offsets[6][2] = { 58 [PIPE_TEX_FACE_POS_X] = {0, 0}, [PIPE_TEX_FACE_POS_Y] = {1, 0}, 59 [PIPE_TEX_FACE_POS_Z] = {1, 1}, [PIPE_TEX_FACE_NEG_X] = {0, 2}, 60 [PIPE_TEX_FACE_NEG_Y] = {1, 2}, [PIPE_TEX_FACE_NEG_Z] = {1, 3}, 61}; 62 63/** 64 * Step offsets for Cube map. 65 */ 66static const int step_offsets[6][2] = { 67 [PIPE_TEX_FACE_POS_X] = {0, 2}, [PIPE_TEX_FACE_POS_Y] = {-1, 2}, 68 [PIPE_TEX_FACE_POS_Z] = {-1, 1}, [PIPE_TEX_FACE_NEG_X] = {0, 2}, 69 [PIPE_TEX_FACE_NEG_Y] = {-1, 2}, [PIPE_TEX_FACE_NEG_Z] = {-1, 1}, 70}; 71 72/** 73 * For compressed level 2 74 */ 75static const int bottom_offsets[6] = { 76 [PIPE_TEX_FACE_POS_X] = 16 + 0 * 8, [PIPE_TEX_FACE_POS_Y] = 16 + 1 * 8, 77 [PIPE_TEX_FACE_POS_Z] = 16 + 2 * 8, [PIPE_TEX_FACE_NEG_X] = 16 + 3 * 8, 78 [PIPE_TEX_FACE_NEG_Y] = 16 + 4 * 8, [PIPE_TEX_FACE_NEG_Z] = 16 + 5 * 8, 79}; 80 81static inline unsigned 82align_nblocksx(enum pipe_format format, unsigned width, unsigned align_to) 83{ 84 return align(util_format_get_nblocksx(format, width), align_to); 85} 86 87static inline unsigned 88align_nblocksy(enum pipe_format format, unsigned width, unsigned align_to) 89{ 90 return align(util_format_get_nblocksy(format, width), align_to); 91} 92 93static inline unsigned 94get_pot_stride(enum pipe_format format, unsigned width) 95{ 96 return util_next_power_of_two(util_format_get_stride(format, width)); 97} 98 99static inline const char * 100get_tiling_string(enum i915_winsys_buffer_tile tile) 101{ 102 switch (tile) { 103 case I915_TILE_NONE: 104 return "none"; 105 case I915_TILE_X: 106 return "x"; 107 case I915_TILE_Y: 108 return "y"; 109 default: 110 assert(false); 111 return "?"; 112 } 113} 114 115/* 116 * More advanced helper funcs 117 */ 118 119static void 120i915_texture_set_level_info(struct i915_texture *tex, unsigned level, 121 unsigned nr_images) 122{ 123 assert(level < ARRAY_SIZE(tex->nr_images)); 124 assert(nr_images); 125 assert(!tex->image_offset[level]); 126 127 tex->nr_images[level] = nr_images; 128 tex->image_offset[level] = MALLOC(nr_images * sizeof(struct offset_pair)); 129 tex->image_offset[level][0].nblocksx = 0; 130 tex->image_offset[level][0].nblocksy = 0; 131} 132 133unsigned 134i915_texture_offset(const struct i915_texture *tex, unsigned level, 135 unsigned layer) 136{ 137 unsigned x, y; 138 x = tex->image_offset[level][layer].nblocksx * 139 util_format_get_blocksize(tex->b.format); 140 y = tex->image_offset[level][layer].nblocksy; 141 142 return y * tex->stride + x; 143} 144 145static void 146i915_texture_set_image_offset(struct i915_texture *tex, unsigned level, 147 unsigned img, unsigned nblocksx, 148 unsigned nblocksy) 149{ 150 /* for the first image and level make sure offset is zero */ 151 assert(!(img == 0 && level == 0) || (nblocksx == 0 && nblocksy == 0)); 152 assert(img < tex->nr_images[level]); 153 154 tex->image_offset[level][img].nblocksx = nblocksx; 155 tex->image_offset[level][img].nblocksy = nblocksy; 156 157#if DEBUG_TEXTURES 158 debug_printf("%s: %p level %u, img %u (%u, %u)\n", __FUNCTION__, tex, level, 159 img, x, y); 160#endif 161} 162 163static enum i915_winsys_buffer_tile 164i915_texture_tiling(struct i915_screen *is, struct i915_texture *tex) 165{ 166 if (!is->debug.tiling) 167 return I915_TILE_NONE; 168 169 if (tex->b.target == PIPE_TEXTURE_1D) 170 return I915_TILE_NONE; 171 172 if (util_format_is_compressed(tex->b.format)) 173 return I915_TILE_X; 174 175 if (is->debug.use_blitter) 176 return I915_TILE_X; 177 else 178 return I915_TILE_Y; 179} 180 181/* 182 * Shared layout functions 183 */ 184 185/** 186 * Special case to deal with scanout textures. 187 */ 188static bool 189i9x5_scanout_layout(struct i915_texture *tex) 190{ 191 struct pipe_resource *pt = &tex->b; 192 193 if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4) 194 return false; 195 196 if (pt->width0 >= 240) { 197 tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64); 198 tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); 199 tex->tiling = I915_TILE_X; 200 /* special case for cursors */ 201 } else if (pt->width0 == 64 && pt->height0 == 64) { 202 tex->stride = get_pot_stride(pt->format, pt->width0); 203 tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); 204 } else { 205 return false; 206 } 207 208 i915_texture_set_level_info(tex, 0, 1); 209 i915_texture_set_image_offset(tex, 0, 0, 0, 0); 210 211 212#if DEBUG_TEXTURE 213 debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, 214 pt->width0, pt->height0, util_format_get_blocksize(pt->format), 215 tex->stride, tex->total_nblocksy, 216 tex->stride * tex->total_nblocksy); 217#endif 218 219 return true; 220} 221 222/** 223 * Special case to deal with shared textures. 224 */ 225static bool 226i9x5_display_target_layout(struct i915_texture *tex) 227{ 228 struct pipe_resource *pt = &tex->b; 229 230 if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4) 231 return false; 232 233 /* fallback to normal textures for small textures */ 234 if (pt->width0 < 240) 235 return false; 236 237 i915_texture_set_level_info(tex, 0, 1); 238 i915_texture_set_image_offset(tex, 0, 0, 0, 0); 239 240 tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64); 241 tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); 242 tex->tiling = I915_TILE_X; 243 244#if DEBUG_TEXTURE 245 debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, 246 pt->width0, pt->height0, util_format_get_blocksize(pt->format), 247 tex->stride, tex->total_nblocksy, 248 tex->stride * tex->total_nblocksy); 249#endif 250 251 return true; 252} 253 254/** 255 * Helper function for special layouts 256 */ 257static bool 258i9x5_special_layout(struct i915_texture *tex) 259{ 260 struct pipe_resource *pt = &tex->b; 261 262 /* Scanouts needs special care */ 263 if (pt->bind & PIPE_BIND_SCANOUT) 264 if (i9x5_scanout_layout(tex)) 265 return true; 266 267 /* Shared buffers needs to be compatible with X servers 268 * 269 * XXX: need a better name than shared for this if it is to be part 270 * of core gallium, and probably move the flag to resource.flags, 271 * rather than bindings. 272 */ 273 if (pt->bind & (PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET)) 274 if (i9x5_display_target_layout(tex)) 275 return true; 276 277 return false; 278} 279 280/** 281 * Cube layout used on i915 and for non-compressed textures on i945. 282 * 283 * Hardware layout looks like: 284 * 285 * +-------+-------+ 286 * | | | 287 * | | | 288 * | | | 289 * | +x | +y | 290 * | | | 291 * | | | 292 * | | | 293 * | | | 294 * +---+---+-------+ 295 * | | | | 296 * | +x| +y| | 297 * | | | | 298 * | | | | 299 * +-+-+---+ +z | 300 * | | | | | 301 * +-+-+ +z| | 302 * | | | | 303 * +-+-+---+-------+ 304 * | | | 305 * | | | 306 * | | | 307 * | -x | -y | 308 * | | | 309 * | | | 310 * | | | 311 * | | | 312 * +---+---+-------+ 313 * | | | | 314 * | -x| -y| | 315 * | | | | 316 * | | | | 317 * +-+-+---+ -z | 318 * | | | | | 319 * +-+-+ -z| | 320 * | | | | 321 * +-+---+-------+ 322 * 323 */ 324static void 325i9x5_texture_layout_cube(struct i915_texture *tex) 326{ 327 struct pipe_resource *pt = &tex->b; 328 unsigned width = util_next_power_of_two(pt->width0); 329 const unsigned nblocks = util_format_get_nblocksx(pt->format, width); 330 unsigned level; 331 unsigned face; 332 333 assert(pt->width0 == pt->height0); /* cubemap images are square */ 334 335 /* double pitch for cube layouts */ 336 tex->stride = align(nblocks * util_format_get_blocksize(pt->format) * 2, 4); 337 tex->total_nblocksy = nblocks * 4; 338 339 for (level = 0; level <= pt->last_level; level++) 340 i915_texture_set_level_info(tex, level, 6); 341 342 for (face = 0; face < 6; face++) { 343 unsigned x = initial_offsets[face][0] * nblocks; 344 unsigned y = initial_offsets[face][1] * nblocks; 345 unsigned d = nblocks; 346 347 for (level = 0; level <= pt->last_level; level++) { 348 i915_texture_set_image_offset(tex, level, face, x, y); 349 d >>= 1; 350 x += step_offsets[face][0] * d; 351 y += step_offsets[face][1] * d; 352 } 353 } 354} 355 356/* 357 * i915 layout functions 358 */ 359 360static void 361i915_texture_layout_2d(struct i915_texture *tex) 362{ 363 struct pipe_resource *pt = &tex->b; 364 unsigned level; 365 unsigned width = util_next_power_of_two(pt->width0); 366 unsigned height = util_next_power_of_two(pt->height0); 367 unsigned nblocksy = util_format_get_nblocksy(pt->format, width); 368 unsigned align_y = 2; 369 370 if (util_format_is_compressed(pt->format)) 371 align_y = 1; 372 373 tex->stride = align(util_format_get_stride(pt->format, width), 4); 374 tex->total_nblocksy = 0; 375 376 for (level = 0; level <= pt->last_level; level++) { 377 i915_texture_set_level_info(tex, level, 1); 378 i915_texture_set_image_offset(tex, level, 0, 0, tex->total_nblocksy); 379 380 tex->total_nblocksy += nblocksy; 381 382 width = u_minify(width, 1); 383 height = u_minify(height, 1); 384 nblocksy = align_nblocksy(pt->format, height, align_y); 385 } 386} 387 388static void 389i915_texture_layout_3d(struct i915_texture *tex) 390{ 391 struct pipe_resource *pt = &tex->b; 392 unsigned level; 393 394 unsigned width = util_next_power_of_two(pt->width0); 395 unsigned height = util_next_power_of_two(pt->height0); 396 unsigned depth = util_next_power_of_two(pt->depth0); 397 unsigned nblocksy = util_format_get_nblocksy(pt->format, height); 398 unsigned stack_nblocksy = 0; 399 400 /* Calculate the size of a single slice. 401 */ 402 tex->stride = align(util_format_get_stride(pt->format, width), 4); 403 404 /* XXX: hardware expects/requires 9 levels at minimum. 405 */ 406 for (level = 0; level <= MAX2(8, pt->last_level); level++) { 407 i915_texture_set_level_info(tex, level, depth); 408 409 stack_nblocksy += MAX2(2, nblocksy); 410 411 width = u_minify(width, 1); 412 height = u_minify(height, 1); 413 nblocksy = util_format_get_nblocksy(pt->format, height); 414 } 415 416 /* Fixup depth image_offsets: 417 */ 418 for (level = 0; level <= pt->last_level; level++) { 419 unsigned i; 420 for (i = 0; i < depth; i++) 421 i915_texture_set_image_offset(tex, level, i, 0, i * stack_nblocksy); 422 423 depth = u_minify(depth, 1); 424 } 425 426 /* Multiply slice size by texture depth for total size. It's 427 * remarkable how wasteful of memory the i915 texture layouts 428 * are. They are largely fixed in the i945. 429 */ 430 tex->total_nblocksy = stack_nblocksy * util_next_power_of_two(pt->depth0); 431} 432 433static bool 434i915_texture_layout(struct i915_texture *tex) 435{ 436 switch (tex->b.target) { 437 case PIPE_TEXTURE_1D: 438 case PIPE_TEXTURE_2D: 439 case PIPE_TEXTURE_RECT: 440 if (!i9x5_special_layout(tex)) 441 i915_texture_layout_2d(tex); 442 break; 443 case PIPE_TEXTURE_3D: 444 i915_texture_layout_3d(tex); 445 break; 446 case PIPE_TEXTURE_CUBE: 447 i9x5_texture_layout_cube(tex); 448 break; 449 default: 450 assert(0); 451 return false; 452 } 453 454 return true; 455} 456 457/* 458 * i945 layout functions 459 */ 460 461static void 462i945_texture_layout_2d(struct i915_texture *tex) 463{ 464 struct pipe_resource *pt = &tex->b; 465 int align_x = 4, align_y = 2; 466 unsigned level; 467 unsigned x = 0; 468 unsigned y = 0; 469 unsigned width = util_next_power_of_two(pt->width0); 470 unsigned height = util_next_power_of_two(pt->height0); 471 unsigned nblocksx = util_format_get_nblocksx(pt->format, width); 472 unsigned nblocksy = util_format_get_nblocksy(pt->format, height); 473 474 if (util_format_is_compressed(pt->format)) { 475 align_x = 1; 476 align_y = 1; 477 } 478 479 tex->stride = align(util_format_get_stride(pt->format, width), 4); 480 481 /* May need to adjust pitch to accommodate the placement of 482 * the 2nd mipmap level. This occurs when the alignment 483 * constraints of mipmap placement push the right edge of the 484 * 2nd mipmap level out past the width of its parent. 485 */ 486 if (pt->last_level > 0) { 487 unsigned mip1_nblocksx = 488 align_nblocksx(pt->format, u_minify(width, 1), align_x) + 489 util_format_get_nblocksx(pt->format, u_minify(width, 2)); 490 491 if (mip1_nblocksx > nblocksx) 492 tex->stride = mip1_nblocksx * util_format_get_blocksize(pt->format); 493 } 494 495 /* Pitch must be a whole number of dwords 496 */ 497 tex->stride = align(tex->stride, 64); 498 tex->total_nblocksy = 0; 499 500 for (level = 0; level <= pt->last_level; level++) { 501 i915_texture_set_level_info(tex, level, 1); 502 i915_texture_set_image_offset(tex, level, 0, x, y); 503 504 /* Because the images are packed better, the final offset 505 * might not be the maximal one: 506 */ 507 tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy); 508 509 /* Layout_below: step right after second mipmap level. 510 */ 511 if (level == 1) { 512 x += nblocksx; 513 } else { 514 y += nblocksy; 515 } 516 517 width = u_minify(width, 1); 518 height = u_minify(height, 1); 519 nblocksx = align_nblocksx(pt->format, width, align_x); 520 nblocksy = align_nblocksy(pt->format, height, align_y); 521 } 522} 523 524static void 525i945_texture_layout_3d(struct i915_texture *tex) 526{ 527 struct pipe_resource *pt = &tex->b; 528 unsigned width = util_next_power_of_two(pt->width0); 529 unsigned height = util_next_power_of_two(pt->height0); 530 unsigned depth = util_next_power_of_two(pt->depth0); 531 unsigned nblocksy = util_format_get_nblocksy(pt->format, height); 532 unsigned pack_x_pitch, pack_x_nr; 533 unsigned pack_y_pitch; 534 unsigned level; 535 536 tex->stride = align(util_format_get_stride(pt->format, width), 4); 537 tex->total_nblocksy = 0; 538 539 pack_y_pitch = MAX2(nblocksy, 2); 540 pack_x_pitch = tex->stride / util_format_get_blocksize(pt->format); 541 pack_x_nr = 1; 542 543 for (level = 0; level <= pt->last_level; level++) { 544 int x = 0; 545 int y = 0; 546 unsigned q, j; 547 548 i915_texture_set_level_info(tex, level, depth); 549 550 for (q = 0; q < depth;) { 551 for (j = 0; j < pack_x_nr && q < depth; j++, q++) { 552 i915_texture_set_image_offset(tex, level, q, x, 553 y + tex->total_nblocksy); 554 x += pack_x_pitch; 555 } 556 557 x = 0; 558 y += pack_y_pitch; 559 } 560 561 tex->total_nblocksy += y; 562 563 if (pack_x_pitch > 4) { 564 pack_x_pitch >>= 1; 565 pack_x_nr <<= 1; 566 assert(pack_x_pitch * pack_x_nr * 567 util_format_get_blocksize(pt->format) <= 568 tex->stride); 569 } 570 571 if (pack_y_pitch > 2) { 572 pack_y_pitch >>= 1; 573 } 574 575 width = u_minify(width, 1); 576 height = u_minify(height, 1); 577 depth = u_minify(depth, 1); 578 nblocksy = util_format_get_nblocksy(pt->format, height); 579 } 580} 581 582/** 583 * Compressed cube texture map layout for i945 and later. 584 * 585 * The hardware layout looks like the 830-915 layout, except for the small 586 * sizes. A zoomed in view of the layout for 945 is: 587 * 588 * +-------+-------+ 589 * | 8x8 | 8x8 | 590 * | | | 591 * | | | 592 * | +x | +y | 593 * | | | 594 * | | | 595 * | | | 596 * | | | 597 * +---+---+-------+ 598 * |4x4| | 8x8 | 599 * | +x| | | 600 * | | | | 601 * | | | | 602 * +---+ | +z | 603 * |4x4| | | 604 * | +y| | | 605 * | | | | 606 * +---+ +-------+ 607 * 608 * ... 609 * 610 * +-------+-------+ 611 * | 8x8 | 8x8 | 612 * | | | 613 * | | | 614 * | -x | -y | 615 * | | | 616 * | | | 617 * | | | 618 * | | | 619 * +---+---+-------+ 620 * |4x4| | 8x8 | 621 * | -x| | | 622 * | | | | 623 * | | | | 624 * +---+ | -z | 625 * |4x4| | | 626 * | -y| | | 627 * | | | | 628 * +---+ +---+---+---+---+---+---+---+---+---+ 629 * |4x4| |4x4| |2x2| |2x2| |2x2| |2x2| 630 * | +z| | -z| | +x| | +y| | +z| | -x| ... 631 * | | | | | | | | | | | | 632 * +---+ +---+ +---+ +---+ +---+ +---+ 633 * 634 * The bottom row continues with the remaining 2x2 then the 1x1 mip contents 635 * in order, with each of them aligned to a 8x8 block boundary. Thus, for 636 * 32x32 cube maps and smaller, the bottom row layout is going to dictate the 637 * pitch of the tree. For a tree with 4x4 images, the pitch is at least 638 * 14 * 8 = 112 texels, for 2x2 it is at least 12 * 8 texels, and for 1x1 639 * it is 6 * 8 texels. 640 */ 641static void 642i945_texture_layout_cube(struct i915_texture *tex) 643{ 644 struct pipe_resource *pt = &tex->b; 645 unsigned width = util_next_power_of_two(pt->width0); 646 const unsigned nblocks = util_format_get_nblocksx(pt->format, width); 647 const unsigned dim = width; 648 unsigned level; 649 unsigned face; 650 651 assert(pt->width0 == pt->height0); /* cubemap images are square */ 652 assert(util_format_is_compressed(pt->format)); /* compressed only */ 653 654 /* 655 * Depending on the size of the largest images, pitch can be 656 * determined either by the old-style packing of cubemap faces, 657 * or the final row of 4x4, 2x2 and 1x1 faces below this. 658 * 659 * 64 * 2 / 4 = 32 660 * 14 * 2 = 28 661 */ 662 if (width >= 64) 663 tex->stride = nblocks * 2 * util_format_get_blocksize(pt->format); 664 else 665 tex->stride = 14 * 2 * util_format_get_blocksize(pt->format); 666 667 /* 668 * Something similary apply for height as well. 669 */ 670 if (width >= 4) 671 tex->total_nblocksy = nblocks * 4 + 1; 672 else 673 tex->total_nblocksy = 1; 674 675 /* Set all the levels to effectively occupy the whole rectangular region */ 676 for (level = 0; level <= pt->last_level; level++) 677 i915_texture_set_level_info(tex, level, 6); 678 679 for (face = 0; face < 6; face++) { 680 /* all calculations in pixels */ 681 unsigned total_height = tex->total_nblocksy * 4; 682 unsigned x = initial_offsets[face][0] * dim; 683 unsigned y = initial_offsets[face][1] * dim; 684 unsigned d = dim; 685 686 if (dim == 4 && face >= 4) { 687 x = (face - 4) * 8; 688 y = tex->total_nblocksy * 4 - 4; /* 4 = 1 block */ 689 } else if (dim < 4 && (face > 0)) { 690 x = face * 8; 691 y = total_height - 4; 692 } 693 694 for (level = 0; level <= pt->last_level; level++) { 695 i915_texture_set_image_offset(tex, level, face, 696 util_format_get_nblocksx(pt->format, x), 697 util_format_get_nblocksy(pt->format, y)); 698 699 d >>= 1; 700 701 switch (d) { 702 case 4: 703 switch (face) { 704 case PIPE_TEX_FACE_POS_X: 705 case PIPE_TEX_FACE_NEG_X: 706 x += step_offsets[face][0] * d; 707 y += step_offsets[face][1] * d; 708 break; 709 case PIPE_TEX_FACE_POS_Y: 710 case PIPE_TEX_FACE_NEG_Y: 711 y += 12; 712 x -= 8; 713 break; 714 case PIPE_TEX_FACE_POS_Z: 715 case PIPE_TEX_FACE_NEG_Z: 716 y = total_height - 4; 717 x = (face - 4) * 8; 718 break; 719 } 720 break; 721 case 2: 722 y = total_height - 4; 723 x = bottom_offsets[face]; 724 break; 725 case 1: 726 x += 48; 727 break; 728 default: 729 x += step_offsets[face][0] * d; 730 y += step_offsets[face][1] * d; 731 break; 732 } 733 } 734 } 735} 736 737static bool 738i945_texture_layout(struct i915_texture *tex) 739{ 740 switch (tex->b.target) { 741 case PIPE_TEXTURE_1D: 742 case PIPE_TEXTURE_2D: 743 case PIPE_TEXTURE_RECT: 744 if (!i9x5_special_layout(tex)) 745 i945_texture_layout_2d(tex); 746 break; 747 case PIPE_TEXTURE_3D: 748 i945_texture_layout_3d(tex); 749 break; 750 case PIPE_TEXTURE_CUBE: 751 if (!util_format_is_compressed(tex->b.format)) 752 i9x5_texture_layout_cube(tex); 753 else 754 i945_texture_layout_cube(tex); 755 break; 756 default: 757 assert(0); 758 return false; 759 } 760 761 return true; 762} 763 764/* 765 * Screen texture functions 766 */ 767 768bool 769i915_resource_get_handle(struct pipe_screen *screen, 770 struct pipe_context *context, 771 struct pipe_resource *texture, 772 struct winsys_handle *whandle, unsigned usage) 773{ 774 if (texture->target == PIPE_BUFFER) 775 return false; 776 777 struct i915_screen *is = i915_screen(screen); 778 struct i915_texture *tex = i915_texture(texture); 779 struct i915_winsys *iws = is->iws; 780 781 return iws->buffer_get_handle(iws, tex->buffer, whandle, tex->stride); 782} 783 784void * 785i915_texture_transfer_map(struct pipe_context *pipe, 786 struct pipe_resource *resource, unsigned level, 787 unsigned usage, const struct pipe_box *box, 788 struct pipe_transfer **ptransfer) 789{ 790 struct i915_context *i915 = i915_context(pipe); 791 struct i915_texture *tex = i915_texture(resource); 792 struct i915_transfer *transfer = slab_alloc_st(&i915->texture_transfer_pool); 793 bool use_staging_texture = false; 794 struct i915_winsys *iws = i915_screen(pipe->screen)->iws; 795 enum pipe_format format = resource->format; 796 unsigned offset; 797 char *map; 798 799 if (!transfer) 800 return NULL; 801 802 transfer->b.resource = resource; 803 transfer->b.level = level; 804 transfer->b.usage = usage; 805 transfer->b.box = *box; 806 transfer->b.stride = tex->stride; 807 transfer->staging_texture = NULL; 808 /* XXX: handle depth textures everyhwere*/ 809 transfer->b.layer_stride = 0; 810 811 /* if we use staging transfers, only support textures we can render to, 812 * because we need that for u_blitter */ 813 if (i915->blitter && 814 util_blitter_is_copy_supported(i915->blitter, resource, resource) && 815 (usage & PIPE_MAP_WRITE) && 816 !(usage & 817 (PIPE_MAP_READ | PIPE_MAP_DONTBLOCK | PIPE_MAP_UNSYNCHRONIZED))) 818 use_staging_texture = true; 819 820 use_staging_texture = false; 821 822 if (use_staging_texture) { 823 /* 824 * Allocate the untiled staging texture. 825 * If the alloc fails, transfer->staging_texture is NULL and we fallback 826 * to a map() 827 */ 828 transfer->staging_texture = 829 i915_texture_create(pipe->screen, resource, true); 830 } 831 832 if (resource->target != PIPE_TEXTURE_3D && 833 resource->target != PIPE_TEXTURE_CUBE) { 834 assert(box->z == 0); 835 assert(box->depth == 1); 836 } 837 838 if (transfer->staging_texture) { 839 tex = i915_texture(transfer->staging_texture); 840 } else { 841 /* TODO this is a sledgehammer */ 842 tex = i915_texture(resource); 843 pipe->flush(pipe, NULL, 0); 844 } 845 846 offset = i915_texture_offset(tex, transfer->b.level, box->z); 847 848 map = iws->buffer_map(iws, tex->buffer, 849 (transfer->b.usage & PIPE_MAP_WRITE) ? true : false); 850 if (!map) { 851 pipe_resource_reference(&transfer->staging_texture, NULL); 852 FREE(transfer); 853 return NULL; 854 } 855 856 *ptransfer = &transfer->b; 857 858 return map + offset + 859 box->y / util_format_get_blockheight(format) * transfer->b.stride + 860 box->x / util_format_get_blockwidth(format) * 861 util_format_get_blocksize(format); 862} 863 864void 865i915_texture_transfer_unmap(struct pipe_context *pipe, 866 struct pipe_transfer *transfer) 867{ 868 struct i915_context *i915 = i915_context(pipe); 869 struct i915_transfer *itransfer = (struct i915_transfer *)transfer; 870 struct i915_texture *tex = i915_texture(itransfer->b.resource); 871 struct i915_winsys *iws = i915_screen(tex->b.screen)->iws; 872 873 if (itransfer->staging_texture) 874 tex = i915_texture(itransfer->staging_texture); 875 876 iws->buffer_unmap(iws, tex->buffer); 877 878 if ((itransfer->staging_texture) && (transfer->usage & PIPE_MAP_WRITE)) { 879 struct pipe_box sbox; 880 881 u_box_origin_2d(itransfer->b.box.width, itransfer->b.box.height, &sbox); 882 pipe->resource_copy_region(pipe, itransfer->b.resource, 883 itransfer->b.level, itransfer->b.box.x, 884 itransfer->b.box.y, itransfer->b.box.z, 885 itransfer->staging_texture, 0, &sbox); 886 pipe->flush(pipe, NULL, 0); 887 pipe_resource_reference(&itransfer->staging_texture, NULL); 888 } 889 890 slab_free_st(&i915->texture_transfer_pool, itransfer); 891} 892 893void 894i915_texture_subdata(struct pipe_context *pipe, struct pipe_resource *resource, 895 unsigned level, unsigned usage, const struct pipe_box *box, 896 const void *data, unsigned stride, unsigned layer_stride) 897{ 898 /* i915's cube and 3D maps are not laid out such that one could use a 899 * layer_stride to get from one layer to the next, so we have to walk the 900 * layers individually. 901 */ 902 struct pipe_box layer_box = *box; 903 layer_box.depth = 1; 904 for (layer_box.z = box->z; layer_box.z < box->z + box->depth; 905 layer_box.z++) { 906 u_default_texture_subdata(pipe, resource, level, usage, &layer_box, data, 907 stride, layer_stride); 908 data += layer_stride; 909 } 910} 911 912struct pipe_resource * 913i915_texture_create(struct pipe_screen *screen, 914 const struct pipe_resource *template, bool force_untiled) 915{ 916 struct i915_screen *is = i915_screen(screen); 917 struct i915_winsys *iws = is->iws; 918 struct i915_texture *tex = CALLOC_STRUCT(i915_texture); 919 unsigned buf_usage = 0; 920 921 if (!tex) 922 return NULL; 923 924 tex->b = *template; 925 pipe_reference_init(&tex->b.reference, 1); 926 tex->b.screen = screen; 927 928 if ((force_untiled) || (template->usage == PIPE_USAGE_STREAM)) 929 tex->tiling = I915_TILE_NONE; 930 else 931 tex->tiling = i915_texture_tiling(is, tex); 932 933 if (is->is_i945) { 934 if (!i945_texture_layout(tex)) 935 goto fail; 936 } else { 937 if (!i915_texture_layout(tex)) 938 goto fail; 939 } 940 941 /* for scanouts and cursors, cursors arn't scanouts */ 942 943 /* XXX: use a custom flag for cursors, don't rely on magically 944 * guessing that this is Xorg asking for a cursor 945 */ 946 if ((template->bind & PIPE_BIND_SCANOUT) && template->width0 != 64) 947 buf_usage = I915_NEW_SCANOUT; 948 else 949 buf_usage = I915_NEW_TEXTURE; 950 951 tex->buffer = iws->buffer_create_tiled( 952 iws, &tex->stride, tex->total_nblocksy, &tex->tiling, buf_usage); 953 if (!tex->buffer) 954 goto fail; 955 956 I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n", 957 __func__, tex, tex->stride, 958 tex->stride / util_format_get_blocksize(tex->b.format), 959 tex->total_nblocksy, get_tiling_string(tex->tiling)); 960 961 return &tex->b; 962 963fail: 964 FREE(tex); 965 return NULL; 966} 967 968struct pipe_resource * 969i915_texture_from_handle(struct pipe_screen *screen, 970 const struct pipe_resource *template, 971 struct winsys_handle *whandle) 972{ 973 struct i915_screen *is = i915_screen(screen); 974 struct i915_texture *tex; 975 struct i915_winsys *iws = is->iws; 976 struct i915_winsys_buffer *buffer; 977 unsigned stride; 978 enum i915_winsys_buffer_tile tiling; 979 980 assert(screen); 981 982 buffer = iws->buffer_from_handle(iws, whandle, template->height0, &tiling, 983 &stride); 984 985 /* Only supports one type */ 986 if ((template->target != PIPE_TEXTURE_2D && 987 template->target != PIPE_TEXTURE_RECT) || 988 template->last_level != 0 || template->depth0 != 1) { 989 return NULL; 990 } 991 992 tex = CALLOC_STRUCT(i915_texture); 993 if (!tex) 994 return NULL; 995 996 tex->b = *template; 997 pipe_reference_init(&tex->b.reference, 1); 998 tex->b.screen = screen; 999 1000 tex->stride = stride; 1001 tex->tiling = tiling; 1002 tex->total_nblocksy = align_nblocksy(tex->b.format, tex->b.height0, 8); 1003 1004 i915_texture_set_level_info(tex, 0, 1); 1005 i915_texture_set_image_offset(tex, 0, 0, 0, 0); 1006 1007 tex->buffer = buffer; 1008 1009 I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n", 1010 __func__, tex, tex->stride, 1011 tex->stride / util_format_get_blocksize(tex->b.format), 1012 tex->total_nblocksy, get_tiling_string(tex->tiling)); 1013 1014 return &tex->b; 1015} 1016