@@ -53,6 +53,8 @@ struct swaybg_state {
5353 struct wl_list outputs ; // struct swaybg_output::link
5454 struct wl_list images ; // struct swaybg_image::link
5555 bool run_display ;
56+ bool has_xrgb2101010 ;
57+ bool has_xbgr2101010 ;
5658};
5759
5860struct swaybg_image {
@@ -117,10 +119,26 @@ static struct wl_buffer *draw_buffer(const struct swaybg_output *output,
117119 r32 , g32 , b32 , 0xFFFFFFFF );
118120 }
119121
122+ bool deep_image = false;
123+ if (surface ) {
124+ cairo_format_t fmt = cairo_image_surface_get_format (surface );
125+ deep_image = deep_image || fmt == CAIRO_FORMAT_RGB30 ;
126+ #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE (1 , 17 , 2 )
127+ deep_image = deep_image || fmt == CAIRO_FORMAT_RGB96F ;
128+ deep_image = deep_image || fmt == CAIRO_FORMAT_RGBA128F ;
129+ #endif
130+ }
131+
132+ uint32_t format = WL_SHM_FORMAT_XRGB8888 ;
133+ if (deep_image && output -> state -> has_xrgb2101010 ) {
134+ format = WL_SHM_FORMAT_XRGB2101010 ;
135+ } else if (deep_image && output -> state -> has_xbgr2101010 ) {
136+ format = WL_SHM_FORMAT_XBGR2101010 ;
137+ }
120138
121139 struct pool_buffer buffer ;
122140 if (!create_buffer (& buffer , output -> state -> shm ,
123- buffer_width , buffer_height , WL_SHM_FORMAT_XRGB8888 )) {
141+ buffer_width , buffer_height , format )) {
124142 return NULL ;
125143 }
126144
@@ -133,6 +151,10 @@ static struct wl_buffer *draw_buffer(const struct swaybg_output *output,
133151 output -> config -> mode , buffer_width , buffer_height );
134152 }
135153
154+ if (format == WL_SHM_FORMAT_XBGR2101010 ) {
155+ cairo_rgb30_swap_rb (buffer .surface );
156+ }
157+
136158 // return wl_buffer for caller to use and destroy
137159 struct wl_buffer * wl_buf = buffer .buffer ;
138160 buffer .buffer = NULL ;
@@ -398,6 +420,21 @@ static const struct wl_output_listener output_listener = {
398420 .description = output_description ,
399421};
400422
423+
424+ static void shm_format (void * data , struct wl_shm * wl_shm , uint32_t format ) {
425+ struct swaybg_state * state = data ;
426+ if (format == WL_SHM_FORMAT_XBGR2101010 ) {
427+ state -> has_xbgr2101010 = true;
428+ }
429+ if (format == WL_SHM_FORMAT_XRGB2101010 ) {
430+ state -> has_xrgb2101010 = true;
431+ }
432+ }
433+
434+ static const struct wl_shm_listener shm_listener = {
435+ .format = shm_format ,
436+ };
437+
401438static void handle_global (void * data , struct wl_registry * registry ,
402439 uint32_t name , const char * interface , uint32_t version ) {
403440 struct swaybg_state * state = data ;
@@ -406,6 +443,7 @@ static void handle_global(void *data, struct wl_registry *registry,
406443 wl_registry_bind (registry , name , & wl_compositor_interface , 4 );
407444 } else if (strcmp (interface , wl_shm_interface .name ) == 0 ) {
408445 state -> shm = wl_registry_bind (registry , name , & wl_shm_interface , 1 );
446+ wl_shm_add_listener (state -> shm , & shm_listener , state );
409447 } else if (strcmp (interface , wl_output_interface .name ) == 0 ) {
410448 struct swaybg_output * output = calloc (1 , sizeof (struct swaybg_output ));
411449 output -> state = state ;
0 commit comments