Skip to content

Commit e5cd2f4

Browse files
committed
feat: toplevel mapping (BABY!) and optimized colorspace conversions
this commit also changes the name of the library from `libglace` to just `glace` for those who use the library in C this is the pursuit of optimizations, both the processor and the user are now happy, future maintainers can pray though.
1 parent aa83ad7 commit e5cd2f4

File tree

11 files changed

+270
-56
lines changed

11 files changed

+270
-56
lines changed

glace/buffer-utils.h

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#include <glib-2.0/glib.h>
2+
#include <stddef.h>
3+
#include <stdint.h>
4+
5+
#if defined(__SSSE3__)
6+
#include <tmmintrin.h>
7+
#elif defined(__SSE2__)
8+
#include <emmintrin.h>
9+
#endif
10+
#if defined(__AVX2__)
11+
#include <immintrin.h>
12+
#endif
13+
14+
static inline void buffer_utils_bgrx_to_rgbx(unsigned char* restrict data, long pixels) {
15+
#if defined(__AVX2__)
16+
// 8 pixels (32 bytes) per iteration
17+
long i = 0;
18+
long n = pixels & ~7UL;
19+
20+
const __m256i shuffle_mask = _mm256_setr_epi8(
21+
2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15, 18, 17, 16, 19, 22, 21, 20, 23, 26, 25, 24, 27, 30, 29, 28, 31
22+
);
23+
24+
for (; i < n; i += 8) {
25+
__m256i px = _mm256_loadu_si256((__m256i*)(data + i * 4));
26+
px = _mm256_shuffle_epi8(px, shuffle_mask);
27+
_mm256_storeu_si256((__m256i*)(data + i * 4), px);
28+
}
29+
30+
// leftovers
31+
for (; i < pixels; i++) {
32+
unsigned char pixel = data[i];
33+
data[i] = (pixel & 0xFF00FF00) | ((pixel << 16) & 0x00FF0000) | ((pixel >> 16) & 0xFF);
34+
}
35+
#elif defined(__SSSE3__)
36+
// 4 pixels (16 bytes) per iteration
37+
long i = 0;
38+
long n = pixels & ~3UL;
39+
40+
const __m128i shuffle_mask = _mm_setr_epi8(
41+
2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15
42+
);
43+
44+
for (; i < n; i += 4) {
45+
__m128i px = _mm_loadu_si128((__m128i*)(data + i * 4));
46+
px = _mm_shuffle_epi8(px, shuffle_mask);
47+
_mm_storeu_si128((__m128i*)(data + i * 4), px);
48+
}
49+
50+
for (; i < pixels; i++) {
51+
unsigned char pixel = data[i];
52+
data[i] = (pixel & 0xFF00FF00) | ((pixel << 16) & 0x00FF0000) | ((pixel >> 16) & 0xFF);
53+
}
54+
#elif defined(__SSE2__)
55+
// 4 pixels (16 bytes) per iteration (shift & mask)
56+
long i = 0;
57+
long n = pixels & ~3UL;
58+
59+
__m128i mask_rb = _mm_set1_epi32(0x00FF00FF); // R and B
60+
__m128i mask_gx = _mm_set1_epi32(0xFF00FF00); // G and X
61+
62+
for (; i < n; i += 4) {
63+
__m128i px = _mm_loadu_si128((__m128i*)(data + i * 4));
64+
65+
__m128i rb = _mm_and_si128(px, mask_rb);
66+
__m128i gx = _mm_and_si128(px, mask_gx);
67+
68+
__m128i r = _mm_slli_epi32(rb, 16);
69+
__m128i b = _mm_srli_epi32(rb, 16);
70+
71+
__m128i swapped = _mm_or_si128(gx, _mm_or_si128(r, b));
72+
_mm_storeu_si128((__m128i*)(data + i * 4), swapped);
73+
}
74+
75+
for (; i < pixels; i++) {
76+
unsigned char pixel = data[i];
77+
data[i] = (pixel & 0xFF00FF00) | ((pixel << 16) & 0x00FF0000) | ((pixel >> 16) & 0xFF);
78+
}
79+
80+
#else
81+
for (long i = 0; i < pixels; i++) {
82+
unsigned char pixel = data[i];
83+
84+
data[i] = (pixel & 0xFF00FF00) | ((pixel << 16) & 0x00FF0000) | ((pixel >> 16) & 0xFF);
85+
}
86+
#endif
87+
}
88+
89+
static void buffer_utils_log_available_accelerator() {
90+
const char* prefix = "[INFO][BUFFER]";
91+
#if defined(__AVX2__)
92+
g_debug("%s using AVX2 for buffer format conversion acceleration", prefix);
93+
#elif defined(__SSSE3__)
94+
g_debug("%s using SSSE3 for buffer format conversion acceleration", prefix);
95+
#elif defined(__SSE2__)
96+
g_debug("%s using SSE2 for buffer format conversion acceleration", prefix);
97+
#else
98+
g_debug("%s compiled with no buffer conversion acceleration", prefix);
99+
#endif
100+
}

