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 "pipe/p_defines.h" 34848b8605Smrg#include "util/u_inlines.h" 35848b8605Smrg 36848b8605Smrg#include "util/u_format.h" 37848b8605Smrg#include "util/u_math.h" 38848b8605Smrg#include "util/u_memory.h" 39848b8605Smrg#include "util/u_transfer.h" 40b8e80941Smrg#include "util/u_surface.h" 41848b8605Smrg 42848b8605Smrg#include "sp_context.h" 43848b8605Smrg#include "sp_flush.h" 44848b8605Smrg#include "sp_texture.h" 45848b8605Smrg#include "sp_screen.h" 46848b8605Smrg 47848b8605Smrg#include "state_tracker/sw_winsys.h" 48848b8605Smrg 49848b8605Smrg 50848b8605Smrg/** 51848b8605Smrg * Conventional allocation path for non-display textures: 52848b8605Smrg * Use a simple, maximally packed layout. 53848b8605Smrg */ 54848b8605Smrgstatic boolean 55848b8605Smrgsoftpipe_resource_layout(struct pipe_screen *screen, 56848b8605Smrg struct softpipe_resource *spr, 57848b8605Smrg boolean allocate) 58848b8605Smrg{ 59848b8605Smrg struct pipe_resource *pt = &spr->base; 60848b8605Smrg unsigned level; 61848b8605Smrg unsigned width = pt->width0; 62848b8605Smrg unsigned height = pt->height0; 63848b8605Smrg unsigned depth = pt->depth0; 64848b8605Smrg uint64_t buffer_size = 0; 65848b8605Smrg 66848b8605Smrg for (level = 0; level <= pt->last_level; level++) { 67b8e80941Smrg unsigned slices, nblocksy; 68b8e80941Smrg 69b8e80941Smrg nblocksy = util_format_get_nblocksy(pt->format, height); 70848b8605Smrg 71848b8605Smrg if (pt->target == PIPE_TEXTURE_CUBE) 72b8e80941Smrg assert(pt->array_size == 6); 73b8e80941Smrg 74b8e80941Smrg if (pt->target == PIPE_TEXTURE_3D) 75848b8605Smrg slices = depth; 76848b8605Smrg else 77848b8605Smrg slices = pt->array_size; 78848b8605Smrg 79848b8605Smrg spr->stride[level] = util_format_get_stride(pt->format, width); 80848b8605Smrg 81848b8605Smrg spr->level_offset[level] = buffer_size; 82848b8605Smrg 83b8e80941Smrg /* if row_stride * height > SP_MAX_TEXTURE_SIZE */ 84b8e80941Smrg if ((uint64_t)spr->stride[level] * nblocksy > SP_MAX_TEXTURE_SIZE) { 85b8e80941Smrg /* image too large */ 86b8e80941Smrg return FALSE; 87b8e80941Smrg } 88b8e80941Smrg 89b8e80941Smrg spr->img_stride[level] = spr->stride[level] * nblocksy; 90b8e80941Smrg 91b8e80941Smrg buffer_size += (uint64_t) spr->img_stride[level] * slices; 92848b8605Smrg 93848b8605Smrg width = u_minify(width, 1); 94848b8605Smrg height = u_minify(height, 1); 95848b8605Smrg depth = u_minify(depth, 1); 96848b8605Smrg } 97848b8605Smrg 98848b8605Smrg if (buffer_size > SP_MAX_TEXTURE_SIZE) 99848b8605Smrg return FALSE; 100848b8605Smrg 101848b8605Smrg if (allocate) { 102848b8605Smrg spr->data = align_malloc(buffer_size, 64); 103848b8605Smrg return spr->data != NULL; 104848b8605Smrg } 105848b8605Smrg else { 106848b8605Smrg return TRUE; 107848b8605Smrg } 108848b8605Smrg} 109848b8605Smrg 110848b8605Smrg 111848b8605Smrg/** 112848b8605Smrg * Check the size of the texture specified by 'res'. 113848b8605Smrg * \return TRUE if OK, FALSE if too large. 114848b8605Smrg */ 115848b8605Smrgstatic boolean 116848b8605Smrgsoftpipe_can_create_resource(struct pipe_screen *screen, 117848b8605Smrg const struct pipe_resource *res) 118848b8605Smrg{ 119848b8605Smrg struct softpipe_resource spr; 120848b8605Smrg memset(&spr, 0, sizeof(spr)); 121848b8605Smrg spr.base = *res; 122848b8605Smrg return softpipe_resource_layout(screen, &spr, FALSE); 123848b8605Smrg} 124848b8605Smrg 125848b8605Smrg 126848b8605Smrg/** 127848b8605Smrg * Texture layout for simple color buffers. 128848b8605Smrg */ 129848b8605Smrgstatic boolean 130848b8605Smrgsoftpipe_displaytarget_layout(struct pipe_screen *screen, 131b8e80941Smrg struct softpipe_resource *spr, 132b8e80941Smrg const void *map_front_private) 133848b8605Smrg{ 134848b8605Smrg struct sw_winsys *winsys = softpipe_screen(screen)->winsys; 135848b8605Smrg 136848b8605Smrg /* Round up the surface size to a multiple of the tile size? 137848b8605Smrg */ 138848b8605Smrg spr->dt = winsys->displaytarget_create(winsys, 139848b8605Smrg spr->base.bind, 140848b8605Smrg spr->base.format, 141848b8605Smrg spr->base.width0, 142848b8605Smrg spr->base.height0, 143848b8605Smrg 64, 144b8e80941Smrg map_front_private, 145848b8605Smrg &spr->stride[0] ); 146848b8605Smrg 147848b8605Smrg return spr->dt != NULL; 148848b8605Smrg} 149848b8605Smrg 150848b8605Smrg 151848b8605Smrg/** 152848b8605Smrg * Create new pipe_resource given the template information. 153848b8605Smrg */ 154848b8605Smrgstatic struct pipe_resource * 155b8e80941Smrgsoftpipe_resource_create_front(struct pipe_screen *screen, 156b8e80941Smrg const struct pipe_resource *templat, 157b8e80941Smrg const void *map_front_private) 158848b8605Smrg{ 159848b8605Smrg struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource); 160848b8605Smrg if (!spr) 161848b8605Smrg return NULL; 162848b8605Smrg 163848b8605Smrg assert(templat->format != PIPE_FORMAT_NONE); 164848b8605Smrg 165848b8605Smrg spr->base = *templat; 166848b8605Smrg pipe_reference_init(&spr->base.reference, 1); 167848b8605Smrg spr->base.screen = screen; 168848b8605Smrg 169b8e80941Smrg spr->pot = (util_is_power_of_two_or_zero(templat->width0) && 170b8e80941Smrg util_is_power_of_two_or_zero(templat->height0) && 171b8e80941Smrg util_is_power_of_two_or_zero(templat->depth0)); 172848b8605Smrg 173848b8605Smrg if (spr->base.bind & (PIPE_BIND_DISPLAY_TARGET | 174848b8605Smrg PIPE_BIND_SCANOUT | 175848b8605Smrg PIPE_BIND_SHARED)) { 176b8e80941Smrg if (!softpipe_displaytarget_layout(screen, spr, map_front_private)) 177848b8605Smrg goto fail; 178848b8605Smrg } 179848b8605Smrg else { 180848b8605Smrg if (!softpipe_resource_layout(screen, spr, TRUE)) 181848b8605Smrg goto fail; 182848b8605Smrg } 183848b8605Smrg 184848b8605Smrg return &spr->base; 185848b8605Smrg 186848b8605Smrg fail: 187848b8605Smrg FREE(spr); 188848b8605Smrg return NULL; 189848b8605Smrg} 190848b8605Smrg 191b8e80941Smrgstatic struct pipe_resource * 192b8e80941Smrgsoftpipe_resource_create(struct pipe_screen *screen, 193b8e80941Smrg const struct pipe_resource *templat) 194b8e80941Smrg{ 195b8e80941Smrg return softpipe_resource_create_front(screen, templat, NULL); 196b8e80941Smrg} 197848b8605Smrg 198848b8605Smrgstatic void 199848b8605Smrgsoftpipe_resource_destroy(struct pipe_screen *pscreen, 200848b8605Smrg struct pipe_resource *pt) 201848b8605Smrg{ 202848b8605Smrg struct softpipe_screen *screen = softpipe_screen(pscreen); 203848b8605Smrg struct softpipe_resource *spr = softpipe_resource(pt); 204848b8605Smrg 205848b8605Smrg if (spr->dt) { 206848b8605Smrg /* display target */ 207848b8605Smrg struct sw_winsys *winsys = screen->winsys; 208848b8605Smrg winsys->displaytarget_destroy(winsys, spr->dt); 209848b8605Smrg } 210848b8605Smrg else if (!spr->userBuffer) { 211848b8605Smrg /* regular texture */ 212848b8605Smrg align_free(spr->data); 213848b8605Smrg } 214848b8605Smrg 215848b8605Smrg FREE(spr); 216848b8605Smrg} 217848b8605Smrg 218848b8605Smrg 219848b8605Smrgstatic struct pipe_resource * 220848b8605Smrgsoftpipe_resource_from_handle(struct pipe_screen *screen, 221848b8605Smrg const struct pipe_resource *templat, 222b8e80941Smrg struct winsys_handle *whandle, 223b8e80941Smrg unsigned usage) 224848b8605Smrg{ 225848b8605Smrg struct sw_winsys *winsys = softpipe_screen(screen)->winsys; 226848b8605Smrg struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource); 227848b8605Smrg if (!spr) 228848b8605Smrg return NULL; 229848b8605Smrg 230848b8605Smrg spr->base = *templat; 231848b8605Smrg pipe_reference_init(&spr->base.reference, 1); 232848b8605Smrg spr->base.screen = screen; 233848b8605Smrg 234b8e80941Smrg spr->pot = (util_is_power_of_two_or_zero(templat->width0) && 235b8e80941Smrg util_is_power_of_two_or_zero(templat->height0) && 236b8e80941Smrg util_is_power_of_two_or_zero(templat->depth0)); 237848b8605Smrg 238848b8605Smrg spr->dt = winsys->displaytarget_from_handle(winsys, 239848b8605Smrg templat, 240848b8605Smrg whandle, 241848b8605Smrg &spr->stride[0]); 242848b8605Smrg if (!spr->dt) 243848b8605Smrg goto fail; 244848b8605Smrg 245848b8605Smrg return &spr->base; 246848b8605Smrg 247848b8605Smrg fail: 248848b8605Smrg FREE(spr); 249848b8605Smrg return NULL; 250848b8605Smrg} 251848b8605Smrg 252848b8605Smrg 253848b8605Smrgstatic boolean 254848b8605Smrgsoftpipe_resource_get_handle(struct pipe_screen *screen, 255b8e80941Smrg struct pipe_context *ctx, 256848b8605Smrg struct pipe_resource *pt, 257b8e80941Smrg struct winsys_handle *whandle, 258b8e80941Smrg unsigned usage) 259848b8605Smrg{ 260848b8605Smrg struct sw_winsys *winsys = softpipe_screen(screen)->winsys; 261848b8605Smrg struct softpipe_resource *spr = softpipe_resource(pt); 262848b8605Smrg 263848b8605Smrg assert(spr->dt); 264848b8605Smrg if (!spr->dt) 265848b8605Smrg return FALSE; 266848b8605Smrg 267848b8605Smrg return winsys->displaytarget_get_handle(winsys, spr->dt, whandle); 268848b8605Smrg} 269848b8605Smrg 270848b8605Smrg 271848b8605Smrg/** 272848b8605Smrg * Helper function to compute offset (in bytes) for a particular 273848b8605Smrg * texture level/face/slice from the start of the buffer. 274848b8605Smrg */ 275b8e80941Smrgunsigned 276b8e80941Smrgsoftpipe_get_tex_image_offset(const struct softpipe_resource *spr, 277b8e80941Smrg unsigned level, unsigned layer) 278848b8605Smrg{ 279848b8605Smrg unsigned offset = spr->level_offset[level]; 280848b8605Smrg 281b8e80941Smrg offset += layer * spr->img_stride[level]; 282848b8605Smrg 283848b8605Smrg return offset; 284848b8605Smrg} 285848b8605Smrg 286848b8605Smrg 287848b8605Smrg/** 288848b8605Smrg * Get a pipe_surface "view" into a texture resource. 289848b8605Smrg */ 290848b8605Smrgstatic struct pipe_surface * 291848b8605Smrgsoftpipe_create_surface(struct pipe_context *pipe, 292848b8605Smrg struct pipe_resource *pt, 293848b8605Smrg const struct pipe_surface *surf_tmpl) 294848b8605Smrg{ 295848b8605Smrg struct pipe_surface *ps; 296848b8605Smrg 297848b8605Smrg ps = CALLOC_STRUCT(pipe_surface); 298848b8605Smrg if (ps) { 299848b8605Smrg pipe_reference_init(&ps->reference, 1); 300848b8605Smrg pipe_resource_reference(&ps->texture, pt); 301848b8605Smrg ps->context = pipe; 302848b8605Smrg ps->format = surf_tmpl->format; 303848b8605Smrg if (pt->target != PIPE_BUFFER) { 304848b8605Smrg assert(surf_tmpl->u.tex.level <= pt->last_level); 305848b8605Smrg ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); 306848b8605Smrg ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); 307848b8605Smrg ps->u.tex.level = surf_tmpl->u.tex.level; 308848b8605Smrg ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; 309848b8605Smrg ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; 310848b8605Smrg if (ps->u.tex.first_layer != ps->u.tex.last_layer) { 311848b8605Smrg debug_printf("creating surface with multiple layers, rendering to first layer only\n"); 312848b8605Smrg } 313848b8605Smrg } 314848b8605Smrg else { 315848b8605Smrg /* setting width as number of elements should get us correct renderbuffer width */ 316848b8605Smrg ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1; 317848b8605Smrg ps->height = pt->height0; 318848b8605Smrg ps->u.buf.first_element = surf_tmpl->u.buf.first_element; 319848b8605Smrg ps->u.buf.last_element = surf_tmpl->u.buf.last_element; 320848b8605Smrg assert(ps->u.buf.first_element <= ps->u.buf.last_element); 321848b8605Smrg assert(ps->u.buf.last_element < ps->width); 322848b8605Smrg } 323848b8605Smrg } 324848b8605Smrg return ps; 325848b8605Smrg} 326848b8605Smrg 327848b8605Smrg 328848b8605Smrg/** 329848b8605Smrg * Free a pipe_surface which was created with softpipe_create_surface(). 330848b8605Smrg */ 331848b8605Smrgstatic void 332848b8605Smrgsoftpipe_surface_destroy(struct pipe_context *pipe, 333848b8605Smrg struct pipe_surface *surf) 334848b8605Smrg{ 335848b8605Smrg /* Effectively do the texture_update work here - if texture images 336848b8605Smrg * needed post-processing to put them into hardware layout, this is 337848b8605Smrg * where it would happen. For softpipe, nothing to do. 338848b8605Smrg */ 339848b8605Smrg assert(surf->texture); 340848b8605Smrg pipe_resource_reference(&surf->texture, NULL); 341848b8605Smrg FREE(surf); 342848b8605Smrg} 343848b8605Smrg 344848b8605Smrg 345848b8605Smrg/** 346848b8605Smrg * Geta pipe_transfer object which is used for moving data in/out of 347848b8605Smrg * a resource object. 348848b8605Smrg * \param pipe rendering context 349848b8605Smrg * \param resource the resource to transfer in/out of 350848b8605Smrg * \param level which mipmap level 351848b8605Smrg * \param usage bitmask of PIPE_TRANSFER_x flags 352848b8605Smrg * \param box the 1D/2D/3D region of interest 353848b8605Smrg */ 354848b8605Smrgstatic void * 355848b8605Smrgsoftpipe_transfer_map(struct pipe_context *pipe, 356848b8605Smrg struct pipe_resource *resource, 357848b8605Smrg unsigned level, 358848b8605Smrg unsigned usage, 359848b8605Smrg const struct pipe_box *box, 360848b8605Smrg struct pipe_transfer **transfer) 361848b8605Smrg{ 362848b8605Smrg struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys; 363848b8605Smrg struct softpipe_resource *spr = softpipe_resource(resource); 364848b8605Smrg struct softpipe_transfer *spt; 365848b8605Smrg struct pipe_transfer *pt; 366848b8605Smrg enum pipe_format format = resource->format; 367848b8605Smrg uint8_t *map; 368848b8605Smrg 369848b8605Smrg assert(resource); 370848b8605Smrg assert(level <= resource->last_level); 371848b8605Smrg 372848b8605Smrg /* make sure the requested region is in the image bounds */ 373848b8605Smrg assert(box->x + box->width <= (int) u_minify(resource->width0, level)); 374848b8605Smrg if (resource->target == PIPE_TEXTURE_1D_ARRAY) { 375848b8605Smrg assert(box->y + box->height <= (int) resource->array_size); 376848b8605Smrg } 377848b8605Smrg else { 378848b8605Smrg assert(box->y + box->height <= (int) u_minify(resource->height0, level)); 379848b8605Smrg if (resource->target == PIPE_TEXTURE_2D_ARRAY) { 380848b8605Smrg assert(box->z + box->depth <= (int) resource->array_size); 381848b8605Smrg } 382848b8605Smrg else if (resource->target == PIPE_TEXTURE_CUBE) { 383848b8605Smrg assert(box->z < 6); 384848b8605Smrg } 385848b8605Smrg else if (resource->target == PIPE_TEXTURE_CUBE_ARRAY) { 386848b8605Smrg assert(box->z <= (int) resource->array_size); 387848b8605Smrg } 388848b8605Smrg else { 389848b8605Smrg assert(box->z + box->depth <= (int) u_minify(resource->depth0, level)); 390848b8605Smrg } 391848b8605Smrg } 392848b8605Smrg 393848b8605Smrg /* 394848b8605Smrg * Transfers, like other pipe operations, must happen in order, so flush the 395848b8605Smrg * context if necessary. 396848b8605Smrg */ 397848b8605Smrg if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { 398848b8605Smrg boolean read_only = !(usage & PIPE_TRANSFER_WRITE); 399848b8605Smrg boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK); 400848b8605Smrg if (!softpipe_flush_resource(pipe, resource, 401848b8605Smrg level, box->depth > 1 ? -1 : box->z, 402848b8605Smrg 0, /* flush_flags */ 403848b8605Smrg read_only, 404848b8605Smrg TRUE, /* cpu_access */ 405848b8605Smrg do_not_block)) { 406848b8605Smrg /* 407848b8605Smrg * It would have blocked, but state tracker requested no to. 408848b8605Smrg */ 409848b8605Smrg assert(do_not_block); 410848b8605Smrg return NULL; 411848b8605Smrg } 412848b8605Smrg } 413848b8605Smrg 414848b8605Smrg spt = CALLOC_STRUCT(softpipe_transfer); 415848b8605Smrg if (!spt) 416848b8605Smrg return NULL; 417848b8605Smrg 418848b8605Smrg pt = &spt->base; 419848b8605Smrg 420848b8605Smrg pipe_resource_reference(&pt->resource, resource); 421848b8605Smrg pt->level = level; 422848b8605Smrg pt->usage = usage; 423848b8605Smrg pt->box = *box; 424848b8605Smrg pt->stride = spr->stride[level]; 425b8e80941Smrg pt->layer_stride = spr->img_stride[level]; 426848b8605Smrg 427b8e80941Smrg spt->offset = softpipe_get_tex_image_offset(spr, level, box->z); 428848b8605Smrg 429848b8605Smrg spt->offset += 430848b8605Smrg box->y / util_format_get_blockheight(format) * spt->base.stride + 431848b8605Smrg box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); 432848b8605Smrg 433848b8605Smrg /* resources backed by display target treated specially: 434848b8605Smrg */ 435848b8605Smrg if (spr->dt) { 436848b8605Smrg map = winsys->displaytarget_map(winsys, spr->dt, usage); 437848b8605Smrg } 438848b8605Smrg else { 439848b8605Smrg map = spr->data; 440848b8605Smrg } 441848b8605Smrg 442b8e80941Smrg if (!map) { 443848b8605Smrg pipe_resource_reference(&pt->resource, NULL); 444848b8605Smrg FREE(spt); 445848b8605Smrg return NULL; 446848b8605Smrg } 447848b8605Smrg 448848b8605Smrg *transfer = pt; 449848b8605Smrg return map + spt->offset; 450848b8605Smrg} 451848b8605Smrg 452848b8605Smrg 453848b8605Smrg/** 454848b8605Smrg * Unmap memory mapping for given pipe_transfer object. 455848b8605Smrg */ 456848b8605Smrgstatic void 457848b8605Smrgsoftpipe_transfer_unmap(struct pipe_context *pipe, 458848b8605Smrg struct pipe_transfer *transfer) 459848b8605Smrg{ 460848b8605Smrg struct softpipe_resource *spr; 461848b8605Smrg 462848b8605Smrg assert(transfer->resource); 463848b8605Smrg spr = softpipe_resource(transfer->resource); 464848b8605Smrg 465848b8605Smrg if (spr->dt) { 466848b8605Smrg /* display target */ 467848b8605Smrg struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys; 468848b8605Smrg winsys->displaytarget_unmap(winsys, spr->dt); 469848b8605Smrg } 470848b8605Smrg 471848b8605Smrg if (transfer->usage & PIPE_TRANSFER_WRITE) { 472848b8605Smrg /* Mark the texture as dirty to expire the tile caches. */ 473848b8605Smrg spr->timestamp++; 474848b8605Smrg } 475848b8605Smrg 476848b8605Smrg pipe_resource_reference(&transfer->resource, NULL); 477848b8605Smrg FREE(transfer); 478848b8605Smrg} 479848b8605Smrg 480848b8605Smrg/** 481848b8605Smrg * Create buffer which wraps user-space data. 482848b8605Smrg */ 483848b8605Smrgstruct pipe_resource * 484848b8605Smrgsoftpipe_user_buffer_create(struct pipe_screen *screen, 485848b8605Smrg void *ptr, 486848b8605Smrg unsigned bytes, 487848b8605Smrg unsigned bind_flags) 488848b8605Smrg{ 489848b8605Smrg struct softpipe_resource *spr; 490848b8605Smrg 491848b8605Smrg spr = CALLOC_STRUCT(softpipe_resource); 492848b8605Smrg if (!spr) 493848b8605Smrg return NULL; 494848b8605Smrg 495848b8605Smrg pipe_reference_init(&spr->base.reference, 1); 496848b8605Smrg spr->base.screen = screen; 497848b8605Smrg spr->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */ 498848b8605Smrg spr->base.bind = bind_flags; 499848b8605Smrg spr->base.usage = PIPE_USAGE_IMMUTABLE; 500848b8605Smrg spr->base.flags = 0; 501848b8605Smrg spr->base.width0 = bytes; 502848b8605Smrg spr->base.height0 = 1; 503848b8605Smrg spr->base.depth0 = 1; 504848b8605Smrg spr->base.array_size = 1; 505848b8605Smrg spr->userBuffer = TRUE; 506848b8605Smrg spr->data = ptr; 507848b8605Smrg 508848b8605Smrg return &spr->base; 509848b8605Smrg} 510848b8605Smrg 511848b8605Smrg 512848b8605Smrgvoid 513848b8605Smrgsoftpipe_init_texture_funcs(struct pipe_context *pipe) 514848b8605Smrg{ 515848b8605Smrg pipe->transfer_map = softpipe_transfer_map; 516848b8605Smrg pipe->transfer_unmap = softpipe_transfer_unmap; 517848b8605Smrg 518848b8605Smrg pipe->transfer_flush_region = u_default_transfer_flush_region; 519b8e80941Smrg pipe->buffer_subdata = u_default_buffer_subdata; 520b8e80941Smrg pipe->texture_subdata = u_default_texture_subdata; 521848b8605Smrg 522848b8605Smrg pipe->create_surface = softpipe_create_surface; 523848b8605Smrg pipe->surface_destroy = softpipe_surface_destroy; 524b8e80941Smrg pipe->clear_texture = util_clear_texture; 525848b8605Smrg} 526848b8605Smrg 527848b8605Smrg 528848b8605Smrgvoid 529848b8605Smrgsoftpipe_init_screen_texture_funcs(struct pipe_screen *screen) 530848b8605Smrg{ 531848b8605Smrg screen->resource_create = softpipe_resource_create; 532b8e80941Smrg screen->resource_create_front = softpipe_resource_create_front; 533848b8605Smrg screen->resource_destroy = softpipe_resource_destroy; 534848b8605Smrg screen->resource_from_handle = softpipe_resource_from_handle; 535848b8605Smrg screen->resource_get_handle = softpipe_resource_get_handle; 536848b8605Smrg screen->can_create_resource = softpipe_can_create_resource; 537848b8605Smrg} 538