Initial use of a centralized caching border generator

This commit is contained in:
Jack Zeal 2026-03-27 20:24:24 -07:00
parent c37f343377
commit 2a0ff0d5b4
7 changed files with 218 additions and 61 deletions

View file

@ -0,0 +1,30 @@
#include <stdint.h>
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_BORDERSET_H
#define LABWC_BORDERSET_H
struct borderset {
uint32_t id; // Base colour, but could be used as a tracking hash for images or whatever in the future
int size; // width (since I suspect a 2px border scaled up to 20px might look weird)
int type; // Single or double bevel
uint32_t * top;
uint32_t * left;
uint32_t * right;
uint32_t * bottom;
uint32_t * tl;
uint32_t * tr;
uint32_t * bl;
uint32_t * br;
struct borderset * next;
};
extern struct borderset * borderCache;
struct borderset * getBorders(uint32_t id, int size, int type);
struct borderset * createBuffer(uint32_t id, int size, int type);
void clearBorderCache(struct borderset *borderset);
#endif /* LABWC_LAB_SCENE_RECT_H */

View file

@ -66,13 +66,16 @@
(WLR_VERSION_NUM >= (((major) << 16) | ((minor) << 8) | (micro)))
/**
* PIXEL () - calculate pixel offset in an array of "bw" columns wide.
* PIXEL () - calculate pixel offset in an array
*
* @param x x-coordinate
* @param y y-coordinate
* @param size width of the buffer in pixes
* Assumes "bw" was defined externally
*/
#define PIXEL(x, y) (bw * y + x)
#define PIXELSIZED(x, y, size) (size * y + x)
#endif /* LABWC_MACROS_H */

115
src/common/borderset.c Normal file
View file

@ -0,0 +1,115 @@
#include "common/borderset.h"
#include "common/mem.h"
#include "common/macros.h"
struct borderset * getBorders(uint32_t id, int size, int type) {
struct borderset * current = borderCache;
struct borderset * last;
while (current != NULL) {
if (current->size == size && current->id == id && current->type == type) {
return current;
}
last = current;
current = current -> next;
}
// Fall through, we need to create a buffer.
if (borderCache == NULL) {
borderCache = createBuffer(id, size, type);
return borderCache;
} else {
last->next = createBuffer(id, size, type);
return last->next;
}
return NULL;
}
struct borderset * createBuffer(uint32_t id, int size, int type) {
struct borderset *newBorderset = znew(*newBorderset);
newBorderset->next = NULL;
newBorderset->id = id;
newBorderset->size = size;
newBorderset->type = type;
// Use ID as a AARRGGBB colour
uint8_t a = id >> 24 & 255;
uint8_t r = id >> 16 & 255;
uint8_t g = id >> 8 & 255;
uint8_t b = id & 255;
uint32_t r1 = r * 5 / 4;
if (r1 > a) r1=a;
uint32_t g1 = g * 5 / 4;
if (g1 > a) g1=a;
uint32_t b1 = b * 5 / 4;
if (b1 > a) b1=a;
/* darker outline */
uint32_t r0 = r / 2;
uint32_t g0 = g / 2;
uint32_t b0 = b / 2;
uint32_t hl32 = ((uint32_t)a << 24) | ((uint32_t)r1 << 16)
| ((uint32_t)g1 << 8) | (uint32_t)b1;
uint32_t ll32 = ((uint32_t)a << 24) | ((uint32_t)r0 << 16)
| ((uint32_t)g0 << 8) | (uint32_t)b0;
newBorderset->tl = znew_n(uint32_t, size*size);
newBorderset->tr = znew_n(uint32_t, size*size);
newBorderset->bl = znew_n(uint32_t, size*size);
newBorderset->br = znew_n(uint32_t, size*size);
newBorderset->top = znew(uint32_t);
newBorderset->left = znew(uint32_t);
newBorderset->right = znew(uint32_t);
newBorderset->bottom = znew(uint32_t);
switch(type) {
case 1:
*newBorderset->top = hl32;
*newBorderset->left = hl32;
*newBorderset->right = ll32;
*newBorderset->bottom = ll32;
// Fill with solid
for (int j=0; j<size;j++) {
for (int k=0; k<size;k++) {
newBorderset->tl[PIXELSIZED(j, k, size)] = hl32;
newBorderset->tr[PIXELSIZED(size - 1 - j, k, size)] = (j > k) ? hl32 : ll32;
newBorderset->bl[PIXELSIZED(size - 1 -j, k, size)] = (j > k) ? hl32 : ll32;
newBorderset->br[PIXELSIZED(j, k, size)] = ll32;
}
}
break;
case 2:
break;
}
return newBorderset;
}
void clearBorderCache(struct borderset * borderset)
{
if (borderset == NULL)
return;
if (borderset->next != NULL) {
clearBorderCache(borderset->next);
}
free(borderset->top);
free(borderset->left);
free(borderset->right);
free(borderset->bottom);
free(borderset->tl);
free(borderset->tr);
free(borderset->bl);
free(borderset->br);
free(borderset);
}

