Skip to content

Commit

Permalink
Support 10-bit screenshots by downsampling to 8-bit
Browse files Browse the repository at this point in the history
This commit introduces support for all eight 10-bit colour formats
supported by wl_shm.

le32toh is used to convert little endian pixels to host endianness.
This function is available on Linux in <endian.h> and FreeBSD in
<sys/endian.h>.
  • Loading branch information
quantum5 committed Dec 4, 2021
1 parent a8fc557 commit 6773a96
Showing 1 changed file with 83 additions and 0 deletions.
83 changes: 83 additions & 0 deletions background-image.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#define _DEFAULT_SOURCE
#include <assert.h>
#include "background-image.h"
#include "cairo.h"
#include "log.h"
#include "swaylock.h"

#ifdef __FreeBSD__
# include <sys/endian.h>
#else
# include <endian.h>
#endif

// Cairo RGB24 uses 32 bits per pixel, as XRGB, in native endianness.
// xrgb32_le uses 32 bits per pixel, as XRGB, little endian (BGRX big endian).
void cairo_rgb24_from_xrgb32_le(unsigned char *buf, int width, int height, int stride) {
Expand Down Expand Up @@ -32,6 +39,58 @@ void cairo_rgb24_from_xbgr32_le(unsigned char *buf, int width, int height, int s
}
}

void cairo_rgb24_from_xrgb2101010_le(unsigned char *buf, int width, int height, int stride) {
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
uint32_t *pix = (uint32_t *) (buf + y * stride + x * 4);
uint32_t color = le32toh(*pix);
*pix = 0 |
((color >> 22) & 0xFF) << 16 |
((color >> 12) & 0xFF) << 8 |
((color >> 2) & 0xFF);
}
}
}

void cairo_rgb24_from_xbgr2101010_le(unsigned char *buf, int width, int height, int stride) {
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
uint32_t *pix = (uint32_t *) (buf + y * stride + x * 4);
uint32_t color = le32toh(*pix);
*pix = 0 |
((color >> 2) & 0xFF) << 16 |
((color >> 12) & 0xFF) << 8 |
((color >> 22) & 0xFF);
}
}
}

void cairo_rgb24_from_rgbx1010102_le(unsigned char *buf, int width, int height, int stride) {
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
uint32_t *pix = (uint32_t *) (buf + y * stride + x * 4);
uint32_t color = le32toh(*pix);
*pix = 0 |
((color >> 24) & 0xFF) << 16 |
((color >> 14) & 0xFF) << 8 |
((color >> 4) & 0xFF);
}
}
}

void cairo_rgb24_from_bgrx1010102_le(unsigned char *buf, int width, int height, int stride) {
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
uint32_t *pix = (uint32_t *) (buf + y * stride + x * 4);
uint32_t color = le32toh(*pix);
*pix = 0 |
((color >> 4) & 0xFF) << 16 |
((color >> 14) & 0xFF) << 8 |
((color >> 24) & 0xFF);
}
}
}

enum background_mode parse_background_mode(const char *mode) {
if (strcmp(mode, "stretch") == 0) {
return BACKGROUND_MODE_STRETCH;
Expand Down Expand Up @@ -169,6 +228,30 @@ cairo_surface_t *load_background_from_buffer(void *buf, uint32_t format,
cairo_image_surface_get_width(image),
cairo_image_surface_get_height(image),
cairo_image_surface_get_stride(image));
} else if (format == WL_SHM_FORMAT_XRGB2101010 || format == WL_SHM_FORMAT_ARGB2101010) {
cairo_rgb24_from_xrgb2101010_le(
cairo_image_surface_get_data(image),
cairo_image_surface_get_width(image),
cairo_image_surface_get_height(image),
cairo_image_surface_get_stride(image));
} else if (format == WL_SHM_FORMAT_XBGR2101010 || format == WL_SHM_FORMAT_ABGR2101010) {
cairo_rgb24_from_xbgr2101010_le(
cairo_image_surface_get_data(image),
cairo_image_surface_get_width(image),
cairo_image_surface_get_height(image),
cairo_image_surface_get_stride(image));
} else if (format == WL_SHM_FORMAT_RGBX1010102 || format == WL_SHM_FORMAT_RGBA1010102) {
cairo_rgb24_from_rgbx1010102_le(
cairo_image_surface_get_data(image),
cairo_image_surface_get_width(image),
cairo_image_surface_get_height(image),
cairo_image_surface_get_stride(image));
} else if (format == WL_SHM_FORMAT_BGRX1010102 || format == WL_SHM_FORMAT_BGRA1010102) {
cairo_rgb24_from_bgrx1010102_le(
cairo_image_surface_get_data(image),
cairo_image_surface_get_width(image),
cairo_image_surface_get_height(image),
cairo_image_surface_get_stride(image));
} else {
if (format != WL_SHM_FORMAT_XRGB8888 && format != WL_SHM_FORMAT_ARGB8888) {
swaylock_log(LOG_ERROR,
Expand Down

0 comments on commit 6773a96

Please sign in to comment.