e73797f1b7e62d64a7837619a777472d9c0d0f71
[profile/ivi/mesa.git] / src / gallium / auxiliary / util / u_rect.c
1 /**************************************************************************
2  * 
3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  * 
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  * 
26  **************************************************************************/
27
28 /**
29  * Rectangle-related helper functions.
30  */
31
32
33 #include "pipe/p_defines.h"
34 #include "pipe/p_format.h"
35 #include "pipe/p_context.h"
36 #include "pipe/p_screen.h"
37 #include "util/u_format.h"
38 #include "util/u_rect.h"
39
40
41 /**
42  * Copy 2D rect from one place to another.
43  * Position and sizes are in pixels.
44  * src_stride may be negative to do vertical flip of pixels from source.
45  */
46 void
47 util_copy_rect(ubyte * dst,
48                enum pipe_format format,
49                unsigned dst_stride,
50                unsigned dst_x,
51                unsigned dst_y,
52                unsigned width,
53                unsigned height,
54                const ubyte * src,
55                int src_stride,
56                unsigned src_x, 
57                unsigned src_y)
58 {
59    unsigned i;
60    int src_stride_pos = src_stride < 0 ? -src_stride : src_stride;
61    int blocksize = util_format_get_blocksize(format);
62    int blockwidth = util_format_get_blockwidth(format);
63    int blockheight = util_format_get_blockheight(format);
64
65    assert(blocksize > 0);
66    assert(blockwidth > 0);
67    assert(blockheight > 0);
68
69    dst_x /= blockwidth;
70    dst_y /= blockheight;
71    width = (width + blockwidth - 1)/blockwidth;
72    height = (height + blockheight - 1)/blockheight;
73    src_x /= blockwidth;
74    src_y /= blockheight;
75    
76    dst += dst_x * blocksize;
77    src += src_x * blocksize;
78    dst += dst_y * dst_stride;
79    src += src_y * src_stride_pos;
80    width *= blocksize;
81
82    if (width == dst_stride && width == src_stride)
83       memcpy(dst, src, height * width);
84    else {
85       for (i = 0; i < height; i++) {
86          memcpy(dst, src, width);
87          dst += dst_stride;
88          src += src_stride;
89       }
90    }
91 }
92
93 void
94 util_fill_rect(ubyte * dst,
95                enum pipe_format format,
96                unsigned dst_stride,
97                unsigned dst_x,
98                unsigned dst_y,
99                unsigned width,
100                unsigned height,
101                uint32_t value)
102 {
103    unsigned i, j;
104    unsigned width_size;
105    int blocksize = util_format_get_blocksize(format);
106    int blockwidth = util_format_get_blockwidth(format);
107    int blockheight = util_format_get_blockheight(format);
108
109    assert(blocksize > 0);
110    assert(blockwidth > 0);
111    assert(blockheight > 0);
112
113    dst_x /= blockwidth;
114    dst_y /= blockheight;
115    width = (width + blockwidth - 1)/blockwidth;
116    height = (height + blockheight - 1)/blockheight;
117    
118    dst += dst_x * blocksize;
119    dst += dst_y * dst_stride;
120    width_size = width * blocksize;
121    
122    switch (blocksize) {
123    case 1:
124       if(dst_stride == width_size)
125          memset(dst, (ubyte) value, height * width_size);
126       else {
127          for (i = 0; i < height; i++) {
128             memset(dst, (ubyte) value, width_size);
129             dst += dst_stride;
130          }
131       }
132       break;
133    case 2:
134       for (i = 0; i < height; i++) {
135          uint16_t *row = (uint16_t *)dst;
136          for (j = 0; j < width; j++)
137             *row++ = (uint16_t) value;
138          dst += dst_stride;
139       }
140       break;
141    case 4:
142       for (i = 0; i < height; i++) {
143          uint32_t *row = (uint32_t *)dst;
144          for (j = 0; j < width; j++)
145             *row++ = value;
146          dst += dst_stride;
147       }
148       break;
149    default:
150          assert(0);
151          break;
152    }
153 }
154
155
156
157 /**
158  * Fallback function for pipe->surface_copy().
159  * Note: (X,Y)=(0,0) is always the upper-left corner.
160  * if do_flip, flip the image vertically on its way from src rect to dst rect.
161  * XXX should probably put this in new u_surface.c file...
162  */
163 void
164 util_surface_copy(struct pipe_context *pipe,
165                   boolean do_flip,
166                   struct pipe_surface *dst,
167                   unsigned dst_x, unsigned dst_y,
168                   struct pipe_surface *src,
169                   unsigned src_x, unsigned src_y, 
170                   unsigned w, unsigned h)
171 {
172    struct pipe_transfer *src_trans, *dst_trans;
173    void *dst_map;
174    const void *src_map;
175    enum pipe_format src_format, dst_format;
176
177    assert(src->texture && dst->texture);
178    if (!src->texture || !dst->texture)
179       return;
180
181    src_format = src->texture->format;
182    dst_format = dst->texture->format;
183
184    src_trans = pipe->get_tex_transfer(pipe,
185                                         src->texture,
186                                         src->face,
187                                         src->level,
188                                         src->zslice,
189                                         PIPE_TRANSFER_READ,
190                                         src_x, src_y, w, h);
191
192    dst_trans = pipe->get_tex_transfer(pipe,
193                                         dst->texture,
194                                         dst->face,
195                                         dst->level,
196                                         dst->zslice,
197                                         PIPE_TRANSFER_WRITE,
198                                         dst_x, dst_y, w, h);
199
200    assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format));
201    assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format));
202    assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format));
203
204    src_map = pipe->transfer_map(pipe, src_trans);
205    dst_map = pipe->transfer_map(pipe, dst_trans);
206
207    assert(src_map);
208    assert(dst_map);
209
210    if (src_map && dst_map) {
211       /* If do_flip, invert src_y position and pass negative src stride */
212       util_copy_rect(dst_map,
213                      dst_format,
214                      dst_trans->stride,
215                      0, 0,
216                      w, h,
217                      src_map,
218                      do_flip ? -(int) src_trans->stride : src_trans->stride,
219                      0,
220                      do_flip ? h - 1 : 0);
221    }
222
223    pipe->transfer_unmap(pipe, src_trans);
224    pipe->transfer_unmap(pipe, dst_trans);
225
226    pipe->tex_transfer_destroy(pipe, src_trans);
227    pipe->tex_transfer_destroy(pipe, dst_trans);
228 }
229
230
231
232 #define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
233
234
235 /**
236  * Fallback for pipe->surface_fill() function.
237  * XXX should probably put this in new u_surface.c file...
238  */
239 void
240 util_surface_fill(struct pipe_context *pipe,
241                   struct pipe_surface *dst,
242                   unsigned dstx, unsigned dsty,
243                   unsigned width, unsigned height, unsigned value)
244 {
245    struct pipe_transfer *dst_trans;
246    void *dst_map;
247
248    assert(dst->texture);
249    if (!dst->texture)
250       return;
251    dst_trans = pipe->get_tex_transfer(pipe,
252                                         dst->texture,
253                                         dst->face,
254                                         dst->level,
255                                         dst->zslice,
256                                         PIPE_TRANSFER_WRITE,
257                                         dstx, dsty, width, height);
258
259    dst_map = pipe->transfer_map(pipe, dst_trans);
260
261    assert(dst_map);
262
263    if (dst_map) {
264       assert(dst_trans->stride > 0);
265
266       switch (util_format_get_blocksize(dst_trans->texture->format)) {
267       case 1:
268       case 2:
269       case 4:
270          util_fill_rect(dst_map, dst_trans->texture->format, dst_trans->stride,
271                         0, 0, width, height, value);
272          break;
273       case 8:
274          {
275             /* expand the 4-byte clear value to an 8-byte value */
276             ushort *row = (ushort *) dst_map;
277             ushort val0 = UBYTE_TO_USHORT((value >>  0) & 0xff);
278             ushort val1 = UBYTE_TO_USHORT((value >>  8) & 0xff);
279             ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff);
280             ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff);
281             unsigned i, j;
282             val0 = (val0 << 8) | val0;
283             val1 = (val1 << 8) | val1;
284             val2 = (val2 << 8) | val2;
285             val3 = (val3 << 8) | val3;
286             for (i = 0; i < height; i++) {
287                for (j = 0; j < width; j++) {
288                   row[j*4+0] = val0;
289                   row[j*4+1] = val1;
290                   row[j*4+2] = val2;
291                   row[j*4+3] = val3;
292                }
293                row += dst_trans->stride/2;
294             }
295          }
296          break;
297       default:
298          assert(0);
299          break;
300       }
301    }
302
303    pipe->transfer_unmap(pipe, dst_trans);
304    pipe->tex_transfer_destroy(pipe, dst_trans);
305 }