{"id":26946,"url":"https://patchwork.libcamera.org/api/patches/26946/?format=json","web_url":"https://patchwork.libcamera.org/patch/26946/","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":"<20260618122245.946138-14-bryan.odonoghue@linaro.org>","date":"2026-06-18T12:22:26","name":"[13/30] libcamera: shaders: bayer_glr16_to_rgba.frag: Use bilinear filtering","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"8db8e8ca37e91591be1df616b62b770035c7cb4b","submitter":{"id":175,"url":"https://patchwork.libcamera.org/api/people/175/?format=json","name":"Bryan O'Donoghue","email":"bryan.odonoghue@linaro.org"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/26946/mbox/","series":[{"id":6005,"url":"https://patchwork.libcamera.org/api/series/6005/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=6005","date":"2026-06-18T12:22:13","name":"RFC/RFT: gpuisp: Multipass with speed optimisations on top","version":1,"mbox":"https://patchwork.libcamera.org/series/6005/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/26946/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/26946/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 09728BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 18 Jun 2026 12:23:25 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6983F656C7;\n\tThu, 18 Jun 2026 14:23:24 +0200 (CEST)","from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com\n\t[IPv6:2a00:1450:4864:20::32a])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 98D1C62B2B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 18 Jun 2026 14:23:07 +0200 (CEST)","by mail-wm1-x32a.google.com with SMTP id\n\t5b1f17b1804b1-490b613a17bso6482045e9.3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 18 Jun 2026 05:23:07 -0700 (PDT)","from inspiron14p-linux ([109.76.144.236])\n\tby smtp.gmail.com with ESMTPSA id\n\t5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.06\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 18 Jun 2026 05:23:06 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=linaro.org header.i=@linaro.org\n\theader.b=\"osAukbaX\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=linaro.org; s=google; t=1781785387; x=1782390187;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=oHBRpAaxg79VoY7KRUqI2QqDEabR3Qd+XLpjHZnpia4=;\n\tb=osAukbaXFwPLDJRWjC/C1Vm8RQpGMY5Er3HZNocTuRT2FeRre11mv4M3WpFgwITupD\n\t7JytcX2lCo05Fyv96EWKpjY1RjqxaYL4xmd9EZq2BzYgnWip2R8YfGI0V05tsz4Pk/wG\n\t5dHZB2ONugEWmxI8GYwKD/3tJSIa2fBSpmYHBbP1rNrh8dEBvSdUm5NfpD/vqVgVTiaV\n\t7z43ns0n5IxkKc5r668KAGrJh3aCyCu39vEEpPuRIifyC+kkznkch4R6YRocN3aywNGR\n\tsgdvX+Cvw4RkUKdj8zJ0Dm0WEsRACS0M3cKEYhP+qTDtta1/3jzhY8inOYPGwekKTNov\n\tuEUg==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1781785387; x=1782390187;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n\t:to:cc:subject:date:message-id:reply-to;\n\tbh=oHBRpAaxg79VoY7KRUqI2QqDEabR3Qd+XLpjHZnpia4=;\n\tb=Y+8rHuOhAfDswLtcBFrtUzO3Fkcsi8/vx1G5DOBExi1R8K27SitNg+gBJZU/J3VS+a\n\tk3qJgHTwrz8amDZZi1AUO2y8ERuhL/ka0NJkbnJyZYHgxShhLvz1eOfIWWEIZCP5xE/X\n\tlGVyYRuRVIUmQu9Km583uZ6Vts5IL4M2UuLf2ormo9E4wncNw2RnbI9eONDhqBqb2XXA\n\tlOyNcKvaU5Fm4YnwpaPsc6KbDYKCpKq+1ODAESqC0kzqvVyw5Cfq49kkhEIFoyxlvKpF\n\tADWhnPJbKn1/QoXVjTiLvKoz3q57xjHncrYeKDIXOZ9+yugaYOjjSsjMZopG1li1D8J4\n\tviYg==","X-Gm-Message-State":"AOJu0YyhFYHq0vCDwsXxVu8HKnBgOmHzc+Yyq8iXF0z7VHl0O7vVP5K1\n\tEwbYVbw727JHDRwm9TmzopU8xEPpYRU8zCGzbwF7cZ1RzzERsFvjI8Xp2CudI+1H5s8g1/iT1kQ\n\tgoINmlSs=","X-Gm-Gg":"AfdE7clJSW2MOl/4JKEcbV2HB+lpd1ASKRznhamAXEWBXz3+uIREp8DlwFJDKq1Wmy7\n\tbU1nNKjImrmffYkHSfVoyJIxOFT/ZmJH90Qc+lg3ompCHs95upauog8ZwpEuzwUgekN/u8cAsnk\n\t7j7DOKyzKiAkqIze80pCAQa/ciYyS/ssi9Yrm4itcZ4w/6Ce21KOd9mtHytI7qV78X9JNy19dBA\n\tIuzclMKjjlvVOZKNC9UkqIqZRbnZtrHMdSF9lo3l6wuTF+AGOsgqOZmVvjd5ntdfKKk+iBWRYZ3\n\tx5uZN8U3ujrFG6r0dLmuzmNmzd1y11cJOc1etLdlacrqtHZa2rDYEwHJTW/vFdw6L2XAloSzlrz\n\tvNpB2fUo09rUJarkhDl74ASAzRgwtPg8rGsLpIu25bOfdjquQkwqpm/ssCaqorks4/Pv0hDjkFb\n\t31BpnWthsDv6kFefpHS/c6woYaLbPk","X-Received":"by 2002:a05:600c:6085:b0:490:ec79:3077 with SMTP id\n\t5b1f17b1804b1-4923a99cee0mr33476775e9.16.1781785387019; \n\tThu, 18 Jun 2026 05:23:07 -0700 (PDT)","From":"Bryan O'Donoghue <bryan.odonoghue@linaro.org>","To":"libcamera-devel@lists.libcamera.org","Cc":"bryan.odonoghue@linaro.org,\n\tpavel@ucw.cz","Subject":"[PATCH 13/30] libcamera: shaders: bayer_glr16_to_rgba.frag: Use\n\tbilinear filtering","Date":"Thu, 18 Jun 2026 13:22:26 +0100","Message-ID":"<20260618122245.946138-14-bryan.odonoghue@linaro.org>","X-Mailer":"git-send-email 2.54.0","In-Reply-To":"<20260618122245.946138-1-bryan.odonoghue@linaro.org>","References":"<20260618122245.946138-1-bryan.odonoghue@linaro.org>","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":"Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>\n---\n .../shaders/bayer_glr16_to_rgba.frag          | 114 +++++++-----------\n 1 file changed, 43 insertions(+), 71 deletions(-)","diff":"diff --git a/src/libcamera/shaders/bayer_glr16_to_rgba.frag b/src/libcamera/shaders/bayer_glr16_to_rgba.frag\nindex f3883a82b..4a2e5af87 100644\n--- a/src/libcamera/shaders/bayer_glr16_to_rgba.frag\n+++ b/src/libcamera/shaders/bayer_glr16_to_rgba.frag\n@@ -44,81 +44,53 @@ void main(void) {\n \t#define fetch(x, y) texture2D(tex_y, vec2(x, y)).r\n \n \tfloat C = fetch(center.x, center.y); // ( 0, 0)\n-\tconst vec4 kC = vec4( 4.0,  6.0,  5.0,  5.0) / 8.0;\n \n-\t// Determine which of four types of pixels we are on.\n+\t/* Which of the four CFA phases are we on (0 = even). Same as McGuire. */\n \tvec2 alternate = mod(floor(center.zw), 2.0);\n+\tbool even_col = alternate.x < 1.0;\n+\tbool even_row = alternate.y < 1.0;\n \n-\tvec4 Dvec = vec4(\n-\t\tfetch(xCoord[1], yCoord[1]),  // (-1,-1)\n-\t\tfetch(xCoord[1], yCoord[2]),  // (-1, 1)\n-\t\tfetch(xCoord[2], yCoord[1]),  // ( 1,-1)\n-\t\tfetch(xCoord[2], yCoord[2])); // ( 1, 1)\n-\n-\tvec4 PATTERN = (kC.xyz * C).xyzz;\n-\n-\t// Can also be a dot product with (1,1,1,1) on hardware where that is\n-\t// specially optimized.\n-\t// Equivalent to: D = Dvec[0] + Dvec[1] + Dvec[2] + Dvec[3];\n-\tDvec.xy += Dvec.zw;\n-\tDvec.x  += Dvec.y;\n-\n-\tvec4 value = vec4(\n-\t\tfetch(center.x, yCoord[0]),   // ( 0,-2)\n-\t\tfetch(center.x, yCoord[1]),   // ( 0,-1)\n-\t\tfetch(xCoord[0], center.y),   // (-2, 0)\n-\t\tfetch(xCoord[1], center.y));  // (-1, 0)\n-\n+\t/*\n+\t *   +----+----+----+\n+\t *   | D2 | A1 | D3 |\n+\t *   +----+----+----+\n+\t *   | B0 |  C | B1 |\n+\t *   +----+----+----+\n+\t *   | D0 | A0 | D1 |\n+\t *   +----+----+----+\n+\t *\n+\t * patterns.x = (A0 + A1) / 2      vertical neighbours\n+\t * patterns.y = (B0 + B1) / 2      horizontal neighbours\n+\t * patterns.z = (A0+A1+B0+B1) / 4  cross average  (green at R/B sites)\n+\t * patterns.w = (D0+D1+D2+D3) / 4  diagonal average (other colour at R/B sites)\n+\t *\n+\t * xCoord[1] = -1, xCoord[2] = +1, yCoord[1] = -1, yCoord[2] = +1\n+\t * (xCoord[0]/[3] and yCoord[0]/[3] = +-2 are unused here; the vertex\n+\t *  shader still emits them so the VS is identical to the McGuire path).\n+\t */\n+\tvec4 patterns = vec4(\n+\t\tfetch(center.x,  yCoord[1]),\t/* A0: ( 0,-1) */\n+\t\tfetch(xCoord[1], center.y),\t/* B0: (-1, 0) */\n+\t\tfetch(xCoord[1], yCoord[1]),\t/* D0: (-1,-1) */\n+\t\tfetch(xCoord[2], yCoord[1]));\t/* D1: ( 1,-1) */\n \tvec4 temp = vec4(\n-\t\tfetch(center.x, yCoord[3]),   // ( 0, 2)\n-\t\tfetch(center.x, yCoord[2]),   // ( 0, 1)\n-\t\tfetch(xCoord[3], center.y),   // ( 2, 0)\n-\t\tfetch(xCoord[2], center.y));  // ( 1, 0)\n-\n-\t// Even the simplest compilers should be able to constant-fold these to\n-\t// avoid the division.\n-\t// Note that on scalar processors these constants force computation of some\n-\t// identical products twice.\n-\tconst vec4 kA = vec4(-1.0, -1.5,  0.5, -1.0) / 8.0;\n-\tconst vec4 kB = vec4( 2.0,  0.0,  0.0,  4.0) / 8.0;\n-\tconst vec4 kD = vec4( 0.0,  2.0, -1.0, -1.0) / 8.0;\n-\n-\t// Conserve constant registers and take advantage of free swizzle on load\n-\t#define kE (kA.xywz)\n-\t#define kF (kB.xywz)\n-\n-\tvalue += temp;\n-\n-\t// There are five filter patterns (identity, cross, checker,\n-\t// theta, phi).  Precompute the terms from all of them and then\n-\t// use swizzles to assign to color channels.\n-\t//\n-\t// Channel   Matches\n-\t//   x       cross   (e.g., EE G)\n-\t//   y       checker (e.g., EE B)\n-\t//   z       theta   (e.g., EO R)\n-\t//   w       phi     (e.g., EO R)\n-\t#define A (value[0])\n-\t#define B (value[1])\n-\t#define D (Dvec.x)\n-\t#define E (value[2])\n-\t#define F (value[3])\n-\n-\t// Avoid zero elements. On a scalar processor this saves two MADDs\n-\t// and it has no effect on a vector processor.\n-\tPATTERN.yzw += (kD.yz * D).xyy;\n-\n-\tPATTERN += (kA.xyz * A).xyzx + (kE.xyw * E).xyxz;\n-\tPATTERN.xw  += kB.xw * B;\n-\tPATTERN.xz  += kF.xz * F;\n-\n-\trgb =  (alternate.y == 0.0) ?\n-\t((alternate.x == 0.0) ?\n-\t\tvec3(C, PATTERN.xy) :\n-\t\tvec3(PATTERN.z, C, PATTERN.w)) :\n-\t((alternate.x == 0.0) ?\n-\t\tvec3(PATTERN.w, C, PATTERN.z) :\n-\t\tvec3(PATTERN.yx, C));\n+\t\tfetch(center.x,  yCoord[2]),\t/* A1: ( 0, 1) */\n+\t\tfetch(xCoord[2], center.y),\t/* B1: ( 1, 0) */\n+\t\tfetch(xCoord[2], yCoord[2]),\t/* D3: ( 1, 1) */\n+\t\tfetch(xCoord[1], yCoord[2]));\t/* D2: (-1, 1) */\n+\n+\tpatterns = (patterns + temp) * 0.5;\n+\t\t/* .x=(A0+A1)/2  .y=(B0+B1)/2  .z=(D0+D3)/2  .w=(D1+D2)/2 */\n+\tpatterns.w = (patterns.z + patterns.w) * 0.5;\t/* diagonal avg */\n+\tpatterns.z = (patterns.x + patterns.y) * 0.5;\t/* cross avg */\n+\n+\trgb = even_col ?\n+\t\t(even_row ?\n+\t\t\tvec3(C, patterns.zw) :\n+\t\t\tvec3(patterns.x, C, patterns.y)) :\n+\t\t(even_row ?\n+\t\t\tvec3(patterns.y, C, patterns.x) :\n+\t\t\tvec3(patterns.wz, C));\n \n \t/*\n \t*   CCM is a 3x3 in the format\n","prefixes":["13/30"]}