From patchwork Tue Jun 30 12:52:10 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 27143 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 A4E1AC3261 for ; Tue, 30 Jun 2026 12:52:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 50EFC65F82; Tue, 30 Jun 2026 14:52:20 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="WAIbcj6W"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A814665F66 for ; Tue, 30 Jun 2026 14:52:16 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id BCD17104C; Tue, 30 Jun 2026 14:51:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782823892; bh=DzvDhBfHlKd+OkJwMWghkGqkyc2Jlr4n7jaXslgePbk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WAIbcj6WVgyTJ5Bz7MMNiXFh4z3klOOEKjL/hf9aioIKQqJ/g9ecteLf6/t4PZ7hd 4WhZTCIsFZuoXPi9waowC4m4MarhTMSi63h0RRtq4MUNFLxO8AGwEAqSZzrKtH9npS wuZbPceFkhYOuRC0e7y8bJtdkTQjG0nkmc03IHf4= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Bryan O'Donoghue Subject: [PATCH v2 1/5] libcamera: shaders: Move header generation to shaders directory Date: Tue, 30 Jun 2026 15:52:10 +0300 Message-ID: <20260630125214.3327516-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260630125214.3327516-1-laurent.pinchart@ideasonboard.com> References: <20260630125214.3327516-1-laurent.pinchart@ideasonboard.com> 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" The src/libcamera/shaders/ directory contains all libcamera shaders for the software ISP. Move the related build logic to convert shaders to headers to the same directory to make shaders self-contained. This changes the location of the glsl_shaders.h header, update debayer_egl.cpp accordingly. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal Reviewed-by: Barnabás Pőcze --- src/libcamera/meson.build | 10 ---------- src/libcamera/shaders/meson.build | 10 ++++++++++ src/libcamera/software_isp/debayer_egl.cpp | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 6aedacbdb04d..17c1b2cb3479 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -184,16 +184,6 @@ libcamera_deps += [ libyaml, ] -# Generate headers from shaders -libcamera_shader_headers = custom_target( - 'gen-shader-headers', - input : [shader_files], - output : 'glsl_shaders.h', - command : [gen_shader_headers, meson.project_source_root(), '@OUTPUT@', '@INPUT@'], -) - -libcamera_internal_headers += libcamera_shader_headers - # We add '/' to the build_rpath as a 'safe' path to act as a boolean flag. # The build_rpath is stripped at install time by meson, so we determine at # runtime if the library is running from an installed location by checking diff --git a/src/libcamera/shaders/meson.build b/src/libcamera/shaders/meson.build index dd441a577670..adac77327a3b 100644 --- a/src/libcamera/shaders/meson.build +++ b/src/libcamera/shaders/meson.build @@ -8,3 +8,13 @@ shader_files = files([ 'bayer_unpacked.vert', 'identity.vert', ]) + +# Generate headers from shaders +libcamera_shader_headers = custom_target( + 'gen-shader-headers', + input : [shader_files], + output : 'glsl_shaders.h', + command : [gen_shader_headers, meson.project_source_root(), '@OUTPUT@', '@INPUT@'], +) + +libcamera_internal_headers += libcamera_shader_headers diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 0ec2a98cfafb..af9b9d426920 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -24,7 +24,7 @@ #include "libcamera/internal/formats.h" #include "libcamera/internal/framebuffer.h" -#include "../glsl_shaders.h" +#include "../shaders/glsl_shaders.h" namespace libcamera { From patchwork Tue Jun 30 12:52:11 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 27144 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 AA0D1C3261 for ; Tue, 30 Jun 2026 12:52:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9780765F86; Tue, 30 Jun 2026 14:52:21 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="qJsOCHQy"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F240165F83 for ; Tue, 30 Jun 2026 14:52:17 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 116D8104C; Tue, 30 Jun 2026 14:51:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782823894; bh=sJ3i0n5zX6A30SeRiGQMKWo5vlHoEUSmKe4CmZToEG4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qJsOCHQyTlF5t+6/0eoq2S6DrBFBPm4LWQVUkmHMpqz76OOQVn2NF4GiXAvKLITVH Hob3Ogr2XdhSRW8Pbv2zAl+BfFl8f/39kCBa2oW/uJFj8bBO/sbmiiIBd3GbVKiEhi Gk+IoTXiKPh2y6sfuLVMpA3gHgHNrdqzBaJuvekI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Bryan O'Donoghue Subject: [PATCH v2 2/5] utils: Merge shader header generation scripts Date: Tue, 30 Jun 2026 15:52:11 +0300 Message-ID: <20260630125214.3327516-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260630125214.3327516-1-laurent.pinchart@ideasonboard.com> References: <20260630125214.3327516-1-laurent.pinchart@ideasonboard.com> 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" The shader header is generated by a combination of a shell script and a Python script. Simplify this by merging everything into a single script. The output of the old and new script only differ in white spaces. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal Reviewed-by: Barnabás Pőcze Reviewed-by: Bryan O'Donoghue --- Changes since v1: - Replace os.path with pathlib.Path - Rename "input" argument to "inputs" - Move first line of multi-line strings to left column --- src/libcamera/shaders/meson.build | 2 +- utils/gen-shader-header.py | 37 ---------------- utils/gen-shader-headers.py | 73 +++++++++++++++++++++++++++++++ utils/gen-shader-headers.sh | 54 ----------------------- utils/meson.build | 2 +- 5 files changed, 75 insertions(+), 93 deletions(-) delete mode 100755 utils/gen-shader-header.py create mode 100755 utils/gen-shader-headers.py delete mode 100755 utils/gen-shader-headers.sh diff --git a/src/libcamera/shaders/meson.build b/src/libcamera/shaders/meson.build index adac77327a3b..4f4e8da607c7 100644 --- a/src/libcamera/shaders/meson.build +++ b/src/libcamera/shaders/meson.build @@ -14,7 +14,7 @@ libcamera_shader_headers = custom_target( 'gen-shader-headers', input : [shader_files], output : 'glsl_shaders.h', - command : [gen_shader_headers, meson.project_source_root(), '@OUTPUT@', '@INPUT@'], + command : [gen_shader_headers, '-o', '@OUTPUT@', '@INPUT@'], ) libcamera_internal_headers += libcamera_shader_headers diff --git a/utils/gen-shader-header.py b/utils/gen-shader-header.py deleted file mode 100755 index 745852b4c03f..000000000000 --- a/utils/gen-shader-header.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# SPDX-License-Identifier: GPL-2.0-or-later -# Copyright (C) 2025, Bryan O'Donoghue. -# -# Author: Bryan O'Donoghue -# -# A Python script which takes a list of shader files and converts each of them -# into a C header. -# -import sys - -try: - with open(sys.argv[2], "rb") as file: - data = file.read() - data_len = len(data) - - name = sys.argv[1].replace(".", "_") - name_len = name + "_len" - - j = 0 - print("unsigned char const", name, "[] = {") - for ch in data: - print(f"0x{ch:02x}, ", end="") - j = (j + 1) % 16 - if j == 0: - print() - if j != 0: - print() - print("};") - - print() - print(f"const unsigned int {name_len}={data_len};") - -except FileNotFoundError: - print(f"File {sys.argv[2]} not found", file=sys.stderr) -except IOError: - print(f"Unable to read {sys.argv[2]}", file=sys.stderr) diff --git a/utils/gen-shader-headers.py b/utils/gen-shader-headers.py new file mode 100755 index 000000000000..fe4f06065f0c --- /dev/null +++ b/utils/gen-shader-headers.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2025, Bryan O'Donoghue +# Copyright (C) 2026, Ideas on Board Oy +# +# Generate a C header file containing hex-encoded shader sources + +import argparse +import binascii +import math +import pathlib +import sys + + +def process_file(path, out): + data = open(path, 'rb').read() + + hex_data = [f'0x{c:02x}' for c in data] + var_name = path.name.replace('.', '_') + + out.write(f'unsigned char const {var_name}[] = {{\n') + + for i in range(math.ceil(len(data) / 16)): + out.write('\t') + out.write(', '.join(hex_data[16 * i:16 * (i + 1)])) + out.write(',\n') + + out.write('};\n\n') + out.write(f'const unsigned int {var_name}_len = {len(data)};\n') + + +def main(argv): + parser = argparse.ArgumentParser( + description='Generate a C header file containing hex-encoded shader sources') + parser.add_argument('--output', '-o', metavar='file', default=sys.stdout, + type=argparse.FileType('w', encoding='utf-8'), + help='Output file name. Defaults to standard output if not specified.') + parser.add_argument('inputs', nargs='+', type=pathlib.Path, + help='Input file names.') + args = parser.parse_args(argv[1:]) + + args.output.write('''\ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* This file is auto-generated, do not edit! */ + +#pragma once + +/* + * List the names of the shaders at the top of header for readability's sake. + * +''') + + for path in args.inputs: + name = path.name.replace('.', '_') + args.output.write(f' * unsigned char {name};\n') + + args.output.write('''\ + */ + +/* Hex encoded shader data */ +''') + + for path in args.inputs: + process_file(path, args.output) + args.output.write('\n') + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) + diff --git a/utils/gen-shader-headers.sh b/utils/gen-shader-headers.sh deleted file mode 100755 index 0d6649521a7a..000000000000 --- a/utils/gen-shader-headers.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0-or-later - -set -e - -usage() { - echo "Usage: $0 [shader_file2 ...]" - echo - echo "Generates a C header file containing hex-encoded shader data." - echo - echo "Arguments:" - echo " src_dir Path to the base of the source directory" - echo " output_header Path to the generated header file" - echo " shader_file(s) One or more shader files to embed in the header" - exit 1 -} - -if [ $# -lt 4 ]; then - echo "Error: Invalid argument count." - usage -fi - -src_dir="$1"; shift -build_path="$1"; shift - -cat < "$build_path" -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* This file is auto-generated, do not edit! */ - -#pragma once - -EOF - -cat <> "$build_path" -/* - * List the names of the shaders at the top of - * header for readability's sake - * -EOF - -for file in "$@"; do - name=$(basename "$file" | tr '.' '_') - echo "[SHADER-GEN] $name" - echo " * unsigned char $name;" >> "$build_path" -done - -echo "*/" >> "$build_path" - -echo "/* Hex encoded shader data */" >> "$build_path" -for file in "$@"; do - name=$(basename "$file") - "$src_dir/utils/gen-shader-header.py" "$name" "$file" >> "$build_path" - echo >> "$build_path" -done diff --git a/utils/meson.build b/utils/meson.build index 9c598793035c..17a7aa7c3f5e 100644 --- a/utils/meson.build +++ b/utils/meson.build @@ -3,7 +3,7 @@ subdir('codegen') subdir('ipu3') -gen_shader_headers = files('gen-shader-headers.sh') +gen_shader_headers = files('gen-shader-headers.py') ## Module signing gen_ipa_priv_key = files('gen-ipa-priv-key.sh') From patchwork Tue Jun 30 12:52:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 27145 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 28A5EC3304 for ; Tue, 30 Jun 2026 12:52:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F09F665F7D; Tue, 30 Jun 2026 14:52:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="CtxeyKod"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5486265F66 for ; Tue, 30 Jun 2026 14:52:19 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6E47C104C; Tue, 30 Jun 2026 14:51:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782823895; bh=aoD+5ADldUeovvxl+kWuJl5hJWn4cA6jOC6DlPuOLQw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CtxeyKodJMGgOCmjk/BsFY5zGk5cOsWoqk6JKj+YiemhXdArvx7u4EZ6WP65xKdrJ rm/wr4ORVKHYEcQwiZAyKankDAliCMsXyZWlRN8q4N0uEaUcwBoChtJ9aQj/r1VGEA 4kwxW+ljfVOHTR+fk03N7IZ4akvXhbT1+9PcQxSs= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Bryan O'Donoghue Subject: [PATCH v2 3/5] utils: Rename and move shader header generation script Date: Tue, 30 Jun 2026 15:52:12 +0300 Message-ID: <20260630125214.3327516-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260630125214.3327516-1-laurent.pinchart@ideasonboard.com> References: <20260630125214.3327516-1-laurent.pinchart@ideasonboard.com> 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" The gen-shader-headers.py script generates a single header. Rename it to gen-shader-header.py, and move it to the codegen directory with the other code generation scripts. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal Reviewed-by: Barnabás Pőcze Reviewed-by: Bryan O'Donoghue --- src/libcamera/shaders/meson.build | 8 ++++---- .../gen-shader-header.py} | 0 utils/codegen/meson.build | 1 + utils/meson.build | 2 -- 4 files changed, 5 insertions(+), 6 deletions(-) rename utils/{gen-shader-headers.py => codegen/gen-shader-header.py} (100%) diff --git a/src/libcamera/shaders/meson.build b/src/libcamera/shaders/meson.build index 4f4e8da607c7..c409ff9b0b1c 100644 --- a/src/libcamera/shaders/meson.build +++ b/src/libcamera/shaders/meson.build @@ -9,12 +9,12 @@ shader_files = files([ 'identity.vert', ]) -# Generate headers from shaders -libcamera_shader_headers = custom_target( +# Generate header from shaders +libcamera_shader_header = custom_target( 'gen-shader-headers', input : [shader_files], output : 'glsl_shaders.h', - command : [gen_shader_headers, '-o', '@OUTPUT@', '@INPUT@'], + command : [gen_shader_header, '-o', '@OUTPUT@', '@INPUT@'], ) -libcamera_internal_headers += libcamera_shader_headers +libcamera_internal_headers += libcamera_shader_header diff --git a/utils/gen-shader-headers.py b/utils/codegen/gen-shader-header.py similarity index 100% rename from utils/gen-shader-headers.py rename to utils/codegen/gen-shader-header.py diff --git a/utils/codegen/meson.build b/utils/codegen/meson.build index 8d1c690866e1..70c228d68804 100644 --- a/utils/codegen/meson.build +++ b/utils/codegen/meson.build @@ -14,6 +14,7 @@ gen_formats = files('gen-formats.py') gen_gst_controls = files('gen-gst-controls.py') gen_header = files('gen-header.sh') gen_ipa_pub_key = files('gen-ipa-pub-key.py') +gen_shader_header = files('gen-shader-header.py') gen_tracepoints = files('gen-tp-header.py') py_mod_controls = files('controls.py') diff --git a/utils/meson.build b/utils/meson.build index 17a7aa7c3f5e..6e1b885b3688 100644 --- a/utils/meson.build +++ b/utils/meson.build @@ -3,8 +3,6 @@ subdir('codegen') subdir('ipu3') -gen_shader_headers = files('gen-shader-headers.py') - ## Module signing gen_ipa_priv_key = files('gen-ipa-priv-key.sh') From patchwork Tue Jun 30 12:52:13 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 27146 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 30A90C3261 for ; Tue, 30 Jun 2026 12:52:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2447B65F85; Tue, 30 Jun 2026 14:52:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="a5+hR+c2"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8D4A565F8A for ; Tue, 30 Jun 2026 14:52:20 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A99E1104C; Tue, 30 Jun 2026 14:51:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782823896; bh=3EB43kR/8724N22Ojui+sl9PvDfsTKCtI3RwCjGr5kY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a5+hR+c2Z6n/kW9KQnPExlZnTxcP3XHCNbMnDvP9ASnM39hGWwELXPnufJN54MXdy Uk4ysjMMwmIvEiS1H6urKjK6YaR9rmNY5EYImbAfNffGJA6Qu34nm6YleVjcfpQgBJ e5d+cAbb3P1nBN28O89cIXb97vDvel9EhoHsJGGQ= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Bryan O'Donoghue Subject: [PATCH v2 4/5] libcamera: shaders: Replace C array with std::array Date: Tue, 30 Jun 2026 15:52:13 +0300 Message-ID: <20260630125214.3327516-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260630125214.3327516-1-laurent.pinchart@ideasonboard.com> References: <20260630125214.3327516-1-laurent.pinchart@ideasonboard.com> 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" Using C arrays and separate length variables is error-prone. Replace them with std::array in the generated shader header, and update the software ISP code accordingly. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal Reviewed-by: Barnabás Pőcze Reviewed-by: Bryan O'Donoghue --- Changes since v1: - Drop "unsigned char" from comment block in generated header --- src/libcamera/software_isp/debayer_egl.cpp | 23 +++++++--------------- utils/codegen/gen-shader-header.py | 9 +++++---- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index af9b9d426920..1f5fc6a4466d 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -145,10 +146,8 @@ int DebayerEGL::getShaderVariableLocations(void) int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat) { std::vector shaderEnv; - unsigned int fragmentShaderDataLen = 0; - const unsigned char *fragmentShaderData = 0; - unsigned int vertexShaderDataLen = 0; - const unsigned char *vertexShaderData = 0; + Span fragmentShaderData; + Span vertexShaderData; GLenum err; /* Target gles 100 glsl requires "#version x" as first directive in shader */ @@ -216,9 +215,7 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm case libcamera::formats::SGRBG8: case libcamera::formats::SRGGB8: fragmentShaderData = bayer_unpacked_frag; - fragmentShaderDataLen = bayer_unpacked_frag_len; vertexShaderData = bayer_unpacked_vert; - vertexShaderDataLen = bayer_unpacked_vert_len; break; case libcamera::formats::SBGGR10_CSI2P: case libcamera::formats::SGBRG10_CSI2P: @@ -227,16 +224,12 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm egl_.pushEnv(shaderEnv, "#define RAW10P"); if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { fragmentShaderData = bayer_unpacked_frag; - fragmentShaderDataLen = bayer_unpacked_frag_len; vertexShaderData = bayer_unpacked_vert; - vertexShaderDataLen = bayer_unpacked_vert_len; glFormat_ = GL_RG; bytesPerPixel_ = 2; } else { fragmentShaderData = bayer_1x_packed_frag; - fragmentShaderDataLen = bayer_1x_packed_frag_len; vertexShaderData = identity_vert; - vertexShaderDataLen = identity_vert_len; shaderStridePixels_ = width_; } break; @@ -247,28 +240,26 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm egl_.pushEnv(shaderEnv, "#define RAW12P"); if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { fragmentShaderData = bayer_unpacked_frag; - fragmentShaderDataLen = bayer_unpacked_frag_len; vertexShaderData = bayer_unpacked_vert; - vertexShaderDataLen = bayer_unpacked_vert_len; glFormat_ = GL_RG; bytesPerPixel_ = 2; } else { fragmentShaderData = bayer_1x_packed_frag; - fragmentShaderDataLen = bayer_1x_packed_frag_len; vertexShaderData = identity_vert; - vertexShaderDataLen = identity_vert_len; shaderStridePixels_ = width_; } break; }; - if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData, vertexShaderDataLen, shaderEnv)) { + if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData.data(), + vertexShaderData.size(), shaderEnv)) { LOG(Debayer, Error) << "Compile vertex shader fail"; return -ENODEV; } utils::scope_exit vShaderGuard([&] { glDeleteShader(vertexShaderId_); }); - if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData, fragmentShaderDataLen, shaderEnv)) { + if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData.data(), + fragmentShaderData.size(), shaderEnv)) { LOG(Debayer, Error) << "Compile fragment shader fail"; return -ENODEV; } diff --git a/utils/codegen/gen-shader-header.py b/utils/codegen/gen-shader-header.py index fe4f06065f0c..994e19c8e8e0 100755 --- a/utils/codegen/gen-shader-header.py +++ b/utils/codegen/gen-shader-header.py @@ -19,15 +19,14 @@ def process_file(path, out): hex_data = [f'0x{c:02x}' for c in data] var_name = path.name.replace('.', '_') - out.write(f'unsigned char const {var_name}[] = {{\n') + out.write(f'static constexpr std::array {var_name}{{\n') for i in range(math.ceil(len(data) / 16)): out.write('\t') out.write(', '.join(hex_data[16 * i:16 * (i + 1)])) out.write(',\n') - out.write('};\n\n') - out.write(f'const unsigned int {var_name}_len = {len(data)};\n') + out.write('};\n') def main(argv): @@ -46,6 +45,8 @@ def main(argv): #pragma once +#include + /* * List the names of the shaders at the top of header for readability's sake. * @@ -53,7 +54,7 @@ def main(argv): for path in args.inputs: name = path.name.replace('.', '_') - args.output.write(f' * unsigned char {name};\n') + args.output.write(f' * - {name}\n') args.output.write('''\ */ From patchwork Tue Jun 30 12:52:14 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 27147 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 0D9AEC3304 for ; Tue, 30 Jun 2026 12:52:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B51C565F7E; Tue, 30 Jun 2026 14:52:26 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ps08ho4r"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C9FD165F8E for ; Tue, 30 Jun 2026 14:52:21 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DAB511E8A; Tue, 30 Jun 2026 14:51:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782823898; bh=KHWjspJyNIFBIEH0UtjGouz5PGW3yeXSbCLYzYAoqN8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ps08ho4rr3jmmwK4rIKL29/t7JnPiVteK7E9DQ/Z1xxj3CVblDJm8GrLVUECn87Zr CZLZvtjRNaoTG1D0MF6+rSlTpeVccA6A3aBOzy8aB5g9OJVRDLD/gmLM1s+jv02o+L YZM/lo7v78+QYYSGcPzfoUDCPm37unq0HtYpOcM0= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Bryan O'Donoghue Subject: [PATCH v2 5/5] libcamera: egl: Replace pointer and length with span for shader sources Date: Tue, 30 Jun 2026 15:52:14 +0300 Message-ID: <20260630125214.3327516-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260630125214.3327516-1-laurent.pinchart@ideasonboard.com> References: <20260630125214.3327516-1-laurent.pinchart@ideasonboard.com> 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" The compileVertexShader() and compileFragmentShader() functions take a pointer and length to the shader source code as separate arguments. This is an error-prone practice. Replace them with a Span<>. Suggested-by: Barnabás Pőcze Signed-off-by: Laurent Pinchart Reviewed-by: Bryan O'Donoghue Reviewed-by: Barnabás Pőcze --- include/libcamera/internal/egl.h | 9 +++---- src/libcamera/egl.cpp | 29 ++++++++++------------ src/libcamera/software_isp/debayer_egl.cpp | 8 +++--- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index f7bfb28d4e9a..523a62aa89d5 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -112,11 +112,9 @@ public: void pushEnv(std::vector &shaderEnv, const char *str); void makeCurrent(); - int compileVertexShader(GLuint &shaderId, const unsigned char *shaderData, - unsigned int shaderDataLen, + int compileVertexShader(GLuint &shaderId, Span shaderData, Span shaderEnv); - int compileFragmentShader(GLuint &shaderId, const unsigned char *shaderData, - unsigned int shaderDataLen, + int compileFragmentShader(GLuint &shaderId, Span shaderData, Span shaderEnv); int linkProgram(GLuint &programId, GLuint fragmentshaderId, GLuint vertexshaderId); void dumpShaderSource(GLuint shaderId); @@ -135,8 +133,7 @@ private: EGLSurface surface_ = EGL_NO_SURFACE; static EGLDisplay probeDisplay(); - int compileShader(int shaderType, GLuint &shaderId, const unsigned char *shaderData, - unsigned int shaderDataLen, + int compileShader(int shaderType, GLuint &shaderId, Span shaderData, Span shaderEnv); int createDMABufTexture2D(eGLImage &eglImage, int fd, bool output); diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index f03abb8ae07d..b5a5dc60b110 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -463,8 +463,7 @@ void eGL::pushEnv(std::vector &shaderEnv, const char *str) /** * \brief Compile a vertex shader * \param[out] shaderId OpenGL shader object ID - * \param[in] shaderData Pointer to shader source code - * \param[in] shaderDataLen Length of shader source in bytes + * \param[in] shaderData Shader source code * \param[in] shaderEnv Span of preprocessor definitions to prepend * * Compiles a vertex shader from source code with optional preprocessor @@ -472,18 +471,17 @@ void eGL::pushEnv(std::vector &shaderEnv, const char *str) * * \return 0 on success, or -EINVAL on compilation failure */ -int eGL::compileVertexShader(GLuint &shaderId, const unsigned char *shaderData, - unsigned int shaderDataLen, +int eGL::compileVertexShader(GLuint &shaderId, + Span shaderData, Span shaderEnv) { - return compileShader(GL_VERTEX_SHADER, shaderId, shaderData, shaderDataLen, shaderEnv); + return compileShader(GL_VERTEX_SHADER, shaderId, shaderData, shaderEnv); } /** * \brief Compile a fragment shader * \param[out] shaderId OpenGL shader object ID - * \param[in] shaderData Pointer to shader source code - * \param[in] shaderDataLen Length of shader source in bytes + * \param[in] shaderData Shader source code * \param[in] shaderEnv Span of preprocessor definitions to prepend * * Compiles a fragment shader from source code with optional preprocessor @@ -491,19 +489,18 @@ int eGL::compileVertexShader(GLuint &shaderId, const unsigned char *shaderData, * * \return 0 on success, or -EINVAL on compilation failure */ -int eGL::compileFragmentShader(GLuint &shaderId, const unsigned char *shaderData, - unsigned int shaderDataLen, +int eGL::compileFragmentShader(GLuint &shaderId, + Span shaderData, Span shaderEnv) { - return compileShader(GL_FRAGMENT_SHADER, shaderId, shaderData, shaderDataLen, shaderEnv); + return compileShader(GL_FRAGMENT_SHADER, shaderId, shaderData, shaderEnv); } /** * \brief Compile a shader of specified type * \param[in] shaderType GL_VERTEX_SHADER or GL_FRAGMENT_SHADER * \param[out] shaderId OpenGL shader object ID - * \param[in] shaderData Pointer to shader source code - * \param[in] shaderDataLen Length of shader source in bytes + * \param[in] shaderData Shader source code * \param[in] shaderEnv Span of preprocessor definitions to prepend * * Internal helper function for shader compilation. Prepends environment @@ -511,8 +508,8 @@ int eGL::compileFragmentShader(GLuint &shaderId, const unsigned char *shaderData * * \return 0 on success, or -EINVAL on compilation failure */ -int eGL::compileShader(int shaderType, GLuint &shaderId, const unsigned char *shaderData, - unsigned int shaderDataLen, +int eGL::compileShader(int shaderType, GLuint &shaderId, + Span shaderData, Span shaderEnv) { GLint success; @@ -531,8 +528,8 @@ int eGL::compileShader(int shaderType, GLuint &shaderId, const unsigned char *sh } // Now the main body of the shader program - shaderSourceData[i] = reinterpret_cast(shaderData); - shaderDataLengths[i] = shaderDataLen; + shaderSourceData[i] = reinterpret_cast(shaderData.data()); + shaderDataLengths[i] = shaderData.size(); // And create the shader shaderId = glCreateShader(shaderType); diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 1f5fc6a4466d..56545816ead5 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -251,15 +251,15 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm break; }; - if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData.data(), - vertexShaderData.size(), shaderEnv)) { + if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData, + shaderEnv)) { LOG(Debayer, Error) << "Compile vertex shader fail"; return -ENODEV; } utils::scope_exit vShaderGuard([&] { glDeleteShader(vertexShaderId_); }); - if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData.data(), - fragmentShaderData.size(), shaderEnv)) { + if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData, + shaderEnv)) { LOG(Debayer, Error) << "Compile fragment shader fail"; return -ENODEV; }