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