glace/glace-client-private.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@
5151
} while (0)
5252

5353
// signal emitters
54-
static void glace_client_signal_changed_emit(GlaceClient* self);
55-
static void glace_client_signal_close_emit(GlaceClient* self);
54+
// static void glace_client_signal_changed_emit(GlaceClient* self);
55+
// static void glace_client_signal_close_emit(GlaceClient* self);
5656

5757
// methods
58-
static void glace_client_init(GlaceClient* self);
59-
static void glace_client_class_init(GlaceClientClass* klass);
58+
// static void glace_client_init(GlaceClient* self);
59+
// static void glace_client_class_init(GlaceClientClass* klass);
6060

61-
GlaceClient* glace_client_new(struct zwlr_foreign_toplevel_handle_v1* wlr_handle, GdkWaylandDisplay* gdk_display);
61+
GlaceClient* glace_client_new(struct zwlr_foreign_toplevel_handle_v1* wlr_handle, struct hyprland_toplevel_mapping_manager_v1* hl_mapping_manager, GdkWaylandDisplay* gdk_display);
6262

6363
#endif /* __LIBGLACE_CLIENT_PRIVATE_H__ */

glace/glace-client.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ static GParamSpec* glace_client_properties[GLACE_CLIENT_N_PROPERTIES] = {
55
NULL,
66
};
77

