Skip to content

Commit 2264c04

Browse files
committed
Consolidate all compositing primitive ops
This creates a self-contained built-in renderer implementation. Extract 3 essential screen compositing functions (rgb16_source_argb32, argb32_over_argb32, argb32_source_argb32) to screen-ops.c, which is always compiled regardless of renderer choice. - Eliminate ~97.5% of unnecessary compositing code in PIXMAN mode - Improve naming consistency following draw-*.c pattern - Clear separation between renderer implementations
1 parent e30be04 commit 2264c04

File tree

5 files changed

+336
-225
lines changed

5 files changed

+336
-225
lines changed

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ libtwin.a_files-y = \
3131
src/button.c \
3232
src/fixed.c \
3333
src/label.c \
34-
src/primitive.c \
3534
src/trig.c \
3635
src/convolve.c \
3736
src/font.c \
@@ -72,6 +71,9 @@ libtwin.a_files-$(CONFIG_LOGGING) += src/log.c
7271
libtwin.a_files-$(CONFIG_CURSOR) += src/cursor.c
7372

7473
# Rendering backends
74+
# Screen compositing operations (always needed for screen buffer management)
75+
libtwin.a_files-y += src/screen-ops.c
76+
# Renderer implementations (draw-builtin.c includes all compositing operations)
7577
libtwin.a_files-$(CONFIG_RENDERER_BUILTIN) += src/draw-builtin.c
7678
libtwin.a_files-$(CONFIG_RENDERER_PIXMAN) += src/draw-pixman.c
7779
libtwin.a_cflags-$(CONFIG_RENDERER_PIXMAN) += $(shell pkg-config --cflags pixman-1)

scripts/gen-composite-decls.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ def generate_2operand_decls():
6262
return decls
6363

6464

65+
def generate_screen_ops_decls():
66+
"""
67+
Generate declarations for essential screen compositing functions
68+
These are implemented in screen-ops.c and always available
69+
"""
70+
return [
71+
"twin_op_func _twin_rgb16_source_argb32;",
72+
"twin_op_func _twin_argb32_over_argb32;",
73+
"twin_op_func _twin_argb32_source_argb32;",
74+
]
75+
76+
6577
def generate_vectorized_decls():
6678
"""
6779
Generate declarations for vectorized functions
@@ -78,7 +90,10 @@ def generate_header():
7890
return """/*
7991
* Compositing operation function declarations
8092
*
81-
* These functions are generated by macros in src/primitive.c
93+
* These functions are generated by macros in:
94+
* - src/draw-builtin.c (when CONFIG_RENDERER_BUILTIN=y)
95+
* - src/screen-ops.c (always available)
96+
*
8297
* This file is auto-generated by the build system - DO NOT EDIT
8398
*/
8499
@@ -105,13 +120,19 @@ def generate_footer():
105120
def main():
106121
print(generate_header())
107122

123+
print("\n/* Essential screen compositing (always available from screen-ops.c) */")
124+
for decl in generate_screen_ops_decls():
125+
print(decl)
126+
108127
print("\n/* 3-operand compositing: _twin_{src}_in_{msk}_{op}_{dst} */")
109128
print("/* Total: 2 ops * 3 dsts * 4 srcs * 4 msks = 96 functions */")
129+
print("/* Only available when CONFIG_RENDERER_BUILTIN=y */")
110130
for decl in generate_3operand_decls():
111131
print(decl)
112132

113133
print("\n/* 2-operand compositing: _twin_{src}_{op}_{dst} */")
114134
print("/* Total: 2 ops * 3 dsts * 4 srcs = 24 functions */")
135+
print("/* Only available when CONFIG_RENDERER_BUILTIN=y */")
115136
for decl in generate_2operand_decls():
116137
print(decl)
117138

src/draw-builtin.c

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,235 @@
1515

1616
#include "twin_private.h"
1717

