1diff --git a/dwl.c b/dwl.c
2index 8614fdd..35f611d 100644
3--- a/dwl.c
4+++ b/dwl.c
5@@ -193,6 +193,15 @@ typedef struct {
6 void (*arrange)(Monitor *);
7 } Layout;
8
9+typedef struct {
10+ struct wlr_buffer base;
11+ struct wl_listener release;
12+ size_t stride;
13+ bool acquired;
14+ Img *image;
15+ uint32_t data[];
16+} Buffer;
17+
18 struct Monitor {
19 struct wl_list link;
20 struct wlr_output *wlr_output;
21@@ -222,15 +231,10 @@ struct Monitor {
22 char ltsymbol[16];
23 int asleep;
24 Drwl *drw;
25+ Buffer *pool[2];
26 int lrpad;
27 };
28
29-typedef struct {
30- struct wlr_buffer base;
31- size_t stride;
32- uint32_t data[];
33-} Buffer;
34-
35 typedef struct {
36 const char *name;
37 float mfact;
38@@ -272,6 +276,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
39 static void arrangelayers(Monitor *m);
40 static void axisnotify(struct wl_listener *listener, void *data);
41 static bool bar_accepts_input(struct wlr_scene_buffer *buffer, double *sx, double *sy);
42+static void buffer_release(struct wl_listener *listener, void *data);
43 static void buffer_destroy(struct wlr_buffer *buffer);
44 static bool buffer_begin_data_ptr_access(struct wlr_buffer *buffer, uint32_t flags, void **data, uint32_t *format, size_t *stride);
45 static void buffer_end_data_ptr_access(struct wlr_buffer *buffer);
46@@ -644,11 +649,22 @@ bar_accepts_input(struct wlr_scene_buffer *buffer, double *sx, double *sy)
47 return true;
48 }
49
50+void
51+buffer_release(struct wl_listener *listener, void *data)
52+{
53+ Buffer *buf = wl_container_of(listener, buf, release);
54+ buf->acquired = false;
55+ wlr_log(WLR_ERROR, "buffer %p ready for reuse", buf);
56+ wl_list_remove(&buf->release.link);
57+}
58+
59 void
60 buffer_destroy(struct wlr_buffer *wlr_buffer)
61 {
62- Buffer *buf;
63- buf = wl_container_of(wlr_buffer, buf, base);
64+ Buffer *buf = wl_container_of(wlr_buffer, buf, base);
65+ if (buf->acquired)
66+ wl_list_remove(&buf->release.link);
67+ drwl_image_destroy(buf->image);
68 free(buf);
69 }
70
71@@ -656,8 +672,7 @@ bool
72 buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, uint32_t flags,
73 void **data, uint32_t *format, size_t *stride)
74 {
75- Buffer *buf;
76- buf = wl_container_of(wlr_buffer, buf, base);
77+ Buffer *buf = wl_container_of(wlr_buffer, buf, base);
78
79 if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false;
80
81@@ -669,7 +684,7 @@ buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, uint32_t flags,
82 }
83
84 void
85-buffer_end_data_ptr_access(struct wlr_buffer *buffer)
86+buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer)
87 {
88 }
89
90@@ -821,6 +836,9 @@ cleanupmon(struct wl_listener *listener, void *data)
91 wlr_layer_surface_v1_destroy(l->layer_surface);
92 }
93
94+ for (i = 0; i < LENGTH(m->pool); i++)
95+ wlr_buffer_drop(&m->pool[i]->base);
96+
97 drwl_destroy(m->drw);
98
99 wl_list_remove(&m->destroy.link);
100@@ -1455,6 +1473,50 @@ dirtomon(enum wlr_direction dir)
101 return selmon;
102 }
103
104+Buffer *
105+bufmon(Monitor *m)
106+{
107+ size_t i;
108+ size_t stride = drwl_image_stride(m->b.width);
109+ Buffer *buf = NULL;
110+
111+ wlr_log(WLR_ERROR, "looking for drawbar buffer for stride=%d", stride);
112+
113+ for (i = 0; i < LENGTH(m->pool); i++) {
114+ if (m->pool[i])
115+ wlr_log(WLR_ERROR, "buffer slot %d %p busy=%d stride=%d", i, m->pool[i], m->pool[i]->acquired, m->pool[i]->stride);
116+ if (m->pool[i] && !m->pool[i]->acquired && m->pool[i]->stride != stride) {
117+ wlr_log(WLR_ERROR, "destroying buffer %d (%p) old stride %d vs %d",
118+ i, &m->pool[i], stride, m->pool[i]->stride);
119+ wlr_buffer_drop(&m->pool[i]->base);
120+ m->pool[i] = NULL;
121+ }
122+ if (m->pool[i] && !m->pool[i]->acquired) {
123+ buf = m->pool[i];
124+ wlr_log(WLR_ERROR, "reusing available buffer %d (%p) stride=%d", i, buf, stride);
125+ }
126+ if (m->pool[i] || buf) {
127+ wlr_log(WLR_ERROR, "successfully selected buffer %d (%p) stride=%d", i, buf, stride);
128+ continue;
129+ }
130+
131+ buf = ecalloc(1, sizeof(Buffer) + (stride * m->b.height));
132+ buf->stride = stride;
133+ buf->image = drwl_image_create(m->drw, m->b.width, m->b.height, buf->data, stride);
134+ wlr_buffer_init(&buf->base, &buffer_impl, m->b.width, m->b.height);
135+ m->pool[i] = buf;
136+ wlr_log(WLR_ERROR, "empty slot; creating buffer %d (%p) stride=%d", i, buf, stride);
137+ }
138+ if (!buf)
139+ return NULL;
140+
141+ wlr_log(WLR_ERROR, "using drawbar buffer %p stride=%d", buf, stride);
142+
143+ buf->acquired = true;
144+ LISTEN(&buf->base.events.release, &buf->release, buffer_release);
145+ return buf;
146+}
147+
148 void
149 drawbar(Monitor *m)
150 {
151@@ -1462,21 +1524,20 @@ drawbar(Monitor *m)
152 int boxs = m->drw->font->height / 9;
153 int boxw = m->drw->font->height / 6 + 2;
154 uint32_t i, occ = 0, urg = 0;
155- int32_t stride, size;
156 Client *c;
157 Buffer *buf;
158
159 if (!m->scene_buffer->node.enabled)
160 return;
161
162- stride = drwl_stride(m->b.width);
163- size = stride * m->b.height;
164+ if (!(buf = bufmon(m)))
165+ return;
166
167- buf = ecalloc(1, sizeof(Buffer) + size);
168- buf->stride = stride;
169- wlr_buffer_init(&buf->base, &buffer_impl, m->b.width, m->b.height);
170+ wlr_buffer_lock(&buf->base);
171
172- drwl_prepare_drawing(m->drw, m->b.width, m->b.height, buf->data, stride);
173+ char addr[24];
174+ snprintf(addr, sizeof(addr), "%p %d", buf, buf->stride);
175+ strncpy(stext, addr, 256);
176
177 /* draw status first so it can be overdrawn by tags later */
178 if (m == selmon) { /* status is only drawn on selected monitor */
179@@ -1520,13 +1581,12 @@ drawbar(Monitor *m)
180 }
181 }
182
183- drwl_finish_drawing(m->drw);
184 wlr_scene_buffer_set_dest_size(m->scene_buffer,
185 m->b.real_width, m->b.real_height);
186 wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x,
187 m->m.y + (topbar ? 0 : m->m.height - m->b.real_height));
188 wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base);
189- wlr_buffer_drop(&buf->base);
190+ wlr_buffer_unlock(&buf->base);
191 }
192
193 void