1 /************************************************************************** 2 * 3 * Copyright 2006 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 * Authors: 29 * Keith Whitwell <keith (at) tungstengraphics.com> 30 * Michel Dnzer <michel (at) tungstengraphics.com> 31 */ 32 33 #include <stdio.h> 34 35 #include "pipe/p_context.h" 36 #include "pipe/p_defines.h" 37 38 #include "util/u_inlines.h" 39 #include "util/u_cpu_detect.h" 40 #include "util/u_format.h" 41 #include "util/u_math.h" 42 #include "util/u_memory.h" 43 #include "util/u_simple_list.h" 44 #include "util/u_transfer.h" 45 46 #include "lp_context.h" 47 #include "lp_flush.h" 48 #include "lp_screen.h" 49 #include "lp_tile_image.h" 50 #include "lp_texture.h" 51 #include "lp_setup.h" 52 #include "lp_state.h" 53 54 #include "state_tracker/sw_winsys.h" 55 56 57 #ifdef DEBUG 58 static struct llvmpipe_resource resource_list; 59 #endif 60 static unsigned id_counter = 0; 61 62 63 static INLINE boolean 64 resource_is_texture(const struct pipe_resource *resource) 65 { 66 switch (resource->target) { 67 case PIPE_BUFFER: 68 return FALSE; 69 case PIPE_TEXTURE_1D: 70 case PIPE_TEXTURE_2D: 71 case PIPE_TEXTURE_RECT: 72 case PIPE_TEXTURE_3D: 73 case PIPE_TEXTURE_CUBE: 74 return TRUE; 75 default: 76 assert(0); 77 return FALSE; 78 } 79 } 80 81 82 83 /** 84 * Allocate storage for llvmpipe_texture::layout array. 85 * The number of elements is width_in_tiles * height_in_tiles. 86 */ 87 static enum lp_texture_layout * 88 alloc_layout_array(unsigned num_slices, unsigned width, unsigned height) 89 { 90 const unsigned tx = align(width, TILE_SIZE) / TILE_SIZE; 91 const unsigned ty = align(height, TILE_SIZE) / TILE_SIZE; 92 93 assert(num_slices * tx * ty > 0); 94 assert(LP_TEX_LAYOUT_NONE == 0); /* calloc'ing LP_TEX_LAYOUT_NONE here */ 95 96 return (enum lp_texture_layout *) 97 CALLOC(num_slices * tx * ty, sizeof(enum lp_texture_layout)); 98 } 99 100 101 102 /** 103 * Conventional allocation path for non-display textures: 104 * Just compute row strides here. Storage is allocated on demand later. 105 */ 106 static boolean 107 llvmpipe_texture_layout(struct llvmpipe_screen *screen, 108 struct llvmpipe_resource *lpr) 109 { 110 struct pipe_resource *pt = &lpr->base; 111 unsigned level; 112 unsigned width = pt->width0; 113 unsigned height = pt->height0; 114 unsigned depth = pt->depth0; 115 size_t total_size = 0; 116 117 assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS); 118 assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS); 119 120 for (level = 0; level <= pt->last_level; level++) { 121 122 /* Row stride and image stride (for linear layout) */ 123 { 124 unsigned alignment, nblocksx, nblocksy, block_size; 125 126 /* For non-compressed formats we need to align the texture size 127 * to the tile size to facilitate render-to-texture. 128 */ 129 if (util_format_is_compressed(pt->format)) 130 alignment = 1; 131 else 132 alignment = TILE_SIZE; 133 134 nblocksx = util_format_get_nblocksx(pt->format, 135 align(width, alignment)); 136 nblocksy = util_format_get_nblocksy(pt->format, 137 align(height, alignment)); 138 block_size = util_format_get_blocksize(pt->format); 139 140 lpr->row_stride[level] = align(nblocksx * block_size, 16); 141 142 lpr->img_stride[level] = lpr->row_stride[level] * nblocksy; 143 } 144 145 /* Size of the image in tiles (for tiled layout) */ 146 { 147 const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE; 148 const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE; 149 lpr->tiles_per_row[level] = width_t; 150 lpr->tiles_per_image[level] = width_t * height_t; 151 } 152 153 /* Number of 3D image slices or cube faces */ 154 { 155 unsigned num_slices; 156 157 if (lpr->base.target == PIPE_TEXTURE_CUBE) 158 num_slices = 6; 159 else if (lpr->base.target == PIPE_TEXTURE_3D) 160 num_slices = depth; 161 else 162 num_slices = 1; 163 164 lpr->num_slices_faces[level] = num_slices; 165 166 lpr->layout[level] = alloc_layout_array(num_slices, width, height); 167 if (!lpr->layout[level]) { 168 goto fail; 169 } 170 } 171 172 total_size += lpr->num_slices_faces[level] * lpr->img_stride[level]; 173 if (total_size > LP_MAX_TEXTURE_SIZE) { 174 goto fail; 175 } 176 177 /* Compute size of next mipmap level */ 178 width = u_minify(width, 1); 179 height = u_minify(height, 1); 180 depth = u_minify(depth, 1); 181 } 182 183 return TRUE; 184 185 fail: 186 for (level = 0; level <= pt->last_level; level++) { 187 if (lpr->layout[level]) { 188 FREE(lpr->layout[level]); 189 } 190 } 191 192 return FALSE; 193 } 194 195 196 197 static boolean 198 llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, 199 struct llvmpipe_resource *lpr) 200 { 201 struct sw_winsys *winsys = screen->winsys; 202 203 /* Round up the surface size to a multiple of the tile size to 204 * avoid tile clipping. 205 */ 206 const unsigned width = align(lpr->base.width0, TILE_SIZE); 207 const unsigned height = align(lpr->base.height0, TILE_SIZE); 208 const unsigned width_t = width / TILE_SIZE; 209 const unsigned height_t = height / TILE_SIZE; 210 211 lpr->tiles_per_row[0] = width_t; 212 lpr->tiles_per_image[0] = width_t * height_t; 213 lpr->num_slices_faces[0] = 1; 214 lpr->img_stride[0] = 0; 215 216 lpr->layout[0] = alloc_layout_array(1, width, height); 217 if (!lpr->layout[0]) { 218 return FALSE; 219 } 220 221 lpr->dt = winsys->displaytarget_create(winsys, 222 lpr->base.bind, 223 lpr->base.format, 224 width, height, 225 16, 226 &lpr->row_stride[0] ); 227 228 if (lpr->dt == NULL) 229 return FALSE; 230 231 { 232 void *map = winsys->displaytarget_map(winsys, lpr->dt, 233 PIPE_TRANSFER_WRITE); 234 235 if (map) 236 memset(map, 0, height * lpr->row_stride[0]); 237 238 winsys->displaytarget_unmap(winsys, lpr->dt); 239 } 240 241 return TRUE; 242 } 243 244 245 static struct pipe_resource * 246 llvmpipe_resource_create(struct pipe_screen *_screen, 247 const struct pipe_resource *templat) 248 { 249 struct llvmpipe_screen *screen = llvmpipe_screen(_screen); 250 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource); 251 if (!lpr) 252 return NULL; 253 254 lpr->base = *templat; 255 pipe_reference_init(&lpr->base.reference, 1); 256 lpr->base.screen = &screen->base; 257 258 /* assert(lpr->base.bind); */ 259 260 if (resource_is_texture(&lpr->base)) { 261 if (lpr->base.bind & PIPE_BIND_DISPLAY_TARGET) { 262 /* displayable surface */ 263 if (!llvmpipe_displaytarget_layout(screen, lpr)) 264 goto fail; 265 assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE); 266 } 267 else { 268 /* texture map */ 269 if (!llvmpipe_texture_layout(screen, lpr)) 270 goto fail; 271 assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE); 272 } 273 assert(lpr->layout[0]); 274 } 275 else { 276 /* other data (vertex buffer, const buffer, etc) */ 277 const enum pipe_format format = templat->format; 278 const uint w = templat->width0 / util_format_get_blockheight(format); 279 /* XXX buffers should only have one dimension, those values should be 1 */ 280 const uint h = templat->height0 / util_format_get_blockwidth(format); 281 const uint d = templat->depth0; 282 const uint bpp = util_format_get_blocksize(format); 283 const uint bytes = w * h * d * bpp; 284 lpr->data = align_malloc(bytes, 16); 285 if (!lpr->data) 286 goto fail; 287 memset(lpr->data, 0, bytes); 288 } 289 290 lpr->id = id_counter++; 291 292 #ifdef DEBUG 293 insert_at_tail(&resource_list, lpr); 294 #endif 295 296 return &lpr->base; 297 298 fail: 299 FREE(lpr); 300 return NULL; 301 } 302 303 304 static void 305 llvmpipe_resource_destroy(struct pipe_screen *pscreen, 306 struct pipe_resource *pt) 307 { 308 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen); 309 struct llvmpipe_resource *lpr = llvmpipe_resource(pt); 310 311 if (lpr->dt) { 312 /* display target */ 313 struct sw_winsys *winsys = screen->winsys; 314 winsys->displaytarget_destroy(winsys, lpr->dt); 315 316 if (lpr->tiled[0].data) { 317 align_free(lpr->tiled[0].data); 318 lpr->tiled[0].data = NULL; 319 } 320 321 FREE(lpr->layout[0]); 322 } 323 else if (resource_is_texture(pt)) { 324 /* regular texture */ 325 uint level; 326 327 /* free linear image data */ 328 for (level = 0; level < Elements(lpr->linear); level++) { 329 if (lpr->linear[level].data) { 330 align_free(lpr->linear[level].data); 331 lpr->linear[level].data = NULL; 332 } 333 } 334 335 /* free tiled image data */ 336 for (level = 0; level < Elements(lpr->tiled); level++) { 337 if (lpr->tiled[level].data) { 338 align_free(lpr->tiled[level].data); 339 lpr->tiled[level].data = NULL; 340 } 341 } 342 343 /* free layout flag arrays */ 344 for (level = 0; level < Elements(lpr->tiled); level++) { 345 FREE(lpr->layout[level]); 346 lpr->layout[level] = NULL; 347 } 348 } 349 else if (!lpr->userBuffer) { 350 assert(lpr->data); 351 align_free(lpr->data); 352 } 353 354 #ifdef DEBUG 355 if (lpr->next) 356 remove_from_list(lpr); 357 #endif 358 359 FREE(lpr); 360 } 361 362 363 /** 364 * Map a resource for read/write. 365 */ 366 void * 367 llvmpipe_resource_map(struct pipe_resource *resource, 368 unsigned level, 369 unsigned layer, 370 enum lp_texture_usage tex_usage, 371 enum lp_texture_layout layout) 372 { 373 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 374 uint8_t *map; 375 376 assert(level < LP_MAX_TEXTURE_LEVELS); 377 assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1)); 378 379 assert(tex_usage == LP_TEX_USAGE_READ || 380 tex_usage == LP_TEX_USAGE_READ_WRITE || 381 tex_usage == LP_TEX_USAGE_WRITE_ALL); 382 383 assert(layout == LP_TEX_LAYOUT_NONE || 384 layout == LP_TEX_LAYOUT_TILED || 385 layout == LP_TEX_LAYOUT_LINEAR); 386 387 if (lpr->dt) { 388 /* display target */ 389 struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen); 390 struct sw_winsys *winsys = screen->winsys; 391 unsigned dt_usage; 392 uint8_t *map2; 393 394 if (tex_usage == LP_TEX_USAGE_READ) { 395 dt_usage = PIPE_TRANSFER_READ; 396 } 397 else { 398 dt_usage = PIPE_TRANSFER_READ_WRITE; 399 } 400 401 assert(level == 0); 402 assert(layer == 0); 403 404 /* FIXME: keep map count? */ 405 map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage); 406 407 /* install this linear image in texture data structure */ 408 lpr->linear[level].data = map; 409 410 /* make sure tiled data gets converted to linear data */ 411 map2 = llvmpipe_get_texture_image(lpr, 0, 0, tex_usage, layout); 412 if (layout == LP_TEX_LAYOUT_LINEAR) 413 assert(map == map2); 414 415 return map2; 416 } 417 else if (resource_is_texture(resource)) { 418 419 map = llvmpipe_get_texture_image(lpr, layer, level, 420 tex_usage, layout); 421 return map; 422 } 423 else { 424 return lpr->data; 425 } 426 } 427 428 429 /** 430 * Unmap a resource. 431 */ 432 void 433 llvmpipe_resource_unmap(struct pipe_resource *resource, 434 unsigned level, 435 unsigned layer) 436 { 437 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 438 439 if (lpr->dt) { 440 /* display target */ 441 struct llvmpipe_screen *lp_screen = llvmpipe_screen(resource->screen); 442 struct sw_winsys *winsys = lp_screen->winsys; 443 444 assert(level == 0); 445 assert(layer == 0); 446 447 /* make sure linear image is up to date */ 448 (void) llvmpipe_get_texture_image(lpr, layer, level, 449 LP_TEX_USAGE_READ, 450 LP_TEX_LAYOUT_LINEAR); 451 452 winsys->displaytarget_unmap(winsys, lpr->dt); 453 } 454 } 455 456 457 void * 458 llvmpipe_resource_data(struct pipe_resource *resource) 459 { 460 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 461 462 assert(!resource_is_texture(resource)); 463 464 return lpr->data; 465 } 466 467 468 static struct pipe_resource * 469 llvmpipe_resource_from_handle(struct pipe_screen *screen, 470 const struct pipe_resource *template, 471 struct winsys_handle *whandle) 472 { 473 struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; 474 struct llvmpipe_resource *lpr; 475 unsigned width, height, width_t, height_t; 476 477 /* XXX Seems like from_handled depth textures doesn't work that well */ 478 479 lpr = CALLOC_STRUCT(llvmpipe_resource); 480 if (!lpr) { 481 goto no_lpr; 482 } 483 484 lpr->base = *template; 485 pipe_reference_init(&lpr->base.reference, 1); 486 lpr->base.screen = screen; 487 488 width = align(lpr->base.width0, TILE_SIZE); 489 height = align(lpr->base.height0, TILE_SIZE); 490 width_t = width / TILE_SIZE; 491 height_t = height / TILE_SIZE; 492 493 /* 494 * Looks like unaligned displaytargets work just fine, 495 * at least sampler/render ones. 496 */ 497 #if 0 498 assert(lpr->base.width0 == width); 499 assert(lpr->base.height0 == height); 500 #endif 501 502 lpr->tiles_per_row[0] = width_t; 503 lpr->tiles_per_image[0] = width_t * height_t; 504 lpr->num_slices_faces[0] = 1; 505 lpr->img_stride[0] = 0; 506 507 lpr->dt = winsys->displaytarget_from_handle(winsys, 508 template, 509 whandle, 510 &lpr->row_stride[0]); 511 if (!lpr->dt) { 512 goto no_dt; 513 } 514 515 lpr->layout[0] = alloc_layout_array(1, lpr->base.width0, lpr->base.height0); 516 if (!lpr->layout[0]) { 517 goto no_layout_0; 518 } 519 520 assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE); 521 522 lpr->id = id_counter++; 523 524 #ifdef DEBUG 525 insert_at_tail(&resource_list, lpr); 526 #endif 527 528 return &lpr->base; 529 530 no_layout_0: 531 winsys->displaytarget_destroy(winsys, lpr->dt); 532 no_dt: 533 FREE(lpr); 534 no_lpr: 535 return NULL; 536 } 537 538 539 static boolean 540 llvmpipe_resource_get_handle(struct pipe_screen *screen, 541 struct pipe_resource *pt, 542 struct winsys_handle *whandle) 543 { 544 struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; 545 struct llvmpipe_resource *lpr = llvmpipe_resource(pt); 546 547 assert(lpr->dt); 548 if (!lpr->dt) 549 return FALSE; 550 551 return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle); 552 } 553 554 555 static struct pipe_surface * 556 llvmpipe_create_surface(struct pipe_context *pipe, 557 struct pipe_resource *pt, 558 const struct pipe_surface *surf_tmpl) 559 { 560 struct pipe_surface *ps; 561 562 assert(surf_tmpl->u.tex.level <= pt->last_level); 563 564 ps = CALLOC_STRUCT(pipe_surface); 565 if (ps) { 566 pipe_reference_init(&ps->reference, 1); 567 pipe_resource_reference(&ps->texture, pt); 568 ps->context = pipe; 569 ps->format = surf_tmpl->format; 570 ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); 571 ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); 572 ps->usage = surf_tmpl->usage; 573 574 ps->u.tex.level = surf_tmpl->u.tex.level; 575 ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; 576 ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; 577 } 578 return ps; 579 } 580 581 582 static void 583 llvmpipe_surface_destroy(struct pipe_context *pipe, 584 struct pipe_surface *surf) 585 { 586 /* Effectively do the texture_update work here - if texture images 587 * needed post-processing to put them into hardware layout, this is 588 * where it would happen. For llvmpipe, nothing to do. 589 */ 590 assert(surf->texture); 591 pipe_resource_reference(&surf->texture, NULL); 592 FREE(surf); 593 } 594 595 596 static struct pipe_transfer * 597 llvmpipe_get_transfer(struct pipe_context *pipe, 598 struct pipe_resource *resource, 599 unsigned level, 600 unsigned usage, 601 const struct pipe_box *box) 602 { 603 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 604 struct llvmpipe_resource *lprex = llvmpipe_resource(resource); 605 struct llvmpipe_transfer *lpr; 606 607 assert(resource); 608 assert(level <= resource->last_level); 609 610 /* 611 * Transfers, like other pipe operations, must happen in order, so flush the 612 * context if necessary. 613 */ 614 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { 615 boolean read_only = !(usage & PIPE_TRANSFER_WRITE); 616 boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK); 617 if (!llvmpipe_flush_resource(pipe, resource, 618 level, 619 box->depth > 1 ? -1 : box->z, 620 read_only, 621 TRUE, /* cpu_access */ 622 do_not_block, 623 __FUNCTION__)) { 624 /* 625 * It would have blocked, but state tracker requested no to. 626 */ 627 assert(do_not_block); 628 return NULL; 629 } 630 } 631 632 if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][0]) 633 llvmpipe->dirty |= LP_NEW_CONSTANTS; 634 635 lpr = CALLOC_STRUCT(llvmpipe_transfer); 636 if (lpr) { 637 struct pipe_transfer *pt = &lpr->base; 638 pipe_resource_reference(&pt->resource, resource); 639 pt->box = *box; 640 pt->level = level; 641 pt->stride = lprex->row_stride[level]; 642 pt->layer_stride = lprex->img_stride[level]; 643 pt->usage = usage; 644 645 return pt; 646 } 647 return NULL; 648 } 649 650 651 static void 652 llvmpipe_transfer_destroy(struct pipe_context *pipe, 653 struct pipe_transfer *transfer) 654 { 655 /* Effectively do the texture_update work here - if texture images 656 * needed post-processing to put them into hardware layout, this is 657 * where it would happen. For llvmpipe, nothing to do. 658 */ 659 assert (transfer->resource); 660 pipe_resource_reference(&transfer->resource, NULL); 661 FREE(transfer); 662 } 663 664 665 static void * 666 llvmpipe_transfer_map( struct pipe_context *pipe, 667 struct pipe_transfer *transfer ) 668 { 669 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 670 ubyte *map; 671 struct llvmpipe_resource *lpr; 672 enum pipe_format format; 673 enum lp_texture_usage tex_usage; 674 const char *mode; 675 676 assert(transfer->level < LP_MAX_TEXTURE_LEVELS); 677 678 /* 679 printf("tex_transfer_map(%d, %d %d x %d of %d x %d, usage %d )\n", 680 transfer->x, transfer->y, transfer->width, transfer->height, 681 transfer->texture->width0, 682 transfer->texture->height0, 683 transfer->usage); 684 */ 685 686 if (transfer->usage == PIPE_TRANSFER_READ) { 687 tex_usage = LP_TEX_USAGE_READ; 688 mode = "read"; 689 } 690 else { 691 tex_usage = LP_TEX_USAGE_READ_WRITE; 692 mode = "read/write"; 693 } 694 695 if (0) { 696 struct llvmpipe_resource *lpr = llvmpipe_resource(transfer->resource); 697 printf("transfer map tex %u mode %s\n", lpr->id, mode); 698 } 699 700 701 assert(transfer->resource); 702 lpr = llvmpipe_resource(transfer->resource); 703 format = lpr->base.format; 704 705 map = llvmpipe_resource_map(transfer->resource, 706 transfer->level, 707 transfer->box.z, 708 tex_usage, LP_TEX_LAYOUT_LINEAR); 709 710 711 /* May want to do different things here depending on read/write nature 712 * of the map: 713 */ 714 if (transfer->usage & PIPE_TRANSFER_WRITE) { 715 /* Do something to notify sharing contexts of a texture change. 716 */ 717 screen->timestamp++; 718 } 719 720 map += 721 transfer->box.y / util_format_get_blockheight(format) * transfer->stride + 722 transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); 723 724 return map; 725 } 726 727 728 static void 729 llvmpipe_transfer_unmap(struct pipe_context *pipe, 730 struct pipe_transfer *transfer) 731 { 732 assert(transfer->resource); 733 734 llvmpipe_resource_unmap(transfer->resource, 735 transfer->level, 736 transfer->box.z); 737 } 738 739 unsigned int 740 llvmpipe_is_resource_referenced( struct pipe_context *pipe, 741 struct pipe_resource *presource, 742 unsigned level, int layer) 743 { 744 struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); 745 746 if (presource->target == PIPE_BUFFER) 747 return LP_UNREFERENCED; 748 749 return lp_setup_is_resource_referenced(llvmpipe->setup, presource); 750 } 751 752 753 754 /** 755 * Create buffer which wraps user-space data. 756 */ 757 struct pipe_resource * 758 llvmpipe_user_buffer_create(struct pipe_screen *screen, 759 void *ptr, 760 unsigned bytes, 761 unsigned bind_flags) 762 { 763 struct llvmpipe_resource *buffer; 764 765 buffer = CALLOC_STRUCT(llvmpipe_resource); 766 if(!buffer) 767 return NULL; 768 769 pipe_reference_init(&buffer->base.reference, 1); 770 buffer->base.screen = screen; 771 buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */ 772 buffer->base.bind = bind_flags; 773 buffer->base.usage = PIPE_USAGE_IMMUTABLE; 774 buffer->base.flags = 0; 775 buffer->base.width0 = bytes; 776 buffer->base.height0 = 1; 777 buffer->base.depth0 = 1; 778 buffer->base.array_size = 1; 779 buffer->userBuffer = TRUE; 780 buffer->data = ptr; 781 782 return &buffer->base; 783 } 784 785 786 /** 787 * Compute size (in bytes) need to store a texture image / mipmap level, 788 * for just one cube face or one 3D texture slice 789 */ 790 static unsigned 791 tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level, 792 enum lp_texture_layout layout) 793 { 794 const unsigned width = u_minify(lpr->base.width0, level); 795 const unsigned height = u_minify(lpr->base.height0, level); 796 797 assert(layout == LP_TEX_LAYOUT_TILED || 798 layout == LP_TEX_LAYOUT_LINEAR); 799 800 if (layout == LP_TEX_LAYOUT_TILED) { 801 /* for tiled layout, force a 32bpp format */ 802 const enum pipe_format format = PIPE_FORMAT_B8G8R8A8_UNORM; 803 const unsigned block_size = util_format_get_blocksize(format); 804 const unsigned nblocksy = 805 util_format_get_nblocksy(format, align(height, TILE_SIZE)); 806 const unsigned nblocksx = 807 util_format_get_nblocksx(format, align(width, TILE_SIZE)); 808 const unsigned buffer_size = block_size * nblocksy * nblocksx; 809 return buffer_size; 810 } 811 else { 812 /* we already computed this */ 813 return lpr->img_stride[level]; 814 } 815 } 816 817 818 /** 819 * Compute size (in bytes) need to store a texture image / mipmap level, 820 * including all cube faces or 3D image slices 821 */ 822 static unsigned 823 tex_image_size(const struct llvmpipe_resource *lpr, unsigned level, 824 enum lp_texture_layout layout) 825 { 826 const unsigned buf_size = tex_image_face_size(lpr, level, layout); 827 return buf_size * lpr->num_slices_faces[level]; 828 } 829 830 831 /** 832 * This function encapsulates some complicated logic for determining 833 * how to convert a tile of image data from linear layout to tiled 834 * layout, or vice versa. 835 * \param cur_layout the current tile layout 836 * \param target_layout the desired tile layout 837 * \param usage how the tile will be accessed (R/W vs. read-only, etc) 838 * \param new_layout_return returns the new layout mode 839 * \param convert_return returns TRUE if image conversion is needed 840 */ 841 static void 842 layout_logic(enum lp_texture_layout cur_layout, 843 enum lp_texture_layout target_layout, 844 enum lp_texture_usage usage, 845 enum lp_texture_layout *new_layout_return, 846 boolean *convert) 847 { 848 enum lp_texture_layout other_layout, new_layout; 849 850 *convert = FALSE; 851 852 new_layout = 99; /* debug check */ 853 854 if (target_layout == LP_TEX_LAYOUT_LINEAR) { 855 other_layout = LP_TEX_LAYOUT_TILED; 856 } 857 else { 858 assert(target_layout == LP_TEX_LAYOUT_TILED); 859 other_layout = LP_TEX_LAYOUT_LINEAR; 860 } 861 862 new_layout = target_layout; /* may get changed below */ 863 864 if (cur_layout == LP_TEX_LAYOUT_BOTH) { 865 if (usage == LP_TEX_USAGE_READ) { 866 new_layout = LP_TEX_LAYOUT_BOTH; 867 } 868 } 869 else if (cur_layout == other_layout) { 870 if (usage != LP_TEX_USAGE_WRITE_ALL) { 871 /* need to convert tiled data to linear or vice versa */ 872 *convert = TRUE; 873 874 if (usage == LP_TEX_USAGE_READ) 875 new_layout = LP_TEX_LAYOUT_BOTH; 876 } 877 } 878 else { 879 assert(cur_layout == LP_TEX_LAYOUT_NONE || 880 cur_layout == target_layout); 881 } 882 883 assert(new_layout == LP_TEX_LAYOUT_BOTH || 884 new_layout == target_layout); 885 886 *new_layout_return = new_layout; 887 } 888 889 890 /** 891 * Return pointer to a 2D texture image/face/slice. 892 * No tiled/linear conversion is done. 893 */ 894 ubyte * 895 llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr, 896 unsigned face_slice, unsigned level, 897 enum lp_texture_layout layout) 898 { 899 struct llvmpipe_texture_image *img; 900 unsigned offset; 901 902 if (layout == LP_TEX_LAYOUT_LINEAR) { 903 img = &lpr->linear[level]; 904 } 905 else { 906 assert (layout == LP_TEX_LAYOUT_TILED); 907 img = &lpr->tiled[level]; 908 } 909 910 if (face_slice > 0) 911 offset = face_slice * tex_image_face_size(lpr, level, layout); 912 else 913 offset = 0; 914 915 return (ubyte *) img->data + offset; 916 } 917 918 919 static INLINE enum lp_texture_layout 920 llvmpipe_get_texture_tile_layout(const struct llvmpipe_resource *lpr, 921 unsigned face_slice, unsigned level, 922 unsigned x, unsigned y) 923 { 924 uint i; 925 assert(resource_is_texture(&lpr->base)); 926 assert(x < lpr->tiles_per_row[level]); 927 i = face_slice * lpr->tiles_per_image[level] 928 + y * lpr->tiles_per_row[level] + x; 929 return lpr->layout[level][i]; 930 } 931 932 933 static INLINE void 934 llvmpipe_set_texture_tile_layout(struct llvmpipe_resource *lpr, 935 unsigned face_slice, unsigned level, 936 unsigned x, unsigned y, 937 enum lp_texture_layout layout) 938 { 939 uint i; 940 assert(resource_is_texture(&lpr->base)); 941 assert(x < lpr->tiles_per_row[level]); 942 i = face_slice * lpr->tiles_per_image[level] 943 + y * lpr->tiles_per_row[level] + x; 944 lpr->layout[level][i] = layout; 945 } 946 947 948 /** 949 * Set the layout mode for all tiles in a particular image. 950 */ 951 static INLINE void 952 llvmpipe_set_texture_image_layout(struct llvmpipe_resource *lpr, 953 unsigned face_slice, unsigned level, 954 unsigned width_t, unsigned height_t, 955 enum lp_texture_layout layout) 956 { 957 const unsigned start = face_slice * lpr->tiles_per_image[level]; 958 unsigned i; 959 960 for (i = 0; i < width_t * height_t; i++) { 961 lpr->layout[level][start + i] = layout; 962 } 963 } 964 965 966 /** 967 * Allocate storage for a linear or tile texture image (all cube 968 * faces and all 3D slices. 969 */ 970 static void 971 alloc_image_data(struct llvmpipe_resource *lpr, unsigned level, 972 enum lp_texture_layout layout) 973 { 974 uint alignment = MAX2(16, util_cpu_caps.cacheline); 975 976 if (lpr->dt) 977 assert(level == 0); 978 979 if (layout == LP_TEX_LAYOUT_TILED) { 980 /* tiled data is stored in regular memory */ 981 uint buffer_size = tex_image_size(lpr, level, layout); 982 lpr->tiled[level].data = align_malloc(buffer_size, alignment); 983 if (lpr->tiled[level].data) { 984 memset(lpr->tiled[level].data, 0, buffer_size); 985 } 986 } 987 else { 988 assert(layout == LP_TEX_LAYOUT_LINEAR); 989 if (lpr->dt) { 990 /* we get the linear memory from the winsys, and it has 991 * already been zeroed 992 */ 993 struct llvmpipe_screen *screen = llvmpipe_screen(lpr->base.screen); 994 struct sw_winsys *winsys = screen->winsys; 995 996 lpr->linear[0].data = 997 winsys->displaytarget_map(winsys, lpr->dt, 998 PIPE_TRANSFER_READ_WRITE); 999 } 1000 else { 1001 /* not a display target - allocate regular memory */ 1002 uint buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_LINEAR); 1003 lpr->linear[level].data = align_malloc(buffer_size, alignment); 1004 if (lpr->linear[level].data) { 1005 memset(lpr->linear[level].data, 0, buffer_size); 1006 } 1007 } 1008 } 1009 } 1010 1011 1012 1013 /** 1014 * Return pointer to texture image data (either linear or tiled layout) 1015 * for a particular cube face or 3D texture slice. 1016 * 1017 * \param face_slice the cube face or 3D slice of interest 1018 * \param usage one of LP_TEX_USAGE_READ/WRITE_ALL/READ_WRITE 1019 * \param layout either LP_TEX_LAYOUT_LINEAR or _TILED or _NONE 1020 */ 1021 void * 1022 llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, 1023 unsigned face_slice, unsigned level, 1024 enum lp_texture_usage usage, 1025 enum lp_texture_layout layout) 1026 { 1027 /* 1028 * 'target' refers to the image which we're retrieving (either in 1029 * tiled or linear layout). 1030 * 'other' refers to the same image but in the other layout. (it may 1031 * or may not exist. 1032 */ 1033 struct llvmpipe_texture_image *target_img; 1034 struct llvmpipe_texture_image *other_img; 1035 void *target_data; 1036 void *other_data; 1037 const unsigned width = u_minify(lpr->base.width0, level); 1038 const unsigned height = u_minify(lpr->base.height0, level); 1039 const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE; 1040 const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE; 1041 enum lp_texture_layout other_layout; 1042 boolean only_allocate; 1043 1044 assert(layout == LP_TEX_LAYOUT_NONE || 1045 layout == LP_TEX_LAYOUT_TILED || 1046 layout == LP_TEX_LAYOUT_LINEAR); 1047 1048 assert(usage == LP_TEX_USAGE_READ || 1049 usage == LP_TEX_USAGE_READ_WRITE || 1050 usage == LP_TEX_USAGE_WRITE_ALL); 1051 1052 /* check for the special case of layout == LP_TEX_LAYOUT_NONE */ 1053 if (layout == LP_TEX_LAYOUT_NONE) { 1054 only_allocate = TRUE; 1055 layout = LP_TEX_LAYOUT_TILED; 1056 } 1057 else { 1058 only_allocate = FALSE; 1059 } 1060 1061 if (lpr->dt) { 1062 assert(lpr->linear[level].data); 1063 } 1064 1065 /* which is target? which is other? */ 1066 if (layout == LP_TEX_LAYOUT_LINEAR) { 1067 target_img = &lpr->linear[level]; 1068 other_img = &lpr->tiled[level]; 1069 other_layout = LP_TEX_LAYOUT_TILED; 1070 } 1071 else { 1072 target_img = &lpr->tiled[level]; 1073 other_img = &lpr->linear[level]; 1074 other_layout = LP_TEX_LAYOUT_LINEAR; 1075 } 1076 1077 target_data = target_img->data; 1078 other_data = other_img->data; 1079 1080 if (!target_data) { 1081 /* allocate memory for the target image now */ 1082 alloc_image_data(lpr, level, layout); 1083 target_data = target_img->data; 1084 } 1085 1086 if (face_slice > 0) { 1087 unsigned target_offset, other_offset; 1088 1089 target_offset = face_slice * tex_image_face_size(lpr, level, layout); 1090 other_offset = face_slice * tex_image_face_size(lpr, level, other_layout); 1091 if (target_data) { 1092 target_data = (uint8_t *) target_data + target_offset; 1093 } 1094 if (other_data) { 1095 other_data = (uint8_t *) other_data + other_offset; 1096 } 1097 } 1098 1099 if (only_allocate) { 1100 /* Just allocating tiled memory. Don't initialize it from the 1101 * linear data if it exists. 1102 */ 1103 return target_data; 1104 } 1105 1106 if (other_data) { 1107 /* may need to convert other data to the requested layout */ 1108 enum lp_texture_layout new_layout; 1109 unsigned x, y; 1110 1111 /* loop over all image tiles, doing layout conversion where needed */ 1112 for (y = 0; y < height_t; y++) { 1113 for (x = 0; x < width_t; x++) { 1114 enum lp_texture_layout cur_layout = 1115 llvmpipe_get_texture_tile_layout(lpr, face_slice, level, x, y); 1116 boolean convert; 1117 1118 layout_logic(cur_layout, layout, usage, &new_layout, &convert); 1119 1120 if (convert && other_data && target_data) { 1121 if (layout == LP_TEX_LAYOUT_TILED) { 1122 lp_linear_to_tiled(other_data, target_data, 1123 x * TILE_SIZE, y * TILE_SIZE, 1124 TILE_SIZE, TILE_SIZE, 1125 lpr->base.format, 1126 lpr->row_stride[level], 1127 lpr->tiles_per_row[level]); 1128 } 1129 else { 1130 assert(layout == LP_TEX_LAYOUT_LINEAR); 1131 lp_tiled_to_linear(other_data, target_data, 1132 x * TILE_SIZE, y * TILE_SIZE, 1133 TILE_SIZE, TILE_SIZE, 1134 lpr->base.format, 1135 lpr->row_stride[level], 1136 lpr->tiles_per_row[level]); 1137 } 1138 } 1139 1140 if (new_layout != cur_layout) 1141 llvmpipe_set_texture_tile_layout(lpr, face_slice, level, x, y, 1142 new_layout); 1143 } 1144 } 1145 } 1146 else { 1147 /* no other data */ 1148 llvmpipe_set_texture_image_layout(lpr, face_slice, level, 1149 width_t, height_t, layout); 1150 } 1151 1152 return target_data; 1153 } 1154 1155 1156 /** 1157 * Return pointer to start of a texture image (1D, 2D, 3D, CUBE). 1158 * All cube faces and 3D slices will be converted to the requested 1159 * layout if needed. 1160 * This is typically used when we're about to sample from a texture. 1161 */ 1162 void * 1163 llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr, 1164 unsigned level, 1165 enum lp_texture_usage usage, 1166 enum lp_texture_layout layout) 1167 { 1168 const int slices = lpr->num_slices_faces[level]; 1169 int slice; 1170 void *map = NULL; 1171 1172 assert(slices > 0); 1173 1174 for (slice = slices - 1; slice >= 0; slice--) { 1175 map = llvmpipe_get_texture_image(lpr, slice, level, usage, layout); 1176 } 1177 1178 return map; 1179 } 1180 1181 1182 /** 1183 * Get pointer to a linear image (not the tile!) where the tile at (x,y) 1184 * is known to be in linear layout. 1185 * Conversion from tiled to linear will be done if necessary. 1186 * \return pointer to start of image/face (not the tile) 1187 */ 1188 ubyte * 1189 llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr, 1190 unsigned face_slice, unsigned level, 1191 enum lp_texture_usage usage, 1192 unsigned x, unsigned y) 1193 { 1194 struct llvmpipe_texture_image *linear_img = &lpr->linear[level]; 1195 enum lp_texture_layout cur_layout, new_layout; 1196 const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE; 1197 boolean convert; 1198 uint8_t *tiled_image, *linear_image; 1199 1200 assert(resource_is_texture(&lpr->base)); 1201 assert(x % TILE_SIZE == 0); 1202 assert(y % TILE_SIZE == 0); 1203 1204 if (!linear_img->data) { 1205 /* allocate memory for the linear image now */ 1206 alloc_image_data(lpr, level, LP_TEX_LAYOUT_LINEAR); 1207 } 1208 1209 /* compute address of the slice/face of the image that contains the tile */ 1210 tiled_image = llvmpipe_get_texture_image_address(lpr, face_slice, level, 1211 LP_TEX_LAYOUT_TILED); 1212 linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level, 1213 LP_TEX_LAYOUT_LINEAR); 1214 1215 /* get current tile layout and determine if data conversion is needed */ 1216 cur_layout = llvmpipe_get_texture_tile_layout(lpr, face_slice, level, tx, ty); 1217 1218 layout_logic(cur_layout, LP_TEX_LAYOUT_LINEAR, usage, 1219 &new_layout, &convert); 1220 1221 if (convert && tiled_image && linear_image) { 1222 lp_tiled_to_linear(tiled_image, linear_image, 1223 x, y, TILE_SIZE, TILE_SIZE, lpr->base.format, 1224 lpr->row_stride[level], 1225 lpr->tiles_per_row[level]); 1226 } 1227 1228 if (new_layout != cur_layout) 1229 llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty, new_layout); 1230 1231 return linear_image; 1232 } 1233 1234 1235 /** 1236 * Get pointer to tiled data for rendering. 1237 * \return pointer to the tiled data at the given tile position 1238 */ 1239 ubyte * 1240 llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr, 1241 unsigned face_slice, unsigned level, 1242 enum lp_texture_usage usage, 1243 unsigned x, unsigned y) 1244 { 1245 struct llvmpipe_texture_image *tiled_img = &lpr->tiled[level]; 1246 enum lp_texture_layout cur_layout, new_layout; 1247 const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE; 1248 boolean convert; 1249 uint8_t *tiled_image, *linear_image; 1250 unsigned tile_offset; 1251 1252 assert(x % TILE_SIZE == 0); 1253 assert(y % TILE_SIZE == 0); 1254 1255 if (!tiled_img->data) { 1256 /* allocate memory for the tiled image now */ 1257 alloc_image_data(lpr, level, LP_TEX_LAYOUT_TILED); 1258 } 1259 1260 /* compute address of the slice/face of the image that contains the tile */ 1261 tiled_image = llvmpipe_get_texture_image_address(lpr, face_slice, level, 1262 LP_TEX_LAYOUT_TILED); 1263 linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level, 1264 LP_TEX_LAYOUT_LINEAR); 1265 1266 /* get current tile layout and see if we need to convert the data */ 1267 cur_layout = llvmpipe_get_texture_tile_layout(lpr, face_slice, level, tx, ty); 1268 1269 layout_logic(cur_layout, LP_TEX_LAYOUT_TILED, usage, &new_layout, &convert); 1270 if (convert && linear_image && tiled_image) { 1271 lp_linear_to_tiled(linear_image, tiled_image, 1272 x, y, TILE_SIZE, TILE_SIZE, lpr->base.format, 1273 lpr->row_stride[level], 1274 lpr->tiles_per_row[level]); 1275 } 1276 1277 if (!tiled_image) 1278 return NULL; 1279 1280 if (new_layout != cur_layout) 1281 llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty, new_layout); 1282 1283 /* compute, return address of the 64x64 tile */ 1284 tile_offset = (ty * lpr->tiles_per_row[level] + tx) 1285 * TILE_SIZE * TILE_SIZE * 4; 1286 1287 return (ubyte *) tiled_image + tile_offset; 1288 } 1289 1290 1291 /** 1292 * Get pointer to tiled data for rendering. 1293 * \return pointer to the tiled data at the given tile position 1294 */ 1295 void 1296 llvmpipe_unswizzle_cbuf_tile(struct llvmpipe_resource *lpr, 1297 unsigned face_slice, unsigned level, 1298 unsigned x, unsigned y, 1299 uint8_t *tile) 1300 { 1301 struct llvmpipe_texture_image *linear_img = &lpr->linear[level]; 1302 const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE; 1303 uint8_t *linear_image; 1304 1305 assert(x % TILE_SIZE == 0); 1306 assert(y % TILE_SIZE == 0); 1307 1308 if (!linear_img->data) { 1309 /* allocate memory for the linear image now */ 1310 alloc_image_data(lpr, level, LP_TEX_LAYOUT_LINEAR); 1311 } 1312 1313 /* compute address of the slice/face of the image that contains the tile */ 1314 linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level, 1315 LP_TEX_LAYOUT_LINEAR); 1316 1317 { 1318 uint ii = x, jj = y; 1319 uint tile_offset = jj / TILE_SIZE + ii / TILE_SIZE; 1320 uint byte_offset = tile_offset * TILE_SIZE * TILE_SIZE * 4; 1321 1322 /* Note that lp_tiled_to_linear expects the tile parameter to 1323 * point at the first tile in a whole-image sized array. In 1324 * this code, we have only a single tile and have to do some 1325 * pointer arithmetic to figure out where the "image" would have 1326 * started. 1327 */ 1328 lp_tiled_to_linear(tile - byte_offset, linear_image, 1329 x, y, TILE_SIZE, TILE_SIZE, 1330 lpr->base.format, 1331 lpr->row_stride[level], 1332 1); /* tiles per row */ 1333 } 1334 1335 llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty, 1336 LP_TEX_LAYOUT_LINEAR); 1337 } 1338 1339 1340 /** 1341 * Get pointer to tiled data for rendering. 1342 * \return pointer to the tiled data at the given tile position 1343 */ 1344 void 1345 llvmpipe_swizzle_cbuf_tile(struct llvmpipe_resource *lpr, 1346 unsigned face_slice, unsigned level, 1347 unsigned x, unsigned y, 1348 uint8_t *tile) 1349 { 1350 uint8_t *linear_image; 1351 1352 assert(x % TILE_SIZE == 0); 1353 assert(y % TILE_SIZE == 0); 1354 1355 /* compute address of the slice/face of the image that contains the tile */ 1356 linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level, 1357 LP_TEX_LAYOUT_LINEAR); 1358 1359 if (linear_image) { 1360 uint ii = x, jj = y; 1361 uint tile_offset = jj / TILE_SIZE + ii / TILE_SIZE; 1362 uint byte_offset = tile_offset * TILE_SIZE * TILE_SIZE * 4; 1363 1364 /* Note that lp_linear_to_tiled expects the tile parameter to 1365 * point at the first tile in a whole-image sized array. In 1366 * this code, we have only a single tile and have to do some 1367 * pointer arithmetic to figure out where the "image" would have 1368 * started. 1369 */ 1370 lp_linear_to_tiled(linear_image, tile - byte_offset, 1371 x, y, TILE_SIZE, TILE_SIZE, 1372 lpr->base.format, 1373 lpr->row_stride[level], 1374 1); /* tiles per row */ 1375 } 1376 } 1377 1378 1379 /** 1380 * Return size of resource in bytes 1381 */ 1382 unsigned 1383 llvmpipe_resource_size(const struct pipe_resource *resource) 1384 { 1385 const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource); 1386 unsigned lvl, size = 0; 1387 1388 for (lvl = 0; lvl <= lpr->base.last_level; lvl++) { 1389 if (lpr->linear[lvl].data) 1390 size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_LINEAR); 1391 1392 if (lpr->tiled[lvl].data) 1393 size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_TILED); 1394 } 1395 1396 return size; 1397 } 1398 1399 1400 #ifdef DEBUG 1401 void 1402 llvmpipe_print_resources(void) 1403 { 1404 struct llvmpipe_resource *lpr; 1405 unsigned n = 0, total = 0; 1406 1407 debug_printf("LLVMPIPE: current resources:\n"); 1408 foreach(lpr, &resource_list) { 1409 unsigned size = llvmpipe_resource_size(&lpr->base); 1410 debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n", 1411 lpr->id, (void *) lpr, 1412 lpr->base.width0, lpr->base.height0, lpr->base.depth0, 1413 size, lpr->base.reference.count); 1414 total += size; 1415 n++; 1416 } 1417 debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total); 1418 } 1419 #endif 1420 1421 1422 void 1423 llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen) 1424 { 1425 #ifdef DEBUG 1426 /* init linked list for tracking resources */ 1427 { 1428 static boolean first_call = TRUE; 1429 if (first_call) { 1430 memset(&resource_list, 0, sizeof(resource_list)); 1431 make_empty_list(&resource_list); 1432 first_call = FALSE; 1433 } 1434 } 1435 #endif 1436 1437 screen->resource_create = llvmpipe_resource_create; 1438 screen->resource_destroy = llvmpipe_resource_destroy; 1439 screen->resource_from_handle = llvmpipe_resource_from_handle; 1440 screen->resource_get_handle = llvmpipe_resource_get_handle; 1441 } 1442 1443 1444 void 1445 llvmpipe_init_context_resource_funcs(struct pipe_context *pipe) 1446 { 1447 pipe->get_transfer = llvmpipe_get_transfer; 1448 pipe->transfer_destroy = llvmpipe_transfer_destroy; 1449 pipe->transfer_map = llvmpipe_transfer_map; 1450 pipe->transfer_unmap = llvmpipe_transfer_unmap; 1451 1452 pipe->transfer_flush_region = u_default_transfer_flush_region; 1453 pipe->transfer_inline_write = u_default_transfer_inline_write; 1454 1455 pipe->create_surface = llvmpipe_create_surface; 1456 pipe->surface_destroy = llvmpipe_surface_destroy; 1457 } 1458