commit 554f827
shrub
·
2026-08-13 13:33:03 +0000 UTC
parent 83d1a75
implement blend
5 files changed,
+127,
-6
M
dumb.c
+54,
-5
1@@ -31,6 +31,7 @@
2 #include <xf86drm.h>
3
4 #include <errno.h>
5+#include <string.h>
6
7 struct dumb_context {
8 struct wld_context base;
9@@ -42,8 +43,11 @@ struct dumb_buffer {
10 struct wld_exporter exporter;
11 struct dumb_context *context;
12 uint32_t handle;
13+ void *scanout;
14+ bool shadowed;
15 };
16
17+#define BUFFER_IMPLEMENTS_FLUSH
18 #include "interface/buffer.h"
19 #include "interface/context.h"
20 #define DRM_DRIVER_NAME dumb
21@@ -105,7 +109,7 @@ static struct buffer *
22 new_buffer(struct dumb_context *context,
23 uint32_t width, uint32_t height,
24 uint32_t format, uint32_t handle,
25- unsigned long pitch)
26+ unsigned long pitch, bool shadowed)
27 {
28 struct dumb_buffer *buffer;
29
30@@ -116,6 +120,8 @@ new_buffer(struct dumb_context *context,
31 width, height, format, pitch);
32 buffer->context = context;
33 buffer->handle = handle;
34+ buffer->scanout = NULL;
35+ buffer->shadowed = shadowed;
36 buffer->exporter.export = &export;
37 wld_buffer_add_exporter(&buffer->base.base, &buffer->exporter);
38
39@@ -139,7 +145,8 @@ context_create_buffer(struct wld_context *base,
40 goto error0;
41
42 buffer = new_buffer(context, width, height, format,
43- create_dumb.handle, create_dumb.pitch);
44+ create_dumb.handle, create_dumb.pitch,
45+ flags & WLD_DRM_FLAG_SCANOUT);
46
47 if (!buffer)
48 goto error1;
49@@ -175,7 +182,7 @@ context_import_buffer(struct wld_context *base,
50 return NULL;
51 }
52
53- return new_buffer(context, width, height, format, handle, pitch);
54+ return new_buffer(context, width, height, format, handle, pitch, false);
55 }
56
57 void
58@@ -209,20 +216,62 @@ buffer_map(struct buffer *base)
59 if (data == MAP_FAILED)
60 return false;
61
62- buffer->base.base.map = data;
63+ buffer->scanout = data;
64+ if (buffer->shadowed) {
65+ buffer->base.base.map = calloc(buffer->base.base.height,
66+ buffer->base.base.pitch);
67+ if (!buffer->base.base.map) {
68+ munmap(data, buffer->base.base.pitch * buffer->base.base.height);
69+ buffer->scanout = NULL;
70+ return false;
71+ }
72+ } else {
73+ buffer->base.base.map = data;
74+ }
75
76 return true;
77 }
78
79+void
80+buffer_flush(struct buffer *base)
81+{
82+ struct dumb_buffer *buffer = dumb_buffer(&base->base);
83+ pixman_box32_t *boxes;
84+ int count;
85+
86+ if (!buffer->shadowed || !buffer->scanout)
87+ return;
88+
89+ boxes = pixman_region32_rectangles(&base->base.damage, &count);
90+ while (count--) {
91+ int32_t y;
92+ size_t offset = (size_t)boxes->y1 * base->base.pitch +
93+ (size_t)boxes->x1 * 4;
94+ size_t size = (size_t)(boxes->x2 - boxes->x1) * 4;
95+
96+ for (y = boxes->y1; y < boxes->y2; ++y) {
97+ memcpy((uint8_t *)buffer->scanout + offset,
98+ (uint8_t *)base->base.map + offset, size);
99+ offset += base->base.pitch;
100+ }
101+ ++boxes;
102+ }
103+}
104+
105 bool
106 buffer_unmap(struct buffer *buffer)
107 {
108- if (munmap(buffer->base.map,
109+ struct dumb_buffer *dumb = dumb_buffer(&buffer->base);
110+
111+ if (munmap(dumb->scanout,
112 buffer->base.pitch * buffer->base.height)
113 == -1) {
114 return false;
115 }
116
117+ if (dumb->shadowed)
118+ free(buffer->base.map);
119+ dumb->scanout = NULL;
120 buffer->base.map = NULL;
121
122 return true;
+6,
-0
1@@ -23,10 +23,16 @@
2
3 static bool buffer_map(struct buffer *drawable);
4 static bool buffer_unmap(struct buffer *drawable);
5+#ifdef BUFFER_IMPLEMENTS_FLUSH
6+static void buffer_flush(struct buffer *drawable);
7+#endif
8 static void buffer_destroy(struct buffer *drawable);
9
10 static const struct wld_buffer_impl wld_buffer_impl = {
11 .map = &buffer_map,
12 .unmap = &buffer_unmap,
13+#ifdef BUFFER_IMPLEMENTS_FLUSH
14+ .flush = &buffer_flush,
15+#endif
16 .destroy = &buffer_destroy
17 };
+61,
-1
1@@ -99,7 +99,11 @@ wld_set_target_surface(struct wld_renderer *renderer, struct wld_surface *surfac
2 if (!(back_buffer = surface->impl->back(surface)))
3 return false;
4
5- return renderer->impl->set_target(renderer, back_buffer);
6+ if (!renderer->impl->set_target(renderer, back_buffer))
7+ return false;
8+
9+ renderer->target = &back_buffer->base;
10+ return true;
11 }
12
13 EXPORT
14@@ -139,6 +143,58 @@ wld_copy_region(struct wld_renderer *renderer,
15 dst_x, dst_y, region);
16 }
17
18+EXPORT
19+void
20+wld_blend_region(struct wld_renderer *renderer, struct wld_buffer *buffer,
21+ int32_t dst_x, int32_t dst_y, pixman_region32_t *region)
22+{
23+ pixman_image_t *src = NULL, *dst = NULL;
24+ pixman_region32_t clip;
25+ pixman_box32_t *extents;
26+
27+ if (!renderer->target || !pixman_region32_not_empty(region))
28+ return;
29+
30+ /* Complete accelerator writes before accessing the buffers on the CPU. */
31+ renderer->impl->flush(renderer);
32+ if (!wld_map(buffer))
33+ return;
34+ if (!wld_map(renderer->target))
35+ goto unmap_src;
36+
37+ src = pixman_image_create_bits(format_wld_to_pixman(buffer->format),
38+ buffer->width, buffer->height,
39+ buffer->map, buffer->pitch);
40+ dst = pixman_image_create_bits(format_wld_to_pixman(renderer->target->format),
41+ renderer->target->width,
42+ renderer->target->height,
43+ renderer->target->map,
44+ renderer->target->pitch);
45+ if (!src || !dst)
46+ goto destroy;
47+
48+ pixman_region32_init(&clip);
49+ pixman_region32_copy(&clip, region);
50+ pixman_region32_translate(&clip, dst_x, dst_y);
51+ extents = pixman_region32_extents(region);
52+ pixman_image_set_clip_region32(dst, &clip);
53+ pixman_image_composite32(PIXMAN_OP_OVER, src, NULL, dst,
54+ extents->x1, extents->y1, 0, 0,
55+ extents->x1 + dst_x, extents->y1 + dst_y,
56+ extents->x2 - extents->x1,
57+ extents->y2 - extents->y1);
58+ pixman_region32_fini(&clip);
59+
60+destroy:
61+ if (src)
62+ pixman_image_unref(src);
63+ if (dst)
64+ pixman_image_unref(dst);
65+ wld_unmap(renderer->target);
66+unmap_src:
67+ wld_unmap(buffer);
68+}
69+
70
71 /* https://en.wikipedia.org/wiki/Midpoint_circle_algorithm */
72 static void
73@@ -235,5 +291,9 @@ void
74 wld_flush(struct wld_renderer *renderer)
75 {
76 renderer->impl->flush(renderer);
77+ if (renderer->target && ((struct buffer *)renderer->target)->base.impl->flush)
78+ ((struct buffer *)renderer->target)->base.impl->flush(
79+ (struct buffer *)renderer->target);
80 renderer->impl->set_target(renderer, NULL);
81+ renderer->target = NULL;
82 }
+1,
-0
1@@ -131,6 +131,7 @@ struct buffer {
2 struct wld_buffer_impl {
3 bool (*map)(struct buffer *buffer);
4 bool (*unmap)(struct buffer *buffer);
5+ void (*flush)(struct buffer *buffer);
6 void (*destroy)(struct buffer *buffer);
7 };
8
M
wld.h
+5,
-0
1@@ -253,6 +253,11 @@ void wld_copy_region(struct wld_renderer *renderer,
2 struct wld_buffer *buffer,
3 int32_t dst_x, int32_t dst_y, pixman_region32_t *region);
4
5+void wld_blend_region(struct wld_renderer *renderer,
6+ struct wld_buffer *buffer,
7+ int32_t dst_x, int32_t dst_y,
8+ pixman_region32_t *region);
9+
10 void wld_draw_circle(struct wld_renderer *renderer, uint32_t color,
11 int32_t x, int32_t y, uint32_t r, bool fill);
12