8+
static void on_mapping_handle_window_address(void* user_data, struct hyprland_toplevel_window_mapping_handle_v1* handle, uint32_t address_hi, uint32_t address);
9+
static void on_mapping_handle_failed(void* user_data, struct hyprland_toplevel_window_mapping_handle_v1* handle);
10+
11+
static const struct hyprland_toplevel_window_mapping_handle_v1_listener mapping_handle_listener = {
12+
.window_address = &on_mapping_handle_window_address,
13+
.failed = &on_mapping_handle_failed,
14+
};
15+
816
static void glace_client_signal_changed_emit(GlaceClient* self) {
917
g_signal_emit(
1018
self,
@@ -54,6 +62,9 @@ static void glace_client_get_property(
5462
case GLACE_CLIENT_PROPERTY_CLOSED:
5563
g_value_set_boolean(value, self->priv->closed);
5664
break;
65+
case GLACE_CLIENT_PROPERTY_HYPRLAND_ADDRESS:
66+
g_value_set_uint64(value, self->priv->hyprland_address);
67+
break;
5768
default:
5869
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
5970
break;
@@ -285,6 +296,16 @@ static void glace_client_class_init(GlaceClientClass* klass) {
285296
G_PARAM_READABLE
286297
);
287298

299+
glace_client_properties[GLACE_CLIENT_PROPERTY_HYPRLAND_ADDRESS] = g_param_spec_uint64(
300+
"hyprland-address",
301+
"hyprland-address",
302+
"the internal window address for hyprland in 64bits",
303+
0,
304+
G_MAXUINT64,
305+
0,
306+
G_PARAM_READABLE
307+
);
308+
288309
g_object_class_install_properties(
289310
parent_class,
290311
GLACE_CLIENT_N_PROPERTIES,
@@ -300,6 +321,7 @@ static void glace_client_init(GlaceClient* self) {
300321
);
301322

302323
self->priv->closed = false;
324+
self->priv->hyprland_address = 0;
303325
CLIENT_SET_CURRENT_PROP(self, app_id, false);
304326
CLIENT_SET_CURRENT_PROP(self, title, false);
305327
CLIENT_SET_CURRENT_PROP(self, maximized, false);
@@ -308,8 +330,41 @@ static void glace_client_init(GlaceClient* self) {
308330
CLIENT_SET_CURRENT_PROP(self, fullscreen, false);
309331
}
310332

333+
static void on_mapping_handle_window_address(
334+
void* user_data,
335+
struct hyprland_toplevel_window_mapping_handle_v1* handle,
336+
// that's how you know a protocol is good
337+
uint32_t address_hi,
338+
uint32_t address_lo
339+
) {
340+
GlaceClient* self = GLACE_CLIENT(user_data);
341+
RETURN_IF_INVALID_CLIENT(self, hyprland_toplevel_window_mapping_handle_v1_destroy(handle));
342+
343+
self->priv->hyprland_address = ((guint64)address_hi << 32) | address_lo;
344+
345+
// we have a proper address now, notify the user...
346+
g_object_notify_by_pspec(
347+
G_OBJECT(self),
348+
glace_client_properties[GLACE_CLIENT_PROPERTY_HYPRLAND_ADDRESS]
349+
);
350+
351+
glace_client_signal_changed_emit(self);
352+
353+
hyprland_toplevel_window_mapping_handle_v1_destroy(handle);
354+
}
355+
356+
static void on_mapping_handle_failed(
357+
void* user_data,
358+
struct hyprland_toplevel_window_mapping_handle_v1* handle
359+
) {
360+
// something's fucked up, cleanup meanwhile
361+
hyprland_toplevel_window_mapping_handle_v1_destroy(handle);
362+
return;
363+
}
364+
311365
GlaceClient* glace_client_new(
312366
struct zwlr_foreign_toplevel_handle_v1* wlr_handle,
367+
struct hyprland_toplevel_mapping_manager_v1* hl_mapping_manager,
313368
GdkWaylandDisplay* gdk_display
314369
) {
315370
GlaceClient* self = g_object_new(GLACE_TYPE_CLIENT, NULL);
@@ -321,6 +376,22 @@ GlaceClient* glace_client_new(
321376
&toplevel_handle_listener,
322377
self
323378
);
379+
380+
if (!hl_mapping_manager)
381+
return self;
382+
383+
struct hyprland_toplevel_window_mapping_handle_v1*
384+
handle = hyprland_toplevel_mapping_manager_v1_get_window_for_toplevel_wlr(
385+
hl_mapping_manager,
386+
self->priv->wlr_handle
387+
);
388+
389+
hyprland_toplevel_window_mapping_handle_v1_add_listener(
390+
handle,
391+
&mapping_handle_listener,
392+
self // Pass the client instance as user data
393+
);
394+
324395
return self;
325396
}
326397

@@ -329,6 +400,10 @@ guint glace_client_get_id(GlaceClient* self) {
329400
return (guint)self->priv->id;
330401
}
331402

403+
guint64 glace_client_get_hyprland_address(GlaceClient* self) {
404+
return (guint64)self->priv->hyprland_address;
405+
}
406+
332407
const gchar* glace_client_get_app_id(GlaceClient* self) {
333408
return CLIENT_GET_CURRENT_PROP(self, app_id);
334409
}

glace/glace-client.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ struct _GlaceClientPrivate {
6969
GdkWaylandDisplay* gdk_display;
7070
GlaceClientProperties current_properties;
7171
GlaceClientProperties pending_properties;
72+
73+
uint64_t hyprland_address;
7274
};
7375

7476
enum {
@@ -87,6 +89,7 @@ enum {
8789
GLACE_CLIENT_PROPERTY_ACTIVATED,
8890
GLACE_CLIENT_PROPERTY_FULLSCREEN,
8991
GLACE_CLIENT_PROPERTY_CLOSED,
92+
GLACE_CLIENT_PROPERTY_HYPRLAND_ADDRESS,
9093
GLACE_CLIENT_N_PROPERTIES
9194
};
9295

@@ -99,6 +102,7 @@ gboolean glace_client_get_minimized(GlaceClient* self);
99102
gboolean glace_client_get_activated(GlaceClient* self);
100103
gboolean glace_client_get_fullscreen(GlaceClient* self);
101104
gboolean glace_client_get_closed(GlaceClient* self);
105+
guint64 glace_client_get_hyprland_address(GlaceClient* self);
102106

103107
// methods
104108
GType glace_client_get_type();

glace/glace-manager-private.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@
2626
typedef struct _GlaceFrameData GlaceFrameData;
2727
typedef struct _GlaceFrameBuffer GlaceFrameBuffer;
2828

29+
struct _GlaceManagerPrivate {
30+
GdkWaylandDisplay* gdk_display;
31+
struct wl_display* display;
32+
struct wl_shm* wl_shm;
33+
struct zwlr_foreign_toplevel_manager_v1* wlr_manager;
34+
struct hyprland_toplevel_export_manager_v1* hl_export_manager;
35+
struct hyprland_toplevel_mapping_manager_v1* hl_mapping_manager;
36+
};
37+
2938
struct _GlaceFrameBuffer {
3039
struct wl_buffer* wl_buffer;
3140
void* raw_buffer;
@@ -52,8 +61,8 @@ const static struct hyprland_toplevel_export_frame_v1_listener export_manager_fr
5261
// static void glace_manager_init(GlaceManager* self);
5362
// static void glace_manager_class_init(GlaceManagerClass* klass);
5463

55-
static void glace_manager_signal_changed_emit(GlaceManager* self);
56-
static void glace_manager_signal_client_added_emit(GlaceManager* self, GlaceClient* client);
57-
static void glace_manager_signal_client_removed_emit(GlaceManager* self, GlaceClient* client);
64+
// static void glace_manager_signal_changed_emit(GlaceManager* self);
65+
// static void glace_manager_signal_client_added_emit(GlaceManager* self, GlaceClient* client);
66+
// static void glace_manager_signal_client_removed_emit(GlaceManager* self, GlaceClient* client);
5867

5968
#endif /* __LIBGLACE_MANAGER_PRIVATE_H__ */

0 commit comments

Comments
 (0)