Skip to content

Commit 2615b1d

Browse files
committed
Utilize pixman for efficient pixel manipulation
According to issue #6, I replace original image compositing and trapezoid rasterization with Pixman function. Briefly, include: - pixman_image_composite: image compositing - pixman_fill_rect: use pixman_image_fill_rectangles to fill the image with retangles - pixman_image_fill_boxes: span is filled with the boxs Close #6
1 parent 9530bc5 commit 2615b1d

File tree

16 files changed

+325
-14
lines changed

16 files changed

+325
-14
lines changed

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ libtwin.a_includes-y := \
6262
libtwin.a_files-$(CONFIG_LOGGING) += src/log.c
6363
libtwin.a_files-$(CONFIG_CURSOR) += src/cursor.c
6464

65+
# Pixman
66+
ifeq ($(CONFIG_PIXMAN), y)
67+
libtwin.a_files-y += src/pixman.c
68+
libtwin.a_cflags-y += $(shell pkg-config --cflags pixman-1)
69+
TARGET_LIBS += $(shell pkg-config --libs pixman-1)
70+
endif
71+
6572
# Image loaders
6673

6774
ifeq ($(CONFIG_LOADER_JPEG), y)
@@ -118,6 +125,10 @@ endif
118125

119126
CFLAGS += -include config.h
120127

