Add blit color conversion, use GP_Coord and GP_Size in blits
[gfxprim.git] / pylib / gfxprim / generators / core / gen_blit.py
blob78be0f8978146e3de3c782d9cf88ce3df37695f4
1 # Module generating C source and headers for various PixelTypes
2 # - submodule for blit and friends
3 # 2011 - Tomas Gavenciak <gavento@ucw.cz>
5 from gfxprim.generators.utils import *
7 ## all generated direct blits, for generating GP_Blit() and others
8 generated_blits = []
10 # TODO: adapt for both bit-endianness (in-byte prefix and suffix)
11 # WARN: assuming little-endian in sub-byte pixels order (probably)
12 def gen_blit_same_t(size, size_suffix, header, code):
13 "Generate a function blitting the same type of pixel."
14 "Only depends on bpp (bit size), size_suffix must be"
15 "of form 8BPP, 2BPP_LE and the like."
17 header.rbody(
18 "\n/*** Blit preserving type, variant for {{ size_suffix }} ***\n"
19 " * Assumes the contexts to be of the right types and sizes\n"
20 " * Ignores transformations and clipping */\n\n"
21 "void GP_Blit_{{ size_suffix }}(const GP_Context *c1, GP_Coord x1, GP_Coord y1, GP_Size w, GP_Size h,\n"
22 " GP_Context *c2, GP_Coord x2, GP_Coord y2);\n",
23 size=size, size_suffix=size_suffix)
25 code.rbody(
26 "\n/*** Blit preservimg type, variant for {{ size_suffix }} ***/\n"
27 "void GP_Blit_{{ size_suffix }}(const GP_Context *c1, GP_Coord x1, GP_Coord y1, GP_Size w, GP_Size h,\n"
28 " GP_Context *c2, GP_Coord x2, GP_Coord y2)\n"
29 "{\n"
30 " if (unlikely(w == 0 || h == 0)) return;\n\n"
31 " /* Special case - copy whole line-block with one memcpy() */\n"
32 " if ((x1 == 0) && (x2 == 0) && (w == c1->w) && (c1->w == c2->w) &&\n"
33 " (c1->bytes_per_row == c2->bytes_per_row)) {\n"
34 " memcpy(c2->pixels + c2->bytes_per_row * y2,\n"
35 " c1->pixels + c1->bytes_per_row * y1,\n"
36 " c1->bytes_per_row * h);\n"
37 " return;\n"
38 " }\n\n"
39 "{% if size>=8 %}"
40 " /* General case - memcpy() each horizontal line */\n"
41 " for (GP_Size i = 0; i < h; i++)\n"
42 " memcpy(GP_PIXEL_ADDR_{{ size_suffix }}(c2, x2, y2 + i), \n"
43 " GP_PIXEL_ADDR_{{ size_suffix }}(c1, x2, y2 + i),\n"
44 " {{ size/8 }} * w);\n"
45 "{% else %}" # subtle - rectangles may not be byte aligned in the same way
46 " /* Alignment (index) of first bits in the first byte */\n"
47 " int al1 = GP_PIXEL_ADDR_OFFSET_{{ size_suffix }}(x1);\n"
48 " int al2 = GP_PIXEL_ADDR_OFFSET_{{ size_suffix }}(x2);\n"
49 " /* Special case of the same alignment and width >=2 bytes */\n"
50 " if ((al1 == al2) && (w * {{ size }} >= 16)) {\n"
51 " /* Number of bits in the last partial byte */\n"
52 " int end_al = GP_PIXEL_ADDR_OFFSET_{{ size_suffix }}(x1 + w);\n"
53 " GP_ASSERT(({{ size }} * w - al1 - end_al) % 8 == 0);\n"
54 " int copy_size = ({{ size }} * w - al1 - end_al) / 8;\n"
55 " /* First and last byte incident to the line */\n"
56 " uint8_t *p1 = GP_PIXEL_ADDR_{{ size_suffix }}(c1, x1, y1);\n"
57 " uint8_t *p2 = GP_PIXEL_ADDR_{{ size_suffix }}(c2, x2, y2);\n"
58 " uint8_t *end_p1 = GP_PIXEL_ADDR_{{ size_suffix }}(c1, x1 + w - 1, y1);\n"
59 " uint8_t *end_p2 = GP_PIXEL_ADDR_{{ size_suffix }}(c2, x2 + w - 1, y2);\n"
60 " for (GP_Size i = 0; i < h; i++) {\n"
61 " if (al1 != 0)\n"
62 " GP_SET_BITS(al1, 8-al1, *p2, GP_GET_BITS(al1, 8-al1, *p1));\n"
63 " memcpy(p2+(al1!=0), p1+(al1!=0), copy_size);\n"
64 " if (end_al != 0)\n"
65 " GP_SET_BITS(0, end_al, *end_p2, GP_GET_BITS(0, end_al, *end_p1));\n"
66 " p1 += c1->bytes_per_row;\n"
67 " end_p1 += c1->bytes_per_row;\n"
68 " p2 += c2->bytes_per_row;\n"
69 " end_p2 += c2->bytes_per_row;\n"
70 " }\n"
71 " } else /* Different bit-alignment, can't use memcpy() */\n"
72 " GP_Blit_Naive(c1, x1, y1, w, h, c2, x2, y2);\n"
73 "{% endif %}"
74 "}\n", size=size, size_suffix=size_suffix)