{"id":20253,"url":"https://patchwork.libcamera.org/api/patches/20253/?format=json","web_url":"https://patchwork.libcamera.org/patch/20253/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20240611110721.10690-1-robert.mader@collabora.com>","date":"2024-06-11T11:07:01","name":"libcamera: debayer_cpu: Add 32bits/aligned output formats","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"1194d2054540143f1b22f9aa46c9f8eb0625d380","submitter":{"id":140,"url":"https://patchwork.libcamera.org/api/people/140/?format=json","name":"Robert Mader","email":"robert.mader@collabora.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/20253/mbox/","series":[{"id":4380,"url":"https://patchwork.libcamera.org/api/series/4380/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=4380","date":"2024-06-11T11:07:01","name":"libcamera: debayer_cpu: Add 32bits/aligned output formats","version":1,"mbox":"https://patchwork.libcamera.org/series/4380/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/20253/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/20253/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 237B1C31E9\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 11 Jun 2024 11:08:12 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1997065456;\n\tTue, 11 Jun 2024 13:08:11 +0200 (CEST)","from madrid.collaboradmins.com (madrid.collaboradmins.com\n\t[46.235.227.194])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D162D61A26\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 11 Jun 2024 13:08:09 +0200 (CEST)","from desktop-fedora.fritz.box (cola.collaboradmins.com\n\t[195.201.22.229])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (4096 bits)\n\tserver-digest SHA256)\n\t(No client certificate requested) (Authenticated sender: rmader)\n\tby madrid.collaboradmins.com (Postfix) with ESMTPSA id A672A37804C6; \n\tTue, 11 Jun 2024 11:08:08 +0000 (UTC)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=collabora.com header.i=@collabora.com\n\theader.b=\"waMx1tnR\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com;\n\ts=mail; t=1718104088;\n\tbh=m9JmiTcuUE/MdQMk4iVrH88U+wk/vehOf77nnIqpdkg=;\n\th=From:To:Cc:Subject:Date:From;\n\tb=waMx1tnRaCHkaREwbLfjuMSXKI+SQBEHxnHeg9GnNcC039Le3eNH/y09QK6kGfQ6k\n\tfcCyt4/JJiA6a9HpxBxHUBhj2SdbNJN1vLvvq6gaqf6ypoaTt3oEC/se7JfmElMrpK\n\tczMkAPvJZGofQ0f126Icxvhb4U32y8x/5fJ44xxbKYW+edYljkUKRwpAzCAituz1Av\n\tJvDrfAlOX55R3KD30SP5QxEnGqVysk+9RCXTEfdzlDuJPwU/fOwcfxqRolKonMnDEQ\n\tMwbbSL7tJU0hrCFYFj7IPn7/h0ELGfV5RqWtah0UYw7DT9ULCD4I5xvP7l6i0aeaaP\n\tGMm33FBiy5icA==","From":"Robert Mader <robert.mader@collabora.com>","To":"libcamera-devel@lists.libcamera.org","Cc":"Robert Mader <robert.mader@collabora.com>","Subject":"[PATCH] libcamera: debayer_cpu: Add 32bits/aligned output formats","Date":"Tue, 11 Jun 2024 13:07:01 +0200","Message-ID":"<20240611110721.10690-1-robert.mader@collabora.com>","X-Mailer":"git-send-email 2.45.2","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"In order to be more compatible with modern hardware and APIs. This\nnotably allows GL implementations to directly import the buffers more\noften and seems to be required for Wayland.\n\nFurther more, as we already enforce a 8 byte stride, these formats work\nbetter for clients that don't support padding - such as libwebrtc at the\ntime of writing.\n\nTested on the Librem5 and PinePhone.\n\nSigned-off-by: Robert Mader <robert.mader@collabora.com>\n---\n src/libcamera/software_isp/debayer_cpu.cpp | 244 +++++++++++++++++++--\n src/libcamera/software_isp/debayer_cpu.h   |  10 +\n 2 files changed, 238 insertions(+), 16 deletions(-)","diff":"diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\nindex c038eed4..73c66a88 100644\n--- a/src/libcamera/software_isp/debayer_cpu.cpp\n+++ b/src/libcamera/software_isp/debayer_cpu.cpp\n@@ -76,6 +76,13 @@ DebayerCpu::~DebayerCpu()\n \t*dst++ = red_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \\\n \tx++;\n \n+#define BGGR_XBGR8888(p, n, div)                                                              \\\n+\t*dst++ = blue_[curr[x] / (div)];                                                      \\\n+\t*dst++ = green_[(prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div))];       \\\n+\t*dst++ = red_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \\\n+\t*dst++ = 255;                                                                         \\\n+\tx++;\n+\n /*\n  * GBG\n  * RGR\n@@ -87,6 +94,13 @@ DebayerCpu::~DebayerCpu()\n \t*dst++ = red_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \\\n \tx++;\n \n+#define GRBG_XBGR8888(p, n, div)                                  \\\n+\t*dst++ = blue_[(prev[x] + next[x]) / (2 * (div))];        \\\n+\t*dst++ = green_[curr[x] / (div)];                         \\\n+\t*dst++ = red_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \\\n+\t*dst++ = 255;                                             \\\n+\tx++;\n+\n /*\n  * GRG\n  * BGB\n@@ -98,6 +112,13 @@ DebayerCpu::~DebayerCpu()\n \t*dst++ = red_[(prev[x] + next[x]) / (2 * (div))];          \\\n \tx++;\n \n+#define GBRG_XBGR8888(p, n, div)                                   \\\n+\t*dst++ = blue_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \\\n+\t*dst++ = green_[curr[x] / (div)];                          \\\n+\t*dst++ = red_[(prev[x] + next[x]) / (2 * (div))];          \\\n+\t*dst++ = 255;                                              \\\n+\tx++;\n+\n /*\n  * BGB\n  * GRG\n@@ -109,6 +130,13 @@ DebayerCpu::~DebayerCpu()\n \t*dst++ = red_[curr[x] / (div)];                                                        \\\n \tx++;\n \n+#define RGGB_XBGR8888(p, n, div)                                                               \\\n+\t*dst++ = blue_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \\\n+\t*dst++ = green_[(prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div))];        \\\n+\t*dst++ = red_[curr[x] / (div)];                                                        \\\n+\t*dst++ = 255;                                                                          \\\n+\tx++;\n+\n void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n {\n \tDECLARE_SRC_POINTERS(uint8_t)\n@@ -119,6 +147,16 @@ void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n \t}\n }\n \n+void DebayerCpu::debayer8_BGBG_XBGR8888(uint8_t *dst, const uint8_t *src[])\n+{\n+\tDECLARE_SRC_POINTERS(uint8_t)\n+\n+\tfor (int x = 0; x < (int)window_.width;) {\n+\t\tBGGR_XBGR8888(1, 1, 1)\n+\t\tGBRG_XBGR8888(1, 1, 1)\n+\t}\n+}\n+\n void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n {\n \tDECLARE_SRC_POINTERS(uint8_t)\n@@ -129,6 +167,16 @@ void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n \t}\n }\n \n+void DebayerCpu::debayer8_GRGR_XBGR8888(uint8_t *dst, const uint8_t *src[])\n+{\n+\tDECLARE_SRC_POINTERS(uint8_t)\n+\n+\tfor (int x = 0; x < (int)window_.width;) {\n+\t\tGRBG_XBGR8888(1, 1, 1)\n+\t\tRGGB_XBGR8888(1, 1, 1)\n+\t}\n+}\n+\n void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n {\n \tDECLARE_SRC_POINTERS(uint16_t)\n@@ -140,6 +188,17 @@ void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n \t}\n }\n \n+void DebayerCpu::debayer10_BGBG_XBGR8888(uint8_t *dst, const uint8_t *src[])\n+{\n+\tDECLARE_SRC_POINTERS(uint16_t)\n+\n+\tfor (int x = 0; x < (int)window_.width;) {\n+\t\t/* divide values by 4 for 10 -> 8 bpp value */\n+\t\tBGGR_XBGR8888(1, 1, 4)\n+\t\tGBRG_XBGR8888(1, 1, 4)\n+\t}\n+}\n+\n void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n {\n \tDECLARE_SRC_POINTERS(uint16_t)\n@@ -151,6 +210,17 @@ void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n \t}\n }\n \n+void DebayerCpu::debayer10_GRGR_XBGR8888(uint8_t *dst, const uint8_t *src[])\n+{\n+\tDECLARE_SRC_POINTERS(uint16_t)\n+\n+\tfor (int x = 0; x < (int)window_.width;) {\n+\t\t/* divide values by 4 for 10 -> 8 bpp value */\n+\t\tGRBG_XBGR8888(1, 1, 4)\n+\t\tRGGB_XBGR8888(1, 1, 4)\n+\t}\n+}\n+\n void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n {\n \tDECLARE_SRC_POINTERS(uint16_t)\n@@ -162,6 +232,17 @@ void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n \t}\n }\n \n+void DebayerCpu::debayer12_BGBG_XBGR8888(uint8_t *dst, const uint8_t *src[])\n+{\n+\tDECLARE_SRC_POINTERS(uint16_t)\n+\n+\tfor (int x = 0; x < (int)window_.width;) {\n+\t\t/* divide values by 16 for 12 -> 8 bpp value */\n+\t\tBGGR_XBGR8888(1, 1, 16)\n+\t\tGBRG_XBGR8888(1, 1, 16)\n+\t}\n+}\n+\n void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n {\n \tDECLARE_SRC_POINTERS(uint16_t)\n@@ -173,6 +254,17 @@ void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n \t}\n }\n \n+void DebayerCpu::debayer12_GRGR_XBGR8888(uint8_t *dst, const uint8_t *src[])\n+{\n+\tDECLARE_SRC_POINTERS(uint16_t)\n+\n+\tfor (int x = 0; x < (int)window_.width;) {\n+\t\t/* divide values by 16 for 12 -> 8 bpp value */\n+\t\tGRBG_XBGR8888(1, 1, 16)\n+\t\tRGGB_XBGR8888(1, 1, 16)\n+\t}\n+}\n+\n void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n {\n \tconst int widthInBytes = window_.width * 5 / 4;\n@@ -198,6 +290,31 @@ void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n \t}\n }\n \n+void DebayerCpu::debayer10P_BGBG_XBGR8888(uint8_t *dst, const uint8_t *src[])\n+{\n+\tconst int widthInBytes = window_.width * 5 / 4;\n+\tconst uint8_t *prev = src[0];\n+\tconst uint8_t *curr = src[1];\n+\tconst uint8_t *next = src[2];\n+\n+\t/*\n+\t * For the first pixel getting a pixel from the previous column uses\n+\t * x - 2 to skip the 5th byte with least-significant bits for 4 pixels.\n+\t * Same for last pixel (uses x + 2) and looking at the next column.\n+\t */\n+\tfor (int x = 0; x < widthInBytes;) {\n+\t\t/* First pixel */\n+\t\tBGGR_XBGR8888(2, 1, 1)\n+\t\t/* Second pixel BGGR -> GBRG */\n+\t\tGBRG_XBGR8888(1, 1, 1)\n+\t\t/* Same thing for third and fourth pixels */\n+\t\tBGGR_XBGR8888(1, 1, 1)\n+\t\tGBRG_XBGR8888(1, 2, 1)\n+\t\t/* Skip 5th src byte with 4 x 2 least-significant-bits */\n+\t\tx++;\n+\t}\n+}\n+\n void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n {\n \tconst int widthInBytes = window_.width * 5 / 4;\n@@ -218,6 +335,26 @@ void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n \t}\n }\n \n+void DebayerCpu::debayer10P_GRGR_XBGR8888(uint8_t *dst, const uint8_t *src[])\n+{\n+\tconst int widthInBytes = window_.width * 5 / 4;\n+\tconst uint8_t *prev = src[0];\n+\tconst uint8_t *curr = src[1];\n+\tconst uint8_t *next = src[2];\n+\n+\tfor (int x = 0; x < widthInBytes;) {\n+\t\t/* First pixel */\n+\t\tGRBG_XBGR8888(2, 1, 1)\n+\t\t/* Second pixel GRBG -> RGGB */\n+\t\tRGGB_XBGR8888(1, 1, 1)\n+\t\t/* Same thing for third and fourth pixels */\n+\t\tGRBG_XBGR8888(1, 1, 1)\n+\t\tRGGB_XBGR8888(1, 2, 1)\n+\t\t/* Skip 5th src byte with 4 x 2 least-significant-bits */\n+\t\tx++;\n+\t}\n+}\n+\n void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[])\n {\n \tconst int widthInBytes = window_.width * 5 / 4;\n@@ -238,6 +375,26 @@ void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[])\n \t}\n }\n \n+void DebayerCpu::debayer10P_GBGB_XBGR8888(uint8_t *dst, const uint8_t *src[])\n+{\n+\tconst int widthInBytes = window_.width * 5 / 4;\n+\tconst uint8_t *prev = src[0];\n+\tconst uint8_t *curr = src[1];\n+\tconst uint8_t *next = src[2];\n+\n+\tfor (int x = 0; x < widthInBytes;) {\n+\t\t/* Even pixel */\n+\t\tGBRG_XBGR8888(2, 1, 1)\n+\t\t/* Odd pixel GBGR -> BGGR */\n+\t\tBGGR_XBGR8888(1, 1, 1)\n+\t\t/* Same thing for next 2 pixels */\n+\t\tGBRG_XBGR8888(1, 1, 1)\n+\t\tBGGR_XBGR8888(1, 2, 1)\n+\t\t/* Skip 5th src byte with 4 x 2 least-significant-bits */\n+\t\tx++;\n+\t}\n+}\n+\n void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[])\n {\n \tconst int widthInBytes = window_.width * 5 / 4;\n@@ -258,6 +415,26 @@ void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[])\n \t}\n }\n \n+void DebayerCpu::debayer10P_RGRG_XBGR8888(uint8_t *dst, const uint8_t *src[])\n+{\n+\tconst int widthInBytes = window_.width * 5 / 4;\n+\tconst uint8_t *prev = src[0];\n+\tconst uint8_t *curr = src[1];\n+\tconst uint8_t *next = src[2];\n+\n+\tfor (int x = 0; x < widthInBytes;) {\n+\t\t/* Even pixel */\n+\t\tRGGB_XBGR8888(2, 1, 1)\n+\t\t/* Odd pixel RGGB -> GRBG */\n+\t\tGRBG_XBGR8888(1, 1, 1)\n+\t\t/* Same thing for next 2 pixels */\n+\t\tRGGB_XBGR8888(1, 1, 1)\n+\t\tGRBG_XBGR8888(1, 2, 1)\n+\t\t/* Skip 5th src byte with 4 x 2 least-significant-bits */\n+\t\tx++;\n+\t}\n+}\n+\n static bool isStandardBayerOrder(BayerFormat::Order order)\n {\n \treturn order == BayerFormat::BGGR || order == BayerFormat::GBRG ||\n@@ -280,7 +457,14 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf\n \t\tconfig.bpp = (bayerFormat.bitDepth + 7) & ~7;\n \t\tconfig.patternSize.width = 2;\n \t\tconfig.patternSize.height = 2;\n-\t\tconfig.outputFormats = std::vector<PixelFormat>({ formats::RGB888, formats::BGR888 });\n+\t\tconfig.outputFormats = std::vector<PixelFormat>({\n+\t\t\tformats::RGB888,\n+\t\t\tformats::XRGB8888,\n+\t\t\tformats::ARGB8888,\n+\t\t\tformats::BGR888,\n+\t\t\tformats::XBGR8888,\n+\t\t\tformats::ABGR8888\n+\t\t});\n \t\treturn 0;\n \t}\n \n@@ -290,7 +474,14 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf\n \t\tconfig.bpp = 10;\n \t\tconfig.patternSize.width = 4; /* 5 bytes per *4* pixels */\n \t\tconfig.patternSize.height = 2;\n-\t\tconfig.outputFormats = std::vector<PixelFormat>({ formats::RGB888, formats::BGR888 });\n+\t\tconfig.outputFormats = std::vector<PixelFormat>({\n+\t\t\tformats::RGB888,\n+\t\t\tformats::XRGB8888,\n+\t\t\tformats::ARGB8888,\n+\t\t\tformats::BGR888,\n+\t\t\tformats::XBGR8888,\n+\t\t\tformats::ABGR8888\n+\t\t});\n \t\treturn 0;\n \t}\n \n@@ -306,6 +497,12 @@ int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c\n \t\treturn 0;\n \t}\n \n+\tif (outputFormat == formats::XRGB8888 || outputFormat == formats::ARGB8888 ||\n+\t    outputFormat == formats::XBGR8888 || outputFormat == formats::ABGR8888) {\n+\t\tconfig.bpp = 32;\n+\t\treturn 0;\n+\t}\n+\n \tLOG(Debayer, Info)\n \t\t<< \"Unsupported output format \" << outputFormat.toString();\n \treturn -EINVAL;\n@@ -341,6 +538,7 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF\n {\n \tBayerFormat bayerFormat =\n \t\tBayerFormat::fromPixelFormat(inputFormat);\n+\tbool is_aligned = false;\n \n \txShift_ = 0;\n \tswapRedBlueGains_ = false;\n@@ -351,8 +549,16 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF\n \t};\n \n \tswitch (outputFormat) {\n+\tcase formats::XRGB8888:\n+\tcase formats::ARGB8888:\n+\t  is_aligned = true;\n+\t  [[fallthrough]];\n \tcase formats::RGB888:\n \t\tbreak;\n+\tcase formats::XBGR8888:\n+\tcase formats::ABGR8888:\n+\t  is_aligned = true;\n+\t  [[fallthrough]];\n \tcase formats::BGR888:\n \t\t/* Swap R and B in bayer order to generate BGR888 instead of RGB888 */\n \t\tswapRedBlueGains_ = true;\n@@ -383,16 +589,19 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF\n \t    isStandardBayerOrder(bayerFormat.order)) {\n \t\tswitch (bayerFormat.bitDepth) {\n \t\tcase 8:\n-\t\t\tdebayer0_ = &DebayerCpu::debayer8_BGBG_BGR888;\n-\t\t\tdebayer1_ = &DebayerCpu::debayer8_GRGR_BGR888;\n+\t\t  LOG(Debayer, Warning) << \"8bit no packing\";\n+\t\t  debayer0_ = is_aligned ? &DebayerCpu::debayer8_BGBG_XBGR8888 : &DebayerCpu::debayer8_BGBG_BGR888;\n+\t\t  debayer1_ = is_aligned ? &DebayerCpu::debayer8_GRGR_XBGR8888 : &DebayerCpu::debayer8_GRGR_BGR888;\n \t\t\tbreak;\n \t\tcase 10:\n-\t\t\tdebayer0_ = &DebayerCpu::debayer10_BGBG_BGR888;\n-\t\t\tdebayer1_ = &DebayerCpu::debayer10_GRGR_BGR888;\n+\t\t  LOG(Debayer, Warning) << \"10bit no packing\";\n+\t\t\tdebayer0_ = is_aligned ? &DebayerCpu::debayer10_BGBG_XBGR8888 : &DebayerCpu::debayer10_BGBG_BGR888;\n+\t\t\tdebayer1_ = is_aligned ? &DebayerCpu::debayer10_GRGR_XBGR8888 : &DebayerCpu::debayer10_GRGR_BGR888;\n \t\t\tbreak;\n \t\tcase 12:\n-\t\t\tdebayer0_ = &DebayerCpu::debayer12_BGBG_BGR888;\n-\t\t\tdebayer1_ = &DebayerCpu::debayer12_GRGR_BGR888;\n+\t\t  LOG(Debayer, Warning) << \"12bit no packing\";\n+\t\t\tdebayer0_ = is_aligned ? &DebayerCpu::debayer12_BGBG_XBGR8888 : &DebayerCpu::debayer12_BGBG_BGR888;\n+\t\t\tdebayer1_ = is_aligned ? &DebayerCpu::debayer12_GRGR_XBGR8888 : &DebayerCpu::debayer12_GRGR_BGR888;\n \t\t\tbreak;\n \t\t}\n \t\tsetupStandardBayerOrder(bayerFormat.order);\n@@ -401,22 +610,23 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF\n \n \tif (bayerFormat.bitDepth == 10 &&\n \t    bayerFormat.packing == BayerFormat::Packing::CSI2) {\n+\t  LOG(Debayer, Warning) << \"10bit csi2\";\n \t\tswitch (bayerFormat.order) {\n \t\tcase BayerFormat::BGGR:\n-\t\t\tdebayer0_ = &DebayerCpu::debayer10P_BGBG_BGR888;\n-\t\t\tdebayer1_ = &DebayerCpu::debayer10P_GRGR_BGR888;\n+\t\t\tdebayer0_ = is_aligned ? &DebayerCpu::debayer10P_BGBG_XBGR8888 : &DebayerCpu::debayer10P_BGBG_BGR888;\n+\t\t\tdebayer1_ = is_aligned ? &DebayerCpu::debayer10P_GRGR_XBGR8888 : &DebayerCpu::debayer10P_GRGR_BGR888;\n \t\t\treturn 0;\n \t\tcase BayerFormat::GBRG:\n-\t\t\tdebayer0_ = &DebayerCpu::debayer10P_GBGB_BGR888;\n-\t\t\tdebayer1_ = &DebayerCpu::debayer10P_RGRG_BGR888;\n+\t\t\tdebayer0_ = is_aligned ? &DebayerCpu::debayer10P_GBGB_XBGR8888 : &DebayerCpu::debayer10P_GBGB_BGR888;\n+\t\t\tdebayer1_ = is_aligned ? &DebayerCpu::debayer10P_RGRG_XBGR8888 : &DebayerCpu::debayer10P_RGRG_BGR888;\n \t\t\treturn 0;\n \t\tcase BayerFormat::GRBG:\n-\t\t\tdebayer0_ = &DebayerCpu::debayer10P_GRGR_BGR888;\n-\t\t\tdebayer1_ = &DebayerCpu::debayer10P_BGBG_BGR888;\n+\t\t\tdebayer0_ = is_aligned ? &DebayerCpu::debayer10P_GRGR_XBGR8888 : &DebayerCpu::debayer10P_GRGR_BGR888;\n+\t\t\tdebayer1_ = is_aligned ? &DebayerCpu::debayer10P_BGBG_XBGR8888 : &DebayerCpu::debayer10P_BGBG_BGR888;\n \t\t\treturn 0;\n \t\tcase BayerFormat::RGGB:\n-\t\t\tdebayer0_ = &DebayerCpu::debayer10P_RGRG_BGR888;\n-\t\t\tdebayer1_ = &DebayerCpu::debayer10P_GBGB_BGR888;\n+\t\t\tdebayer0_ = is_aligned ? &DebayerCpu::debayer10P_RGRG_XBGR8888 : &DebayerCpu::debayer10P_RGRG_BGR888;\n+\t\t\tdebayer1_ = is_aligned ? &DebayerCpu::debayer10P_GBGB_XBGR8888 : &DebayerCpu::debayer10P_GBGB_BGR888;\n \t\t\treturn 0;\n \t\tdefault:\n \t\t\tbreak;\n@@ -533,6 +743,8 @@ DebayerCpu::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size\n \t/* round up to multiple of 8 for 64 bits alignment */\n \tunsigned int stride = (size.width * config.bpp / 8 + 7) & ~7;\n \n+\tLOG(Debayer, Warning) << outputFormat.toString() << \" \" << size.width << \" \" << size.height << \" \" << config.bpp << \" \" << stride << \" \" << stride * size.height;\n+\n \treturn std::make_tuple(stride, stride * size.height);\n }\n \ndiff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\nindex be7dcdca..c30f44aa 100644\n--- a/src/libcamera/software_isp/debayer_cpu.h\n+++ b/src/libcamera/software_isp/debayer_cpu.h\n@@ -86,18 +86,28 @@ private:\n \n \t/* 8-bit raw bayer format */\n \tvoid debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n+\tvoid debayer8_BGBG_XBGR8888(uint8_t *dst, const uint8_t *src[]);\n \tvoid debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n+\tvoid debayer8_GRGR_XBGR8888(uint8_t *dst, const uint8_t *src[]);\n \t/* unpacked 10-bit raw bayer format */\n \tvoid debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n+\tvoid debayer10_BGBG_XBGR8888(uint8_t *dst, const uint8_t *src[]);\n \tvoid debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n+\tvoid debayer10_GRGR_XBGR8888(uint8_t *dst, const uint8_t *src[]);\n \t/* unpacked 12-bit raw bayer format */\n \tvoid debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n+\tvoid debayer12_BGBG_XBGR8888(uint8_t *dst, const uint8_t *src[]);\n \tvoid debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n+\tvoid debayer12_GRGR_XBGR8888(uint8_t *dst, const uint8_t *src[]);\n \t/* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */\n \tvoid debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n+\tvoid debayer10P_BGBG_XBGR8888(uint8_t *dst, const uint8_t *src[]);\n \tvoid debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n+\tvoid debayer10P_GRGR_XBGR8888(uint8_t *dst, const uint8_t *src[]);\n \tvoid debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]);\n+\tvoid debayer10P_GBGB_XBGR8888(uint8_t *dst, const uint8_t *src[]);\n \tvoid debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]);\n+\tvoid debayer10P_RGRG_XBGR8888(uint8_t *dst, const uint8_t *src[]);\n \n \tstruct DebayerInputConfig {\n \t\tSize patternSize;\n","prefixes":[]}