14a49301eSmrg/************************************************************************** 24a49301eSmrg * 3af69d88dSmrg * Copyright 2006 VMware, Inc. 44a49301eSmrg * All Rights Reserved. 54a49301eSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the 84a49301eSmrg * "Software"), to deal in the Software without restriction, including 94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish, 104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to 114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to 124a49301eSmrg * the following conditions: 134a49301eSmrg * 144a49301eSmrg * The above copyright notice and this permission notice (including the 154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions 164a49301eSmrg * of the Software. 174a49301eSmrg * 184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 254a49301eSmrg * 264a49301eSmrg **************************************************************************/ 274a49301eSmrg /* 284a49301eSmrg * Authors: 29af69d88dSmrg * Keith Whitwell <keithw@vmware.com> 30af69d88dSmrg * Michel Dänzer <daenzer@vmware.com> 314a49301eSmrg */ 324a49301eSmrg 334a49301eSmrg#include "pipe/p_defines.h" 34cdc920a0Smrg#include "util/u_inlines.h" 35cdc920a0Smrg 367ec681f3Smrg#include "util/format/u_format.h" 374a49301eSmrg#include "util/u_math.h" 384a49301eSmrg#include "util/u_memory.h" 393464ebd5Sriastradh#include "util/u_transfer.h" 4001e04c3fSmrg#include "util/u_surface.h" 414a49301eSmrg 424a49301eSmrg#include "sp_context.h" 433464ebd5Sriastradh#include "sp_flush.h" 444a49301eSmrg#include "sp_texture.h" 454a49301eSmrg#include "sp_screen.h" 463464ebd5Sriastradh 477ec681f3Smrg#include "frontend/sw_winsys.h" 484a49301eSmrg 494a49301eSmrg 504a49301eSmrg/** 514a49301eSmrg * Conventional allocation path for non-display textures: 524a49301eSmrg * Use a simple, maximally packed layout. 534a49301eSmrg */ 544a49301eSmrgstatic boolean 553464ebd5Sriastradhsoftpipe_resource_layout(struct pipe_screen *screen, 56af69d88dSmrg struct softpipe_resource *spr, 57af69d88dSmrg boolean allocate) 584a49301eSmrg{ 593464ebd5Sriastradh struct pipe_resource *pt = &spr->base; 604a49301eSmrg unsigned level; 61cdc920a0Smrg unsigned width = pt->width0; 62cdc920a0Smrg unsigned height = pt->height0; 63cdc920a0Smrg unsigned depth = pt->depth0; 64af69d88dSmrg uint64_t buffer_size = 0; 654a49301eSmrg 664a49301eSmrg for (level = 0; level <= pt->last_level; level++) { 6701e04c3fSmrg unsigned slices, nblocksy; 6801e04c3fSmrg 6901e04c3fSmrg nblocksy = util_format_get_nblocksy(pt->format, height); 703464ebd5Sriastradh 713464ebd5Sriastradh if (pt->target == PIPE_TEXTURE_CUBE) 7201e04c3fSmrg assert(pt->array_size == 6); 7301e04c3fSmrg 7401e04c3fSmrg if (pt->target == PIPE_TEXTURE_3D) 753464ebd5Sriastradh slices = depth; 763464ebd5Sriastradh else 773464ebd5Sriastradh slices = pt->array_size; 784a49301eSmrg 793464ebd5Sriastradh spr->stride[level] = util_format_get_stride(pt->format, width); 803464ebd5Sriastradh 813464ebd5Sriastradh spr->level_offset[level] = buffer_size; 824a49301eSmrg 8301e04c3fSmrg /* if row_stride * height > SP_MAX_TEXTURE_SIZE */ 8401e04c3fSmrg if ((uint64_t)spr->stride[level] * nblocksy > SP_MAX_TEXTURE_SIZE) { 8501e04c3fSmrg /* image too large */ 8601e04c3fSmrg return FALSE; 8701e04c3fSmrg } 8801e04c3fSmrg 8901e04c3fSmrg spr->img_stride[level] = spr->stride[level] * nblocksy; 9001e04c3fSmrg 9101e04c3fSmrg buffer_size += (uint64_t) spr->img_stride[level] * slices; 924a49301eSmrg 93cdc920a0Smrg width = u_minify(width, 1); 94cdc920a0Smrg height = u_minify(height, 1); 95cdc920a0Smrg depth = u_minify(depth, 1); 964a49301eSmrg } 974a49301eSmrg 98af69d88dSmrg if (buffer_size > SP_MAX_TEXTURE_SIZE) 99af69d88dSmrg return FALSE; 1004a49301eSmrg 101af69d88dSmrg if (allocate) { 102af69d88dSmrg spr->data = align_malloc(buffer_size, 64); 103af69d88dSmrg return spr->data != NULL; 104af69d88dSmrg } 105af69d88dSmrg else { 106af69d88dSmrg return TRUE; 107af69d88dSmrg } 108af69d88dSmrg} 109af69d88dSmrg 110af69d88dSmrg 111af69d88dSmrg/** 112af69d88dSmrg * Check the size of the texture specified by 'res'. 113af69d88dSmrg * \return TRUE if OK, FALSE if too large. 114af69d88dSmrg */ 1157ec681f3Smrgstatic bool 116af69d88dSmrgsoftpipe_can_create_resource(struct pipe_screen *screen, 117af69d88dSmrg const struct pipe_resource *res) 118af69d88dSmrg{ 119af69d88dSmrg struct softpipe_resource spr; 120af69d88dSmrg memset(&spr, 0, sizeof(spr)); 121af69d88dSmrg spr.base = *res; 122af69d88dSmrg return softpipe_resource_layout(screen, &spr, FALSE); 1234a49301eSmrg} 1244a49301eSmrg 1254a49301eSmrg 1264a49301eSmrg/** 1274a49301eSmrg * Texture layout for simple color buffers. 1284a49301eSmrg */ 1294a49301eSmrgstatic boolean 1304a49301eSmrgsoftpipe_displaytarget_layout(struct pipe_screen *screen, 13101e04c3fSmrg struct softpipe_resource *spr, 13201e04c3fSmrg const void *map_front_private) 1334a49301eSmrg{ 1343464ebd5Sriastradh struct sw_winsys *winsys = softpipe_screen(screen)->winsys; 1353464ebd5Sriastradh 1363464ebd5Sriastradh /* Round up the surface size to a multiple of the tile size? 1373464ebd5Sriastradh */ 1383464ebd5Sriastradh spr->dt = winsys->displaytarget_create(winsys, 1393464ebd5Sriastradh spr->base.bind, 1403464ebd5Sriastradh spr->base.format, 1413464ebd5Sriastradh spr->base.width0, 1423464ebd5Sriastradh spr->base.height0, 143af69d88dSmrg 64, 14401e04c3fSmrg map_front_private, 1453464ebd5Sriastradh &spr->stride[0] ); 1463464ebd5Sriastradh 1473464ebd5Sriastradh return spr->dt != NULL; 1484a49301eSmrg} 1494a49301eSmrg 1504a49301eSmrg 1514a49301eSmrg/** 1523464ebd5Sriastradh * Create new pipe_resource given the template information. 1534a49301eSmrg */ 1543464ebd5Sriastradhstatic struct pipe_resource * 15501e04c3fSmrgsoftpipe_resource_create_front(struct pipe_screen *screen, 15601e04c3fSmrg const struct pipe_resource *templat, 15701e04c3fSmrg const void *map_front_private) 1584a49301eSmrg{ 1593464ebd5Sriastradh struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource); 1603464ebd5Sriastradh if (!spr) 1614a49301eSmrg return NULL; 1624a49301eSmrg 1633464ebd5Sriastradh assert(templat->format != PIPE_FORMAT_NONE); 1643464ebd5Sriastradh 1653464ebd5Sriastradh spr->base = *templat; 1663464ebd5Sriastradh pipe_reference_init(&spr->base.reference, 1); 1673464ebd5Sriastradh spr->base.screen = screen; 1684a49301eSmrg 16901e04c3fSmrg spr->pot = (util_is_power_of_two_or_zero(templat->width0) && 17001e04c3fSmrg util_is_power_of_two_or_zero(templat->height0) && 17101e04c3fSmrg util_is_power_of_two_or_zero(templat->depth0)); 1724a49301eSmrg 1733464ebd5Sriastradh if (spr->base.bind & (PIPE_BIND_DISPLAY_TARGET | 1743464ebd5Sriastradh PIPE_BIND_SCANOUT | 1753464ebd5Sriastradh PIPE_BIND_SHARED)) { 17601e04c3fSmrg if (!softpipe_displaytarget_layout(screen, spr, map_front_private)) 1774a49301eSmrg goto fail; 1784a49301eSmrg } 1794a49301eSmrg else { 180af69d88dSmrg if (!softpipe_resource_layout(screen, spr, TRUE)) 1814a49301eSmrg goto fail; 1824a49301eSmrg } 1834a49301eSmrg 1843464ebd5Sriastradh return &spr->base; 1854a49301eSmrg 1864a49301eSmrg fail: 1873464ebd5Sriastradh FREE(spr); 1884a49301eSmrg return NULL; 1894a49301eSmrg} 1904a49301eSmrg 19101e04c3fSmrgstatic struct pipe_resource * 19201e04c3fSmrgsoftpipe_resource_create(struct pipe_screen *screen, 19301e04c3fSmrg const struct pipe_resource *templat) 19401e04c3fSmrg{ 19501e04c3fSmrg return softpipe_resource_create_front(screen, templat, NULL); 19601e04c3fSmrg} 1974a49301eSmrg 1983464ebd5Sriastradhstatic void 1993464ebd5Sriastradhsoftpipe_resource_destroy(struct pipe_screen *pscreen, 2003464ebd5Sriastradh struct pipe_resource *pt) 2014a49301eSmrg{ 2023464ebd5Sriastradh struct softpipe_screen *screen = softpipe_screen(pscreen); 2033464ebd5Sriastradh struct softpipe_resource *spr = softpipe_resource(pt); 2044a49301eSmrg 2053464ebd5Sriastradh if (spr->dt) { 2063464ebd5Sriastradh /* display target */ 2073464ebd5Sriastradh struct sw_winsys *winsys = screen->winsys; 2083464ebd5Sriastradh winsys->displaytarget_destroy(winsys, spr->dt); 2094a49301eSmrg } 2103464ebd5Sriastradh else if (!spr->userBuffer) { 2113464ebd5Sriastradh /* regular texture */ 2123464ebd5Sriastradh align_free(spr->data); 2133464ebd5Sriastradh } 2143464ebd5Sriastradh 2153464ebd5Sriastradh FREE(spr); 2163464ebd5Sriastradh} 2174a49301eSmrg 2183464ebd5Sriastradh 2193464ebd5Sriastradhstatic struct pipe_resource * 2203464ebd5Sriastradhsoftpipe_resource_from_handle(struct pipe_screen *screen, 2213464ebd5Sriastradh const struct pipe_resource *templat, 22201e04c3fSmrg struct winsys_handle *whandle, 22301e04c3fSmrg unsigned usage) 2243464ebd5Sriastradh{ 2253464ebd5Sriastradh struct sw_winsys *winsys = softpipe_screen(screen)->winsys; 2263464ebd5Sriastradh struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource); 2273464ebd5Sriastradh if (!spr) 2284a49301eSmrg return NULL; 2294a49301eSmrg 2303464ebd5Sriastradh spr->base = *templat; 2313464ebd5Sriastradh pipe_reference_init(&spr->base.reference, 1); 2323464ebd5Sriastradh spr->base.screen = screen; 2333464ebd5Sriastradh 23401e04c3fSmrg spr->pot = (util_is_power_of_two_or_zero(templat->width0) && 23501e04c3fSmrg util_is_power_of_two_or_zero(templat->height0) && 23601e04c3fSmrg util_is_power_of_two_or_zero(templat->depth0)); 2374a49301eSmrg 2383464ebd5Sriastradh spr->dt = winsys->displaytarget_from_handle(winsys, 2393464ebd5Sriastradh templat, 2403464ebd5Sriastradh whandle, 2413464ebd5Sriastradh &spr->stride[0]); 2423464ebd5Sriastradh if (!spr->dt) 2433464ebd5Sriastradh goto fail; 2444a49301eSmrg 2453464ebd5Sriastradh return &spr->base; 2463464ebd5Sriastradh 2473464ebd5Sriastradh fail: 2483464ebd5Sriastradh FREE(spr); 2493464ebd5Sriastradh return NULL; 2504a49301eSmrg} 2514a49301eSmrg 2524a49301eSmrg 2537ec681f3Smrgstatic bool 2543464ebd5Sriastradhsoftpipe_resource_get_handle(struct pipe_screen *screen, 25501e04c3fSmrg struct pipe_context *ctx, 2563464ebd5Sriastradh struct pipe_resource *pt, 25701e04c3fSmrg struct winsys_handle *whandle, 25801e04c3fSmrg unsigned usage) 2594a49301eSmrg{ 2603464ebd5Sriastradh struct sw_winsys *winsys = softpipe_screen(screen)->winsys; 2613464ebd5Sriastradh struct softpipe_resource *spr = softpipe_resource(pt); 2623464ebd5Sriastradh 2633464ebd5Sriastradh assert(spr->dt); 2643464ebd5Sriastradh if (!spr->dt) 2657ec681f3Smrg return false; 2664a49301eSmrg 2673464ebd5Sriastradh return winsys->displaytarget_get_handle(winsys, spr->dt, whandle); 2684a49301eSmrg} 2694a49301eSmrg 2704a49301eSmrg 2714a49301eSmrg/** 2723464ebd5Sriastradh * Helper function to compute offset (in bytes) for a particular 2733464ebd5Sriastradh * texture level/face/slice from the start of the buffer. 2743464ebd5Sriastradh */ 27501e04c3fSmrgunsigned 27601e04c3fSmrgsoftpipe_get_tex_image_offset(const struct softpipe_resource *spr, 27701e04c3fSmrg unsigned level, unsigned layer) 2783464ebd5Sriastradh{ 2793464ebd5Sriastradh unsigned offset = spr->level_offset[level]; 2803464ebd5Sriastradh 28101e04c3fSmrg offset += layer * spr->img_stride[level]; 2823464ebd5Sriastradh 2833464ebd5Sriastradh return offset; 2843464ebd5Sriastradh} 2853464ebd5Sriastradh 2863464ebd5Sriastradh 2873464ebd5Sriastradh/** 2883464ebd5Sriastradh * Get a pipe_surface "view" into a texture resource. 2894a49301eSmrg */ 2904a49301eSmrgstatic struct pipe_surface * 2913464ebd5Sriastradhsoftpipe_create_surface(struct pipe_context *pipe, 2923464ebd5Sriastradh struct pipe_resource *pt, 2933464ebd5Sriastradh const struct pipe_surface *surf_tmpl) 2944a49301eSmrg{ 2954a49301eSmrg struct pipe_surface *ps; 2964a49301eSmrg 2974a49301eSmrg ps = CALLOC_STRUCT(pipe_surface); 2984a49301eSmrg if (ps) { 2994a49301eSmrg pipe_reference_init(&ps->reference, 1); 3003464ebd5Sriastradh pipe_resource_reference(&ps->texture, pt); 3013464ebd5Sriastradh ps->context = pipe; 3023464ebd5Sriastradh ps->format = surf_tmpl->format; 303af69d88dSmrg if (pt->target != PIPE_BUFFER) { 304af69d88dSmrg assert(surf_tmpl->u.tex.level <= pt->last_level); 305af69d88dSmrg ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); 306af69d88dSmrg ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); 307af69d88dSmrg ps->u.tex.level = surf_tmpl->u.tex.level; 308af69d88dSmrg ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; 309af69d88dSmrg ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; 310af69d88dSmrg if (ps->u.tex.first_layer != ps->u.tex.last_layer) { 311af69d88dSmrg debug_printf("creating surface with multiple layers, rendering to first layer only\n"); 312af69d88dSmrg } 313af69d88dSmrg } 314af69d88dSmrg else { 315af69d88dSmrg /* setting width as number of elements should get us correct renderbuffer width */ 316af69d88dSmrg ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1; 317af69d88dSmrg ps->height = pt->height0; 318af69d88dSmrg ps->u.buf.first_element = surf_tmpl->u.buf.first_element; 319af69d88dSmrg ps->u.buf.last_element = surf_tmpl->u.buf.last_element; 320af69d88dSmrg assert(ps->u.buf.first_element <= ps->u.buf.last_element); 321af69d88dSmrg assert(ps->u.buf.last_element < ps->width); 322af69d88dSmrg } 3234a49301eSmrg } 3244a49301eSmrg return ps; 3254a49301eSmrg} 3264a49301eSmrg 3274a49301eSmrg 3284a49301eSmrg/** 3293464ebd5Sriastradh * Free a pipe_surface which was created with softpipe_create_surface(). 3304a49301eSmrg */ 3314a49301eSmrgstatic void 3323464ebd5Sriastradhsoftpipe_surface_destroy(struct pipe_context *pipe, 3333464ebd5Sriastradh struct pipe_surface *surf) 3344a49301eSmrg{ 3354a49301eSmrg /* Effectively do the texture_update work here - if texture images 3364a49301eSmrg * needed post-processing to put them into hardware layout, this is 3374a49301eSmrg * where it would happen. For softpipe, nothing to do. 3384a49301eSmrg */ 3394a49301eSmrg assert(surf->texture); 3403464ebd5Sriastradh pipe_resource_reference(&surf->texture, NULL); 3414a49301eSmrg FREE(surf); 3424a49301eSmrg} 3434a49301eSmrg 3444a49301eSmrg 3454a49301eSmrg/** 3464a49301eSmrg * Geta pipe_transfer object which is used for moving data in/out of 3473464ebd5Sriastradh * a resource object. 3483464ebd5Sriastradh * \param pipe rendering context 3493464ebd5Sriastradh * \param resource the resource to transfer in/out of 3503464ebd5Sriastradh * \param level which mipmap level 3517ec681f3Smrg * \param usage bitmask of PIPE_MAP_x flags 3523464ebd5Sriastradh * \param box the 1D/2D/3D region of interest 3534a49301eSmrg */ 354af69d88dSmrgstatic void * 355af69d88dSmrgsoftpipe_transfer_map(struct pipe_context *pipe, 3563464ebd5Sriastradh struct pipe_resource *resource, 3573464ebd5Sriastradh unsigned level, 3583464ebd5Sriastradh unsigned usage, 359af69d88dSmrg const struct pipe_box *box, 360af69d88dSmrg struct pipe_transfer **transfer) 3614a49301eSmrg{ 362af69d88dSmrg struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys; 3633464ebd5Sriastradh struct softpipe_resource *spr = softpipe_resource(resource); 3644a49301eSmrg struct softpipe_transfer *spt; 365af69d88dSmrg struct pipe_transfer *pt; 366af69d88dSmrg enum pipe_format format = resource->format; 367af69d88dSmrg uint8_t *map; 3684a49301eSmrg 3693464ebd5Sriastradh assert(resource); 3703464ebd5Sriastradh assert(level <= resource->last_level); 3714a49301eSmrg 372cdc920a0Smrg /* make sure the requested region is in the image bounds */ 373af69d88dSmrg assert(box->x + box->width <= (int) u_minify(resource->width0, level)); 3743464ebd5Sriastradh if (resource->target == PIPE_TEXTURE_1D_ARRAY) { 375af69d88dSmrg assert(box->y + box->height <= (int) resource->array_size); 3763464ebd5Sriastradh } 3773464ebd5Sriastradh else { 378af69d88dSmrg assert(box->y + box->height <= (int) u_minify(resource->height0, level)); 3793464ebd5Sriastradh if (resource->target == PIPE_TEXTURE_2D_ARRAY) { 380af69d88dSmrg assert(box->z + box->depth <= (int) resource->array_size); 3813464ebd5Sriastradh } 3823464ebd5Sriastradh else if (resource->target == PIPE_TEXTURE_CUBE) { 3833464ebd5Sriastradh assert(box->z < 6); 3843464ebd5Sriastradh } 385af69d88dSmrg else if (resource->target == PIPE_TEXTURE_CUBE_ARRAY) { 386af69d88dSmrg assert(box->z <= (int) resource->array_size); 387af69d88dSmrg } 3883464ebd5Sriastradh else { 389af69d88dSmrg assert(box->z + box->depth <= (int) u_minify(resource->depth0, level)); 3903464ebd5Sriastradh } 3913464ebd5Sriastradh } 3923464ebd5Sriastradh 3933464ebd5Sriastradh /* 3943464ebd5Sriastradh * Transfers, like other pipe operations, must happen in order, so flush the 3953464ebd5Sriastradh * context if necessary. 3963464ebd5Sriastradh */ 3977ec681f3Smrg if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) { 3987ec681f3Smrg boolean read_only = !(usage & PIPE_MAP_WRITE); 3997ec681f3Smrg boolean do_not_block = !!(usage & PIPE_MAP_DONTBLOCK); 4003464ebd5Sriastradh if (!softpipe_flush_resource(pipe, resource, 4013464ebd5Sriastradh level, box->depth > 1 ? -1 : box->z, 4023464ebd5Sriastradh 0, /* flush_flags */ 4033464ebd5Sriastradh read_only, 4043464ebd5Sriastradh TRUE, /* cpu_access */ 4053464ebd5Sriastradh do_not_block)) { 4063464ebd5Sriastradh /* 4073464ebd5Sriastradh * It would have blocked, but state tracker requested no to. 4083464ebd5Sriastradh */ 4093464ebd5Sriastradh assert(do_not_block); 4103464ebd5Sriastradh return NULL; 4113464ebd5Sriastradh } 4123464ebd5Sriastradh } 413cdc920a0Smrg 4144a49301eSmrg spt = CALLOC_STRUCT(softpipe_transfer); 415af69d88dSmrg if (!spt) 416af69d88dSmrg return NULL; 4174a49301eSmrg 418af69d88dSmrg pt = &spt->base; 4194a49301eSmrg 420af69d88dSmrg pipe_resource_reference(&pt->resource, resource); 421af69d88dSmrg pt->level = level; 422af69d88dSmrg pt->usage = usage; 423af69d88dSmrg pt->box = *box; 424af69d88dSmrg pt->stride = spr->stride[level]; 42501e04c3fSmrg pt->layer_stride = spr->img_stride[level]; 4264a49301eSmrg 42701e04c3fSmrg spt->offset = softpipe_get_tex_image_offset(spr, level, box->z); 4284a49301eSmrg 429af69d88dSmrg spt->offset += 430af69d88dSmrg box->y / util_format_get_blockheight(format) * spt->base.stride + 431af69d88dSmrg box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); 4324a49301eSmrg 4333464ebd5Sriastradh /* resources backed by display target treated specially: 4344a49301eSmrg */ 4353464ebd5Sriastradh if (spr->dt) { 436af69d88dSmrg map = winsys->displaytarget_map(winsys, spr->dt, usage); 4373464ebd5Sriastradh } 4383464ebd5Sriastradh else { 4393464ebd5Sriastradh map = spr->data; 4404a49301eSmrg } 4414a49301eSmrg 44201e04c3fSmrg if (!map) { 443af69d88dSmrg pipe_resource_reference(&pt->resource, NULL); 444af69d88dSmrg FREE(spt); 4453464ebd5Sriastradh return NULL; 446af69d88dSmrg } 447af69d88dSmrg 448af69d88dSmrg *transfer = pt; 449af69d88dSmrg return map + spt->offset; 4504a49301eSmrg} 4514a49301eSmrg 4524a49301eSmrg 4534a49301eSmrg/** 4544a49301eSmrg * Unmap memory mapping for given pipe_transfer object. 4554a49301eSmrg */ 4564a49301eSmrgstatic void 4573464ebd5Sriastradhsoftpipe_transfer_unmap(struct pipe_context *pipe, 4584a49301eSmrg struct pipe_transfer *transfer) 4594a49301eSmrg{ 4603464ebd5Sriastradh struct softpipe_resource *spr; 4614a49301eSmrg 4623464ebd5Sriastradh assert(transfer->resource); 4633464ebd5Sriastradh spr = softpipe_resource(transfer->resource); 4644a49301eSmrg 4653464ebd5Sriastradh if (spr->dt) { 4663464ebd5Sriastradh /* display target */ 4673464ebd5Sriastradh struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys; 4683464ebd5Sriastradh winsys->displaytarget_unmap(winsys, spr->dt); 4693464ebd5Sriastradh } 4704a49301eSmrg 4717ec681f3Smrg if (transfer->usage & PIPE_MAP_WRITE) { 4724a49301eSmrg /* Mark the texture as dirty to expire the tile caches. */ 4733464ebd5Sriastradh spr->timestamp++; 4744a49301eSmrg } 475af69d88dSmrg 476af69d88dSmrg pipe_resource_reference(&transfer->resource, NULL); 477af69d88dSmrg FREE(transfer); 4784a49301eSmrg} 4794a49301eSmrg 4803464ebd5Sriastradh/** 4813464ebd5Sriastradh * Create buffer which wraps user-space data. 4823464ebd5Sriastradh */ 483af69d88dSmrgstruct pipe_resource * 4843464ebd5Sriastradhsoftpipe_user_buffer_create(struct pipe_screen *screen, 4853464ebd5Sriastradh void *ptr, 4863464ebd5Sriastradh unsigned bytes, 4873464ebd5Sriastradh unsigned bind_flags) 4884a49301eSmrg{ 4893464ebd5Sriastradh struct softpipe_resource *spr; 4904a49301eSmrg 4913464ebd5Sriastradh spr = CALLOC_STRUCT(softpipe_resource); 4923464ebd5Sriastradh if (!spr) 4934a49301eSmrg return NULL; 4944a49301eSmrg 4953464ebd5Sriastradh pipe_reference_init(&spr->base.reference, 1); 4963464ebd5Sriastradh spr->base.screen = screen; 4973464ebd5Sriastradh spr->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */ 4983464ebd5Sriastradh spr->base.bind = bind_flags; 4993464ebd5Sriastradh spr->base.usage = PIPE_USAGE_IMMUTABLE; 5003464ebd5Sriastradh spr->base.flags = 0; 5013464ebd5Sriastradh spr->base.width0 = bytes; 5023464ebd5Sriastradh spr->base.height0 = 1; 5033464ebd5Sriastradh spr->base.depth0 = 1; 5043464ebd5Sriastradh spr->base.array_size = 1; 5053464ebd5Sriastradh spr->userBuffer = TRUE; 5063464ebd5Sriastradh spr->data = ptr; 5073464ebd5Sriastradh 5083464ebd5Sriastradh return &spr->base; 5094a49301eSmrg} 5104a49301eSmrg 5114a49301eSmrg 5124a49301eSmrgvoid 5133464ebd5Sriastradhsoftpipe_init_texture_funcs(struct pipe_context *pipe) 5144a49301eSmrg{ 5157ec681f3Smrg pipe->buffer_map = softpipe_transfer_map; 5167ec681f3Smrg pipe->buffer_unmap = softpipe_transfer_unmap; 5177ec681f3Smrg pipe->texture_map = softpipe_transfer_map; 5187ec681f3Smrg pipe->texture_unmap = softpipe_transfer_unmap; 5194a49301eSmrg 5203464ebd5Sriastradh pipe->transfer_flush_region = u_default_transfer_flush_region; 52101e04c3fSmrg pipe->buffer_subdata = u_default_buffer_subdata; 52201e04c3fSmrg pipe->texture_subdata = u_default_texture_subdata; 5234a49301eSmrg 5243464ebd5Sriastradh pipe->create_surface = softpipe_create_surface; 5253464ebd5Sriastradh pipe->surface_destroy = softpipe_surface_destroy; 52601e04c3fSmrg pipe->clear_texture = util_clear_texture; 5274a49301eSmrg} 5284a49301eSmrg 5294a49301eSmrg 5303464ebd5Sriastradhvoid 5313464ebd5Sriastradhsoftpipe_init_screen_texture_funcs(struct pipe_screen *screen) 5324a49301eSmrg{ 5333464ebd5Sriastradh screen->resource_create = softpipe_resource_create; 53401e04c3fSmrg screen->resource_create_front = softpipe_resource_create_front; 5353464ebd5Sriastradh screen->resource_destroy = softpipe_resource_destroy; 5363464ebd5Sriastradh screen->resource_from_handle = softpipe_resource_from_handle; 5373464ebd5Sriastradh screen->resource_get_handle = softpipe_resource_get_handle; 538af69d88dSmrg screen->can_create_resource = softpipe_can_create_resource; 5394a49301eSmrg} 540