From patchwork Thu Jun 18 12:22:26 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26946 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 09728BF415 for ; Thu, 18 Jun 2026 12:23:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6983F656C7; Thu, 18 Jun 2026 14:23:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="osAukbaX"; dkim-atps=neutral Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 98D1C62B2B for ; Thu, 18 Jun 2026 14:23:07 +0200 (CEST) Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-490b613a17bso6482045e9.3 for ; Thu, 18 Jun 2026 05:23:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785387; x=1782390187; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=oHBRpAaxg79VoY7KRUqI2QqDEabR3Qd+XLpjHZnpia4=; b=osAukbaXFwPLDJRWjC/C1Vm8RQpGMY5Er3HZNocTuRT2FeRre11mv4M3WpFgwITupD 7JytcX2lCo05Fyv96EWKpjY1RjqxaYL4xmd9EZq2BzYgnWip2R8YfGI0V05tsz4Pk/wG 5dHZB2ONugEWmxI8GYwKD/3tJSIa2fBSpmYHBbP1rNrh8dEBvSdUm5NfpD/vqVgVTiaV 7z43ns0n5IxkKc5r668KAGrJh3aCyCu39vEEpPuRIifyC+kkznkch4R6YRocN3aywNGR sgdvX+Cvw4RkUKdj8zJ0Dm0WEsRACS0M3cKEYhP+qTDtta1/3jzhY8inOYPGwekKTNov uEUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785387; x=1782390187; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=oHBRpAaxg79VoY7KRUqI2QqDEabR3Qd+XLpjHZnpia4=; b=Y+8rHuOhAfDswLtcBFrtUzO3Fkcsi8/vx1G5DOBExi1R8K27SitNg+gBJZU/J3VS+a k3qJgHTwrz8amDZZi1AUO2y8ERuhL/ka0NJkbnJyZYHgxShhLvz1eOfIWWEIZCP5xE/X lGVyYRuRVIUmQu9Km583uZ6Vts5IL4M2UuLf2ormo9E4wncNw2RnbI9eONDhqBqb2XXA lOyNcKvaU5Fm4YnwpaPsc6KbDYKCpKq+1ODAESqC0kzqvVyw5Cfq49kkhEIFoyxlvKpF ADWhnPJbKn1/QoXVjTiLvKoz3q57xjHncrYeKDIXOZ9+yugaYOjjSsjMZopG1li1D8J4 viYg== X-Gm-Message-State: AOJu0YyhFYHq0vCDwsXxVu8HKnBgOmHzc+Yyq8iXF0z7VHl0O7vVP5K1 EwbYVbw727JHDRwm9TmzopU8xEPpYRU8zCGzbwF7cZ1RzzERsFvjI8Xp2CudI+1H5s8g1/iT1kQ goINmlSs= X-Gm-Gg: AfdE7clJSW2MOl/4JKEcbV2HB+lpd1ASKRznhamAXEWBXz3+uIREp8DlwFJDKq1Wmy7 bU1nNKjImrmffYkHSfVoyJIxOFT/ZmJH90Qc+lg3ompCHs95upauog8ZwpEuzwUgekN/u8cAsnk 7j7DOKyzKiAkqIze80pCAQa/ciYyS/ssi9Yrm4itcZ4w/6Ce21KOd9mtHytI7qV78X9JNy19dBA IuzclMKjjlvVOZKNC9UkqIqZRbnZtrHMdSF9lo3l6wuTF+AGOsgqOZmVvjd5ntdfKKk+iBWRYZ3 x5uZN8U3ujrFG6r0dLmuzmNmzd1y11cJOc1etLdlacrqtHZa2rDYEwHJTW/vFdw6L2XAloSzlrz vNpB2fUo09rUJarkhDl74ASAzRgwtPg8rGsLpIu25bOfdjquQkwqpm/ssCaqorks4/Pv0hDjkFb 31BpnWthsDv6kFefpHS/c6woYaLbPk X-Received: by 2002:a05:600c:6085:b0:490:ec79:3077 with SMTP id 5b1f17b1804b1-4923a99cee0mr33476775e9.16.1781785387019; Thu, 18 Jun 2026 05:23:07 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:06 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 13/30] libcamera: shaders: bayer_glr16_to_rgba.frag: Use bilinear 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 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Signed-off-by: Bryan O'Donoghue --- .../shaders/bayer_glr16_to_rgba.frag | 114 +++++++----------- 1 file changed, 43 insertions(+), 71 deletions(-) diff --git a/src/libcamera/shaders/bayer_glr16_to_rgba.frag b/src/libcamera/shaders/bayer_glr16_to_rgba.frag index f3883a82b..4a2e5af87 100644 --- a/src/libcamera/shaders/bayer_glr16_to_rgba.frag +++ b/src/libcamera/shaders/bayer_glr16_to_rgba.frag @@ -44,81 +44,53 @@ void main(void) { #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r float C = fetch(center.x, center.y); // ( 0, 0) - const vec4 kC = vec4( 4.0, 6.0, 5.0, 5.0) / 8.0; - // Determine which of four types of pixels we are on. + /* Which of the four CFA phases are we on (0 = even). Same as McGuire. */ vec2 alternate = mod(floor(center.zw), 2.0); + bool even_col = alternate.x < 1.0; + bool even_row = alternate.y < 1.0; - vec4 Dvec = vec4( - fetch(xCoord[1], yCoord[1]), // (-1,-1) - fetch(xCoord[1], yCoord[2]), // (-1, 1) - fetch(xCoord[2], yCoord[1]), // ( 1,-1) - fetch(xCoord[2], yCoord[2])); // ( 1, 1) - - vec4 PATTERN = (kC.xyz * C).xyzz; - - // Can also be a dot product with (1,1,1,1) on hardware where that is - // specially optimized. - // Equivalent to: D = Dvec[0] + Dvec[1] + Dvec[2] + Dvec[3]; - Dvec.xy += Dvec.zw; - Dvec.x += Dvec.y; - - vec4 value = vec4( - fetch(center.x, yCoord[0]), // ( 0,-2) - fetch(center.x, yCoord[1]), // ( 0,-1) - fetch(xCoord[0], center.y), // (-2, 0) - fetch(xCoord[1], center.y)); // (-1, 0) - + /* + * +----+----+----+ + * | D2 | A1 | D3 | + * +----+----+----+ + * | B0 | C | B1 | + * +----+----+----+ + * | D0 | A0 | D1 | + * +----+----+----+ + * + * patterns.x = (A0 + A1) / 2 vertical neighbours + * patterns.y = (B0 + B1) / 2 horizontal neighbours + * patterns.z = (A0+A1+B0+B1) / 4 cross average (green at R/B sites) + * patterns.w = (D0+D1+D2+D3) / 4 diagonal average (other colour at R/B sites) + * + * xCoord[1] = -1, xCoord[2] = +1, yCoord[1] = -1, yCoord[2] = +1 + * (xCoord[0]/[3] and yCoord[0]/[3] = +-2 are unused here; the vertex + * shader still emits them so the VS is identical to the McGuire path). + */ + vec4 patterns = vec4( + fetch(center.x, yCoord[1]), /* A0: ( 0,-1) */ + fetch(xCoord[1], center.y), /* B0: (-1, 0) */ + fetch(xCoord[1], yCoord[1]), /* D0: (-1,-1) */ + fetch(xCoord[2], yCoord[1])); /* D1: ( 1,-1) */ vec4 temp = vec4( - fetch(center.x, yCoord[3]), // ( 0, 2) - fetch(center.x, yCoord[2]), // ( 0, 1) - fetch(xCoord[3], center.y), // ( 2, 0) - fetch(xCoord[2], center.y)); // ( 1, 0) - - // Even the simplest compilers should be able to constant-fold these to - // avoid the division. - // Note that on scalar processors these constants force computation of some - // identical products twice. - const vec4 kA = vec4(-1.0, -1.5, 0.5, -1.0) / 8.0; - const vec4 kB = vec4( 2.0, 0.0, 0.0, 4.0) / 8.0; - const vec4 kD = vec4( 0.0, 2.0, -1.0, -1.0) / 8.0; - - // Conserve constant registers and take advantage of free swizzle on load - #define kE (kA.xywz) - #define kF (kB.xywz) - - value += temp; - - // There are five filter patterns (identity, cross, checker, - // theta, phi). Precompute the terms from all of them and then - // use swizzles to assign to color channels. - // - // Channel Matches - // x cross (e.g., EE G) - // y checker (e.g., EE B) - // z theta (e.g., EO R) - // w phi (e.g., EO R) - #define A (value[0]) - #define B (value[1]) - #define D (Dvec.x) - #define E (value[2]) - #define F (value[3]) - - // Avoid zero elements. On a scalar processor this saves two MADDs - // and it has no effect on a vector processor. - PATTERN.yzw += (kD.yz * D).xyy; - - PATTERN += (kA.xyz * A).xyzx + (kE.xyw * E).xyxz; - PATTERN.xw += kB.xw * B; - PATTERN.xz += kF.xz * F; - - rgb = (alternate.y == 0.0) ? - ((alternate.x == 0.0) ? - vec3(C, PATTERN.xy) : - vec3(PATTERN.z, C, PATTERN.w)) : - ((alternate.x == 0.0) ? - vec3(PATTERN.w, C, PATTERN.z) : - vec3(PATTERN.yx, C)); + fetch(center.x, yCoord[2]), /* A1: ( 0, 1) */ + fetch(xCoord[2], center.y), /* B1: ( 1, 0) */ + fetch(xCoord[2], yCoord[2]), /* D3: ( 1, 1) */ + fetch(xCoord[1], yCoord[2])); /* D2: (-1, 1) */ + + patterns = (patterns + temp) * 0.5; + /* .x=(A0+A1)/2 .y=(B0+B1)/2 .z=(D0+D3)/2 .w=(D1+D2)/2 */ + patterns.w = (patterns.z + patterns.w) * 0.5; /* diagonal avg */ + patterns.z = (patterns.x + patterns.y) * 0.5; /* cross avg */ + + rgb = even_col ? + (even_row ? + vec3(C, patterns.zw) : + vec3(patterns.x, C, patterns.y)) : + (even_row ? + vec3(patterns.y, C, patterns.x) : + vec3(patterns.wz, C)); /* * CCM is a 3x3 in the format