Squashed commit of the following:
[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_inlines.h"
39 #include "util/u_rect.h"
40
41
42 /**
43  * Copy 2D rect from one place to another.
44  * Position and sizes are in pixels.
45  * src_stride may be negative to do vertical flip of pixels from source.
46  */
47 void
48 util_copy_rect(ubyte * dst,
49                enum pipe_format format,
50                unsigned dst_stride,
51                unsigned dst_x,
52                unsigned dst_y,
53                unsigned width,
54                unsigned height,
55                const ubyte * src,
56                int src_stride,
57                unsigned src_x, 
58                unsigned src_y)
59 {
60    unsigned i;
61    int src_stride_pos = src_stride < 0 ? -src_stride : src_stride;
62    int blocksize = util_format_get_blocksize(format);
63    int blockwidth = util_format_get_blockwidth(format);
64    int blockheight = util_format_get_blockheight(format);
65
66    assert(blocksize > 0);
67    assert(blockwidth > 0);
68    assert(blockheight > 0);
69
70    dst_x /= blockwidth;
71    dst_y /= blockheight;
72    width = (width + blockwidth - 1)/blockwidth;
73    height = (height + blockheight - 1)/blockheight;
74    src_x /= blockwidth;
75    src_y /= blockheight;
76    
77    dst += dst_x * blocksize;
78    src += src_x * blocksize;
79    dst += dst_y * dst_stride;
80    src += src_y * src_stride_pos;
81    width *= blocksize;
82
83    if (width == dst_stride && width == src_stride)
84       memcpy(dst, src, height * width);
85    else {
86       for (i = 0; i < height; i++) {
87          memcpy(dst, src, width);
88          dst += dst_stride;
89          src += src_stride;
90       }
91    }
92 }
93
94 void
95 util_fill_rect(ubyte * dst,
96                enum pipe_format format,
97                unsigned dst_stride,
98                unsigned dst_x,
99                unsigned dst_y,
100                unsigned width,
101                unsigned height,
102                uint32_t value)
103 {
104    unsigned i, j;
105    unsigned width_size;
106    int blocksize = util_format_get_blocksize(format);
107    int blockwidth = util_format_get_blockwidth(format);
108    int blockheight = util_format_get_blockheight(format);
109
110    assert(blocksize > 0);
111    assert(blockwidth > 0);
112    assert(blockheight > 0);
113
114    dst_x /= blockwidth;
115    dst_y /= blockheight;
116    width = (width + blockwidth - 1)/blockwidth;
117    height = (height + blockheight - 1)/blockheight;
118    
119    dst += dst_x * blocksize;
120    dst += dst_y * dst_stride;
121    width_size = width * blocksize;
122    
123    switch (blocksize) {
124    case 1:
125       if(dst_stride == width_size)
126          memset(dst, (ubyte) value, height * width_size);
127       else {
128          for (i = 0; i < height; i++) {
129             memset(dst, (ubyte) value, width_size);
130             dst += dst_stride;
131          }
132       }
133       break;
134    case 2:
135       for (i = 0; i < height; i++) {
136          uint16_t *row = (uint16_t *)dst;
137          for (j = 0; j < width; j++)
138             *row++ = (uint16_t) value;
139          dst += dst_stride;
140       }
141       break;
142    case 4:
143       for (i = 0; i < height; i++) {
144          uint32_t *row = (uint32_t *)dst;
145          for (j = 0; j < width; j++)
146             *row++ = value;
147          dst += dst_stride;
148       }
149       break;
150    default:
151          assert(0);
152          break;
153    }
154 }
155
156
157
158 /**
159  * Fallback function for pipe->surface_copy().
160  * Note: (X,Y)=(0,0) is always the upper-left corner.
161  * if do_flip, flip the image vertically on its way from src rect to dst rect.
162  * XXX should probably put this in new u_surface.c file...
163  */
164 void
165 util_surface_copy(struct pipe_context *pipe,
166                   boolean do_flip,
167                   struct pipe_surface *dst,
168                   unsigned dst_x, unsigned dst_y,
169                   struct pipe_surface *src,
170                   unsigned src_x, unsigned src_y, 
171                   unsigned w, unsigned h)
172 {
173    struct pipe_transfer *src_trans, *dst_trans;
174    void *dst_map;
175    const void *src_map;
176    enum pipe_format src_format, dst_format;
177
178    assert(src->texture && dst->texture);
179    if (!src->texture || !dst->texture)
180       return;
181
182    src_format = src->texture->format;
183    dst_format = dst->texture->format;
184
185    src_trans = pipe_get_transfer(pipe,
186                                  src->texture,
187                                  src->face,
188                                  src->level,
189                                  src->zslice,
190                                  PIPE_TRANSFER_READ,
191                                  src_x, src_y, w, h);
192
193    dst_trans = pipe_get_transfer(pipe,
194                                  dst->texture,
195                                  dst->face,
196                                  dst->level,
197                                  dst->zslice,
198                                  PIPE_TRANSFER_WRITE,
199                                  dst_x, dst_y, w, h);
200
201    assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format));
202    assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format));
203    assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format));
204
205    src_map = pipe->transfer_map(pipe, src_trans);
206    dst_map = pipe->transfer_map(pipe, dst_trans);
207
208    assert(src_map);
209    assert(dst_map);
210
211    if (src_map && dst_map) {
212       /* If do_flip, invert src_y position and pass negative src stride */
213       util_copy_rect(dst_map,
214                      dst_format,
215                      dst_trans->stride,
216                      0, 0,
217                      w, h,
218                      src_map,
219                      do_flip ? -(int) src_trans->stride : src_trans->stride,
220                      0,
221                      do_flip ? h - 1 : 0);
222    }
223
224    pipe->transfer_unmap(pipe, src_trans);
225    pipe->transfer_unmap(pipe, dst_trans);
226
227    pipe->transfer_destroy(pipe, src_trans);
228    pipe->transfer_destroy(pipe, dst_trans);
229 }
230
231
232
233 #define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
234
235
236 /**
237  * Fallback for pipe->surface_fill() function.
238  * XXX should probably put this in new u_surface.c file...
239  */
240 void
241 util_surface_fill(struct pipe_context *pipe,
242                   struct pipe_surface *dst,
243                   unsigned dstx, unsigned dsty,
244                   unsigned width, unsigned height, unsigned value)
245 {
246    struct pipe_transfer *dst_trans;
247    void *dst_map;
248
249    assert(dst->texture);
250    if (!dst->texture)
251       return;
252    dst_trans = pipe_get_transfer(pipe,
253                                  dst->texture,
254                                  dst->face,
255                                  dst->level,
256                                  dst->zslice,
257                                  PIPE_TRANSFER_WRITE,
258                                  dstx, dsty, width, height);
259
260    dst_map = pipe->transfer_map(pipe, dst_trans);
261
262    assert(dst_map);
263
264    if (dst_map) {
265       assert(dst_trans->stride > 0);
266
267       switch (util_format_get_blocksize(dst->texture->format)) {
268       case 1:
269       case 2:
270       case 4:
271          util_fill_rect(dst_map, dst->texture->format,
272                         dst_trans->stride,
273                         0, 0, width, height, value);
274          break;
275       case 8:
276       {
277          /* expand the 4-byte clear value to an 8-byte value */
278          ushort *row = (ushort *) dst_map;
279          ushort val0 = UBYTE_TO_USHORT((value >>  0) & 0xff);
280          ushort val1 = UBYTE_TO_USHORT((value >>  8) & 0xff);
281          ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff);
282          ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff);
283          unsigned i, j;
284          val0 = (val0 << 8) | val0;
285          val1 = (val1 << 8) | val1;
286          val2 = (val2 << 8) | val2;
287          val3 = (val3 << 8) | val3;
288          for (i = 0; i < height; i++) {
289             for (j = 0; j < width; j++) {
290                row[j*4+0] = val0;
291                row[j*4+1] = val1;
292                row[j*4+2] = val2;
293                row[j*4+3] = val3;
294             }
295             row += dst_trans->stride/2;
296          }
297       }
298       break;
299       default:
300          assert(0);
301          break;
302       }
303    }
304
305    pipe->transfer_unmap(pipe, dst_trans);
306    pipe->transfer_destroy(pipe, dst_trans);
307 }