1/************************************************************************** 2 * 3 * Copyright 2010 Luca Barbieri 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27#include "util/u_staging.h" 28#include "pipe/p_context.h" 29#include "util/u_memory.h" 30#include "util/u_inlines.h" 31 32static void 33util_staging_resource_template(struct pipe_resource *pt, unsigned width, unsigned height, unsigned depth, struct pipe_resource *template) 34{ 35 memset(template, 0, sizeof(struct pipe_resource)); 36 if(pt->target != PIPE_BUFFER && depth <= 1) 37 template->target = PIPE_TEXTURE_RECT; 38 else 39 template->target = pt->target; 40 template->format = pt->format; 41 template->width0 = width; 42 template->height0 = height; 43 template->depth0 = depth; 44 template->array_size = 1; 45 template->last_level = 0; 46 template->nr_samples = pt->nr_samples; 47 template->bind = 0; 48 template->usage = PIPE_USAGE_STAGING; 49 template->flags = 0; 50} 51 52struct util_staging_transfer * 53util_staging_transfer_init(struct pipe_context *pipe, 54 struct pipe_resource *pt, 55 unsigned level, 56 unsigned usage, 57 const struct pipe_box *box, 58 boolean direct, struct util_staging_transfer *tx) 59{ 60 struct pipe_screen *pscreen = pipe->screen; 61 62 struct pipe_resource staging_resource_template; 63 64 pipe_resource_reference(&tx->base.resource, pt); 65 tx->base.level = level; 66 tx->base.usage = usage; 67 tx->base.box = *box; 68 69 if (direct) 70 { 71 tx->staging_resource = pt; 72 return tx; 73 } 74 75 util_staging_resource_template(pt, box->width, box->height, box->depth, &staging_resource_template); 76 tx->staging_resource = pscreen->resource_create(pscreen, &staging_resource_template); 77 if (!tx->staging_resource) 78 { 79 pipe_resource_reference(&tx->base.resource, NULL); 80 FREE(tx); 81 return NULL; 82 } 83 84 if (usage & PIPE_TRANSFER_READ) 85 { 86 /* XXX this looks wrong dst is always the same but looping over src z? */ 87 unsigned zi; 88 struct pipe_box sbox; 89 sbox.x = box->x; 90 sbox.y = box->y; 91 sbox.z = box->z; 92 sbox.width = box->width; 93 sbox.height = box->height; 94 sbox.depth = 1; 95 for(zi = 0; zi < box->depth; ++zi) { 96 sbox.z = sbox.z + zi; 97 pipe->resource_copy_region(pipe, tx->staging_resource, 0, 0, 0, 0, 98 tx->base.resource, level, &sbox); 99 } 100 } 101 102 return tx; 103} 104 105void 106util_staging_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx) 107{ 108 struct util_staging_transfer *tx = (struct util_staging_transfer *)ptx; 109 110 if (tx->staging_resource != tx->base.resource) 111 { 112 if(tx->base.usage & PIPE_TRANSFER_WRITE) { 113 /* XXX this looks wrong src is always the same but looping over dst z? */ 114 unsigned zi; 115 struct pipe_box sbox; 116 sbox.x = 0; 117 sbox.y = 0; 118 sbox.z = 0; 119 sbox.width = tx->base.box.width; 120 sbox.height = tx->base.box.height; 121 sbox.depth = 1; 122 for(zi = 0; zi < tx->base.box.depth; ++zi) 123 pipe->resource_copy_region(pipe, tx->base.resource, tx->base.level, tx->base.box.x, tx->base.box.y, tx->base.box.z + zi, 124 tx->staging_resource, 0, &sbox); 125 } 126 127 pipe_resource_reference(&tx->staging_resource, NULL); 128 } 129 130 pipe_resource_reference(&ptx->resource, NULL); 131 FREE(ptx); 132} 133