Rename GP_Context -> GP_Pixmap
[gfxprim.git] / libs / core / GP_Blit.gen.c.t
blobc53a7c072ec34638d8443a49b7c4f2510b5847c6
1 @ include source.t
2 /*
3  * Specialized blit functions and macros.
4  *
5  * Copyright (C) 2011      Tomas Gavenciak <gavento@ucw.cz>
6  * Copyright (C) 2011-2014 Cyril Hrubis <metan@ucw.cz>
7  */
9 #include <string.h>
11 #include "core/GP_Pixel.h"
12 #include "core/GP_GetPutPixel.h"
13 #include "core/GP_Pixmap.h"
14 #include "core/GP_Blit.h"
15 #include "core/GP_Debug.h"
16 #include "core/GP_Convert.h"
17 #include "core/GP_Convert.gen.h"
18 #include "core/GP_Convert_Scale.gen.h"
19 #include "core/GP_MixPixels2.gen.h"
22  * TODO: this is used for same pixel but different offset, could still be optimized
23  */
24 static void blitXYXY_Naive_Raw(const GP_Pixmap *src,
25                         GP_Coord x0, GP_Coord y0, GP_Coord x1, GP_Coord y1,
26                         GP_Pixmap *dst, GP_Coord x2, GP_Coord y2)
28         GP_Coord x, y;
30         for (y = y0; y <= y1; y++) {
31                 for (x = x0; x <= x1; x++) {
32                         GP_Pixel p = GP_GetPixel_Raw(src, x, y);
34                         if (src->pixel_type != dst->pixel_type)
35                                 p = GP_ConvertPixmapPixel(p, src, dst);
37                         GP_PutPixel_Raw(dst, x2 + (x - x0), y2 + (y - y0), p);
38                 }
40         }
43 @ for ps in pixelsizes:
45  * Blit for equal pixel types {{ ps.suffix }}
46  */
47 static void blitXYXY_Raw_{{ ps.suffix }}(const GP_Pixmap *src,
48         GP_Coord x0, GP_Coord y0, GP_Coord x1, GP_Coord y1,
49         GP_Pixmap *dst, GP_Coord x2, GP_Coord y2)
51 @     if not ps.needs_bit_endian():
52         /* memcpy() each horizontal line */
53         GP_Coord y;
55         for (y = 0; y <= (y1 - y0); y++)
56                 memcpy(GP_PIXEL_ADDR_{{ ps.suffix }}(dst, x2, y2 + y),
57                        GP_PIXEL_ADDR_{{ ps.suffix }}(src, x0, y0 + y),
58                        {{ int(ps.size/8) }} * (x1 - x0 + 1));
59 @     else:
60 # if 0
61         /* Rectangles may not be bit-aligned in the same way! */
62         /* Alignment (index) of first bits in the first byte */
63         //TODO: This is wrong for subpixmaps where the offset
64         //      needs to be summed with pixmap->offset and moduled
65         int al1 = GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x0);
66         int al2 = GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x2);
67         /* Special case of the same alignment and width >=2 bytes */
68         if ((al1 == al2) && ((x1 - x0 + 1) * {{ ps.size }} >= 16)) {
69                 /* Number of bits in the last partial byte */
70                 int end_al = GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x1);
71                 GP_ASSERT(({{ ps.size }} * (x1 - x0 + 1) - al1 - end_al) % 8 == 0);
72                 int copy_size = ({{ ps.size }} * (x1 - x0 + 1) - al1 - end_al) / 8;
73                 /* First and last byte incident to the line */
74                 uint8_t *p1 = (uint8_t *) GP_PIXEL_ADDR_{{ ps.suffix }}(src, x1, y1);
75                 uint8_t *p2 = (uint8_t *) GP_PIXEL_ADDR_{{ ps.suffix }}(dst, x2, y2);
76                 uint8_t *end_p1 = (uint8_t *) GP_PIXEL_ADDR_{{ ps.suffix }}(src, x1, y0);
77                 uint8_t *end_p2 = (uint8_t *) GP_PIXEL_ADDR_{{ ps.suffix }}(dst, x2, y2);
79                 GP_Coord i;
81                 for (i = 0; i < (y1 - y0 + 1); i++) {
82                         if (al1 != 0)
83                                 GP_SET_BITS(al1, 8-al1, *p2, GP_GET_BITS(al1, 8-al1, *p1));
84                         memcpy(p2+(al1!=0), p1+(al1!=0), copy_size);
85                         if (end_al != 0)
86                                 GP_SET_BITS(0, end_al, *end_p2, GP_GET_BITS(0, end_al, *end_p1));
87                         p1 += src->bytes_per_row;
88                         end_p1 += src->bytes_per_row;
89                         p2 += dst->bytes_per_row;
90                         end_p2 += dst->bytes_per_row;
91                 }
92         } else /* Different bit-alignment, can't use memcpy() */
93 #endif
94                 blitXYXY_Naive_Raw(src, x0, y0, x1, y1, dst, x2, y2);
95 @     end
98 @ end
100  * Generate Blits, I know this is n^2 variants but the gain is in speed is
101  * more than 50% and the size footprint for two for cycles is really small.
102  */
103 @ for src in pixeltypes:
104 @     if not src.is_unknown() and not src.is_palette():
105 @         for dst in pixeltypes:
106 @             if not dst.is_unknown() and not dst.is_palette():
107 @                 if dst.name != src.name:
109  * Blits {{ src.name }} to {{ dst.name }}
110  */
111 static void blitXYXY_Raw_{{ src.name }}_{{ dst.name }}(const GP_Pixmap *src,
112         GP_Coord x0, GP_Coord y0, GP_Coord x1, GP_Coord y1,
113         GP_Pixmap *dst, GP_Coord x2, GP_Coord y2)
115         GP_Coord x, y, dx, dy;
117         for (y = y0; y <= y1; y++) {
118                 for (x = x0; x <= x1; x++) {
119                         dx = x2 + (x - x0);
120                         dy = y2 + (y - y0);
122                         GP_Pixel p1, p2 = 0, p3 = 0;
124                         p1 = GP_GetPixel_Raw_{{ src.pixelsize.suffix }}(src, x, y);
125 @                     if src.is_alpha():
126                         p2 = GP_GetPixel_Raw_{{ dst.pixelsize.suffix }}(dst, dx, dy);
127                         p3 = GP_MixPixels_{{ src.name }}_{{ dst.name }}(p1, p2);
128 @                     else:
129                         GP_Pixel_{{ src.name }}_TO_RGB888(p1, p2);
130                         GP_Pixel_RGB888_TO_{{ dst.name }}(p2, p3);
131 @                     end
132                         GP_PutPixel_Raw_{{ dst.pixelsize.suffix }}(dst, dx, dy, p3);
133                 }
134         }
137 @ end
139 void GP_BlitXYXY_Raw_Fast(const GP_Pixmap *src,
140                           GP_Coord x0, GP_Coord y0, GP_Coord x1, GP_Coord y1,
141                           GP_Pixmap *dst, GP_Coord x2, GP_Coord y2)
143         /* Same pixel type, could be (mostly) optimized to memcpy() */
144         if (src->pixel_type == dst->pixel_type) {
145                 GP_FN_PER_BPP(blitXYXY_Raw, src->bpp, src->bit_endian,
146                               src, x0, y0, x1, y1, dst, x2, y2);
147                 return;
148         }
150         /* Specialized functions */
151         switch (src->pixel_type) {
152 @ for src in pixeltypes:
153 @     if not src.is_unknown() and not src.is_palette():
154         case GP_PIXEL_{{ src.name }}:
155                 switch (dst->pixel_type) {
156 @         for dst in pixeltypes:
157 @             if not dst.is_unknown() and not dst.is_palette():
158 @                 if dst.name != src.name:
159                 case GP_PIXEL_{{ dst.name }}:
160                         blitXYXY_Raw_{{ src.name }}_{{ dst.name }}(src, x0, y0, x1, y1, dst, x2, y2);
161                 break;
162 @         end
163                 default:
164                         GP_ABORT("Invalid destination pixel %s",
165                                  GP_PixelTypeName(dst->pixel_type));
166                 }
167         break;
168 @ end
169         default:
170                 GP_ABORT("Invalid source pixel %s",
171                          GP_PixelTypeName(src->pixel_type));
172         }
176  * And the same for non-raw variants.
177  */
178 @ for src in pixeltypes:
179 @     if not src.is_unknown() and not src.is_palette():
180 @         for dst in pixeltypes:
181 @             if not dst.is_unknown() and not dst.is_palette():
182 @                 if dst.name != src.name:
184  * Blits {{ src.name }} to {{ dst.name }}
185  */
186 static void blitXYXY_{{ src.name }}_{{ dst.name }}(const GP_Pixmap *src,
187         GP_Coord x0, GP_Coord y0, GP_Coord x1, GP_Coord y1,
188         GP_Pixmap *dst, GP_Coord x2, GP_Coord y2)
190         GP_Coord x, y, xt, yt;
192         for (y = y0; y <= y1; y++)
193                 for (x = x0; x <= x1; x++) {
194                         GP_Pixel p1, p2 = 0;
195                         xt = x; yt = y;
196                         GP_TRANSFORM_POINT(src, xt, yt);
197                         p1 = GP_GetPixel_Raw_{{ src.pixelsize.suffix }}(src, xt, yt);
198                         GP_Pixel_{{ src.name }}_TO_RGB888(p1, p2);
199                         GP_Pixel_RGB888_TO_{{ dst.name }}(p2, p1);
200                         xt = x2 + (x - x0);
201                         yt = y2 + (y - y0);
202                         GP_TRANSFORM_POINT(dst, xt, yt);
203                         GP_PutPixel_Raw_{{ dst.pixelsize.suffix }}(dst, xt, yt, p1);
204                 }
207 @ end
210  * Same pixel type but with rotation.
211  */
212 @ for ps in pixelsizes:
214  * Blits for same pixel type and bpp {{ ps.suffix }}
215  */
216 static void blitXYXY_{{ ps.suffix }}(const GP_Pixmap *src,
217         GP_Coord x0, GP_Coord y0, GP_Coord x1, GP_Coord y1,
218         GP_Pixmap *dst, GP_Coord x2, GP_Coord y2)
220         GP_Coord x, y, xt, yt;
222         for (y = y0; y <= y1; y++)
223                 for (x = x0; x <= x1; x++) {
224                         GP_Pixel p;
225                         xt = x; yt = y;
226                         GP_TRANSFORM_POINT(src, xt, yt);
227                         p = GP_GetPixel_Raw_{{ ps.suffix }}(src, xt, yt);
228                         xt = x2 + (x - x0);
229                         yt = y2 + (y - y0);
230                         GP_TRANSFORM_POINT(dst, xt, yt);
231                         GP_PutPixel_Raw_{{ ps.suffix }}(dst, xt, yt, p);
232                 }
234 @ end
236 void GP_BlitXYXY_Fast(const GP_Pixmap *src,
237                       GP_Coord x0, GP_Coord y0, GP_Coord x1, GP_Coord y1,
238                       GP_Pixmap *dst, GP_Coord x2, GP_Coord y2)
240         GP_DEBUG(2, "Blitting %s -> %s",
241                  GP_PixelTypeName(src->pixel_type),
242                  GP_PixelTypeName(dst->pixel_type));
244         /* Same pixel type */
245         if (src->pixel_type == dst->pixel_type) {
246                 GP_FN_PER_BPP(blitXYXY, src->bpp, src->bit_endian,
247                               src, x0, y0, x1, y1, dst, x2, y2);
248                 return;
249         }
251         if (GP_PixmapRotationEqual(src, dst)) {
252                 GP_BlitXYXY_Raw_Fast(src, x0, y0, x1, y1, dst, x2, y2);
253                 return;
254         }
256         /* Specialized functions */
257         switch (src->pixel_type) {
258 @ for src in pixeltypes:
259 @     if not src.is_unknown() and not src.is_palette():
260         case GP_PIXEL_{{ src.name }}:
261                 switch (dst->pixel_type) {
262 @         for dst in pixeltypes:
263 @             if not dst.is_unknown() and not dst.is_palette():
264 @                 if dst.name != src.name:
265                 case GP_PIXEL_{{ dst.name }}:
266                         blitXYXY_{{ src.name }}_{{ dst.name }}(src, x0, y0, x1, y1, dst, x2, y2);
267                 break;
268 @         end
269                 default:
270                         GP_ABORT("Invalid destination pixel %s",
271                                  GP_PixelTypeName(dst->pixel_type));
272                 }
273         break;
274 @ end
275         default:
276                 GP_ABORT("Invalid source pixel %s",
277                          GP_PixelTypeName(src->pixel_type));
278         }