18+
/* Compositing Primitive Operations
19+
*
20+
* The following section contains low-level pixel compositing operations
21+
* that implement Porter-Duff compositing algebra for various pixel formats.
22+
* These functions are generated via C preprocessor macros to create all
23+
* combinations of source/mask/destination format operations.
24+
*/
25+
26+
static inline twin_argb32_t in_over(twin_argb32_t dst,
27+
twin_argb32_t src,
28+
twin_a8_t msk)
29+
{
30+
uint16_t t1, t2, t3, t4;
31+
twin_a8_t a;
32+
33+
switch (msk) {
34+
case 0:
35+
return dst;
36+
case 0xff:
37+
break;
38+
default:
39+
src = (twin_in(src, 0, msk, t1) | twin_in(src, 8, msk, t2) |
40+
twin_in(src, 16, msk, t3) | twin_in(src, 24, msk, t4));
41+
break;
42+
}
43+
if (!src)
44+
return dst;
45+
a = ~(src >> 24);
46+
switch (a) {
47+
case 0:
48+
return src;
49+
case 0xff:
50+
dst = (twin_add(src, dst, 0, t1) | twin_add(src, dst, 8, t2) |
51+
twin_add(src, dst, 16, t3) | twin_add(src, dst, 24, t4));
52+
break;
53+
default:
54+
dst = (twin_over(src, dst, 0, a, t1) | twin_over(src, dst, 8, a, t2) |
55+
twin_over(src, dst, 16, a, t3) | twin_over(src, dst, 24, a, t4));
56+
break;
57+
}
58+
return dst;
59+
}
60+
61+
static inline twin_argb32_t in(twin_argb32_t src, twin_a8_t msk)
62+
{
63+
uint16_t t1, t2, t3, t4;
64+
65+
return (twin_in(src, 0, msk, t1) | twin_in(src, 8, msk, t2) |
66+
twin_in(src, 16, msk, t3) | twin_in(src, 24, msk, t4));
67+
}
68+
69+
static inline twin_argb32_t over(twin_argb32_t dst, twin_argb32_t src)
70+
{
71+
uint16_t t1, t2, t3, t4;
72+
twin_a8_t a;
73+
74+
if (!src)
75+
return dst;
76+
a = ~(src >> 24);
77+
switch (a) {
78+
case 0:
79+
return src;
80+
case 0xff:
81+
dst = (twin_add(src, dst, 0, t1) | twin_add(src, dst, 8, t2) |
82+
twin_add(src, dst, 16, t3) | twin_add(src, dst, 24, t4));
83+
break;
84+
default:
85+
dst = (twin_over(src, dst, 0, a, t1) | twin_over(src, dst, 8, a, t2) |
86+
twin_over(src, dst, 16, a, t3) | twin_over(src, dst, 24, a, t4));
87+
break;
88+
}
89+
return dst;
90+
}
91+
92+
static inline twin_argb32_t rgb16_to_argb32(twin_rgb16_t v)
93+
{
94+
return twin_rgb16_to_argb32(v);
95+
}
96+
97+
static inline twin_argb32_t a8_to_argb32(twin_a8_t v)
98+
{
99+
return v << 24;
100+
}
101+
102+
static inline twin_rgb16_t argb32_to_rgb16(twin_argb32_t v)
103+
{
104+
return twin_argb32_to_rgb16(v);
105+
}
106+
107+
static inline twin_a8_t argb32_to_a8(twin_argb32_t v)
108+
{
109+
return v >> 24;
110+
}
111+
112+
/* Naming convention
113+
*
114+
* _twin_<src>_in_<msk>_op_<dst>
115+
*
116+
* Use 'c' for constant
117+
*/
118+
119+
#define dst_argb32_get (*dst.argb32)
120+
#define dst_argb32_set (*dst.argb32++) =
121+
#define dst_rgb16_get (rgb16_to_argb32(*dst.rgb16))
122+
#define dst_rgb16_set (*dst.rgb16++) = argb32_to_rgb16
123+
#define dst_a8_get (a8_to_argb32(*dst.a8))
124+
#define dst_a8_set (*dst.a8++) = argb32_to_a8
125+
126+
#define src_c (src.c)
127+
#define src_argb32 (*src.p.argb32++)
128+
#define src_rgb16 (rgb16_to_argb32(*src.p.rgb16++))
129+
#define src_a8 (a8_to_argb32(*src.p.a8++))
130+
131+
#define msk_c (argb32_to_a8(msk.c))
132+
#define msk_argb32 (argb32_to_a8(*msk.p.argb32++))
133+
#define msk_rgb16 \
134+
(0xff); \
135+
(void) msk
136+
#define msk_a8 (*msk.p.a8++)
137+
138+
#define CAT2(a, b) a##b
139+
#define CAT3(a, b, c) a##b##c
140+
#define CAT4(a, b, c, d) a##b##c##d
141+
#define CAT6(a, b, c, d, e, f) a##b##c##d##e##f
142+
143+
#define _twin_in_op_name(src, op, msk, dst) \
144+
CAT6(_twin_, src, _in_, msk, op, dst)
145+
146+
#define _twin_op_name(src, op, dst) CAT4(_twin_, src, op, dst)
147+
148+
#define MAKE_TWIN_in_over(__dst, __src, __msk) \
149+
void _twin_in_op_name(__src, _over_, __msk, __dst)( \
150+
twin_pointer_t dst, twin_source_u src, twin_source_u msk, int width) \
151+
{ \
152+
twin_argb32_t dst32; \
153+
twin_argb32_t src32; \
154+
twin_a8_t msk8; \
155+
while (width--) { \
156+
dst32 = CAT3(dst_, __dst, _get); \
157+
src32 = CAT2(src_, __src); \
158+
msk8 = CAT2(msk_, __msk); \
159+
dst32 = in_over(dst32, src32, msk8); \
160+
CAT3(dst_, __dst, _set)(dst32); \
161+
} \
162+
}
163+
164+
#define MAKE_TWIN_in_source(__dst, __src, __msk) \
165+
void _twin_in_op_name(__src, _source_, __msk, __dst)( \
166+
twin_pointer_t dst, twin_source_u src, twin_source_u msk, int width) \
167+
{ \
168+
twin_argb32_t dst32; \
169+
twin_argb32_t src32; \
170+
twin_a8_t msk8; \
171+
while (width--) { \
172+
src32 = CAT2(src_, __src); \
173+
msk8 = CAT2(msk_, __msk); \
174+
dst32 = in(src32, msk8); \
175+
CAT3(dst_, __dst, _set)(dst32); \
176+
} \
177+
}
178+
179+
/* clang-format off */
180+
#define MAKE_TWIN_in_op_msks(op, dst, src) \
181+
CAT2(MAKE_TWIN_in_, op)(dst, src, argb32) \
182+
CAT2(MAKE_TWIN_in_, op)(dst, src, rgb16) \
183+
CAT2(MAKE_TWIN_in_, op)(dst, src, a8) \
184+
CAT2(MAKE_TWIN_in_, op)(dst, src, c)
185+
/* clang-format on */
186+
187+
#define MAKE_TWIN_in_op_srcs_msks(op, dst) \
188+
MAKE_TWIN_in_op_msks(op, dst, argb32) MAKE_TWIN_in_op_msks(op, dst, rgb16) \
189+
MAKE_TWIN_in_op_msks(op, dst, a8) MAKE_TWIN_in_op_msks(op, dst, c)
190+
191+
#define MAKE_TWIN_in_op_dsts_srcs_msks(op) \
192+
MAKE_TWIN_in_op_srcs_msks(op, argb32) MAKE_TWIN_in_op_srcs_msks(op, rgb16) \
193+
MAKE_TWIN_in_op_srcs_msks(op, a8)
194+
195+
MAKE_TWIN_in_op_dsts_srcs_msks(over) MAKE_TWIN_in_op_dsts_srcs_msks(source)
196+
197+
#define MAKE_TWIN_over(__dst, __src) \
198+
void _twin_op_name(__src, _over_, __dst)(twin_pointer_t dst, \
199+
twin_source_u src, int width) \
200+
{ \
201+
twin_argb32_t dst32; \
202+
twin_argb32_t src32; \
203+
while (width--) { \
204+
dst32 = CAT3(dst_, __dst, _get); \
205+
src32 = CAT2(src_, __src); \
206+
dst32 = over(dst32, src32); \
207+
CAT3(dst_, __dst, _set)(dst32); \
208+
} \
209+
}
210+
211+
#define MAKE_TWIN_source(__dst, __src) \
212+
void _twin_op_name(__src, _source_, __dst)(twin_pointer_t dst, \
213+
twin_source_u src, int width) \
214+
{ \
215+
twin_argb32_t dst32; \
216+
twin_argb32_t src32; \
217+
while (width--) { \
218+
src32 = CAT2(src_, __src); \
219+
dst32 = src32; \
220+
CAT3(dst_, __dst, _set)(dst32); \
221+
} \
222+
}
223+
224+
/* clang-format off */
225+
#define MAKE_TWIN_op_srcs(op, dst) \
226+
CAT2(MAKE_TWIN_, op)(dst, argb32) \
227+
CAT2(MAKE_TWIN_, op)(dst, rgb16) \
228+
CAT2(MAKE_TWIN_, op)(dst, a8) \
229+
CAT2(MAKE_TWIN_, op)(dst, c)
230+
231+
#define MAKE_TWIN_op_dsts_srcs(op) \
232+
MAKE_TWIN_op_srcs(op, argb32) \
233+
MAKE_TWIN_op_srcs(op, rgb16) \
234+
MAKE_TWIN_op_srcs(op, a8)
235+
236+
MAKE_TWIN_op_dsts_srcs(over);
237+
MAKE_TWIN_op_dsts_srcs(source);
238+
239+
/* clang-format on */
240+
241+
/* Built-in Renderer Implementation
242+
*
243+
* The following section implements the twin_composite() and twin_fill()
244+
* functions using the primitive operations defined above.
245+
*/
246+
18247
/* op, src, dst */
19248
static const twin_src_op comp2[2][4][3] = {
20249
[TWIN_OVER] =

0 commit comments

Comments
 (0)