sync with tizen_2.2
[sdk/emulator/qemu.git] / gl / mesa / src / gallium / auxiliary / util / u_staging.c
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 }