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 <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/format/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 "frontend/sw_winsys.h" 55#include "git_sha1.h" 56 57#ifndef _WIN32 58#include "drm-uapi/drm_fourcc.h" 59#endif 60 61 62#ifdef DEBUG 63static struct llvmpipe_resource resource_list; 64static mtx_t resource_list_mutex = _MTX_INITIALIZER_NP; 65#endif 66static unsigned id_counter = 0; 67 68 69/** 70 * Conventional allocation path for non-display textures: 71 * Compute strides and allocate data (unless asked not to). 72 */ 73static boolean 74llvmpipe_texture_layout(struct llvmpipe_screen *screen, 75 struct llvmpipe_resource *lpr, 76 boolean allocate) 77{ 78 struct pipe_resource *pt = &lpr->base; 79 unsigned level; 80 unsigned width = pt->width0; 81 unsigned height = pt->height0; 82 unsigned depth = pt->depth0; 83 uint64_t total_size = 0; 84 unsigned layers = pt->array_size; 85 unsigned num_samples = util_res_sample_count(pt); 86 87 /* XXX: 88 * This alignment here (same for displaytarget) was added for the purpose of 89 * ARB_map_buffer_alignment. I am not convinced it's needed for non-buffer 90 * resources. Otherwise we'd want the max of cacheline size and 16 (max size 91 * of a block for all formats) though this should not be strictly necessary 92 * neither. In any case it can only affect compressed or 1d textures. 93 */ 94 unsigned mip_align = MAX2(64, util_get_cpu_caps()->cacheline); 95 96 assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS); 97 assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS); 98 99 for (level = 0; level <= pt->last_level; level++) { 100 uint64_t mipsize; 101 unsigned align_x, align_y, nblocksx, nblocksy, block_size, num_slices; 102 103 /* Row stride and image stride */ 104 105 /* For non-compressed formats we need 4x4 pixel alignment 106 * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them. 107 * We also want cache line size in x direction, 108 * otherwise same cache line could end up in multiple threads. 109 * For explicit 1d resources however we reduce this to 4x1 and 110 * handle specially in render output code (as we need to do special 111 * handling there for buffers in any case). 112 */ 113 if (util_format_is_compressed(pt->format)) 114 align_x = align_y = 1; 115 else { 116 align_x = LP_RASTER_BLOCK_SIZE; 117 if (llvmpipe_resource_is_1d(&lpr->base)) 118 align_y = 1; 119 else 120 align_y = LP_RASTER_BLOCK_SIZE; 121 } 122 123 nblocksx = util_format_get_nblocksx(pt->format, 124 align(width, align_x)); 125 nblocksy = util_format_get_nblocksy(pt->format, 126 align(height, align_y)); 127 block_size = util_format_get_blocksize(pt->format); 128 129 if (util_format_is_compressed(pt->format)) 130 lpr->row_stride[level] = nblocksx * block_size; 131 else 132 lpr->row_stride[level] = align(nblocksx * block_size, util_get_cpu_caps()->cacheline); 133 134 lpr->img_stride[level] = (uint64_t)lpr->row_stride[level] * nblocksy; 135 136 /* Number of 3D image slices, cube faces or texture array layers */ 137 if (lpr->base.target == PIPE_TEXTURE_CUBE) { 138 assert(layers == 6); 139 } 140 141 if (lpr->base.target == PIPE_TEXTURE_3D) 142 num_slices = depth; 143 else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY || 144 lpr->base.target == PIPE_TEXTURE_2D_ARRAY || 145 lpr->base.target == PIPE_TEXTURE_CUBE || 146 lpr->base.target == PIPE_TEXTURE_CUBE_ARRAY) 147 num_slices = layers; 148 else 149 num_slices = 1; 150 151 mipsize = lpr->img_stride[level] * num_slices; 152 lpr->mip_offsets[level] = total_size; 153 154 total_size += align64(mipsize, mip_align); 155 156 /* Compute size of next mipmap level */ 157 width = u_minify(width, 1); 158 height = u_minify(height, 1); 159 depth = u_minify(depth, 1); 160 } 161 162 lpr->sample_stride = total_size; 163 total_size *= num_samples; 164 165 lpr->size_required = total_size; 166 if (allocate) { 167 if (total_size > LP_MAX_TEXTURE_SIZE) 168 goto fail; 169 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 181fail: 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 */ 190static bool 191llvmpipe_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 if (!llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false)) 198 return false; 199 200 return lpr.size_required <= LP_MAX_TEXTURE_SIZE; 201} 202 203 204static boolean 205llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, 206 struct llvmpipe_resource *lpr, 207 const void *map_front_private) 208{ 209 struct sw_winsys *winsys = screen->winsys; 210 211 /* Round up the surface size to a multiple of the tile size to 212 * avoid tile clipping. 213 */ 214 const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE)); 215 const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE)); 216 217 lpr->dt = winsys->displaytarget_create(winsys, 218 lpr->base.bind, 219 lpr->base.format, 220 width, height, 221 64, 222 map_front_private, 223 &lpr->row_stride[0] ); 224 225 return lpr->dt != NULL; 226} 227 228 229static struct pipe_resource * 230llvmpipe_resource_create_all(struct pipe_screen *_screen, 231 const struct pipe_resource *templat, 232 const void *map_front_private, bool alloc_backing) 233{ 234 struct llvmpipe_screen *screen = llvmpipe_screen(_screen); 235 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource); 236 if (!lpr) 237 return NULL; 238 239 lpr->base = *templat; 240 lpr->screen = screen; 241 pipe_reference_init(&lpr->base.reference, 1); 242 lpr->base.screen = &screen->base; 243 244 /* assert(lpr->base.bind); */ 245 246 if (llvmpipe_resource_is_texture(&lpr->base)) { 247 if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET | 248 PIPE_BIND_SCANOUT | 249 PIPE_BIND_SHARED)) { 250 /* displayable surface */ 251 if (!llvmpipe_displaytarget_layout(screen, lpr, map_front_private)) 252 goto fail; 253 } 254 else { 255 /* texture map */ 256 if (!llvmpipe_texture_layout(screen, lpr, alloc_backing)) 257 goto fail; 258 } 259 } 260 else { 261 /* other data (vertex buffer, const buffer, etc) */ 262 const uint bytes = templat->width0; 263 assert(util_format_get_blocksize(templat->format) == 1); 264 assert(templat->height0 == 1); 265 assert(templat->depth0 == 1); 266 assert(templat->last_level == 0); 267 /* 268 * Reserve some extra storage since if we'd render to a buffer we 269 * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element 270 * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE. 271 */ 272 /* 273 * buffers don't really have stride but it's probably safer 274 * (for code doing same calculations for buffers and textures) 275 * to put something sane in there. 276 */ 277 lpr->row_stride[0] = bytes; 278 279 lpr->size_required = bytes; 280 if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE)) 281 lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float); 282 283 if (alloc_backing) { 284 lpr->data = align_malloc(lpr->size_required, 64); 285 286 if (!lpr->data) 287 goto fail; 288 memset(lpr->data, 0, bytes); 289 } 290 } 291 292 lpr->id = id_counter++; 293 294#ifdef DEBUG 295 mtx_lock(&resource_list_mutex); 296 insert_at_tail(&resource_list, lpr); 297 mtx_unlock(&resource_list_mutex); 298#endif 299 300 return &lpr->base; 301 302 fail: 303 FREE(lpr); 304 return NULL; 305} 306 307static struct pipe_resource * 308llvmpipe_resource_create_front(struct pipe_screen *_screen, 309 const struct pipe_resource *templat, 310 const void *map_front_private) 311{ 312 return llvmpipe_resource_create_all(_screen, templat, map_front_private, true); 313} 314 315static struct pipe_resource * 316llvmpipe_resource_create(struct pipe_screen *_screen, 317 const struct pipe_resource *templat) 318{ 319 return llvmpipe_resource_create_front(_screen, templat, NULL); 320} 321 322static struct pipe_resource * 323llvmpipe_resource_create_unbacked(struct pipe_screen *_screen, 324 const struct pipe_resource *templat, 325 uint64_t *size_required) 326{ 327 struct pipe_resource *pt; 328 struct llvmpipe_resource *lpr; 329 pt = llvmpipe_resource_create_all(_screen, templat, NULL, false); 330 if (!pt) 331 return pt; 332 lpr = llvmpipe_resource(pt); 333 lpr->backable = true; 334 *size_required = lpr->size_required; 335 return pt; 336} 337 338static struct pipe_memory_object * 339llvmpipe_memobj_create_from_handle(struct pipe_screen *pscreen, 340 struct winsys_handle *handle, 341 bool dedicated) 342{ 343#ifdef PIPE_MEMORY_FD 344 struct llvmpipe_memory_object *memobj = CALLOC_STRUCT(llvmpipe_memory_object); 345 346 if (handle->type == WINSYS_HANDLE_TYPE_FD && 347 pscreen->import_memory_fd(pscreen, handle->handle, &memobj->data, &memobj->size)) { 348 return &memobj->b; 349 } 350 free(memobj); 351#endif 352 return NULL; 353} 354 355static void 356llvmpipe_memobj_destroy(struct pipe_screen *pscreen, 357 struct pipe_memory_object *memobj) 358{ 359 if (!memobj) 360 return; 361 struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj); 362#ifdef PIPE_MEMORY_FD 363 pscreen->free_memory_fd(pscreen, lpmo->data); 364#endif 365 free(lpmo); 366} 367 368static struct pipe_resource * 369llvmpipe_resource_from_memobj(struct pipe_screen *pscreen, 370 const struct pipe_resource *templat, 371 struct pipe_memory_object *memobj, 372 uint64_t offset) 373{ 374 if (!memobj) 375 return NULL; 376 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen); 377 struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj); 378 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource); 379 lpr->base = *templat; 380 381 lpr->screen = screen; 382 pipe_reference_init(&lpr->base.reference, 1); 383 lpr->base.screen = &screen->base; 384 385 if (llvmpipe_resource_is_texture(&lpr->base)) { 386 /* texture map */ 387 if (!llvmpipe_texture_layout(screen, lpr, false)) 388 goto fail; 389 if(lpmo->size < lpr->size_required) 390 goto fail; 391 lpr->tex_data = lpmo->data; 392 } 393 else { 394 /* other data (vertex buffer, const buffer, etc) */ 395 const uint bytes = templat->width0; 396 assert(util_format_get_blocksize(templat->format) == 1); 397 assert(templat->height0 == 1); 398 assert(templat->depth0 == 1); 399 assert(templat->last_level == 0); 400 /* 401 * Reserve some extra storage since if we'd render to a buffer we 402 * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element 403 * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE. 404 */ 405 /* 406 * buffers don't really have stride but it's probably safer 407 * (for code doing same calculations for buffers and textures) 408 * to put something reasonable in there. 409 */ 410 lpr->row_stride[0] = bytes; 411 412 lpr->size_required = bytes; 413 if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE)) 414 lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float); 415 416 if(lpmo->size < lpr->size_required) 417 goto fail; 418 lpr->data = lpmo->data; 419 } 420 lpr->id = id_counter++; 421 lpr->imported_memory = true; 422 423#ifdef DEBUG 424 mtx_lock(&resource_list_mutex); 425 insert_at_tail(&resource_list, lpr); 426 mtx_unlock(&resource_list_mutex); 427#endif 428 429 return &lpr->base; 430 431fail: 432 free(lpr); 433 return NULL; 434} 435 436static void 437llvmpipe_resource_destroy(struct pipe_screen *pscreen, 438 struct pipe_resource *pt) 439{ 440 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen); 441 struct llvmpipe_resource *lpr = llvmpipe_resource(pt); 442 443 if (!lpr->backable && !lpr->user_ptr) { 444 if (lpr->dt) { 445 /* display target */ 446 struct sw_winsys *winsys = screen->winsys; 447 winsys->displaytarget_destroy(winsys, lpr->dt); 448 } 449 else if (llvmpipe_resource_is_texture(pt)) { 450 /* free linear image data */ 451 if (lpr->tex_data) { 452 if (!lpr->imported_memory) 453 align_free(lpr->tex_data); 454 lpr->tex_data = NULL; 455 } 456 } 457 else if (lpr->data) { 458 if (!lpr->imported_memory) 459 align_free(lpr->data); 460 } 461 } 462#ifdef DEBUG 463 mtx_lock(&resource_list_mutex); 464 if (lpr->next) 465 remove_from_list(lpr); 466 mtx_unlock(&resource_list_mutex); 467#endif 468 469 FREE(lpr); 470} 471 472 473/** 474 * Map a resource for read/write. 475 */ 476void * 477llvmpipe_resource_map(struct pipe_resource *resource, 478 unsigned level, 479 unsigned layer, 480 enum lp_texture_usage tex_usage) 481{ 482 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 483 uint8_t *map; 484 485 assert(level < LP_MAX_TEXTURE_LEVELS); 486 assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1)); 487 488 assert(tex_usage == LP_TEX_USAGE_READ || 489 tex_usage == LP_TEX_USAGE_READ_WRITE || 490 tex_usage == LP_TEX_USAGE_WRITE_ALL); 491 492 if (lpr->dt) { 493 /* display target */ 494 struct llvmpipe_screen *screen = lpr->screen; 495 struct sw_winsys *winsys = screen->winsys; 496 unsigned dt_usage; 497 498 if (tex_usage == LP_TEX_USAGE_READ) { 499 dt_usage = PIPE_MAP_READ; 500 } 501 else { 502 dt_usage = PIPE_MAP_READ_WRITE; 503 } 504 505 assert(level == 0); 506 assert(layer == 0); 507 508 /* FIXME: keep map count? */ 509 map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage); 510 511 /* install this linear image in texture data structure */ 512 lpr->tex_data = map; 513 514 return map; 515 } 516 else if (llvmpipe_resource_is_texture(resource)) { 517 518 map = llvmpipe_get_texture_image_address(lpr, layer, level); 519 return map; 520 } 521 else { 522 return lpr->data; 523 } 524} 525 526 527/** 528 * Unmap a resource. 529 */ 530void 531llvmpipe_resource_unmap(struct pipe_resource *resource, 532 unsigned level, 533 unsigned layer) 534{ 535 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 536 537 if (lpr->dt) { 538 /* display target */ 539 struct llvmpipe_screen *lp_screen = lpr->screen; 540 struct sw_winsys *winsys = lp_screen->winsys; 541 542 assert(level == 0); 543 assert(layer == 0); 544 545 winsys->displaytarget_unmap(winsys, lpr->dt); 546 } 547} 548 549 550void * 551llvmpipe_resource_data(struct pipe_resource *resource) 552{ 553 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 554 555 assert(!llvmpipe_resource_is_texture(resource)); 556 557 return lpr->data; 558} 559 560 561static struct pipe_resource * 562llvmpipe_resource_from_handle(struct pipe_screen *_screen, 563 const struct pipe_resource *template, 564 struct winsys_handle *whandle, 565 unsigned usage) 566{ 567 struct llvmpipe_screen *screen = llvmpipe_screen(_screen); 568 struct sw_winsys *winsys = screen->winsys; 569 struct llvmpipe_resource *lpr; 570 571 /* XXX Seems like from_handled depth textures doesn't work that well */ 572 573 lpr = CALLOC_STRUCT(llvmpipe_resource); 574 if (!lpr) { 575 goto no_lpr; 576 } 577 578 lpr->base = *template; 579 lpr->screen = screen; 580 pipe_reference_init(&lpr->base.reference, 1); 581 lpr->base.screen = _screen; 582 583 /* 584 * Looks like unaligned displaytargets work just fine, 585 * at least sampler/render ones. 586 */ 587#if 0 588 assert(lpr->base.width0 == width); 589 assert(lpr->base.height0 == height); 590#endif 591 592 lpr->dt = winsys->displaytarget_from_handle(winsys, 593 template, 594 whandle, 595 &lpr->row_stride[0]); 596 if (!lpr->dt) { 597 goto no_dt; 598 } 599 600 lpr->id = id_counter++; 601 602#ifdef DEBUG 603 mtx_lock(&resource_list_mutex); 604 insert_at_tail(&resource_list, lpr); 605 mtx_unlock(&resource_list_mutex); 606#endif 607 608 return &lpr->base; 609 610no_dt: 611 FREE(lpr); 612no_lpr: 613 return NULL; 614} 615 616 617static bool 618llvmpipe_resource_get_handle(struct pipe_screen *screen, 619 struct pipe_context *ctx, 620 struct pipe_resource *pt, 621 struct winsys_handle *whandle, 622 unsigned usage) 623{ 624 struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; 625 struct llvmpipe_resource *lpr = llvmpipe_resource(pt); 626 627 assert(lpr->dt); 628 if (!lpr->dt) 629 return false; 630 631 return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle); 632} 633 634static struct pipe_resource * 635llvmpipe_resource_from_user_memory(struct pipe_screen *_screen, 636 const struct pipe_resource *resource, 637 void *user_memory) 638{ 639 struct llvmpipe_screen *screen = llvmpipe_screen(_screen); 640 struct llvmpipe_resource *lpr; 641 642 lpr = CALLOC_STRUCT(llvmpipe_resource); 643 if (!lpr) { 644 return NULL; 645 } 646 647 lpr->base = *resource; 648 lpr->screen = screen; 649 pipe_reference_init(&lpr->base.reference, 1); 650 lpr->base.screen = _screen; 651 652 if (llvmpipe_resource_is_texture(&lpr->base)) { 653 if (!llvmpipe_texture_layout(screen, lpr, false)) 654 goto fail; 655 656 lpr->tex_data = user_memory; 657 } else 658 lpr->data = user_memory; 659 lpr->user_ptr = true; 660 return &lpr->base; 661fail: 662 FREE(lpr); 663 return NULL; 664} 665 666void * 667llvmpipe_transfer_map_ms( struct pipe_context *pipe, 668 struct pipe_resource *resource, 669 unsigned level, 670 unsigned usage, 671 unsigned sample, 672 const struct pipe_box *box, 673 struct pipe_transfer **transfer ) 674{ 675 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 676 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 677 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 678 struct llvmpipe_transfer *lpt; 679 struct pipe_transfer *pt; 680 ubyte *map; 681 enum pipe_format format; 682 enum lp_texture_usage tex_usage; 683 const char *mode; 684 685 assert(resource); 686 assert(level <= resource->last_level); 687 688 /* 689 * Transfers, like other pipe operations, must happen in order, so flush the 690 * context if necessary. 691 */ 692 if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) { 693 boolean read_only = !(usage & PIPE_MAP_WRITE); 694 boolean do_not_block = !!(usage & PIPE_MAP_DONTBLOCK); 695 if (!llvmpipe_flush_resource(pipe, resource, 696 level, 697 read_only, 698 TRUE, /* cpu_access */ 699 do_not_block, 700 __FUNCTION__)) { 701 /* 702 * It would have blocked, but gallium frontend requested no to. 703 */ 704 assert(do_not_block); 705 return NULL; 706 } 707 } 708 709 /* Check if we're mapping a current constant buffer */ 710 if ((usage & PIPE_MAP_WRITE) && 711 (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) { 712 unsigned i; 713 for (i = 0; i < ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) { 714 if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) { 715 /* constants may have changed */ 716 llvmpipe->dirty |= LP_NEW_FS_CONSTANTS; 717 break; 718 } 719 } 720 } 721 722 lpt = CALLOC_STRUCT(llvmpipe_transfer); 723 if (!lpt) 724 return NULL; 725 pt = &lpt->base; 726 pipe_resource_reference(&pt->resource, resource); 727 pt->box = *box; 728 pt->level = level; 729 pt->stride = lpr->row_stride[level]; 730 pt->layer_stride = lpr->img_stride[level]; 731 pt->usage = usage; 732 *transfer = pt; 733 734 assert(level < LP_MAX_TEXTURE_LEVELS); 735 736 /* 737 printf("tex_transfer_map(%d, %d %d x %d of %d x %d, usage %d )\n", 738 transfer->x, transfer->y, transfer->width, transfer->height, 739 transfer->texture->width0, 740 transfer->texture->height0, 741 transfer->usage); 742 */ 743 744 if (usage == PIPE_MAP_READ) { 745 tex_usage = LP_TEX_USAGE_READ; 746 mode = "read"; 747 } 748 else { 749 tex_usage = LP_TEX_USAGE_READ_WRITE; 750 mode = "read/write"; 751 } 752 753 if (0) { 754 printf("transfer map tex %u mode %s\n", lpr->id, mode); 755 } 756 757 format = lpr->base.format; 758 759 map = llvmpipe_resource_map(resource, 760 level, 761 box->z, 762 tex_usage); 763 764 765 /* May want to do different things here depending on read/write nature 766 * of the map: 767 */ 768 if (usage & PIPE_MAP_WRITE) { 769 /* Do something to notify sharing contexts of a texture change. 770 */ 771 screen->timestamp++; 772 } 773 774 map += 775 box->y / util_format_get_blockheight(format) * pt->stride + 776 box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); 777 778 map += sample * lpr->sample_stride; 779 return map; 780} 781 782static void * 783llvmpipe_transfer_map( struct pipe_context *pipe, 784 struct pipe_resource *resource, 785 unsigned level, 786 unsigned usage, 787 const struct pipe_box *box, 788 struct pipe_transfer **transfer ) 789{ 790 return llvmpipe_transfer_map_ms(pipe, resource, level, usage, 0, box, transfer); 791} 792 793static void 794llvmpipe_transfer_unmap(struct pipe_context *pipe, 795 struct pipe_transfer *transfer) 796{ 797 assert(transfer->resource); 798 799 llvmpipe_resource_unmap(transfer->resource, 800 transfer->level, 801 transfer->box.z); 802 803 /* Effectively do the texture_update work here - if texture images 804 * needed post-processing to put them into hardware layout, this is 805 * where it would happen. For llvmpipe, nothing to do. 806 */ 807 assert (transfer->resource); 808 pipe_resource_reference(&transfer->resource, NULL); 809 FREE(transfer); 810} 811 812unsigned int 813llvmpipe_is_resource_referenced( struct pipe_context *pipe, 814 struct pipe_resource *presource, 815 unsigned level) 816{ 817 struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); 818 if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL | 819 PIPE_BIND_RENDER_TARGET | 820 PIPE_BIND_SAMPLER_VIEW | 821 PIPE_BIND_SHADER_BUFFER | 822 PIPE_BIND_SHADER_IMAGE))) 823 return LP_UNREFERENCED; 824 825 return lp_setup_is_resource_referenced(llvmpipe->setup, presource); 826} 827 828 829/** 830 * Returns the largest possible alignment for a format in llvmpipe 831 */ 832unsigned 833llvmpipe_get_format_alignment( enum pipe_format format ) 834{ 835 const struct util_format_description *desc = util_format_description(format); 836 unsigned size = 0; 837 unsigned bytes; 838 unsigned i; 839 840 for (i = 0; i < desc->nr_channels; ++i) { 841 size += desc->channel[i].size; 842 } 843 844 bytes = size / 8; 845 846 if (!util_is_power_of_two_or_zero(bytes)) { 847 bytes /= desc->nr_channels; 848 } 849 850 if (bytes % 2 || bytes < 1) { 851 return 1; 852 } else { 853 return bytes; 854 } 855} 856 857 858/** 859 * Create buffer which wraps user-space data. 860 * XXX unreachable. 861 */ 862struct pipe_resource * 863llvmpipe_user_buffer_create(struct pipe_screen *screen, 864 void *ptr, 865 unsigned bytes, 866 unsigned bind_flags) 867{ 868 struct llvmpipe_resource *buffer; 869 870 buffer = CALLOC_STRUCT(llvmpipe_resource); 871 if (!buffer) 872 return NULL; 873 874 buffer->screen = llvmpipe_screen(screen); 875 pipe_reference_init(&buffer->base.reference, 1); 876 buffer->base.screen = screen; 877 buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */ 878 buffer->base.bind = bind_flags; 879 buffer->base.usage = PIPE_USAGE_IMMUTABLE; 880 buffer->base.flags = 0; 881 buffer->base.width0 = bytes; 882 buffer->base.height0 = 1; 883 buffer->base.depth0 = 1; 884 buffer->base.array_size = 1; 885 buffer->user_ptr = true; 886 buffer->data = ptr; 887 888 return &buffer->base; 889} 890 891 892/** 893 * Compute size (in bytes) need to store a texture image / mipmap level, 894 * for just one cube face, one array layer or one 3D texture slice 895 */ 896static unsigned 897tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level) 898{ 899 return lpr->img_stride[level]; 900} 901 902 903/** 904 * Return pointer to a 2D texture image/face/slice. 905 * No tiled/linear conversion is done. 906 */ 907ubyte * 908llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr, 909 unsigned face_slice, unsigned level) 910{ 911 unsigned offset; 912 913 assert(llvmpipe_resource_is_texture(&lpr->base)); 914 915 offset = lpr->mip_offsets[level]; 916 917 if (face_slice > 0) 918 offset += face_slice * tex_image_face_size(lpr, level); 919 920 return (ubyte *) lpr->tex_data + offset; 921} 922 923 924/** 925 * Return size of resource in bytes 926 */ 927unsigned 928llvmpipe_resource_size(const struct pipe_resource *resource) 929{ 930 const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource); 931 unsigned size = 0; 932 933 if (llvmpipe_resource_is_texture(resource)) { 934 /* Note this will always return 0 for displaytarget resources */ 935 size = lpr->total_alloc_size; 936 } 937 else { 938 size = resource->width0; 939 } 940 return size; 941} 942 943static void 944llvmpipe_memory_barrier(struct pipe_context *pipe, 945 unsigned flags) 946{ 947 /* this may be an overly large hammer for this nut. */ 948 llvmpipe_finish(pipe, "barrier"); 949} 950 951static struct pipe_memory_allocation *llvmpipe_allocate_memory(struct pipe_screen *screen, uint64_t size) 952{ 953 return os_malloc_aligned(size, 256); 954} 955 956static void llvmpipe_free_memory(struct pipe_screen *screen, 957 struct pipe_memory_allocation *pmem) 958{ 959 os_free_aligned(pmem); 960} 961 962#ifdef PIPE_MEMORY_FD 963 964static const char *driver_id = "llvmpipe" MESA_GIT_SHA1; 965 966static struct pipe_memory_allocation *llvmpipe_allocate_memory_fd(struct pipe_screen *screen, uint64_t size, int *fd) 967{ 968 return os_malloc_aligned_fd(size, 256, fd, "llvmpipe memory fd", driver_id); 969} 970 971static bool llvmpipe_import_memory_fd(struct pipe_screen *screen, int fd, struct pipe_memory_allocation **ptr, uint64_t *size) 972{ 973 return os_import_memory_fd(fd, (void**)ptr, size, driver_id); 974} 975 976static void llvmpipe_free_memory_fd(struct pipe_screen *screen, 977 struct pipe_memory_allocation *pmem) 978{ 979 os_free_fd(pmem); 980} 981 982#endif 983 984static bool llvmpipe_resource_bind_backing(struct pipe_screen *screen, 985 struct pipe_resource *pt, 986 struct pipe_memory_allocation *pmem, 987 uint64_t offset) 988{ 989 struct llvmpipe_resource *lpr = llvmpipe_resource(pt); 990 991 if (!lpr->backable) 992 return FALSE; 993 994 if (llvmpipe_resource_is_texture(&lpr->base)) { 995 if (lpr->size_required > LP_MAX_TEXTURE_SIZE) 996 return FALSE; 997 998 lpr->tex_data = (char *)pmem + offset; 999 } else 1000 lpr->data = (char *)pmem + offset; 1001 lpr->backing_offset = offset; 1002 1003 return TRUE; 1004} 1005 1006static void *llvmpipe_map_memory(struct pipe_screen *screen, 1007 struct pipe_memory_allocation *pmem) 1008{ 1009 return pmem; 1010} 1011 1012static void llvmpipe_unmap_memory(struct pipe_screen *screen, 1013 struct pipe_memory_allocation *pmem) 1014{ 1015} 1016 1017#ifdef DEBUG 1018void 1019llvmpipe_print_resources(void) 1020{ 1021 struct llvmpipe_resource *lpr; 1022 unsigned n = 0, total = 0; 1023 1024 debug_printf("LLVMPIPE: current resources:\n"); 1025 mtx_lock(&resource_list_mutex); 1026 foreach(lpr, &resource_list) { 1027 unsigned size = llvmpipe_resource_size(&lpr->base); 1028 debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n", 1029 lpr->id, (void *) lpr, 1030 lpr->base.width0, lpr->base.height0, lpr->base.depth0, 1031 size, lpr->base.reference.count); 1032 total += size; 1033 n++; 1034 } 1035 mtx_unlock(&resource_list_mutex); 1036 debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total); 1037} 1038#endif 1039 1040static void 1041llvmpipe_get_resource_info(struct pipe_screen *screen, 1042 struct pipe_resource *resource, 1043 unsigned *stride, 1044 unsigned *offset) 1045{ 1046 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 1047 1048 *stride = lpr->row_stride[0]; 1049 *offset = 0; 1050} 1051 1052static bool 1053llvmpipe_resource_get_param(struct pipe_screen *screen, 1054 struct pipe_context *context, 1055 struct pipe_resource *resource, 1056 unsigned plane, 1057 unsigned layer, 1058 unsigned level, 1059 enum pipe_resource_param param, 1060 unsigned handle_usage, 1061 uint64_t *value) 1062{ 1063 struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 1064 struct winsys_handle whandle; 1065 1066 switch (param) { 1067 case PIPE_RESOURCE_PARAM_NPLANES: 1068 *value = 1; 1069 return true; 1070 case PIPE_RESOURCE_PARAM_STRIDE: 1071 *value = lpr->row_stride[level]; 1072 return true; 1073 case PIPE_RESOURCE_PARAM_OFFSET: 1074 *value = lpr->mip_offsets[level] + (lpr->img_stride[level] * layer); 1075 return true; 1076 case PIPE_RESOURCE_PARAM_LAYER_STRIDE: 1077 *value = lpr->img_stride[level]; 1078 return true; 1079#ifndef _WIN32 1080 case PIPE_RESOURCE_PARAM_MODIFIER: 1081 *value = DRM_FORMAT_MOD_INVALID; 1082 return true; 1083#endif 1084 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED: 1085 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS: 1086 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD: 1087 if (!lpr->dt) 1088 return false; 1089 1090 memset(&whandle, 0, sizeof(whandle)); 1091 if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED) 1092 whandle.type = WINSYS_HANDLE_TYPE_SHARED; 1093 else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS) 1094 whandle.type = WINSYS_HANDLE_TYPE_KMS; 1095 else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD) 1096 whandle.type = WINSYS_HANDLE_TYPE_FD; 1097 1098 if (!llvmpipe_resource_get_handle(screen, context, resource, &whandle, handle_usage)) 1099 return false; 1100 *value = whandle.handle; 1101 return true; 1102 default: 1103 break; 1104 } 1105 assert(0); 1106 *value = 0; 1107 return false; 1108} 1109 1110void 1111llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen) 1112{ 1113#ifdef DEBUG 1114 /* init linked list for tracking resources */ 1115 { 1116 static boolean first_call = TRUE; 1117 if (first_call) { 1118 memset(&resource_list, 0, sizeof(resource_list)); 1119 make_empty_list(&resource_list); 1120 first_call = FALSE; 1121 } 1122 } 1123#endif 1124 1125 screen->resource_create = llvmpipe_resource_create; 1126/* screen->resource_create_front = llvmpipe_resource_create_front; */ 1127 screen->resource_destroy = llvmpipe_resource_destroy; 1128 screen->resource_from_handle = llvmpipe_resource_from_handle; 1129 screen->resource_from_memobj = llvmpipe_resource_from_memobj; 1130 screen->resource_get_handle = llvmpipe_resource_get_handle; 1131 screen->can_create_resource = llvmpipe_can_create_resource; 1132 1133 screen->resource_create_unbacked = llvmpipe_resource_create_unbacked; 1134 1135 screen->memobj_create_from_handle = llvmpipe_memobj_create_from_handle; 1136 screen->memobj_destroy = llvmpipe_memobj_destroy; 1137 1138 screen->resource_get_info = llvmpipe_get_resource_info; 1139 screen->resource_get_param = llvmpipe_resource_get_param; 1140 screen->resource_from_user_memory = llvmpipe_resource_from_user_memory; 1141 screen->allocate_memory = llvmpipe_allocate_memory; 1142 screen->free_memory = llvmpipe_free_memory; 1143#ifdef PIPE_MEMORY_FD 1144 screen->allocate_memory_fd = llvmpipe_allocate_memory_fd; 1145 screen->import_memory_fd = llvmpipe_import_memory_fd; 1146 screen->free_memory_fd = llvmpipe_free_memory_fd; 1147#endif 1148 screen->map_memory = llvmpipe_map_memory; 1149 screen->unmap_memory = llvmpipe_unmap_memory; 1150 1151 screen->resource_bind_backing = llvmpipe_resource_bind_backing; 1152} 1153 1154 1155void 1156llvmpipe_init_context_resource_funcs(struct pipe_context *pipe) 1157{ 1158 pipe->buffer_map = llvmpipe_transfer_map; 1159 pipe->buffer_unmap = llvmpipe_transfer_unmap; 1160 pipe->texture_map = llvmpipe_transfer_map; 1161 pipe->texture_unmap = llvmpipe_transfer_unmap; 1162 1163 pipe->transfer_flush_region = u_default_transfer_flush_region; 1164 pipe->buffer_subdata = u_default_buffer_subdata; 1165 pipe->texture_subdata = u_default_texture_subdata; 1166 1167 pipe->memory_barrier = llvmpipe_memory_barrier; 1168} 1169