commit d28fe22

uint  ·  2026-06-11 23:35:01 +0000 UTC
parent a56ad36
Backbuffer for double buffered output
3 files changed,  +33, -5
M maus.h
M maus.h
+3, -2
 1@@ -45,7 +45,7 @@
 2 	 ((uint32_t)(c).g <<  8) | \
 3 	 ((uint32_t)(c).b))
 4 /* ... */
 5-#define MAUS_PIXEL_AT(mw, x, y) ((mw)->fb[(y) * (mw)->stride + (x)])
 6+#define MAUS_PIXEL_AT(mw, x, y) ((mw)->bfb[(y) * (mw)->stride + (x)])
 7 
 8 typedef enum {
 9 	MAUS_EV_NONE,
10@@ -97,7 +97,8 @@ typedef struct {
11 	uint64_t       frame_time_last;
12 	char*          clipboard;
13 
14-	uint32_t*      fb;
15+	uint32_t*      fb;  /* front frame buffer */
16+	uint32_t*      bfb; /* back frame buffer */
17 	uint32_t       stride;
18 
19 	const char*    title;
+1, -1
1@@ -8,7 +8,7 @@
2 void maus_draw_text(Maus* mw, MausFont* font, int32_t x, int32_t y,
3                     const char* text, MausColor col)
4 {
5-	if (!mw || !mw->fb || !font || !text)
6+	if (!mw || !mw->bfb || !font || !text)
7 		return;
8 
9 	uint32_t col_up = MAUS_UNPACK_COL(col);
+29, -2
 1@@ -453,6 +453,10 @@ void maus_close(Maus* mw)
 2 {
 3 	MausBackend* be = &mw->backend;
 4 	fb_destroy(mw);
 5+	if (mw->bfb) {
 6+		free(mw->bfb);
 7+		mw->bfb = NULL;
 8+	}
 9 	if (mw->clipboard) {
10 		free(mw->clipboard);
11 		mw->clipboard = NULL;
12@@ -523,7 +527,7 @@ bool maus_create_window(Maus* mw)
13 void maus_fb_clear(Maus* mw, MausColor col)
14 {
15 	for (uint32_t y = 0; y < mw->height; y++) {
16-		uint32_t* row = mw->fb + (y * mw->stride);
17+		uint32_t* row = mw->bfb + (y * mw->stride);
18 		for (uint32_t x = 0; x < mw->width; x++)
19 			row[x] = (uint32_t) MAUS_UNPACK_COL(col);
20 	}
21@@ -566,6 +570,13 @@ Maus* maus_init(const char* title, int x, int y, int width, int height)
22 		free(mw);
23 		return NULL;
24 	}
25+	mw->bfb = calloc(mw->stride * mw->height, sizeof(uint32_t));
26+	if (!mw->bfb) {
27+		maus_log(stderr, "failed to allocate back buffer");
28+		maus_close(mw);
29+		free(mw);
30+		return NULL;
31+	}
32 
33 	return mw;
34 }
35@@ -603,6 +614,9 @@ void maus_present(Maus* mw)
36 	if (!be->image || be->win == None)
37 		return;
38 
39+	uint32_t bytes = mw->stride * mw->height * sizeof(uint32_t);
40+	memcpy(mw->fb, mw->bfb, bytes);
41+
42 	XShmPutImage(
43 		be->display, be->win, be->gc, be->image,
44 		0, 0, 0, 0, mw->width, mw->height, False
45@@ -617,14 +631,27 @@ bool maus_resize(Maus* mw, uint32_t width, uint32_t height)
46 	if (width == 0 || height == 0 ||
47 	    mw->width == width || mw->height == height)
48 		return false;
49+
50 	fb_destroy(mw);
51+	if (mw->bfb) {
52+		free(mw->bfb);
53+		mw->bfb = NULL;
54+	}
55 
56 	mw->width = width;
57 	mw->height = height;
58 
59 	XSync(be->display, False);
60 	XFlush(be->display);
61-	return fb_create(mw);
62+
63+	if (!fb_create(mw))
64+		return false;
65+
66+	mw->bfb = calloc(mw->stride * mw->height, sizeof(uint32_t));
67+	if (!mw->bfb)
68+		return false;
69+
70+	return true;
71 }
72 
73 void maus_cur_set_mode(Maus* mw, MausCursorState state)