View file

@ -5,12 +5,14 @@
#include "common/mem.h"
#include "common/scene-helpers.h"
#include "common/macros.h"
#include "common/borderset.h"
#include "buffer.h"
struct border_scene {
struct wlr_scene_tree *tree;
struct wlr_scene_rect *top, *bottom, *left, *right;
struct wlr_scene_buffer *tlcorner, *trcorner, *blcorner, *brcorner;
struct wlr_scene_buffer *tlcorner, *trcorner, *blcorner, *brcorner,
*ttexture, *ltexture, *rtexture, *btexture;
};
static void
@ -43,90 +45,65 @@ lab_scene_rect_create(struct wlr_scene_tree *parent,
// Beveled mode 0 = normal outline
// Beveled mode 1 = full bevel with sharp internal corners
if (opts->beveled > 0) {
/* From Pull request 3382 */
int bw = rect->border_width;
// Floats for the rect versions.
float r = color[0];
float g = color[1];
float b = color[2];
float a = color[3];
float r1 = r * 5 / 4;
if (r1 > a) r1=a;
float g1 = g * 5 / 4;
if (g1 > a) g1=a;
float b1 = b * 5 / 4;
if (b1 > a) b1=a;
/* darker outline */
float r0 = r / 2;
float g0 = g / 2;
float b0 = b / 2;
int bw = rect->border_width;
uint32_t colour32 = (uint32_t)(a*255) << 24 | (uint32_t)(r*255) << 16 | (uint32_t)(g*255) << 8 | (uint32_t)(b*255);
struct borderset * renderedborders = getBorders(colour32, bw, 1);
// Buffers are AARRGGBB 32-bit packed int
uint32_t ll32 = ((uint32_t)(255*a) << 24) | ((uint32_t)(255*r0) << 16)
| ((uint32_t)(255*g0) << 8) | (uint32_t)(255*b0);
uint32_t hl32 = ((uint32_t)(255*a) << 24) | ((uint32_t)(255*r1) << 16)
| ((uint32_t)(255*g1) << 8) | (uint32_t)(255*b1);
const float highlight[4] = {r1, g1, b1, a};
const float lowlight[4] = {r0, g0, b0, a};
border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, highlight);
border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, lowlight);
border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, lowlight);
border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, highlight);
uint32_t *tl_data = znew_n(uint32_t, bw*bw);
uint32_t *tr_data = znew_n(uint32_t, bw*bw);
uint32_t *bl_data = znew_n(uint32_t, bw*bw);
uint32_t *br_data = znew_n(uint32_t, bw*bw);
// Fill with solid
for (int j=0; j<bw;j++) {
for (int k=0; k<bw;k++) {
tl_data[PIXEL(j, k)] = hl32;
tr_data[PIXEL(bw - 1 - j, k)] = (j > k) ? hl32 : ll32;
bl_data[PIXEL(bw - 1 -j, k)] = (j > k) ? hl32 : ll32;
br_data[PIXEL(j, k)] = ll32;
}
}
border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color);
border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color);
border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color);
border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, color);
struct lab_data_buffer *ttexture_buffer =
buffer_create_from_data(renderedborders->top, 1, 1, 4);
border->ttexture = wlr_scene_buffer_create(border->tree, &ttexture_buffer->base);
struct lab_data_buffer *ltexture_buffer =
buffer_create_from_data(renderedborders->left, 1, 1, 4);
border->ltexture = wlr_scene_buffer_create(border->tree, &ltexture_buffer->base);
struct lab_data_buffer *rtexture_buffer =
buffer_create_from_data(renderedborders->right, 1, 1, 4);
border->rtexture = wlr_scene_buffer_create(border->tree, &rtexture_buffer->base);
struct lab_data_buffer *btexture_buffer =
buffer_create_from_data(renderedborders->bottom, 1, 1, 4);
border->btexture = wlr_scene_buffer_create(border->tree, &btexture_buffer->base);
struct lab_data_buffer *tltexture_buffer =
buffer_create_from_data(tl_data, bw, bw, 4*bw);
buffer_create_from_data(renderedborders->tl, bw, bw, 4*bw);
border->tlcorner = wlr_scene_buffer_create(border->tree, &tltexture_buffer->base);
wlr_buffer_drop(&tltexture_buffer->base);
struct lab_data_buffer *trtexture_buffer =
buffer_create_from_data(tr_data, bw, bw, 4*bw);
buffer_create_from_data(renderedborders->tr, bw, bw, 4*bw);
border->trcorner = wlr_scene_buffer_create(border->tree, &trtexture_buffer->base);
wlr_buffer_drop(&trtexture_buffer->base);
struct lab_data_buffer *bltexture_buffer =
buffer_create_from_data(bl_data, bw, bw, 4*bw);
buffer_create_from_data(renderedborders->bl, bw, bw, 4*bw);
border->blcorner = wlr_scene_buffer_create(border->tree, &bltexture_buffer->base);
wlr_buffer_drop(&bltexture_buffer->base);
struct lab_data_buffer *brtexture_buffer =
buffer_create_from_data(br_data, bw, bw, 4*bw);
buffer_create_from_data(renderedborders->br, bw, bw, 4*bw);
border->brcorner = wlr_scene_buffer_create(border->tree, &brtexture_buffer->base);
wlr_buffer_drop(&brtexture_buffer->base);
} else {
border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color);
border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color);
@ -181,6 +158,31 @@ resize_border(struct border_scene *border, int border_width, int width, int heig
wlr_scene_rect_set_size(border->right, border_width, height - border_width * 2);
if (border->tlcorner != NULL) {
wlr_scene_buffer_set_dest_size(border->ttexture,
width, border_width);
wlr_scene_node_set_position(&border->ttexture->node,
0,0);
wlr_scene_buffer_set_dest_size(border->btexture,
width, border_width);
wlr_scene_node_set_position(&border->btexture->node,
0, height - border_width);
wlr_scene_buffer_set_dest_size(border->ltexture,
border_width, height - border_width * 2);
wlr_scene_node_set_position(&border->ltexture->node,
0, border_width);
wlr_scene_buffer_set_dest_size(border->rtexture,
border_width, height - border_width * 2);
wlr_scene_node_set_position(&border->rtexture->node,
width - border_width, border_width);
wlr_scene_buffer_set_dest_size(border->tlcorner,
border_width, border_width);
wlr_scene_node_set_position(&border->tlcorner->node,

View file

@ -1,4 +1,5 @@
labwc_sources += files(
'borderset.c',
'box.c',
'buf.c',
'dir.c',

View file

@ -13,6 +13,7 @@
#include "theme.h"
#include "translate.h"
#include "menu/menu.h"
#include "common/borderset.h"
/*
* Globals
@ -40,6 +41,8 @@ static const struct option long_options[] = {
{0, 0, 0, 0}
};
struct borderset * borderCache = NULL;
static const char labwc_usage[] =
"Usage: labwc [options...]\n"
" -c, --config <file> Specify config file (with path)\n"

View file

@ -69,6 +69,7 @@
#include "view.h"
#include "workspaces.h"
#include "xwayland.h"
#include "common/borderset.h"
#define LAB_EXT_DATA_CONTROL_VERSION 1
#define LAB_EXT_FOREIGN_TOPLEVEL_LIST_VERSION 1
@ -100,6 +101,8 @@ reload_config_and_theme(void)
}
cycle_finish(/*switch_focus*/ false);
clearBorderCache(borderCache);
borderCache = NULL;
menu_reconfigure();
seat_reconfigure();
regions_reconfigure();