diff --git a/dwl.c b/dwl.c index 8614fdd..35f611d 100644 --- a/dwl.c +++ b/dwl.c @@ -193,6 +193,15 @@ typedef struct { void (*arrange)(Monitor *); } Layout; +typedef struct { + struct wlr_buffer base; + struct wl_listener release; + size_t stride; + bool acquired; + Img *image; + uint32_t data[]; +} Buffer; + struct Monitor { struct wl_list link; struct wlr_output *wlr_output; @@ -222,15 +231,10 @@ struct Monitor { char ltsymbol[16]; int asleep; Drwl *drw; + Buffer *pool[2]; int lrpad; }; -typedef struct { - struct wlr_buffer base; - size_t stride; - uint32_t data[]; -} Buffer; - typedef struct { const char *name; float mfact; @@ -272,6 +276,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list, static void arrangelayers(Monitor *m); static void axisnotify(struct wl_listener *listener, void *data); static bool bar_accepts_input(struct wlr_scene_buffer *buffer, double *sx, double *sy); +static void buffer_release(struct wl_listener *listener, void *data); static void buffer_destroy(struct wlr_buffer *buffer); static bool buffer_begin_data_ptr_access(struct wlr_buffer *buffer, uint32_t flags, void **data, uint32_t *format, size_t *stride); static void buffer_end_data_ptr_access(struct wlr_buffer *buffer); @@ -644,11 +649,22 @@ bar_accepts_input(struct wlr_scene_buffer *buffer, double *sx, double *sy) return true; } +void +buffer_release(struct wl_listener *listener, void *data) +{ + Buffer *buf = wl_container_of(listener, buf, release); + buf->acquired = false; + wlr_log(WLR_ERROR, "buffer %p ready for reuse", buf); + wl_list_remove(&buf->release.link); +} + void buffer_destroy(struct wlr_buffer *wlr_buffer) { - Buffer *buf; - buf = wl_container_of(wlr_buffer, buf, base); + Buffer *buf = wl_container_of(wlr_buffer, buf, base); + if (buf->acquired) + wl_list_remove(&buf->release.link); + drwl_image_destroy(buf->image); free(buf); } @@ -656,8 +672,7 @@ bool buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, uint32_t flags, void **data, uint32_t *format, size_t *stride) { - Buffer *buf; - buf = wl_container_of(wlr_buffer, buf, base); + Buffer *buf = wl_container_of(wlr_buffer, buf, base); if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false; @@ -669,7 +684,7 @@ buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, uint32_t flags, } void -buffer_end_data_ptr_access(struct wlr_buffer *buffer) +buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) { } @@ -821,6 +836,9 @@ cleanupmon(struct wl_listener *listener, void *data) wlr_layer_surface_v1_destroy(l->layer_surface); } + for (i = 0; i < LENGTH(m->pool); i++) + wlr_buffer_drop(&m->pool[i]->base); + drwl_destroy(m->drw); wl_list_remove(&m->destroy.link); @@ -1455,6 +1473,50 @@ dirtomon(enum wlr_direction dir) return selmon; } +Buffer * +bufmon(Monitor *m) +{ + size_t i; + size_t stride = drwl_image_stride(m->b.width); + Buffer *buf = NULL; + + wlr_log(WLR_ERROR, "looking for drawbar buffer for stride=%d", stride); + + for (i = 0; i < LENGTH(m->pool); i++) { + if (m->pool[i]) + wlr_log(WLR_ERROR, "buffer slot %d %p busy=%d stride=%d", i, m->pool[i], m->pool[i]->acquired, m->pool[i]->stride); + if (m->pool[i] && !m->pool[i]->acquired && m->pool[i]->stride != stride) { + wlr_log(WLR_ERROR, "destroying buffer %d (%p) old stride %d vs %d", + i, &m->pool[i], stride, m->pool[i]->stride); + wlr_buffer_drop(&m->pool[i]->base); + m->pool[i] = NULL; + } + if (m->pool[i] && !m->pool[i]->acquired) { + buf = m->pool[i]; + wlr_log(WLR_ERROR, "reusing available buffer %d (%p) stride=%d", i, buf, stride); + } + if (m->pool[i] || buf) { + wlr_log(WLR_ERROR, "successfully selected buffer %d (%p) stride=%d", i, buf, stride); + continue; + } + + buf = ecalloc(1, sizeof(Buffer) + (stride * m->b.height)); + buf->stride = stride; + buf->image = drwl_image_create(m->drw, m->b.width, m->b.height, buf->data, stride); + wlr_buffer_init(&buf->base, &buffer_impl, m->b.width, m->b.height); + m->pool[i] = buf; + wlr_log(WLR_ERROR, "empty slot; creating buffer %d (%p) stride=%d", i, buf, stride); + } + if (!buf) + return NULL; + + wlr_log(WLR_ERROR, "using drawbar buffer %p stride=%d", buf, stride); + + buf->acquired = true; + LISTEN(&buf->base.events.release, &buf->release, buffer_release); + return buf; +} + void drawbar(Monitor *m) { @@ -1462,21 +1524,20 @@ drawbar(Monitor *m) int boxs = m->drw->font->height / 9; int boxw = m->drw->font->height / 6 + 2; uint32_t i, occ = 0, urg = 0; - int32_t stride, size; Client *c; Buffer *buf; if (!m->scene_buffer->node.enabled) return; - stride = drwl_stride(m->b.width); - size = stride * m->b.height; + if (!(buf = bufmon(m))) + return; - buf = ecalloc(1, sizeof(Buffer) + size); - buf->stride = stride; - wlr_buffer_init(&buf->base, &buffer_impl, m->b.width, m->b.height); + wlr_buffer_lock(&buf->base); - drwl_prepare_drawing(m->drw, m->b.width, m->b.height, buf->data, stride); + char addr[24]; + snprintf(addr, sizeof(addr), "%p %d", buf, buf->stride); + strncpy(stext, addr, 256); /* draw status first so it can be overdrawn by tags later */ if (m == selmon) { /* status is only drawn on selected monitor */ @@ -1520,13 +1581,12 @@ drawbar(Monitor *m) } } - drwl_finish_drawing(m->drw); wlr_scene_buffer_set_dest_size(m->scene_buffer, m->b.real_width, m->b.real_height); wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x, m->m.y + (topbar ? 0 : m->m.height - m->b.real_height)); wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base); - wlr_buffer_drop(&buf->base); + wlr_buffer_unlock(&buf->base); } void