summaryrefslogtreecommitdiff
path: root/gui-libs/wlroots/files/hedronfire-udmabuf-alignment.patch
blob: 7f9df37b19a89572fd2e054b111f597121c08165 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
diff --git a/render/allocator/udmabuf.c b/render/allocator/udmabuf.c
index 8a7109a..93cde90 100644
--- a/render/allocator/udmabuf.c
+++ b/render/allocator/udmabuf.c
@@ -4,6 +4,7 @@
 #include <drm_fourcc.h>
 #include <fcntl.h>
 #include <linux/udmabuf.h>
+#include <limits.h>
 #include <stdlib.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
@@ -47,6 +48,10 @@ static struct wlr_buffer *allocator_create_buffer(
 		struct wlr_allocator *wlr_allocator, int width, int height,
 		const struct wlr_drm_format *format) {
 	struct wlr_udmabuf_allocator *allocator = wl_container_of(wlr_allocator, allocator, base);
+	if (width <= 0 || height <= 0) {
+		wlr_log(WLR_ERROR, "Invalid buffer dimensions");
+		return NULL;
+	}
 
 	const struct wlr_pixel_format_info *info =
 		drm_get_pixel_format_info(format->format);
@@ -67,9 +72,26 @@ static struct wlr_buffer *allocator_create_buffer(
 	}
 	wlr_buffer_init(&buffer->base, &buffer_impl, width, height);
 
+	// llvmpipe accesses render targets in 4x4 pixel blocks, using aligned
+	// vector loads even for partially covered blocks. Pad rows to preserve
+	// alignment and leave room for a complete block at the bottom edge.
+	// Include bytes_per_block so packed formats keep a valid pixel stride.
+	int32_t min_stride = pixel_format_info_min_stride(info, width);
+	int32_t stride_alignment = 16 * info->bytes_per_block;
+	if (min_stride <= 0 || min_stride > INT32_MAX - (stride_alignment - 1)) {
+		wlr_log(WLR_ERROR, "Invalid buffer stride");
+		goto err_buffer;
+	}
+	int32_t stride = (min_stride + stride_alignment - 1) /
+		stride_alignment * stride_alignment;
+	size_t padded_height = ((size_t)height + 3) & ~(size_t)3;
+	if (padded_height > (SIZE_MAX - (size_t)page_size + 1) / (size_t)stride) {
+		wlr_log(WLR_ERROR, "Buffer size overflow");
+		goto err_buffer;
+	}
+
 	// TODO: consider using a single file for multiple buffers
-	int stride = pixel_format_info_min_stride(info, width); // TODO: align?
-	size_t size = stride * height;
+	size_t size = (size_t)stride * padded_height;
 	if (size % page_size != 0) {
 		size += page_size - (size % page_size);
 	}