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 (at) vmware.com> 30 * Michel Dnzer <daenzer (at) vmware.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/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_texture.h" 50 #include "lp_setup.h" 51 #include "lp_state.h" 52 #include "lp_rast.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 /** 64 * Conventional allocation path for non-display textures: 65 * Compute strides and allocate data (unless asked not to). 66 */ 67 static boolean 68 llvmpipe_texture_layout(struct llvmpipe_screen *screen, 69 struct llvmpipe_resource *lpr, 70 boolean allocate) 71 { 72 struct pipe_resource *pt = &lpr->base; 73 unsigned level; 74 unsigned width = pt->width0; 75 unsigned height = pt->height0; 76 unsigned depth = pt->depth0; 77 uint64_t total_size = 0; 78 unsigned layers = pt->array_size; 79 /* XXX: 80 * This alignment here (same for displaytarget) was added for the purpose of 81 * ARB_map_buffer_alignment. I am not convinced it's needed for non-buffer 82 * resources. Otherwise we'd want the max of cacheline size and 16 (max size 83 * of a block for all formats) though this should not be strictly necessary 84 * neither. In any case it can only affect compressed or 1d textures. 85 */ 86 unsigned mip_align = MAX2(64, util_cpu_caps.cacheline); 87 88 assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS); 89 assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS); 90 91 for (level = 0; level <= pt->last_level; level++) { 92 uint64_t mipsize; 93 unsigned align_x, align_y, nblocksx, nblocksy, block_size, num_slices; 94 95 /* Row stride and image stride */ 96 97 /* For non-compressed formats we need 4x4 pixel alignment 98 * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them. 99 * We also want cache line size in x direction, 100 * otherwise same cache line could end up in multiple threads. 101 * For explicit 1d resources however we reduce this to 4x1 and 102 * handle specially in render output code (as we need to do special 103 * handling there for buffers in any case). 104 */ 105 if (util_format_is_compressed(pt->format)) 106 align_x = align_y = 1; 107 else { 108 align_x = LP_RASTER_BLOCK_SIZE; 109 if (llvmpipe_resource_is_1d(&lpr->base)) 110 align_y = 1; 111 else 112 align_y = LP_RASTER_BLOCK_SIZE; 113 } 114 115 nblocksx = util_format_get_nblocksx(pt->format, 116 align(width, align_x)); 117 nblocksy = util_format_get_nblocksy(pt->format, 118 align(height, align_y)); 119 block_size = util_format_get_blocksize(pt->format); 120 121 if (util_format_is_compressed(pt->format)) 122 lpr->row_stride[level] = nblocksx * block_size; 123 else 124 lpr->row_stride[level] = align(nblocksx * block_size, util_cpu_caps.cacheline); 125 126 /* if row_stride * height > LP_MAX_TEXTURE_SIZE */ 127 if ((uint64_t)lpr->row_stride[level] * nblocksy > LP_MAX_TEXTURE_SIZE) { 128 /* image too large */ 129 goto fail; 130 } 131 132 lpr->img_stride[level] = lpr->row_stride[level] * nblocksy; 133 134 /* Number of 3D image slices, cube faces or texture array layers */ 135 if (lpr->base.target == PIPE_TEXTURE_CUBE) { 136 assert(layers == 6); 137 } 138 139 if (lpr->base.target == PIPE_TEXTURE_3D) 140 num_slices = depth; 141 else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY || 142 lpr->base.target == PIPE_TEXTURE_2D_ARRAY || 143 lpr->base.target == PIPE_TEXTURE_CUBE || 144 lpr->base.target == PIPE_TEXTURE_CUBE_ARRAY) 145 num_slices = layers; 146 else 147 num_slices = 1; 148 149 /* if img_stride * num_slices_faces > LP_MAX_TEXTURE_SIZE */ 150 mipsize = (uint64_t)lpr->img_stride[level] * num_slices; 151 if (mipsize > LP_MAX_TEXTURE_SIZE) { 152 /* volume too large */ 153 goto fail; 154 } 155 156 lpr->mip_offsets[level] = total_size; 157 158 total_size += align((unsigned)mipsize, mip_align); 159 if (total_size > LP_MAX_TEXTURE_SIZE) { 160 goto fail; 161 } 162 163 /* Compute size of next mipmap level */ 164 width = u_minify(width, 1); 165 height = u_minify(height, 1); 166 depth = u_minify(depth, 1); 167 } 168 169 if (allocate) { 170 lpr->tex_data = align_malloc(total_size, mip_align); 171 if (!lpr->tex_data) { 172 return FALSE; 173 } 174 else { 175 memset(lpr->tex_data, 0, total_size); 176 } 177 } 178 179 return TRUE; 180 181 fail: 182 return FALSE; 183 } 184 185 186 /** 187 * Check the size of the texture specified by 'res'. 188 * \return TRUE if OK, FALSE if too large. 189 */ 190 static boolean 191 llvmpipe_can_create_resource(struct pipe_screen *screen, 192 const struct pipe_resource *res) 193 { 194 struct llvmpipe_resource lpr; 195 memset(&lpr, 0, sizeof(lpr)); 196 lpr.base = *res; 197 return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false); 198 } 199 200 201 static boolean 202 llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, 203 struct llvmpipe_resource *lpr, 204 const void *map_front_private) 205 { 206 struct sw_winsys *winsys = screen->winsys; 207 208 /* Round up the surface size to a multiple of the tile size to 209 * avoid tile clipping. 210 */ 211 const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE)); 212 const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE)); 213 214 lpr->dt = winsys->displaytarget_create(winsys, 215 lpr->base.bind, 216 lpr->base.format, 217 width, height, 218 64, 219 map_front_private, 220 &lpr->row_stride[0] ); 221 222 if (lpr->dt == NULL) 223 return FALSE; 224 225 if (!map_front_private) { 226 void *map = winsys->displaytarget_map(winsys, lpr->dt, 227 PIPE_TRANSFER_WRITE); 228 229 if (map) 230 memset(map, 0, height * lpr->row_stride[0]); 231 232 winsys->displaytarget_unmap(winsys, lpr->dt); 233 } 234 235 return TRUE; 236 } 237 238 239 static struct pipe_resource * 240 llvmpipe_resource_create_front(struct pipe_screen *_screen, 241 const struct pipe_resource *templat, 242 const void *map_front_private) 243 { 244 struct llvmpipe_screen *screen = llvmpipe_screen(_screen); 245 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource); 246 if (!lpr) 247 return NULL; 248 249 lpr->base = *templat; 250 pipe_reference_init(&lpr->base.reference, 1); 251 lpr->base.screen = &screen->base; 252 253 /* assert(lpr->base.bind); */ 254 255 if (llvmpipe_resource_is_texture(&lpr->base)) { 256 if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET | 257 PIPE_BIND_SCANOUT | 258 PIPE_BIND_SHARED)) { 259 /* displayable surface */ 260 if (!llvmpipe_displaytarget_layout(screen, lpr, map_front_private)) 261 goto fail; 262 } 263 else { 264 /* texture map */ 265 if (!llvmpipe_texture_layout(screen, lpr, true)) 266 goto fail; 267 } 268 } 269 else { 270 /* other data (vertex buffer, const buffer, etc) */ 271 const uint bytes = templat->width0; 272 assert(util_format_get_blocksize(templat->format) == 1); 273 assert(templat->height0 == 1); 274 assert(templat->depth0 == 1); 275 assert(templat->last_level == 0); 276 /* 277 * Reserve some extra storage since if we'd render to a buffer we 278 * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element 279 * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE. 280 */ 281 lpr->data = align_malloc(bytes + (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float), 64); 282 283 /* 284 * buffers don't really have stride but it's probably safer 285 * (for code doing same calculations for buffers and textures) 286 * to put something sane in there. 287 */ 288 lpr->row_stride[0] = bytes; 289 if (!lpr->data) 290 goto fail; 291 memset(lpr->data, 0, bytes); 292 } 293 294 lpr->id = id_counter++; 295 296 #ifdef DEBUG 297 insert_at_tail(&resource_list, lpr); 298 #endif 299 300 return &lpr->base; 301 302 fail: 303 FREE(lpr); 304 return NULL; 305 } 306 static struct pipe_resource * 307 llvmpipe_resource_create(struct pipe_screen *_screen, 308 const struct pipe_resource *templat) 309 { 310 return llvmpipe_resource_create_front(_screen, templat, NULL); 311 } 312 313 static void 314 llvmpipe_resource_destroy(struct pipe_screen *pscreen, 315 struct pipe_resource *pt) 316 { 317 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen); 318 struct llvmpipe_resource *lpr = llvmpipe_resource(pt); 319 320 if (lpr->dt) { 321 /* display target */ 322 struct sw_winsys *winsys = screen->winsys; 323 winsys->displaytarget_destroy(winsys, lpr->dt); 324 } 325 else if (llvmpipe_resource_is_texture(pt)) { 326 /* free linear image data */ 327 if (lpr->tex_data) { 328 align_free(lpr->tex_data); 329 lpr->tex_data = NULL; 330 } 331 } 332 else if (!lpr->userBuffer) { 333 assert(lpr->data); 334 align_free(lpr->data); 335 } 336 337 #ifdef DEBUG 338 if (lpr->next) 339 remove_from_list(lpr); 340 #endif 341 342 FREE(lpr); 343 } 344 345 346 /** 347 * Map a resource for read/write. 348 */ 349 void * 350 llvmpipe_resource_map(struct pipe_resource *resource, 351 unsigned level, 352 unsigned layer, 353 enum lp_texture_usage tex_usage) 354 { 355 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 356 uint8_t *map; 357 358 assert(level < LP_MAX_TEXTURE_LEVELS); 359 assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1)); 360 361 assert(tex_usage == LP_TEX_USAGE_READ || 362 tex_usage == LP_TEX_USAGE_READ_WRITE || 363 tex_usage == LP_TEX_USAGE_WRITE_ALL); 364 365 if (lpr->dt) { 366 /* display target */ 367 struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen); 368 struct sw_winsys *winsys = screen->winsys; 369 unsigned dt_usage; 370 371 if (tex_usage == LP_TEX_USAGE_READ) { 372 dt_usage = PIPE_TRANSFER_READ; 373 } 374 else { 375 dt_usage = PIPE_TRANSFER_READ_WRITE; 376 } 377 378 assert(level == 0); 379 assert(layer == 0); 380 381 /* FIXME: keep map count? */ 382 map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage); 383 384 /* install this linear image in texture data structure */ 385 lpr->tex_data = map; 386 387 return map; 388 } 389 else if (llvmpipe_resource_is_texture(resource)) { 390 391 map = llvmpipe_get_texture_image_address(lpr, layer, level); 392 return map; 393 } 394 else { 395 return lpr->data; 396 } 397 } 398 399 400 /** 401 * Unmap a resource. 402 */ 403 void 404 llvmpipe_resource_unmap(struct pipe_resource *resource, 405 unsigned level, 406 unsigned layer) 407 { 408 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 409 410 if (lpr->dt) { 411 /* display target */ 412 struct llvmpipe_screen *lp_screen = llvmpipe_screen(resource->screen); 413 struct sw_winsys *winsys = lp_screen->winsys; 414 415 assert(level == 0); 416 assert(layer == 0); 417 418 winsys->displaytarget_unmap(winsys, lpr->dt); 419 } 420 } 421 422 423 void * 424 llvmpipe_resource_data(struct pipe_resource *resource) 425 { 426 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 427 428 assert(!llvmpipe_resource_is_texture(resource)); 429 430 return lpr->data; 431 } 432 433 434 static struct pipe_resource * 435 llvmpipe_resource_from_handle(struct pipe_screen *screen, 436 const struct pipe_resource *template, 437 struct winsys_handle *whandle, 438 unsigned usage) 439 { 440 struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; 441 struct llvmpipe_resource *lpr; 442 443 /* XXX Seems like from_handled depth textures doesn't work that well */ 444 445 lpr = CALLOC_STRUCT(llvmpipe_resource); 446 if (!lpr) { 447 goto no_lpr; 448 } 449 450 lpr->base = *template; 451 pipe_reference_init(&lpr->base.reference, 1); 452 lpr->base.screen = screen; 453 454 /* 455 * Looks like unaligned displaytargets work just fine, 456 * at least sampler/render ones. 457 */ 458 #if 0 459 assert(lpr->base.width0 == width); 460 assert(lpr->base.height0 == height); 461 #endif 462 463 lpr->dt = winsys->displaytarget_from_handle(winsys, 464 template, 465 whandle, 466 &lpr->row_stride[0]); 467 if (!lpr->dt) { 468 goto no_dt; 469 } 470 471 lpr->id = id_counter++; 472 473 #ifdef DEBUG 474 insert_at_tail(&resource_list, lpr); 475 #endif 476 477 return &lpr->base; 478 479 no_dt: 480 FREE(lpr); 481 no_lpr: 482 return NULL; 483 } 484 485 486 static boolean 487 llvmpipe_resource_get_handle(struct pipe_screen *screen, 488 struct pipe_context *ctx, 489 struct pipe_resource *pt, 490 struct winsys_handle *whandle, 491 unsigned usage) 492 { 493 struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; 494 struct llvmpipe_resource *lpr = llvmpipe_resource(pt); 495 496 assert(lpr->dt); 497 if (!lpr->dt) 498 return FALSE; 499 500 return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle); 501 } 502 503 504 static void * 505 llvmpipe_transfer_map( struct pipe_context *pipe, 506 struct pipe_resource *resource, 507 unsigned level, 508 unsigned usage, 509 const struct pipe_box *box, 510 struct pipe_transfer **transfer ) 511 { 512 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 513 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 514 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 515 struct llvmpipe_transfer *lpt; 516 struct pipe_transfer *pt; 517 ubyte *map; 518 enum pipe_format format; 519 enum lp_texture_usage tex_usage; 520 const char *mode; 521 522 assert(resource); 523 assert(level <= resource->last_level); 524 525 /* 526 * Transfers, like other pipe operations, must happen in order, so flush the 527 * context if necessary. 528 */ 529 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { 530 boolean read_only = !(usage & PIPE_TRANSFER_WRITE); 531 boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK); 532 if (!llvmpipe_flush_resource(pipe, resource, 533 level, 534 read_only, 535 TRUE, /* cpu_access */ 536 do_not_block, 537 __FUNCTION__)) { 538 /* 539 * It would have blocked, but state tracker requested no to. 540 */ 541 assert(do_not_block); 542 return NULL; 543 } 544 } 545 546 /* Check if we're mapping a current constant buffer */ 547 if ((usage & PIPE_TRANSFER_WRITE) && 548 (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) { 549 unsigned i; 550 for (i = 0; i < ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) { 551 if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) { 552 /* constants may have changed */ 553 llvmpipe->dirty |= LP_NEW_FS_CONSTANTS; 554 break; 555 } 556 } 557 } 558 559 lpt = CALLOC_STRUCT(llvmpipe_transfer); 560 if (!lpt) 561 return NULL; 562 pt = &lpt->base; 563 pipe_resource_reference(&pt->resource, resource); 564 pt->box = *box; 565 pt->level = level; 566 pt->stride = lpr->row_stride[level]; 567 pt->layer_stride = lpr->img_stride[level]; 568 pt->usage = usage; 569 *transfer = pt; 570 571 assert(level < LP_MAX_TEXTURE_LEVELS); 572 573 /* 574 printf("tex_transfer_map(%d, %d %d x %d of %d x %d, usage %d )\n", 575 transfer->x, transfer->y, transfer->width, transfer->height, 576 transfer->texture->width0, 577 transfer->texture->height0, 578 transfer->usage); 579 */ 580 581 if (usage == PIPE_TRANSFER_READ) { 582 tex_usage = LP_TEX_USAGE_READ; 583 mode = "read"; 584 } 585 else { 586 tex_usage = LP_TEX_USAGE_READ_WRITE; 587 mode = "read/write"; 588 } 589 590 if (0) { 591 printf("transfer map tex %u mode %s\n", lpr->id, mode); 592 } 593 594 format = lpr->base.format; 595 596 map = llvmpipe_resource_map(resource, 597 level, 598 box->z, 599 tex_usage); 600 601 602 /* May want to do different things here depending on read/write nature 603 * of the map: 604 */ 605 if (usage & PIPE_TRANSFER_WRITE) { 606 /* Do something to notify sharing contexts of a texture change. 607 */ 608 screen->timestamp++; 609 } 610 611 map += 612 box->y / util_format_get_blockheight(format) * pt->stride + 613 box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); 614 615 return map; 616 } 617 618 619 static void 620 llvmpipe_transfer_unmap(struct pipe_context *pipe, 621 struct pipe_transfer *transfer) 622 { 623 assert(transfer->resource); 624 625 llvmpipe_resource_unmap(transfer->resource, 626 transfer->level, 627 transfer->box.z); 628 629 /* Effectively do the texture_update work here - if texture images 630 * needed post-processing to put them into hardware layout, this is 631 * where it would happen. For llvmpipe, nothing to do. 632 */ 633 assert (transfer->resource); 634 pipe_resource_reference(&transfer->resource, NULL); 635 FREE(transfer); 636 } 637 638 unsigned int 639 llvmpipe_is_resource_referenced( struct pipe_context *pipe, 640 struct pipe_resource *presource, 641 unsigned level) 642 { 643 struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); 644 if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL | 645 PIPE_BIND_RENDER_TARGET | 646 PIPE_BIND_SAMPLER_VIEW))) 647 return LP_UNREFERENCED; 648 649 return lp_setup_is_resource_referenced(llvmpipe->setup, presource); 650 } 651 652 653 /** 654 * Returns the largest possible alignment for a format in llvmpipe 655 */ 656 unsigned 657 llvmpipe_get_format_alignment( enum pipe_format format ) 658 { 659 const struct util_format_description *desc = util_format_description(format); 660 unsigned size = 0; 661 unsigned bytes; 662 unsigned i; 663 664 for (i = 0; i < desc->nr_channels; ++i) { 665 size += desc->channel[i].size; 666 } 667 668 bytes = size / 8; 669 670 if (!util_is_power_of_two(bytes)) { 671 bytes /= desc->nr_channels; 672 } 673 674 if (bytes % 2 || bytes < 1) { 675 return 1; 676 } else { 677 return bytes; 678 } 679 } 680 681 682 /** 683 * Create buffer which wraps user-space data. 684 * XXX unreachable. 685 */ 686 struct pipe_resource * 687 llvmpipe_user_buffer_create(struct pipe_screen *screen, 688 void *ptr, 689 unsigned bytes, 690 unsigned bind_flags) 691 { 692 struct llvmpipe_resource *buffer; 693 694 buffer = CALLOC_STRUCT(llvmpipe_resource); 695 if (!buffer) 696 return NULL; 697 698 pipe_reference_init(&buffer->base.reference, 1); 699 buffer->base.screen = screen; 700 buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */ 701 buffer->base.bind = bind_flags; 702 buffer->base.usage = PIPE_USAGE_IMMUTABLE; 703 buffer->base.flags = 0; 704 buffer->base.width0 = bytes; 705 buffer->base.height0 = 1; 706 buffer->base.depth0 = 1; 707 buffer->base.array_size = 1; 708 buffer->userBuffer = TRUE; 709 buffer->data = ptr; 710 711 return &buffer->base; 712 } 713 714 715 /** 716 * Compute size (in bytes) need to store a texture image / mipmap level, 717 * for just one cube face, one array layer or one 3D texture slice 718 */ 719 static unsigned 720 tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level) 721 { 722 return lpr->img_stride[level]; 723 } 724 725 726 /** 727 * Return pointer to a 2D texture image/face/slice. 728 * No tiled/linear conversion is done. 729 */ 730 ubyte * 731 llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr, 732 unsigned face_slice, unsigned level) 733 { 734 unsigned offset; 735 736 assert(llvmpipe_resource_is_texture(&lpr->base)); 737 738 offset = lpr->mip_offsets[level]; 739 740 if (face_slice > 0) 741 offset += face_slice * tex_image_face_size(lpr, level); 742 743 return (ubyte *) lpr->tex_data + offset; 744 } 745 746 747 /** 748 * Return size of resource in bytes 749 */ 750 unsigned 751 llvmpipe_resource_size(const struct pipe_resource *resource) 752 { 753 const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource); 754 unsigned size = 0; 755 756 if (llvmpipe_resource_is_texture(resource)) { 757 /* Note this will always return 0 for displaytarget resources */ 758 size = lpr->total_alloc_size; 759 } 760 else { 761 size = resource->width0; 762 } 763 return size; 764 } 765 766 767 #ifdef DEBUG 768 void 769 llvmpipe_print_resources(void) 770 { 771 struct llvmpipe_resource *lpr; 772 unsigned n = 0, total = 0; 773 774 debug_printf("LLVMPIPE: current resources:\n"); 775 foreach(lpr, &resource_list) { 776 unsigned size = llvmpipe_resource_size(&lpr->base); 777 debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n", 778 lpr->id, (void *) lpr, 779 lpr->base.width0, lpr->base.height0, lpr->base.depth0, 780 size, lpr->base.reference.count); 781 total += size; 782 n++; 783 } 784 debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total); 785 } 786 #endif 787 788 789 void 790 llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen) 791 { 792 #ifdef DEBUG 793 /* init linked list for tracking resources */ 794 { 795 static boolean first_call = TRUE; 796 if (first_call) { 797 memset(&resource_list, 0, sizeof(resource_list)); 798 make_empty_list(&resource_list); 799 first_call = FALSE; 800 } 801 } 802 #endif 803 804 screen->resource_create = llvmpipe_resource_create; 805 /* screen->resource_create_front = llvmpipe_resource_create_front; */ 806 screen->resource_destroy = llvmpipe_resource_destroy; 807 screen->resource_from_handle = llvmpipe_resource_from_handle; 808 screen->resource_get_handle = llvmpipe_resource_get_handle; 809 screen->can_create_resource = llvmpipe_can_create_resource; 810 } 811 812 813 void 814 llvmpipe_init_context_resource_funcs(struct pipe_context *pipe) 815 { 816 pipe->transfer_map = llvmpipe_transfer_map; 817 pipe->transfer_unmap = llvmpipe_transfer_unmap; 818 819 pipe->transfer_flush_region = u_default_transfer_flush_region; 820 pipe->buffer_subdata = u_default_buffer_subdata; 821 pipe->texture_subdata = u_default_texture_subdata; 822 } 823