@@ -45,6 +45,8 @@ struct swaybg_state {
4545 struct wl_list outputs ; // struct swaybg_output::link
4646 struct wl_list images ; // struct swaybg_image::link
4747 bool run_display ;
48+ bool has_xrgb2101010 ;
49+ bool has_xbgr2101010 ;
4850};
4951
5052struct swaybg_image {
@@ -147,9 +149,26 @@ static void render_frame(struct swaybg_output *output, cairo_surface_t *surface)
147149 return ;
148150 }
149151
152+ bool deep_image = false;
153+ if (surface ) {
154+ cairo_format_t fmt = cairo_image_surface_get_format (surface );
155+ deep_image = deep_image || fmt == CAIRO_FORMAT_RGB30 ;
156+ #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE (1 , 17 , 2 )
157+ deep_image = deep_image || fmt == CAIRO_FORMAT_RGB96F ;
158+ deep_image = deep_image || fmt == CAIRO_FORMAT_RGBA128F ;
159+ #endif
160+ }
161+
162+ uint32_t format = WL_SHM_FORMAT_XRGB8888 ;
163+ if (deep_image && output -> state -> has_xrgb2101010 ) {
164+ format = WL_SHM_FORMAT_XRGB2101010 ;
165+ } else if (deep_image && output -> state -> has_xbgr2101010 ) {
166+ format = WL_SHM_FORMAT_XBGR2101010 ;
167+ }
168+
150169 struct pool_buffer buffer ;
151170 if (!create_buffer (& buffer , output -> state -> shm ,
152- buffer_width , buffer_height , WL_SHM_FORMAT_XRGB8888 )) {
171+ buffer_width , buffer_height , format )) {
153172 return ;
154173 }
155174
@@ -163,6 +182,10 @@ static void render_frame(struct swaybg_output *output, cairo_surface_t *surface)
163182 output -> config -> mode , buffer_width , buffer_height );
164183 }
165184
185+ if (format == WL_SHM_FORMAT_XBGR2101010 ) {
186+ cairo_rgb30_swap_rb (buffer .surface );
187+ }
188+
166189 wl_surface_set_buffer_scale (output -> surface , output -> scale );
167190 wl_surface_attach (output -> surface , buffer .buffer , 0 , 0 );
168191 wl_surface_damage_buffer (output -> surface , 0 , 0 , INT32_MAX , INT32_MAX );
@@ -349,6 +372,21 @@ static const struct wl_output_listener output_listener = {
349372 .description = output_description ,
350373};
351374
375+
376+ static void shm_format (void * data , struct wl_shm * wl_shm , uint32_t format ) {
377+ struct swaybg_state * state = data ;
378+ if (format == WL_SHM_FORMAT_XBGR2101010 ) {
379+ state -> has_xbgr2101010 = true;
380+ }
381+ if (format == WL_SHM_FORMAT_XRGB2101010 ) {
382+ state -> has_xrgb2101010 = true;
383+ }
384+ }
385+
386+ static const struct wl_shm_listener shm_listener = {
387+ .format = shm_format ,
388+ };
389+
352390static void handle_global (void * data , struct wl_registry * registry ,
353391 uint32_t name , const char * interface , uint32_t version ) {
354392 struct swaybg_state * state = data ;
@@ -357,6 +395,7 @@ static void handle_global(void *data, struct wl_registry *registry,
357395 wl_registry_bind (registry , name , & wl_compositor_interface , 4 );
358396 } else if (strcmp (interface , wl_shm_interface .name ) == 0 ) {
359397 state -> shm = wl_registry_bind (registry , name , & wl_shm_interface , 1 );
398+ wl_shm_add_listener (state -> shm , & shm_listener , state );
360399 } else if (strcmp (interface , wl_output_interface .name ) == 0 ) {
361400 struct swaybg_output * output = calloc (1 , sizeof (struct swaybg_output ));
362401 output -> state = state ;
0 commit comments