From d9c97421324b51c8beefacc7e66a2218ab3e5247 Mon Sep 17 00:00:00 2001
From: Yuxuan Shui <yshuiv7@gmail.com>
Date: Wed, 9 Jun 2021 01:51:33 +0100
Subject: [PATCH] backend: xrender: implement read_pixel

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
---
 .clang-tidy                   |  4 +++-
 src/backend/xrender/xrender.c | 24 ++++++++++++++++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/.clang-tidy b/.clang-tidy
index a76f2c7f..59e7273b 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -16,4 +16,6 @@ AnalyzeTemporaryDtors: false
 FormatStyle:     file
 CheckOptions:
   - key: readability-magic-numbers.IgnoredIntegerValues
-    value: 4;8;16;24;32;1;2;3;4096;65536
+    value: 4;8;16;24;32;1;2;3;4096;65536;
+  - key: readability-magic-numbers.IgnoredFloatingPointValues
+    value: 255.0;
diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c
index 5197dfe3..56d31de2 100644
--- a/src/backend/xrender/xrender.c
+++ b/src/backend/xrender/xrender.c
@@ -559,6 +559,29 @@ static void get_blur_size(void *blur_context, int *width, int *height) {
 	*height = ctx->resize_height;
 }
 
+static bool
+read_pixel(backend_t *backend_data, void *image_data, int x, int y, struct color *output) {
+	auto xd = (struct _xrender_data *)backend_data;
+	auto img = (struct _xrender_image_data *)image_data;
+
+	auto r = XCB_AWAIT(xcb_get_image, xd->base.c, XCB_IMAGE_FORMAT_XY_PIXMAP, img->pixmap,
+	                   to_i16_checked(x), to_i16_checked(y), 1, 1, (uint32_t)-1L);
+
+	if (!r) {
+		return false;
+	}
+
+	// Color format seems to be BGRA8888, see glamor_format_for_pixmap from the
+	// Xserver codebase.
+	uint8_t *pixels = xcb_get_image_data(r);
+	output->blue = pixels[0] / 255.0;
+	output->green = pixels[1] / 255.0;
+	output->red = pixels[2] / 255.0;
+	output->alpha = pixels[3] / 255.0;
+
+	return true;
+}
+
 static backend_t *backend_xrender_init(session_t *ps) {
 	auto xd = ccalloc(1, struct _xrender_data);
 	init_backend_base(&xd->base, ps);
@@ -655,6 +678,7 @@ struct backend_operations xrender_ops = {
     .max_buffer_age = 2,
 
     .image_op = image_op,
+    .read_pixel = read_pixel,
     .copy = copy,
     .create_blur_context = create_blur_context,
     .destroy_blur_context = destroy_blur_context,