1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2006 VMware, Inc. 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg /* 28848b8605Smrg * Authors: 29848b8605Smrg * Keith Whitwell <keithw@vmware.com> 30848b8605Smrg * Michel Dänzer <daenzer@vmware.com> 31848b8605Smrg */ 32848b8605Smrg 33848b8605Smrg#include <stdio.h> 34848b8605Smrg 35848b8605Smrg#include "pipe/p_context.h" 36848b8605Smrg#include "pipe/p_defines.h" 37848b8605Smrg 38848b8605Smrg#include "util/u_inlines.h" 39848b8605Smrg#include "util/u_cpu_detect.h" 40848b8605Smrg#include "util/u_format.h" 41848b8605Smrg#include "util/u_math.h" 42848b8605Smrg#include "util/u_memory.h" 43b8e80941Smrg#include "util/simple_list.h" 44848b8605Smrg#include "util/u_transfer.h" 45848b8605Smrg 46848b8605Smrg#include "lp_context.h" 47848b8605Smrg#include "lp_flush.h" 48848b8605Smrg#include "lp_screen.h" 49848b8605Smrg#include "lp_texture.h" 50848b8605Smrg#include "lp_setup.h" 51848b8605Smrg#include "lp_state.h" 52848b8605Smrg#include "lp_rast.h" 53848b8605Smrg 54848b8605Smrg#include "state_tracker/sw_winsys.h" 55848b8605Smrg 56848b8605Smrg 57848b8605Smrg#ifdef DEBUG 58848b8605Smrgstatic struct llvmpipe_resource resource_list; 59848b8605Smrg#endif 60848b8605Smrgstatic unsigned id_counter = 0; 61848b8605Smrg 62848b8605Smrg 63848b8605Smrg/** 64848b8605Smrg * Conventional allocation path for non-display textures: 65848b8605Smrg * Compute strides and allocate data (unless asked not to). 66848b8605Smrg */ 67848b8605Smrgstatic boolean 68848b8605Smrgllvmpipe_texture_layout(struct llvmpipe_screen *screen, 69848b8605Smrg struct llvmpipe_resource *lpr, 70848b8605Smrg boolean allocate) 71848b8605Smrg{ 72848b8605Smrg struct pipe_resource *pt = &lpr->base; 73848b8605Smrg unsigned level; 74848b8605Smrg unsigned width = pt->width0; 75848b8605Smrg unsigned height = pt->height0; 76848b8605Smrg unsigned depth = pt->depth0; 77848b8605Smrg uint64_t total_size = 0; 78848b8605Smrg unsigned layers = pt->array_size; 79848b8605Smrg /* XXX: 80848b8605Smrg * This alignment here (same for displaytarget) was added for the purpose of 81848b8605Smrg * ARB_map_buffer_alignment. I am not convinced it's needed for non-buffer 82848b8605Smrg * resources. Otherwise we'd want the max of cacheline size and 16 (max size 83848b8605Smrg * of a block for all formats) though this should not be strictly necessary 84848b8605Smrg * neither. In any case it can only affect compressed or 1d textures. 85848b8605Smrg */ 86848b8605Smrg unsigned mip_align = MAX2(64, util_cpu_caps.cacheline); 87848b8605Smrg 88848b8605Smrg assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS); 89848b8605Smrg assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS); 90848b8605Smrg 91848b8605Smrg for (level = 0; level <= pt->last_level; level++) { 92848b8605Smrg uint64_t mipsize; 93848b8605Smrg unsigned align_x, align_y, nblocksx, nblocksy, block_size, num_slices; 94848b8605Smrg 95848b8605Smrg /* Row stride and image stride */ 96848b8605Smrg 97848b8605Smrg /* For non-compressed formats we need 4x4 pixel alignment 98848b8605Smrg * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them. 99848b8605Smrg * We also want cache line size in x direction, 100848b8605Smrg * otherwise same cache line could end up in multiple threads. 101848b8605Smrg * For explicit 1d resources however we reduce this to 4x1 and 102848b8605Smrg * handle specially in render output code (as we need to do special 103848b8605Smrg * handling there for buffers in any case). 104848b8605Smrg */ 105848b8605Smrg if (util_format_is_compressed(pt->format)) 106848b8605Smrg align_x = align_y = 1; 107848b8605Smrg else { 108848b8605Smrg align_x = LP_RASTER_BLOCK_SIZE; 109848b8605Smrg if (llvmpipe_resource_is_1d(&lpr->base)) 110848b8605Smrg align_y = 1; 111848b8605Smrg else 112848b8605Smrg align_y = LP_RASTER_BLOCK_SIZE; 113848b8605Smrg } 114848b8605Smrg 115848b8605Smrg nblocksx = util_format_get_nblocksx(pt->format, 116848b8605Smrg align(width, align_x)); 117848b8605Smrg nblocksy = util_format_get_nblocksy(pt->format, 118848b8605Smrg align(height, align_y)); 119848b8605Smrg block_size = util_format_get_blocksize(pt->format); 120848b8605Smrg 121848b8605Smrg if (util_format_is_compressed(pt->format)) 122848b8605Smrg lpr->row_stride[level] = nblocksx * block_size; 123848b8605Smrg else 124848b8605Smrg lpr->row_stride[level] = align(nblocksx * block_size, util_cpu_caps.cacheline); 125848b8605Smrg 126848b8605Smrg /* if row_stride * height > LP_MAX_TEXTURE_SIZE */ 127848b8605Smrg if ((uint64_t)lpr->row_stride[level] * nblocksy > LP_MAX_TEXTURE_SIZE) { 128848b8605Smrg /* image too large */ 129848b8605Smrg goto fail; 130848b8605Smrg } 131848b8605Smrg 132848b8605Smrg lpr->img_stride[level] = lpr->row_stride[level] * nblocksy; 133848b8605Smrg 134848b8605Smrg /* Number of 3D image slices, cube faces or texture array layers */ 135b8e80941Smrg if (lpr->base.target == PIPE_TEXTURE_CUBE) { 136b8e80941Smrg assert(layers == 6); 137b8e80941Smrg } 138b8e80941Smrg 139b8e80941Smrg if (lpr->base.target == PIPE_TEXTURE_3D) 140848b8605Smrg num_slices = depth; 141848b8605Smrg else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY || 142848b8605Smrg lpr->base.target == PIPE_TEXTURE_2D_ARRAY || 143b8e80941Smrg lpr->base.target == PIPE_TEXTURE_CUBE || 144848b8605Smrg lpr->base.target == PIPE_TEXTURE_CUBE_ARRAY) 145848b8605Smrg num_slices = layers; 146848b8605Smrg else 147848b8605Smrg num_slices = 1; 148848b8605Smrg 149848b8605Smrg /* if img_stride * num_slices_faces > LP_MAX_TEXTURE_SIZE */ 150848b8605Smrg mipsize = (uint64_t)lpr->img_stride[level] * num_slices; 151848b8605Smrg if (mipsize > LP_MAX_TEXTURE_SIZE) { 152848b8605Smrg /* volume too large */ 153848b8605Smrg goto fail; 154848b8605Smrg } 155848b8605Smrg 156848b8605Smrg lpr->mip_offsets[level] = total_size; 157848b8605Smrg 158848b8605Smrg total_size += align((unsigned)mipsize, mip_align); 159848b8605Smrg if (total_size > LP_MAX_TEXTURE_SIZE) { 160848b8605Smrg goto fail; 161848b8605Smrg } 162848b8605Smrg 163848b8605Smrg /* Compute size of next mipmap level */ 164848b8605Smrg width = u_minify(width, 1); 165848b8605Smrg height = u_minify(height, 1); 166848b8605Smrg depth = u_minify(depth, 1); 167848b8605Smrg } 168848b8605Smrg 169848b8605Smrg if (allocate) { 170848b8605Smrg lpr->tex_data = align_malloc(total_size, mip_align); 171848b8605Smrg if (!lpr->tex_data) { 172848b8605Smrg return FALSE; 173848b8605Smrg } 174848b8605Smrg else { 175848b8605Smrg memset(lpr->tex_data, 0, total_size); 176848b8605Smrg } 177848b8605Smrg } 178848b8605Smrg 179848b8605Smrg return TRUE; 180848b8605Smrg 181848b8605Smrgfail: 182848b8605Smrg return FALSE; 183848b8605Smrg} 184848b8605Smrg 185848b8605Smrg 186848b8605Smrg/** 187848b8605Smrg * Check the size of the texture specified by 'res'. 188848b8605Smrg * \return TRUE if OK, FALSE if too large. 189848b8605Smrg */ 190848b8605Smrgstatic boolean 191848b8605Smrgllvmpipe_can_create_resource(struct pipe_screen *screen, 192848b8605Smrg const struct pipe_resource *res) 193848b8605Smrg{ 194848b8605Smrg struct llvmpipe_resource lpr; 195848b8605Smrg memset(&lpr, 0, sizeof(lpr)); 196848b8605Smrg lpr.base = *res; 197848b8605Smrg return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false); 198848b8605Smrg} 199848b8605Smrg 200848b8605Smrg 201848b8605Smrgstatic boolean 202848b8605Smrgllvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, 203b8e80941Smrg struct llvmpipe_resource *lpr, 204b8e80941Smrg const void *map_front_private) 205848b8605Smrg{ 206848b8605Smrg struct sw_winsys *winsys = screen->winsys; 207848b8605Smrg 208848b8605Smrg /* Round up the surface size to a multiple of the tile size to 209848b8605Smrg * avoid tile clipping. 210848b8605Smrg */ 211848b8605Smrg const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE)); 212848b8605Smrg const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE)); 213848b8605Smrg 214848b8605Smrg lpr->dt = winsys->displaytarget_create(winsys, 215848b8605Smrg lpr->base.bind, 216848b8605Smrg lpr->base.format, 217848b8605Smrg width, height, 218848b8605Smrg 64, 219b8e80941Smrg map_front_private, 220848b8605Smrg &lpr->row_stride[0] ); 221848b8605Smrg 222848b8605Smrg if (lpr->dt == NULL) 223848b8605Smrg return FALSE; 224848b8605Smrg 225b8e80941Smrg if (!map_front_private) { 226848b8605Smrg void *map = winsys->displaytarget_map(winsys, lpr->dt, 227848b8605Smrg PIPE_TRANSFER_WRITE); 228848b8605Smrg 229848b8605Smrg if (map) 230848b8605Smrg memset(map, 0, height * lpr->row_stride[0]); 231848b8605Smrg 232848b8605Smrg winsys->displaytarget_unmap(winsys, lpr->dt); 233848b8605Smrg } 234848b8605Smrg 235848b8605Smrg return TRUE; 236848b8605Smrg} 237848b8605Smrg 238848b8605Smrg 239848b8605Smrgstatic struct pipe_resource * 240b8e80941Smrgllvmpipe_resource_create_front(struct pipe_screen *_screen, 241b8e80941Smrg const struct pipe_resource *templat, 242b8e80941Smrg const void *map_front_private) 243848b8605Smrg{ 244848b8605Smrg struct llvmpipe_screen *screen = llvmpipe_screen(_screen); 245848b8605Smrg struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource); 246848b8605Smrg if (!lpr) 247848b8605Smrg return NULL; 248848b8605Smrg 249848b8605Smrg lpr->base = *templat; 250848b8605Smrg pipe_reference_init(&lpr->base.reference, 1); 251848b8605Smrg lpr->base.screen = &screen->base; 252848b8605Smrg 253848b8605Smrg /* assert(lpr->base.bind); */ 254848b8605Smrg 255848b8605Smrg if (llvmpipe_resource_is_texture(&lpr->base)) { 256848b8605Smrg if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET | 257848b8605Smrg PIPE_BIND_SCANOUT | 258848b8605Smrg PIPE_BIND_SHARED)) { 259848b8605Smrg /* displayable surface */ 260b8e80941Smrg if (!llvmpipe_displaytarget_layout(screen, lpr, map_front_private)) 261848b8605Smrg goto fail; 262848b8605Smrg } 263848b8605Smrg else { 264848b8605Smrg /* texture map */ 265848b8605Smrg if (!llvmpipe_texture_layout(screen, lpr, true)) 266848b8605Smrg goto fail; 267848b8605Smrg } 268848b8605Smrg } 269848b8605Smrg else { 270848b8605Smrg /* other data (vertex buffer, const buffer, etc) */ 271848b8605Smrg const uint bytes = templat->width0; 272848b8605Smrg assert(util_format_get_blocksize(templat->format) == 1); 273848b8605Smrg assert(templat->height0 == 1); 274848b8605Smrg assert(templat->depth0 == 1); 275848b8605Smrg assert(templat->last_level == 0); 276848b8605Smrg /* 277848b8605Smrg * Reserve some extra storage since if we'd render to a buffer we 278848b8605Smrg * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element 279848b8605Smrg * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE. 280848b8605Smrg */ 281848b8605Smrg lpr->data = align_malloc(bytes + (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float), 64); 282848b8605Smrg 283848b8605Smrg /* 284848b8605Smrg * buffers don't really have stride but it's probably safer 285848b8605Smrg * (for code doing same calculations for buffers and textures) 286848b8605Smrg * to put something sane in there. 287848b8605Smrg */ 288848b8605Smrg lpr->row_stride[0] = bytes; 289848b8605Smrg if (!lpr->data) 290848b8605Smrg goto fail; 291848b8605Smrg memset(lpr->data, 0, bytes); 292848b8605Smrg } 293848b8605Smrg 294848b8605Smrg lpr->id = id_counter++; 295848b8605Smrg 296848b8605Smrg#ifdef DEBUG 297848b8605Smrg insert_at_tail(&resource_list, lpr); 298848b8605Smrg#endif 299848b8605Smrg 300848b8605Smrg return &lpr->base; 301848b8605Smrg 302848b8605Smrg fail: 303848b8605Smrg FREE(lpr); 304848b8605Smrg return NULL; 305848b8605Smrg} 306848b8605Smrg 307848b8605Smrg 308b8e80941Smrgstatic struct pipe_resource * 309b8e80941Smrgllvmpipe_resource_create(struct pipe_screen *_screen, 310b8e80941Smrg const struct pipe_resource *templat) 311b8e80941Smrg{ 312b8e80941Smrg return llvmpipe_resource_create_front(_screen, templat, NULL); 313b8e80941Smrg} 314b8e80941Smrg 315b8e80941Smrg 316848b8605Smrgstatic void 317848b8605Smrgllvmpipe_resource_destroy(struct pipe_screen *pscreen, 318848b8605Smrg struct pipe_resource *pt) 319848b8605Smrg{ 320848b8605Smrg struct llvmpipe_screen *screen = llvmpipe_screen(pscreen); 321848b8605Smrg struct llvmpipe_resource *lpr = llvmpipe_resource(pt); 322848b8605Smrg 323848b8605Smrg if (lpr->dt) { 324848b8605Smrg /* display target */ 325848b8605Smrg struct sw_winsys *winsys = screen->winsys; 326848b8605Smrg winsys->displaytarget_destroy(winsys, lpr->dt); 327848b8605Smrg } 328848b8605Smrg else if (llvmpipe_resource_is_texture(pt)) { 329848b8605Smrg /* free linear image data */ 330848b8605Smrg if (lpr->tex_data) { 331848b8605Smrg align_free(lpr->tex_data); 332848b8605Smrg lpr->tex_data = NULL; 333848b8605Smrg } 334848b8605Smrg } 335848b8605Smrg else if (!lpr->userBuffer) { 336848b8605Smrg assert(lpr->data); 337848b8605Smrg align_free(lpr->data); 338848b8605Smrg } 339848b8605Smrg 340848b8605Smrg#ifdef DEBUG 341848b8605Smrg if (lpr->next) 342848b8605Smrg remove_from_list(lpr); 343848b8605Smrg#endif 344848b8605Smrg 345848b8605Smrg FREE(lpr); 346848b8605Smrg} 347848b8605Smrg 348848b8605Smrg 349848b8605Smrg/** 350848b8605Smrg * Map a resource for read/write. 351848b8605Smrg */ 352848b8605Smrgvoid * 353848b8605Smrgllvmpipe_resource_map(struct pipe_resource *resource, 354848b8605Smrg unsigned level, 355848b8605Smrg unsigned layer, 356848b8605Smrg enum lp_texture_usage tex_usage) 357848b8605Smrg{ 358848b8605Smrg struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 359848b8605Smrg uint8_t *map; 360848b8605Smrg 361848b8605Smrg assert(level < LP_MAX_TEXTURE_LEVELS); 362848b8605Smrg assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1)); 363848b8605Smrg 364848b8605Smrg assert(tex_usage == LP_TEX_USAGE_READ || 365848b8605Smrg tex_usage == LP_TEX_USAGE_READ_WRITE || 366848b8605Smrg tex_usage == LP_TEX_USAGE_WRITE_ALL); 367848b8605Smrg 368848b8605Smrg if (lpr->dt) { 369848b8605Smrg /* display target */ 370848b8605Smrg struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen); 371848b8605Smrg struct sw_winsys *winsys = screen->winsys; 372848b8605Smrg unsigned dt_usage; 373848b8605Smrg 374848b8605Smrg if (tex_usage == LP_TEX_USAGE_READ) { 375848b8605Smrg dt_usage = PIPE_TRANSFER_READ; 376848b8605Smrg } 377848b8605Smrg else { 378848b8605Smrg dt_usage = PIPE_TRANSFER_READ_WRITE; 379848b8605Smrg } 380848b8605Smrg 381848b8605Smrg assert(level == 0); 382848b8605Smrg assert(layer == 0); 383848b8605Smrg 384848b8605Smrg /* FIXME: keep map count? */ 385848b8605Smrg map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage); 386848b8605Smrg 387848b8605Smrg /* install this linear image in texture data structure */ 388848b8605Smrg lpr->tex_data = map; 389848b8605Smrg 390848b8605Smrg return map; 391848b8605Smrg } 392848b8605Smrg else if (llvmpipe_resource_is_texture(resource)) { 393848b8605Smrg 394848b8605Smrg map = llvmpipe_get_texture_image_address(lpr, layer, level); 395848b8605Smrg return map; 396848b8605Smrg } 397848b8605Smrg else { 398848b8605Smrg return lpr->data; 399848b8605Smrg } 400848b8605Smrg} 401848b8605Smrg 402848b8605Smrg 403848b8605Smrg/** 404848b8605Smrg * Unmap a resource. 405848b8605Smrg */ 406848b8605Smrgvoid 407848b8605Smrgllvmpipe_resource_unmap(struct pipe_resource *resource, 408848b8605Smrg unsigned level, 409848b8605Smrg unsigned layer) 410848b8605Smrg{ 411848b8605Smrg struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 412848b8605Smrg 413848b8605Smrg if (lpr->dt) { 414848b8605Smrg /* display target */ 415848b8605Smrg struct llvmpipe_screen *lp_screen = llvmpipe_screen(resource->screen); 416848b8605Smrg struct sw_winsys *winsys = lp_screen->winsys; 417848b8605Smrg 418848b8605Smrg assert(level == 0); 419848b8605Smrg assert(layer == 0); 420848b8605Smrg 421848b8605Smrg winsys->displaytarget_unmap(winsys, lpr->dt); 422848b8605Smrg } 423848b8605Smrg} 424848b8605Smrg 425848b8605Smrg 426848b8605Smrgvoid * 427848b8605Smrgllvmpipe_resource_data(struct pipe_resource *resource) 428848b8605Smrg{ 429848b8605Smrg struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 430848b8605Smrg 431848b8605Smrg assert(!llvmpipe_resource_is_texture(resource)); 432848b8605Smrg 433848b8605Smrg return lpr->data; 434848b8605Smrg} 435848b8605Smrg 436848b8605Smrg 437848b8605Smrgstatic struct pipe_resource * 438848b8605Smrgllvmpipe_resource_from_handle(struct pipe_screen *screen, 439848b8605Smrg const struct pipe_resource *template, 440b8e80941Smrg struct winsys_handle *whandle, 441b8e80941Smrg unsigned usage) 442848b8605Smrg{ 443848b8605Smrg struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; 444848b8605Smrg struct llvmpipe_resource *lpr; 445848b8605Smrg 446848b8605Smrg /* XXX Seems like from_handled depth textures doesn't work that well */ 447848b8605Smrg 448848b8605Smrg lpr = CALLOC_STRUCT(llvmpipe_resource); 449848b8605Smrg if (!lpr) { 450848b8605Smrg goto no_lpr; 451848b8605Smrg } 452848b8605Smrg 453848b8605Smrg lpr->base = *template; 454848b8605Smrg pipe_reference_init(&lpr->base.reference, 1); 455848b8605Smrg lpr->base.screen = screen; 456848b8605Smrg 457848b8605Smrg /* 458848b8605Smrg * Looks like unaligned displaytargets work just fine, 459848b8605Smrg * at least sampler/render ones. 460848b8605Smrg */ 461848b8605Smrg#if 0 462848b8605Smrg assert(lpr->base.width0 == width); 463848b8605Smrg assert(lpr->base.height0 == height); 464848b8605Smrg#endif 465848b8605Smrg 466848b8605Smrg lpr->dt = winsys->displaytarget_from_handle(winsys, 467848b8605Smrg template, 468848b8605Smrg whandle, 469848b8605Smrg &lpr->row_stride[0]); 470848b8605Smrg if (!lpr->dt) { 471848b8605Smrg goto no_dt; 472848b8605Smrg } 473848b8605Smrg 474848b8605Smrg lpr->id = id_counter++; 475848b8605Smrg 476848b8605Smrg#ifdef DEBUG 477848b8605Smrg insert_at_tail(&resource_list, lpr); 478848b8605Smrg#endif 479848b8605Smrg 480848b8605Smrg return &lpr->base; 481848b8605Smrg 482848b8605Smrgno_dt: 483848b8605Smrg FREE(lpr); 484848b8605Smrgno_lpr: 485848b8605Smrg return NULL; 486848b8605Smrg} 487848b8605Smrg 488848b8605Smrg 489848b8605Smrgstatic boolean 490848b8605Smrgllvmpipe_resource_get_handle(struct pipe_screen *screen, 491b8e80941Smrg struct pipe_context *ctx, 492848b8605Smrg struct pipe_resource *pt, 493b8e80941Smrg struct winsys_handle *whandle, 494b8e80941Smrg unsigned usage) 495848b8605Smrg{ 496848b8605Smrg struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; 497848b8605Smrg struct llvmpipe_resource *lpr = llvmpipe_resource(pt); 498848b8605Smrg 499848b8605Smrg assert(lpr->dt); 500848b8605Smrg if (!lpr->dt) 501848b8605Smrg return FALSE; 502848b8605Smrg 503848b8605Smrg return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle); 504848b8605Smrg} 505848b8605Smrg 506848b8605Smrg 507848b8605Smrgstatic void * 508848b8605Smrgllvmpipe_transfer_map( struct pipe_context *pipe, 509848b8605Smrg struct pipe_resource *resource, 510848b8605Smrg unsigned level, 511848b8605Smrg unsigned usage, 512848b8605Smrg const struct pipe_box *box, 513848b8605Smrg struct pipe_transfer **transfer ) 514848b8605Smrg{ 515848b8605Smrg struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 516848b8605Smrg struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 517848b8605Smrg struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 518848b8605Smrg struct llvmpipe_transfer *lpt; 519848b8605Smrg struct pipe_transfer *pt; 520848b8605Smrg ubyte *map; 521848b8605Smrg enum pipe_format format; 522848b8605Smrg enum lp_texture_usage tex_usage; 523848b8605Smrg const char *mode; 524848b8605Smrg 525848b8605Smrg assert(resource); 526848b8605Smrg assert(level <= resource->last_level); 527848b8605Smrg 528848b8605Smrg /* 529848b8605Smrg * Transfers, like other pipe operations, must happen in order, so flush the 530848b8605Smrg * context if necessary. 531848b8605Smrg */ 532848b8605Smrg if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { 533848b8605Smrg boolean read_only = !(usage & PIPE_TRANSFER_WRITE); 534848b8605Smrg boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK); 535848b8605Smrg if (!llvmpipe_flush_resource(pipe, resource, 536848b8605Smrg level, 537848b8605Smrg read_only, 538848b8605Smrg TRUE, /* cpu_access */ 539848b8605Smrg do_not_block, 540848b8605Smrg __FUNCTION__)) { 541848b8605Smrg /* 542848b8605Smrg * It would have blocked, but state tracker requested no to. 543848b8605Smrg */ 544848b8605Smrg assert(do_not_block); 545848b8605Smrg return NULL; 546848b8605Smrg } 547848b8605Smrg } 548848b8605Smrg 549b8e80941Smrg /* Check if we're mapping a current constant buffer */ 550848b8605Smrg if ((usage & PIPE_TRANSFER_WRITE) && 551848b8605Smrg (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) { 552848b8605Smrg unsigned i; 553b8e80941Smrg for (i = 0; i < ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) { 554848b8605Smrg if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) { 555848b8605Smrg /* constants may have changed */ 556b8e80941Smrg llvmpipe->dirty |= LP_NEW_FS_CONSTANTS; 557848b8605Smrg break; 558848b8605Smrg } 559848b8605Smrg } 560848b8605Smrg } 561848b8605Smrg 562848b8605Smrg lpt = CALLOC_STRUCT(llvmpipe_transfer); 563848b8605Smrg if (!lpt) 564848b8605Smrg return NULL; 565848b8605Smrg pt = &lpt->base; 566848b8605Smrg pipe_resource_reference(&pt->resource, resource); 567848b8605Smrg pt->box = *box; 568848b8605Smrg pt->level = level; 569848b8605Smrg pt->stride = lpr->row_stride[level]; 570848b8605Smrg pt->layer_stride = lpr->img_stride[level]; 571848b8605Smrg pt->usage = usage; 572848b8605Smrg *transfer = pt; 573848b8605Smrg 574848b8605Smrg assert(level < LP_MAX_TEXTURE_LEVELS); 575848b8605Smrg 576848b8605Smrg /* 577848b8605Smrg printf("tex_transfer_map(%d, %d %d x %d of %d x %d, usage %d )\n", 578848b8605Smrg transfer->x, transfer->y, transfer->width, transfer->height, 579848b8605Smrg transfer->texture->width0, 580848b8605Smrg transfer->texture->height0, 581848b8605Smrg transfer->usage); 582848b8605Smrg */ 583848b8605Smrg 584848b8605Smrg if (usage == PIPE_TRANSFER_READ) { 585848b8605Smrg tex_usage = LP_TEX_USAGE_READ; 586848b8605Smrg mode = "read"; 587848b8605Smrg } 588848b8605Smrg else { 589848b8605Smrg tex_usage = LP_TEX_USAGE_READ_WRITE; 590848b8605Smrg mode = "read/write"; 591848b8605Smrg } 592848b8605Smrg 593848b8605Smrg if (0) { 594848b8605Smrg printf("transfer map tex %u mode %s\n", lpr->id, mode); 595848b8605Smrg } 596848b8605Smrg 597848b8605Smrg format = lpr->base.format; 598848b8605Smrg 599848b8605Smrg map = llvmpipe_resource_map(resource, 600848b8605Smrg level, 601848b8605Smrg box->z, 602848b8605Smrg tex_usage); 603848b8605Smrg 604848b8605Smrg 605848b8605Smrg /* May want to do different things here depending on read/write nature 606848b8605Smrg * of the map: 607848b8605Smrg */ 608848b8605Smrg if (usage & PIPE_TRANSFER_WRITE) { 609848b8605Smrg /* Do something to notify sharing contexts of a texture change. 610848b8605Smrg */ 611848b8605Smrg screen->timestamp++; 612848b8605Smrg } 613848b8605Smrg 614848b8605Smrg map += 615848b8605Smrg box->y / util_format_get_blockheight(format) * pt->stride + 616848b8605Smrg box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); 617848b8605Smrg 618848b8605Smrg return map; 619848b8605Smrg} 620848b8605Smrg 621848b8605Smrg 622848b8605Smrgstatic void 623848b8605Smrgllvmpipe_transfer_unmap(struct pipe_context *pipe, 624848b8605Smrg struct pipe_transfer *transfer) 625848b8605Smrg{ 626848b8605Smrg assert(transfer->resource); 627848b8605Smrg 628848b8605Smrg llvmpipe_resource_unmap(transfer->resource, 629848b8605Smrg transfer->level, 630848b8605Smrg transfer->box.z); 631848b8605Smrg 632848b8605Smrg /* Effectively do the texture_update work here - if texture images 633848b8605Smrg * needed post-processing to put them into hardware layout, this is 634848b8605Smrg * where it would happen. For llvmpipe, nothing to do. 635848b8605Smrg */ 636848b8605Smrg assert (transfer->resource); 637848b8605Smrg pipe_resource_reference(&transfer->resource, NULL); 638848b8605Smrg FREE(transfer); 639848b8605Smrg} 640848b8605Smrg 641848b8605Smrgunsigned int 642848b8605Smrgllvmpipe_is_resource_referenced( struct pipe_context *pipe, 643848b8605Smrg struct pipe_resource *presource, 644848b8605Smrg unsigned level) 645848b8605Smrg{ 646848b8605Smrg struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); 647848b8605Smrg if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL | 648848b8605Smrg PIPE_BIND_RENDER_TARGET | 649848b8605Smrg PIPE_BIND_SAMPLER_VIEW))) 650848b8605Smrg return LP_UNREFERENCED; 651848b8605Smrg 652848b8605Smrg return lp_setup_is_resource_referenced(llvmpipe->setup, presource); 653848b8605Smrg} 654848b8605Smrg 655848b8605Smrg 656848b8605Smrg/** 657848b8605Smrg * Returns the largest possible alignment for a format in llvmpipe 658848b8605Smrg */ 659848b8605Smrgunsigned 660848b8605Smrgllvmpipe_get_format_alignment( enum pipe_format format ) 661848b8605Smrg{ 662848b8605Smrg const struct util_format_description *desc = util_format_description(format); 663848b8605Smrg unsigned size = 0; 664848b8605Smrg unsigned bytes; 665848b8605Smrg unsigned i; 666848b8605Smrg 667848b8605Smrg for (i = 0; i < desc->nr_channels; ++i) { 668848b8605Smrg size += desc->channel[i].size; 669848b8605Smrg } 670848b8605Smrg 671848b8605Smrg bytes = size / 8; 672848b8605Smrg 673b8e80941Smrg if (!util_is_power_of_two_or_zero(bytes)) { 674848b8605Smrg bytes /= desc->nr_channels; 675848b8605Smrg } 676848b8605Smrg 677848b8605Smrg if (bytes % 2 || bytes < 1) { 678848b8605Smrg return 1; 679848b8605Smrg } else { 680848b8605Smrg return bytes; 681848b8605Smrg } 682848b8605Smrg} 683848b8605Smrg 684848b8605Smrg 685848b8605Smrg/** 686848b8605Smrg * Create buffer which wraps user-space data. 687b8e80941Smrg * XXX unreachable. 688848b8605Smrg */ 689848b8605Smrgstruct pipe_resource * 690848b8605Smrgllvmpipe_user_buffer_create(struct pipe_screen *screen, 691848b8605Smrg void *ptr, 692848b8605Smrg unsigned bytes, 693848b8605Smrg unsigned bind_flags) 694848b8605Smrg{ 695848b8605Smrg struct llvmpipe_resource *buffer; 696848b8605Smrg 697848b8605Smrg buffer = CALLOC_STRUCT(llvmpipe_resource); 698b8e80941Smrg if (!buffer) 699848b8605Smrg return NULL; 700848b8605Smrg 701848b8605Smrg pipe_reference_init(&buffer->base.reference, 1); 702848b8605Smrg buffer->base.screen = screen; 703848b8605Smrg buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */ 704848b8605Smrg buffer->base.bind = bind_flags; 705848b8605Smrg buffer->base.usage = PIPE_USAGE_IMMUTABLE; 706848b8605Smrg buffer->base.flags = 0; 707848b8605Smrg buffer->base.width0 = bytes; 708848b8605Smrg buffer->base.height0 = 1; 709848b8605Smrg buffer->base.depth0 = 1; 710848b8605Smrg buffer->base.array_size = 1; 711848b8605Smrg buffer->userBuffer = TRUE; 712848b8605Smrg buffer->data = ptr; 713848b8605Smrg 714848b8605Smrg return &buffer->base; 715848b8605Smrg} 716848b8605Smrg 717848b8605Smrg 718848b8605Smrg/** 719848b8605Smrg * Compute size (in bytes) need to store a texture image / mipmap level, 720848b8605Smrg * for just one cube face, one array layer or one 3D texture slice 721848b8605Smrg */ 722848b8605Smrgstatic unsigned 723848b8605Smrgtex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level) 724848b8605Smrg{ 725848b8605Smrg return lpr->img_stride[level]; 726848b8605Smrg} 727848b8605Smrg 728848b8605Smrg 729848b8605Smrg/** 730848b8605Smrg * Return pointer to a 2D texture image/face/slice. 731848b8605Smrg * No tiled/linear conversion is done. 732848b8605Smrg */ 733848b8605Smrgubyte * 734848b8605Smrgllvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr, 735848b8605Smrg unsigned face_slice, unsigned level) 736848b8605Smrg{ 737848b8605Smrg unsigned offset; 738848b8605Smrg 739848b8605Smrg assert(llvmpipe_resource_is_texture(&lpr->base)); 740848b8605Smrg 741848b8605Smrg offset = lpr->mip_offsets[level]; 742848b8605Smrg 743848b8605Smrg if (face_slice > 0) 744848b8605Smrg offset += face_slice * tex_image_face_size(lpr, level); 745848b8605Smrg 746848b8605Smrg return (ubyte *) lpr->tex_data + offset; 747848b8605Smrg} 748848b8605Smrg 749848b8605Smrg 750848b8605Smrg/** 751848b8605Smrg * Return size of resource in bytes 752848b8605Smrg */ 753848b8605Smrgunsigned 754848b8605Smrgllvmpipe_resource_size(const struct pipe_resource *resource) 755848b8605Smrg{ 756848b8605Smrg const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource); 757848b8605Smrg unsigned size = 0; 758848b8605Smrg 759848b8605Smrg if (llvmpipe_resource_is_texture(resource)) { 760848b8605Smrg /* Note this will always return 0 for displaytarget resources */ 761848b8605Smrg size = lpr->total_alloc_size; 762848b8605Smrg } 763848b8605Smrg else { 764848b8605Smrg size = resource->width0; 765848b8605Smrg } 766848b8605Smrg return size; 767848b8605Smrg} 768848b8605Smrg 769848b8605Smrg 770848b8605Smrg#ifdef DEBUG 771848b8605Smrgvoid 772848b8605Smrgllvmpipe_print_resources(void) 773848b8605Smrg{ 774848b8605Smrg struct llvmpipe_resource *lpr; 775848b8605Smrg unsigned n = 0, total = 0; 776848b8605Smrg 777848b8605Smrg debug_printf("LLVMPIPE: current resources:\n"); 778848b8605Smrg foreach(lpr, &resource_list) { 779848b8605Smrg unsigned size = llvmpipe_resource_size(&lpr->base); 780848b8605Smrg debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n", 781848b8605Smrg lpr->id, (void *) lpr, 782848b8605Smrg lpr->base.width0, lpr->base.height0, lpr->base.depth0, 783848b8605Smrg size, lpr->base.reference.count); 784848b8605Smrg total += size; 785848b8605Smrg n++; 786848b8605Smrg } 787848b8605Smrg debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total); 788848b8605Smrg} 789848b8605Smrg#endif 790848b8605Smrg 791848b8605Smrg 792848b8605Smrgvoid 793848b8605Smrgllvmpipe_init_screen_resource_funcs(struct pipe_screen *screen) 794848b8605Smrg{ 795848b8605Smrg#ifdef DEBUG 796848b8605Smrg /* init linked list for tracking resources */ 797848b8605Smrg { 798848b8605Smrg static boolean first_call = TRUE; 799848b8605Smrg if (first_call) { 800848b8605Smrg memset(&resource_list, 0, sizeof(resource_list)); 801848b8605Smrg make_empty_list(&resource_list); 802848b8605Smrg first_call = FALSE; 803848b8605Smrg } 804848b8605Smrg } 805848b8605Smrg#endif 806848b8605Smrg 807848b8605Smrg screen->resource_create = llvmpipe_resource_create; 808b8e80941Smrg/* screen->resource_create_front = llvmpipe_resource_create_front; */ 809848b8605Smrg screen->resource_destroy = llvmpipe_resource_destroy; 810848b8605Smrg screen->resource_from_handle = llvmpipe_resource_from_handle; 811848b8605Smrg screen->resource_get_handle = llvmpipe_resource_get_handle; 812848b8605Smrg screen->can_create_resource = llvmpipe_can_create_resource; 813848b8605Smrg} 814848b8605Smrg 815848b8605Smrg 816848b8605Smrgvoid 817848b8605Smrgllvmpipe_init_context_resource_funcs(struct pipe_context *pipe) 818848b8605Smrg{ 819848b8605Smrg pipe->transfer_map = llvmpipe_transfer_map; 820848b8605Smrg pipe->transfer_unmap = llvmpipe_transfer_unmap; 821848b8605Smrg 822848b8605Smrg pipe->transfer_flush_region = u_default_transfer_flush_region; 823b8e80941Smrg pipe->buffer_subdata = u_default_buffer_subdata; 824b8e80941Smrg pipe->texture_subdata = u_default_texture_subdata; 825848b8605Smrg} 826