Home | History | Annotate | Download | only in util
      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 
     32 static void
     33 util_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 
     52 struct util_staging_transfer *
     53 util_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 
    105 void
    106 util_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