128+
ifeq ($(CONFIG_PIXMAN), y)
129+
CFLAGS += $(shell pkg-config --cflags pixman-1)
130+
endif
131+
121132
check_goal := $(strip $(MAKECMDGOALS))
122133
ifneq ($(check_goal), config)
123134
include mk/common.mk

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ benefiting the entire application stack.
6363
`Mado` is built with a minimalist design in mind. However, its verification
6464
relies on certain third-party packages for full functionality and access to all
6565
its features. To ensure proper operation, the development environment should
66-
have the [SDL2 library](https://www.libsdl.org/), [libjpeg](https://www.ijg.org/), and [libpng](https://github.com/pnggroup/libpng) installed.
66+
have the [SDL2 library](https://www.libsdl.org/), [libjpeg](https://www.ijg.org/), [libpng](https://github.com/pnggroup/libpng), and [libpixman-1](https://pixman.org/) installed.
6767
* macOS: `brew install sdl2 jpeg libpng`
68-
* Ubuntu Linux / Debian: `sudo apt install libsdl2-dev libjpeg-dev libpng-dev`
68+
* Ubuntu Linux / Debian: `sudo apt install libsdl2-dev libjpeg-dev libpng-dev libpixman-1-dev`
6969

7070
Configure via [Kconfiglib](https://pypi.org/project/kconfiglib/)
7171
```shell

apps/animation.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,27 @@ static void _apps_animation_paint(apps_animation_t *anim)
2929
} else {
3030
current_frame = anim->pix;
3131
}
32+
#if defined(CONFIG_PIXMAN)
33+
pixman_image_t *src = create_pixman_image_from_twin_pixmap(current_frame);
3234

35+
pixman_image_t *dst =
36+
create_pixman_image_from_twin_pixmap(_apps_animation_pixmap(anim));
37+
38+
twin_coord_t ox, oy;
39+
twin_pixmap_get_origin(_apps_animation_pixmap(anim), &ox, &oy);
40+
pixman_image_composite(PIXMAN_OP_SRC, src, NULL, dst, 0, 0, 0, 0, ox, oy,
41+
current_frame->width, current_frame->height);
42+
43+
pixman_image_unref(src);
44+
pixman_image_unref(dst);
45+
#else
3346
twin_operand_t srcop = {
3447
.source_kind = TWIN_PIXMAP,
3548
.u.pixmap = current_frame,
3649
};
3750
twin_composite(_apps_animation_pixmap(anim), 0, 0, &srcop, 0, 0, NULL, 0, 0,
3851
TWIN_SOURCE, current_frame->width, current_frame->height);
52+
#endif
3953
}
4054

4155
static twin_time_t _apps_animation_timeout(twin_time_t maybe_unused now,

apps/main.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,34 @@ static twin_pixmap_t *load_background(twin_screen_t *screen, const char *path)
4747
twin_pixmap_destroy(raw_background);
4848
return twin_make_pattern();
4949
}
50+
#if defined(CONFIG_PIXMAN)
51+
pixman_image_t *srcop_pix =
52+
create_pixman_image_from_twin_pixmap(raw_background);
53+
54+
pixman_transform_t transform;
55+
pixman_transform_init_identity(&transform);
56+
57+
pixman_fixed_t sx, sy;
58+
sx = twin_fixed_div(twin_int_to_fixed(raw_background->width),
59+
twin_int_to_fixed(screen->width));
60+
sy = twin_fixed_div(twin_int_to_fixed(raw_background->height),
61+
twin_int_to_fixed(screen->height));
62+
63+
pixman_transform_scale(&transform, NULL, sx, sy);
64+
pixman_image_set_transform(srcop_pix, &transform);
65+
66+
pixman_image_t *scaled_background_pix =
67+
create_pixman_image_from_twin_pixmap(scaled_background);
68+
69+
twin_coord_t ox, oy;
70+
twin_pixmap_get_origin(scaled_background, &ox, &oy);
71+
pixman_image_composite(PIXMAN_OP_SRC, srcop_pix, NULL,
72+
scaled_background_pix, 0, 0, 0, 0, ox, oy,
73+
screen->width, screen->height);
74+
75+
pixman_image_unref(srcop_pix);
76+
pixman_image_unref(scaled_background_pix);
77+
#else
5078
twin_fixed_t sx, sy;
5179
sx = twin_fixed_div(twin_int_to_fixed(raw_background->width),
5280
twin_int_to_fixed(screen->width));
@@ -60,7 +88,7 @@ static twin_pixmap_t *load_background(twin_screen_t *screen, const char *path)
6088
};
6189
twin_composite(scaled_background, 0, 0, &srcop, 0, 0, NULL, 0, 0,
6290
TWIN_SOURCE, screen->width, screen->height);
63-
91+
#endif
6492
twin_pixmap_destroy(raw_background);
6593

6694
return scaled_background;

apps/multi.c

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ static void apps_line_start(twin_screen_t *screen, int x, int y, int w, int h)
1717
twin_fixed_t fy;
1818

1919
twin_path_translate(stroke, D(200), D(200));
20+
#if defined(CONFIG_PIXMAN)
21+
pixman_fill_rect(pixmap, &(pixman_color_t){0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF},
22+
pixmap->clip.left, pixmap->clip.top, w, h);
23+
#else
2024
twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, w, h);
25+
#endif
2126

2227
twin_window_set_name(window, "line");
2328

@@ -41,21 +46,30 @@ static void apps_circletext_start(twin_screen_t *screen,
4146
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
4247
int wid = window->client.right - window->client.left;
4348
int hei = window->client.bottom - window->client.top;
44-
twin_pixmap_t *pixmap = window->pixmap;
4549
twin_path_t *path = twin_path_create();
4650
twin_path_t *pen = twin_path_create();
51+
52+
#if defined(CONFIG_PIXMAN)
4753
twin_pixmap_t *alpha = twin_pixmap_create(TWIN_A8, wid, hei);
48-
int s;
49-
twin_operand_t source, mask;
5054

55+
twin_rect_t win_clip = twin_pixmap_get_clip(window->pixmap);
56+
pixman_fill_rect(window->pixmap,
57+
&(pixman_color_t){0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF},
58+
win_clip.left, win_clip.top, wid, hei);
59+
#else
60+
twin_pixmap_t *alpha = twin_pixmap_create(TWIN_A8, wid, hei);
61+
twin_pixmap_t *pixmap = window->pixmap;
5162
twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, wid, hei);
63+
#endif
64+
5265
twin_window_set_name(window, "circletext");
5366

5467
twin_path_set_font_style(path, TWIN_TEXT_UNHINTED);
5568
twin_path_circle(pen, 0, 0, D(1));
5669

5770
twin_path_translate(path, D(200), D(200));
5871
twin_path_set_font_size(path, D(15));
72+
int s;
5973
for (s = 0; s < 41; s++) {
6074
twin_state_t state = twin_path_save(path);
6175
twin_path_rotate(path, twin_degrees_to_angle(9 * s));
@@ -66,12 +80,31 @@ static void apps_circletext_start(twin_screen_t *screen,
6680
twin_fill_path(alpha, path, 0, 0);
6781
twin_path_destroy(path);
6882
twin_path_destroy(pen);
83+
84+
#if defined(CONFIG_PIXMAN)
85+
pixman_image_t *mask = create_pixman_image_from_twin_pixmap(alpha);
86+
pixman_image_t *source = pixman_image_create_solid_fill(
87+
&(pixman_color_t){0x0000, 0x0000, 0x0000, 0xFFFF});
88+
pixman_image_t *dst = create_pixman_image_from_twin_pixmap(window->pixmap);
89+
90+
twin_coord_t ox, oy;
91+
twin_pixmap_get_origin(window->pixmap, &ox, &oy);
92+
pixman_image_composite(PIXMAN_OP_OVER, source, mask, dst, 0, 0, 0, 0, ox,
93+
oy, wid, hei);
94+
95+
pixman_image_unref(source);
96+
pixman_image_unref(mask);
97+
pixman_image_unref(dst);
98+
#else
99+
twin_operand_t source, mask;
69100
source.source_kind = TWIN_SOLID;
70101
source.u.argb = 0xff000000;
71102
mask.source_kind = TWIN_PIXMAP;
72103
mask.u.pixmap = alpha;
73104
twin_composite(pixmap, 0, 0, &source, 0, 0, &mask, 0, 0, TWIN_OVER, wid,
74105
hei);
106+
#endif
107+
75108
twin_pixmap_destroy(alpha);
76109
twin_window_show(window);
77110
}
@@ -90,13 +123,16 @@ static void apps_quickbrown_start(twin_screen_t *screen,
90123
twin_path_t *path = twin_path_create();
91124
twin_path_t *pen = twin_path_create();
92125
twin_pixmap_t *alpha = twin_pixmap_create(TWIN_A8, wid, hei);
93-
twin_operand_t source, mask;
94126
twin_fixed_t fx, fy;
95127
int s;
96128

97129
twin_window_set_name(window, "Quick Brown");
98-
130+
#if defined(CONFIG_PIXMAN)
131+
pixman_fill_rect(pixmap, &(pixman_color_t){0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF},
132+
pixmap->clip.left, pixmap->clip.top, w, h);
133+
#else
99134
twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, wid, hei);
135+
#endif
100136

101137
twin_path_circle(pen, 0, 0, D(1));
102138

@@ -113,12 +149,29 @@ static void apps_quickbrown_start(twin_screen_t *screen,
113149
twin_fill_path(alpha, path, 0, 0);
114150
twin_path_destroy(path);
115151
twin_path_destroy(pen);
152+
#if defined(CONFIG_PIXMAN)
153+
pixman_image_t *mask = create_pixman_image_from_twin_pixmap(alpha);
154+
pixman_image_t *src = pixman_image_create_solid_fill(
155+
&(pixman_color_t){0x0000, 0x0000, 0x0000, 0xFFFF});
156+
pixman_image_t *dst = create_pixman_image_from_twin_pixmap(pixmap);
157+
158+
twin_coord_t ox, oy;
159+
twin_pixmap_get_origin(pixmap, &ox, &oy);
160+
pixman_image_composite(PIXMAN_OP_OVER, src, mask, dst, 0, 0, 0, 0, ox, oy,
161+
wid, hei);
162+
163+
pixman_image_unref(src);
164+
pixman_image_unref(mask);
165+
pixman_image_unref(dst);
166+
#else
167+
twin_operand_t source, mask;
116168
source.source_kind = TWIN_SOLID;
117169
source.u.argb = 0xff000000;
118170
mask.source_kind = TWIN_PIXMAP;
119171
mask.u.pixmap = alpha;
120172
twin_composite(pixmap, 0, 0, &source, 0, 0, &mask, 0, 0, TWIN_OVER, wid,
121173
hei);
174+
#endif
122175
twin_pixmap_destroy(alpha);
123176
twin_window_show(window);
124177
}
@@ -133,13 +186,17 @@ static void apps_ascii_start(twin_screen_t *screen, int x, int y, int w, int h)
133186
twin_path_t *path = twin_path_create();
134187
twin_path_t *pen = twin_path_create();
135188
twin_pixmap_t *alpha = twin_pixmap_create(TWIN_A8, wid, hei);
136-
twin_operand_t source, mask;
137189
twin_fixed_t fx, fy;
138190
int s;
139191

140192
twin_window_set_name(window, "ASCII");
141193

194+
#if defined(CONFIG_PIXMAN)
195+
pixman_fill_rect(pixmap, &(pixman_color_t){0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF},
196+
pixmap->clip.left, pixmap->clip.top, w, h);
197+
#else
142198
twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, wid, hei);
199+
#endif
143200
twin_path_circle(pen, 0, 0, D(1));
144201

145202
fx = D(3);
@@ -161,12 +218,29 @@ static void apps_ascii_start(twin_screen_t *screen, int x, int y, int w, int h)
161218
twin_fill_path(alpha, path, 0, 0);
162219
twin_path_destroy(path);
163220
twin_path_destroy(pen);
221+
#if defined(CONFIG_PIXMAN)
222+
pixman_image_t *mask = create_pixman_image_from_twin_pixmap(alpha);
223+
pixman_image_t *src = pixman_image_create_solid_fill(
224+
&(pixman_color_t){0x0000, 0x0000, 0x0000, 0xFFFF});
225+
pixman_image_t *dst = create_pixman_image_from_twin_pixmap(pixmap);
226+
227+
twin_coord_t ox, oy;
228+
twin_pixmap_get_origin(pixmap, &ox, &oy);
229+
pixman_image_composite(PIXMAN_OP_OVER, src, mask, dst, 0, 0, 0, 0, ox, oy,
230+
wid, hei);
231+
232+
pixman_image_unref(src);
233+
pixman_image_unref(mask);
234+
pixman_image_unref(dst);
235+
#else
236+
twin_operand_t source, mask;
164237
source.source_kind = TWIN_SOLID;
165238
source.u.argb = 0xff000000;
166239
mask.source_kind = TWIN_PIXMAP;
167240
mask.u.pixmap = alpha;
168241
twin_composite(pixmap, 0, 0, &source, 0, 0, &mask, 0, 0, TWIN_OVER, wid,
169242
hei);
243+
#endif
170244
twin_pixmap_destroy(alpha);
171245
twin_window_show(window);
172246
}
@@ -184,7 +258,12 @@ static void apps_jelly_start(twin_screen_t *screen, int x, int y, int w, int h)
184258

185259
twin_window_set_name(window, "Jelly");
186260

261+
#if defined(CONFIG_PIXMAN)
262+
pixman_fill_rect(pixmap, &(pixman_color_t){0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF},
263+
pixmap->clip.left, pixmap->clip.top, wid, hei);
264+
#else
187265
twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, wid, hei);
266+
#endif
188267

189268
fx = D(3);
190269
fy = D(8);

configs/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ config CURSOR
3939
bool "Manipulate cursor"
4040
default n
4141

42+
config PIXMAN
43+
bool "Pixman to pixel manipulation"
44+
default y
45+
4246
endmenu
4347

4448
menu "Image Loaders"

configs/defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
CONFIG_BACKEND_SDL=y
2+
CONFIG_PIXMAN=y
23
CONFIG_LOADER_PNG=y
34
CONFIG_LOADER_JPEG=y
45
CONFIG_LOADER_GIF=y

include/twin.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#include <stdbool.h>
1111
#include <stdint.h>
1212

13+
#if defined(CONFIG_PIXMAN)
14+
#include <pixman.h>
15+
#endif
16+
1317
typedef uint8_t twin_a8_t;
1418
typedef uint16_t twin_a16_t;
1519
typedef uint16_t twin_rgb16_t;
@@ -984,6 +988,33 @@ bool twin_pixmap_transparent(twin_pixmap_t *pixmap,
984988

985989
bool twin_pixmap_dispatch(twin_pixmap_t *pixmap, twin_event_t *event);
986990

991+
/*
992+
* pixman.c
993+
*/
994+
995+
#if defined(CONFIG_PIXMAN)
996+
void twin_argb32_to_pixman_color(twin_argb32_t argb, pixman_color_t *color);
997+
998+
pixman_format_code_t twin_to_pixman_format(twin_format_t twin_format);
999+
1000+
pixman_op_t twin_to_pixman_op(twin_operator_t twin_op);
1001+
1002+
void pixman_fill_rect(twin_pixmap_t *pixmap,
1003+
const pixman_color_t *color,
1004+
int origin_x,
1005+
int origin_y,
1006+
int width,
1007+
int height);
1008+
1009+
#define create_pixman_image_from_twin_pixmap(pixmap) \
1010+
({ \
1011+
typeof(pixmap) _pixmap = (pixmap); \
1012+
pixman_image_create_bits(twin_to_pixman_format((_pixmap)->format), \
1013+
(_pixmap)->width, (_pixmap)->height, \
1014+
(_pixmap)->p.argb32, (_pixmap)->stride); \
1015+
})
1016+
#endif
1017+
9871018
/*
9881019
* poly.c
9891020
*/

include/twin_private.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ typedef int8_t twin_gfixed_t;
8888
#define twin_sfixed_mod(f) ((f) & 0xf)
8989

9090
#define twin_int_to_sfixed(i) ((twin_sfixed_t) ((i) * 16))
91+
#define twin_sfixed_to_int(i) ((int32_t) ((i) >> 4))
9192

9293
#define twin_sfixed_to_fixed(s) (((twin_fixed_t) (s)) << 12)
9394
#define twin_fixed_to_sfixed(f) ((twin_sfixed_t) ((f) >> 12))
@@ -168,6 +169,22 @@ typedef int8_t twin_gfixed_t;
168169
((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
169170
((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)) | 0xff000000)
170171

172+
#define min(x, y) \
173+
({ \
174+
typeof(x) _x = (x); \
175+
typeof(y) _y = (y); \
176+
(void) (&_x == &_y); \
177+
_x < _y ? _x : _y; \
178+
})
179+
180+
#define max(x, y) \
181+
({ \
182+
typeof(x) _x = (x); \
183+
typeof(y) _y = (y); \
184+
(void) (&_x == &_y); \
185+
_x > _y ? _x : _y; \
186+
})
187+
171188
typedef union {
172189
twin_pointer_t p;
173190
twin_argb32_t c;

0 commit comments

Comments
 (0)