| Message ID | 20261021065624.153207-1-faizel.kb@gmail.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
Hi, thanks for the patch! On 21.10.26 08:56, Faizel K B wrote: > Importing unpacked 10/12-bit Bayer input buffers (e.g. SGBRG10) as > dmabufs always fails with Mesa, and DebayerEGL silently falls back to > mapping each input buffer and uploading it with glTexImage2D() on every > frame: > > INFO Debayer debayer_egl.cpp:523 Importing input DMABuf failed, falling back to upload > > The cause is the DRM format used for GL_RG textures. Unpacked Bayer > pixels are 16-bit little-endian words, loaded into a GL_RG texture with > the low byte in .r and the high byte in .g, which the shaders recombine > into a single sample. R and G here are texture channels, not colours. > GL names formats in memory byte order, while DRM fourccs describe the > components of a little-endian word from MSB to LSB: > > DRM_FORMAT_RG88 [15:0] R:G 8:8 little endian -> byte 0 = G, byte 1 = R > DRM_FORMAT_GR88 [15:0] G:R 8:8 little endian -> byte 0 = R, byte 1 = G > > The import path maps GL_RG to DRM_FORMAT_RG88, which has the opposite > byte order. Mesa has no RG88 entry in its DRI image format table, so > eglCreateImageKHR() fails. > > Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is > supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the > output path (GL_RGBA) are not affected. > > Fixes: 6e23162ddcae ("egl: Add GL format parameter to eGLImage constructor") > Signed-off-by: Faizel K B <faizel.kb@gmail.com> > --- > > Notes: > Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an IMX415 > sensor (SGBRG10 unpacked, 3864x2192). > > Panfrost requires the row stride of linear dmabuf imports to be > 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 bytes, so > the import also needed a local rkcif change to honour the 256-byte > aligned stride (7936) that DebayerEGL::preferredInputStride() requests. Note that V4L2 drivers don't need to honor the bytesperline request - you could also just align things to 64 bytes (7744) if that's enough for Panfrost. But optimally the upstream driver would honor the request and not hardcode any values - any chance you're looking into working on that? :) > > src/libcamera/egl.cpp | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp > index 3cde9040a..59a7d8cf9 100644 > --- a/src/libcamera/egl.cpp > +++ b/src/libcamera/egl.cpp > @@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) > drm_format = DRM_FORMAT_R8; > break; > case GL_RG: > - drm_format = DRM_FORMAT_RG88; > + drm_format = DRM_FORMAT_GR88; Good catch! Reviewed-by: Robert Mader <robert.mader@collabora.com> > break; > case GL_RGBA: > drm_format = DRM_FORMAT_ARGB8888;
Hi 2026. 10. 21. 8:56 keltezéssel, Faizel K B írta: > Importing unpacked 10/12-bit Bayer input buffers (e.g. SGBRG10) as > dmabufs always fails with Mesa, and DebayerEGL silently falls back to > mapping each input buffer and uploading it with glTexImage2D() on every > frame: > > INFO Debayer debayer_egl.cpp:523 Importing input DMABuf failed, falling back to upload > > The cause is the DRM format used for GL_RG textures. Unpacked Bayer > pixels are 16-bit little-endian words, loaded into a GL_RG texture with > the low byte in .r and the high byte in .g, which the shaders recombine > into a single sample. R and G here are texture channels, not colours. > GL names formats in memory byte order, while DRM fourccs describe the > components of a little-endian word from MSB to LSB: > > DRM_FORMAT_RG88 [15:0] R:G 8:8 little endian -> byte 0 = G, byte 1 = R > DRM_FORMAT_GR88 [15:0] G:R 8:8 little endian -> byte 0 = R, byte 1 = G > > The import path maps GL_RG to DRM_FORMAT_RG88, which has the opposite > byte order. Mesa has no RG88 entry in its DRI image format table, so > eglCreateImageKHR() fails. > > Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is > supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the > output path (GL_RGBA) are not affected. The only thing that's not entirely clear to me is why GL_RGBA is not affected. Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ipu6 + ov2740 > > Fixes: 6e23162ddcae ("egl: Add GL format parameter to eGLImage constructor") > Signed-off-by: Faizel K B <faizel.kb@gmail.com> > --- > > Notes: > Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an IMX415 > sensor (SGBRG10 unpacked, 3864x2192). > > Panfrost requires the row stride of linear dmabuf imports to be > 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 bytes, so > the import also needed a local rkcif change to honour the 256-byte > aligned stride (7936) that DebayerEGL::preferredInputStride() requests. > > src/libcamera/egl.cpp | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp > index 3cde9040a..59a7d8cf9 100644 > --- a/src/libcamera/egl.cpp > +++ b/src/libcamera/egl.cpp > @@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) > drm_format = DRM_FORMAT_R8; > break; > case GL_RG: > - drm_format = DRM_FORMAT_RG88; > + drm_format = DRM_FORMAT_GR88; > break; > case GL_RGBA: > drm_format = DRM_FORMAT_ARGB8888;
Hi, On 21.10.26 12:30, Barnabás Pőcze wrote: > Hi > > 2026. 10. 21. 8:56 keltezéssel, Faizel K B írta: >> Importing unpacked 10/12-bit Bayer input buffers (e.g. SGBRG10) as >> dmabufs always fails with Mesa, and DebayerEGL silently falls back to >> mapping each input buffer and uploading it with glTexImage2D() on every >> frame: >> >> INFO Debayer debayer_egl.cpp:523 Importing input DMABuf failed, >> falling back to upload >> >> The cause is the DRM format used for GL_RG textures. Unpacked Bayer >> pixels are 16-bit little-endian words, loaded into a GL_RG texture with >> the low byte in .r and the high byte in .g, which the shaders recombine >> into a single sample. R and G here are texture channels, not colours. >> GL names formats in memory byte order, while DRM fourccs describe the >> components of a little-endian word from MSB to LSB: >> >> DRM_FORMAT_RG88 [15:0] R:G 8:8 little endian -> byte 0 = G, byte >> 1 = R >> DRM_FORMAT_GR88 [15:0] G:R 8:8 little endian -> byte 0 = R, byte >> 1 = G >> >> The import path maps GL_RG to DRM_FORMAT_RG88, which has the opposite >> byte order. Mesa has no RG88 entry in its DRI image format table, so >> eglCreateImageKHR() fails. >> >> Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is >> supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the >> output path (GL_RGBA) are not affected. > > The only thing that's not entirely clear to me is why GL_RGBA is not > affected. The mapping from GL_RGBA <-> DRM_FORMAT_ARGB8888 already uses the inverted order, so that makes sense, no? > > Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ipu6 + > ov2740 > > >> >> Fixes: 6e23162ddcae ("egl: Add GL format parameter to eGLImage >> constructor") >> Signed-off-by: Faizel K B <faizel.kb@gmail.com> >> --- >> >> Notes: >> Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an IMX415 >> sensor (SGBRG10 unpacked, 3864x2192). >> Panfrost requires the row stride of linear dmabuf imports >> to be >> 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 >> bytes, so >> the import also needed a local rkcif change to honour the 256-byte >> aligned stride (7936) that DebayerEGL::preferredInputStride() >> requests. >> >> src/libcamera/egl.cpp | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp >> index 3cde9040a..59a7d8cf9 100644 >> --- a/src/libcamera/egl.cpp >> +++ b/src/libcamera/egl.cpp >> @@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage >> &eglImage, int fd, bool output) >> drm_format = DRM_FORMAT_R8; >> break; >> case GL_RG: >> - drm_format = DRM_FORMAT_RG88; >> + drm_format = DRM_FORMAT_GR88; >> break; >> case GL_RGBA: >> drm_format = DRM_FORMAT_ARGB8888;
2026. 10. 21. 13:29 keltezéssel, Robert Mader írta: > Hi, > > On 21.10.26 12:30, Barnabás Pőcze wrote: >> Hi >> >> 2026. 10. 21. 8:56 keltezéssel, Faizel K B írta: >>> Importing unpacked 10/12-bit Bayer input buffers (e.g. SGBRG10) as >>> dmabufs always fails with Mesa, and DebayerEGL silently falls back to >>> mapping each input buffer and uploading it with glTexImage2D() on every >>> frame: >>> >>> INFO Debayer debayer_egl.cpp:523 Importing input DMABuf failed, falling back to upload >>> >>> The cause is the DRM format used for GL_RG textures. Unpacked Bayer >>> pixels are 16-bit little-endian words, loaded into a GL_RG texture with >>> the low byte in .r and the high byte in .g, which the shaders recombine >>> into a single sample. R and G here are texture channels, not colours. >>> GL names formats in memory byte order, while DRM fourccs describe the >>> components of a little-endian word from MSB to LSB: >>> >>> DRM_FORMAT_RG88 [15:0] R:G 8:8 little endian -> byte 0 = G, byte 1 = R >>> DRM_FORMAT_GR88 [15:0] G:R 8:8 little endian -> byte 0 = R, byte 1 = G >>> >>> The import path maps GL_RG to DRM_FORMAT_RG88, which has the opposite >>> byte order. Mesa has no RG88 entry in its DRI image format table, so >>> eglCreateImageKHR() fails. >>> >>> Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is >>> supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the >>> output path (GL_RGBA) are not affected. >> >> The only thing that's not entirely clear to me is why GL_RGBA is not affected. > > The mapping from GL_RGBA <-> DRM_FORMAT_ARGB8888 already uses the inverted order, so that makes sense, no? I'd have expected DRM_FORMAT_ABGR8888, since /* [31:0] A:B:G:R 8:8:8:8 little endian */ so the memory order is RGBA. But I must be missing something. > > >> >> Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ipu6 + ov2740 >> >> >>> >>> Fixes: 6e23162ddcae ("egl: Add GL format parameter to eGLImage constructor") >>> Signed-off-by: Faizel K B <faizel.kb@gmail.com> >>> --- >>> >>> Notes: >>> Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an IMX415 >>> sensor (SGBRG10 unpacked, 3864x2192). >>> Panfrost requires the row stride of linear dmabuf imports to be >>> 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 bytes, so >>> the import also needed a local rkcif change to honour the 256-byte >>> aligned stride (7936) that DebayerEGL::preferredInputStride() requests. >>> >>> src/libcamera/egl.cpp | 2 +- >>> 1 file changed, 1 insertion(+), 1 deletion(-) >>> >>> diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp >>> index 3cde9040a..59a7d8cf9 100644 >>> --- a/src/libcamera/egl.cpp >>> +++ b/src/libcamera/egl.cpp >>> @@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) >>> drm_format = DRM_FORMAT_R8; >>> break; >>> case GL_RG: >>> - drm_format = DRM_FORMAT_RG88; >>> + drm_format = DRM_FORMAT_GR88; >>> break; >>> case GL_RGBA: >>> drm_format = DRM_FORMAT_ARGB8888;
On 21.10.26 13:35, Barnabás Pőcze wrote: > 2026. 10. 21. 13:29 keltezéssel, Robert Mader írta: >> Hi, >> >> On 21.10.26 12:30, Barnabás Pőcze wrote: >>> Hi >>> >>> 2026. 10. 21. 8:56 keltezéssel, Faizel K B írta: >>>> Importing unpacked 10/12-bit Bayer input buffers (e.g. SGBRG10) as >>>> dmabufs always fails with Mesa, and DebayerEGL silently falls back to >>>> mapping each input buffer and uploading it with glTexImage2D() on >>>> every >>>> frame: >>>> >>>> INFO Debayer debayer_egl.cpp:523 Importing input DMABuf failed, >>>> falling back to upload >>>> >>>> The cause is the DRM format used for GL_RG textures. Unpacked Bayer >>>> pixels are 16-bit little-endian words, loaded into a GL_RG texture >>>> with >>>> the low byte in .r and the high byte in .g, which the shaders >>>> recombine >>>> into a single sample. R and G here are texture channels, not colours. >>>> GL names formats in memory byte order, while DRM fourccs describe the >>>> components of a little-endian word from MSB to LSB: >>>> >>>> DRM_FORMAT_RG88 [15:0] R:G 8:8 little endian -> byte 0 = G, >>>> byte 1 = R >>>> DRM_FORMAT_GR88 [15:0] G:R 8:8 little endian -> byte 0 = R, >>>> byte 1 = G >>>> >>>> The import path maps GL_RG to DRM_FORMAT_RG88, which has the opposite >>>> byte order. Mesa has no RG88 entry in its DRI image format table, so >>>> eglCreateImageKHR() fails. >>>> >>>> Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is >>>> supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the >>>> output path (GL_RGBA) are not affected. >>> >>> The only thing that's not entirely clear to me is why GL_RGBA is not >>> affected. >> >> The mapping from GL_RGBA <-> DRM_FORMAT_ARGB8888 already uses the >> inverted order, so that makes sense, no? > > I'd have expected DRM_FORMAT_ABGR8888, since > > /* [31:0] A:B:G:R 8:8:8:8 little endian */ > > so the memory order is RGBA. But I must be missing something. Urgh. I think you're right. This format is only used for the output buffer, not the input ones - and we require the dmabuf import to succeed in that case, so there's no fallback path. If we have a R-B swap here - then we most likely also have one in the shaders, compensating for it. > > >> >> >>> >>> Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ipu6 + >>> ov2740 >>> >>> >>>> >>>> Fixes: 6e23162ddcae ("egl: Add GL format parameter to eGLImage >>>> constructor") >>>> Signed-off-by: Faizel K B <faizel.kb@gmail.com> >>>> --- >>>> >>>> Notes: >>>> Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an >>>> IMX415 >>>> sensor (SGBRG10 unpacked, 3864x2192). >>>> Panfrost requires the row stride of linear dmabuf imports >>>> to be >>>> 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 >>>> bytes, so >>>> the import also needed a local rkcif change to honour the >>>> 256-byte >>>> aligned stride (7936) that DebayerEGL::preferredInputStride() >>>> requests. >>>> >>>> src/libcamera/egl.cpp | 2 +- >>>> 1 file changed, 1 insertion(+), 1 deletion(-) >>>> >>>> diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp >>>> index 3cde9040a..59a7d8cf9 100644 >>>> --- a/src/libcamera/egl.cpp >>>> +++ b/src/libcamera/egl.cpp >>>> @@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage >>>> &eglImage, int fd, bool output) >>>> drm_format = DRM_FORMAT_R8; >>>> break; >>>> case GL_RG: >>>> - drm_format = DRM_FORMAT_RG88; >>>> + drm_format = DRM_FORMAT_GR88; >>>> break; >>>> case GL_RGBA: >>>> drm_format = DRM_FORMAT_ARGB8888; >
On Tue, Oct 20, 2026 at 11:56:24PM -0700, Faizel K B wrote: > Importing unpacked 10/12-bit Bayer input buffers (e.g. SGBRG10) as > dmabufs always fails with Mesa, and DebayerEGL silently falls back to > mapping each input buffer and uploading it with glTexImage2D() on every > frame: > > INFO Debayer debayer_egl.cpp:523 Importing input DMABuf failed, falling back to upload That's not very silent, is it ? > The cause is the DRM format used for GL_RG textures. Unpacked Bayer > pixels are 16-bit little-endian words, loaded into a GL_RG texture with > the low byte in .r and the high byte in .g, which the shaders recombine > into a single sample. R and G here are texture channels, not colours. > GL names formats in memory byte order, while DRM fourccs describe the > components of a little-endian word from MSB to LSB: > > DRM_FORMAT_RG88 [15:0] R:G 8:8 little endian -> byte 0 = G, byte 1 = R > DRM_FORMAT_GR88 [15:0] G:R 8:8 little endian -> byte 0 = R, byte 1 = G > > The import path maps GL_RG to DRM_FORMAT_RG88, which has the opposite > byte order. Mesa has no RG88 entry in its DRI image format table, so > eglCreateImageKHR() fails. I've checked mesa and can confirm that. > Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is > supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the > output path (GL_RGBA) are not affected. > > Fixes: 6e23162ddcae ("egl: Add GL format parameter to eGLImage constructor") > Signed-off-by: Faizel K B <faizel.kb@gmail.com> > --- > > Notes: > Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an IMX415 > sensor (SGBRG10 unpacked, 3864x2192). > > Panfrost requires the row stride of linear dmabuf imports to be > 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 bytes, so > the import also needed a local rkcif change to honour the 256-byte > aligned stride (7936) that DebayerEGL::preferredInputStride() requests. Do you plan to upstream that ? With s/silently // in the commit message (which we can handle when applying, no need for a v2), Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > src/libcamera/egl.cpp | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp > index 3cde9040a..59a7d8cf9 100644 > --- a/src/libcamera/egl.cpp > +++ b/src/libcamera/egl.cpp > @@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) > drm_format = DRM_FORMAT_R8; > break; > case GL_RG: > - drm_format = DRM_FORMAT_RG88; > + drm_format = DRM_FORMAT_GR88; > break; > case GL_RGBA: > drm_format = DRM_FORMAT_ARGB8888;
2026. 10. 21. 13:44 keltezéssel, Robert Mader írta: > On 21.10.26 13:35, Barnabás Pőcze wrote: >> 2026. 10. 21. 13:29 keltezéssel, Robert Mader írta: >>> Hi, >>> >>> On 21.10.26 12:30, Barnabás Pőcze wrote: >>>> Hi >>>> >>>> 2026. 10. 21. 8:56 keltezéssel, Faizel K B írta: >>>>> Importing unpacked 10/12-bit Bayer input buffers (e.g. SGBRG10) as >>>>> dmabufs always fails with Mesa, and DebayerEGL silently falls back to >>>>> mapping each input buffer and uploading it with glTexImage2D() on every >>>>> frame: >>>>> >>>>> INFO Debayer debayer_egl.cpp:523 Importing input DMABuf failed, falling back to upload >>>>> >>>>> The cause is the DRM format used for GL_RG textures. Unpacked Bayer >>>>> pixels are 16-bit little-endian words, loaded into a GL_RG texture with >>>>> the low byte in .r and the high byte in .g, which the shaders recombine >>>>> into a single sample. R and G here are texture channels, not colours. >>>>> GL names formats in memory byte order, while DRM fourccs describe the >>>>> components of a little-endian word from MSB to LSB: >>>>> >>>>> DRM_FORMAT_RG88 [15:0] R:G 8:8 little endian -> byte 0 = G, byte 1 = R >>>>> DRM_FORMAT_GR88 [15:0] G:R 8:8 little endian -> byte 0 = R, byte 1 = G >>>>> >>>>> The import path maps GL_RG to DRM_FORMAT_RG88, which has the opposite >>>>> byte order. Mesa has no RG88 entry in its DRI image format table, so >>>>> eglCreateImageKHR() fails. >>>>> >>>>> Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is >>>>> supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the >>>>> output path (GL_RGBA) are not affected. >>>> >>>> The only thing that's not entirely clear to me is why GL_RGBA is not affected. >>> >>> The mapping from GL_RGBA <-> DRM_FORMAT_ARGB8888 already uses the inverted order, so that makes sense, no? >> >> I'd have expected DRM_FORMAT_ABGR8888, since >> >> /* [31:0] A:B:G:R 8:8:8:8 little endian */ >> >> so the memory order is RGBA. But I must be missing something. > > Urgh. I think you're right. This format is only used for the output buffer, not the input ones - and we require the dmabuf import to succeed in that case, so there's no fallback path. > > If we have a R-B swap here - then we most likely also have one in the shaders, compensating for it. > After some testing, I think "... output path (GL_RGBA) are not affected" is not entirely correct. It is affected, it's just not visible. ``` diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 0b641a5f3..e5a4f4b10 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -255,4 +255,6 @@ void main(void) #else gl_FragColor = vec4(rgb, 1.0); #endif + + gl_FragColor = vec4(1, 0.5, 0.25, 1); } diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index 10c5e941b..e52164703 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -157,4 +157,6 @@ void main(void) { #else gl_FragColor = vec4(rgb, 1.0); #endif + + gl_FragColor = vec4(1, 0.5, 0.25, 1); } ``` $ cam -c1 -C1 --file=/tmp/asd.bin $ hexdump -n4 -C /tmp/asd.bin 00000000 40 80 ff ff |@...| 00000004 which corresponds to the BGRA memory order. The reason why it apparently works in the first place, well, that eludes me for now, but I think we might want to extend this patch with the following: ``` diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 3cde9040a..aeedc5de3 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -187,7 +187,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) drm_format = DRM_FORMAT_RG88; break; case GL_RGBA: - drm_format = DRM_FORMAT_ARGB8888; + drm_format = DRM_FORMAT_ABGR8888; break; default: LOG(eGL, Error) << "unhandled GL format"; diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 300822f9d..cb9908e1d 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -150,10 +150,10 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm switch (outputFormat) { case formats::ARGB8888: case formats::XRGB8888: + egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); break; case formats::ABGR8888: case formats::XBGR8888: - egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); break; default: LOG(Debayer, Error) << "Unsupported output format"; ``` because that will remove the inconsistency. >> >> >>> >>> >>>> >>>> Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ipu6 + ov2740 >>>> >>>> >>>>> >>>>> Fixes: 6e23162ddcae ("egl: Add GL format parameter to eGLImage constructor") >>>>> Signed-off-by: Faizel K B <faizel.kb@gmail.com> >>>>> --- >>>>> >>>>> Notes: >>>>> Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an IMX415 >>>>> sensor (SGBRG10 unpacked, 3864x2192). >>>>> Panfrost requires the row stride of linear dmabuf imports to be >>>>> 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 bytes, so >>>>> the import also needed a local rkcif change to honour the 256-byte >>>>> aligned stride (7936) that DebayerEGL::preferredInputStride() requests. >>>>> >>>>> src/libcamera/egl.cpp | 2 +- >>>>> 1 file changed, 1 insertion(+), 1 deletion(-) >>>>> >>>>> diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp >>>>> index 3cde9040a..59a7d8cf9 100644 >>>>> --- a/src/libcamera/egl.cpp >>>>> +++ b/src/libcamera/egl.cpp >>>>> @@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) >>>>> drm_format = DRM_FORMAT_R8; >>>>> break; >>>>> case GL_RG: >>>>> - drm_format = DRM_FORMAT_RG88; >>>>> + drm_format = DRM_FORMAT_GR88; >>>>> break; >>>>> case GL_RGBA: >>>>> drm_format = DRM_FORMAT_ARGB8888; >>
On Wed, Oct 21, 2026 at 01:44:03PM +0200, Robert Mader wrote: > On 21.10.26 13:35, Barnabás Pőcze wrote: > > 2026. 10. 21. 13:29 keltezéssel, Robert Mader írta: > >> Hi, > >> > >> On 21.10.26 12:30, Barnabás Pőcze wrote: > >>> Hi > >>> > >>> 2026. 10. 21. 8:56 keltezéssel, Faizel K B írta: > >>>> Importing unpacked 10/12-bit Bayer input buffers (e.g. SGBRG10) as > >>>> dmabufs always fails with Mesa, and DebayerEGL silently falls back to > >>>> mapping each input buffer and uploading it with glTexImage2D() on > >>>> every > >>>> frame: > >>>> > >>>> INFO Debayer debayer_egl.cpp:523 Importing input DMABuf failed, > >>>> falling back to upload > >>>> > >>>> The cause is the DRM format used for GL_RG textures. Unpacked Bayer > >>>> pixels are 16-bit little-endian words, loaded into a GL_RG texture > >>>> with > >>>> the low byte in .r and the high byte in .g, which the shaders > >>>> recombine > >>>> into a single sample. R and G here are texture channels, not colours. > >>>> GL names formats in memory byte order, while DRM fourccs describe the > >>>> components of a little-endian word from MSB to LSB: > >>>> > >>>> DRM_FORMAT_RG88 [15:0] R:G 8:8 little endian -> byte 0 = G, > >>>> byte 1 = R > >>>> DRM_FORMAT_GR88 [15:0] G:R 8:8 little endian -> byte 0 = R, > >>>> byte 1 = G > >>>> > >>>> The import path maps GL_RG to DRM_FORMAT_RG88, which has the opposite > >>>> byte order. Mesa has no RG88 entry in its DRI image format table, so > >>>> eglCreateImageKHR() fails. > >>>> > >>>> Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is > >>>> supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the > >>>> output path (GL_RGBA) are not affected. > >>> > >>> The only thing that's not entirely clear to me is why GL_RGBA is not > >>> affected. > >> > >> The mapping from GL_RGBA <-> DRM_FORMAT_ARGB8888 already uses the > >> inverted order, so that makes sense, no? > > > > I'd have expected DRM_FORMAT_ABGR8888, since > > > > /* [31:0] A:B:G:R 8:8:8:8 little endian */ > > > > so the memory order is RGBA. But I must be missing something. Here are the three relevant entries in dri2_format_table[] (src/gallium/frontends/dri/dri_helpers.c) in Mesa: { DRM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM, 1, { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } }, { DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888, __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM, 1, { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } }, { DRM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88, __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM, 1, { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 } } }, Note that the table doesn't contain any entry for the DRM_FORMAT_RG88, DRM_FORMAT_BGRA8888 or DRM_FORMAT_RGBA8888 formats (even though PIPE_FORMAT_GR88_UNORM, PIPE_FORMAT_ABGR8888_UNORM and PIPE_FORMAT_ARGB8888_UNORM exist in Mesa). It's also worth noting that the format_mapping[] table in src/gallium/frontends/dri/dri_util.c contains the following entries: { .image_format = __DRI_IMAGE_FORMAT_ARGB8888, .mesa_format = MESA_FORMAT_B8G8R8A8_UNORM, .internal_format = GL_RGBA8, }, { .image_format = __DRI_IMAGE_FORMAT_ABGR8888, .mesa_format = MESA_FORMAT_R8G8B8A8_UNORM, .internal_format = GL_RGBA8, }, { .image_format = __DRI_IMAGE_FORMAT_GR88, .mesa_format = MESA_FORMAT_RG_UNORM8, .internal_format = GL_RG8, }, { .image_format = __DRI_IMAGE_FORMAT_GR88, .mesa_format = MESA_FORMAT_LA_UNORM8, .internal_format = GL_RG8, }, > Urgh. I think you're right. This format is only used for the output > buffer, not the input ones - and we require the dmabuf import to succeed > in that case, so there's no fallback path. > > If we have a R-B swap here - then we most likely also have one in the > shaders, compensating for it. We have switch (outputFormat) { case formats::ARGB8888: case formats::XRGB8888: break; case formats::ABGR8888: case formats::XBGR8888: egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); break; default: LOG(Debayer, Error) << "Unsupported output format"; return -EINVAL; } in DebayerEGL::initBayerShaders(), and #if defined (SWAP_BLUE) gl_FragColor = vec4(rgb.bgr, 1.0); #else gl_FragColor = vec4(rgb, 1.0); #endif in the shaders. Unless I'm mistaken, while GL_RG and GL_RGBA may map by default to R, G, B and A stored in bytes 0, 1, 2 and 3 respectively, the actual byte order in memory can be overridden with EGL_LINUX_DRM_FOURCC_EXT when calling eglCreateImageKHR(). This is documented in https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import.txt: The ordering of samples within a plane is taken from the drm_fourcc pixel_format specified for EGL_LINUX_DRM_FOURCC_EXT. It therefore doesn't matter much if we map GL_RGBA to DRM_FORMAT_ARGB8888 or DRM_FORMAT_ABGR8888, as long as both are supported by the GPU. Similarly, mapping GL_RG to DRM_FORMAT_RG88 would be absolutely fine if it wasn't for the fact that Mesa doesn't support that mapping (likely because no GPU supports it). If GL_RGBA would indeed map natively to DRM_FORMAT_ABGR8888 unless specified otherwise, it's probably safe to consider DRM_FORMAT_ABGR8888 as more widely supported by GPUs than DRM_FORMAT_ARGB8888. It would then be better to use DRM_FORMAT_ABGR8888 to ensure compatibility with a wider range of GPUs. Could someone test mapping GL_RGBA to GL_ABGR, and setting SWAP_BLUE for formats::[AX]RGB8888 instead of formats::[AX]BGR8888 ? The commit message of this patch should probably be updated to reflect the above (if my explanation is correct). > >>> Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ipu6 + > >>> ov2740 > >>> > >>>> Fixes: 6e23162ddcae ("egl: Add GL format parameter to eGLImage > >>>> constructor") > >>>> Signed-off-by: Faizel K B <faizel.kb@gmail.com> > >>>> --- > >>>> > >>>> Notes: > >>>> Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an > >>>> IMX415 > >>>> sensor (SGBRG10 unpacked, 3864x2192). > >>>> Panfrost requires the row stride of linear dmabuf imports > >>>> to be > >>>> 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 > >>>> bytes, so > >>>> the import also needed a local rkcif change to honour the > >>>> 256-byte > >>>> aligned stride (7936) that DebayerEGL::preferredInputStride() > >>>> requests. > >>>> > >>>> src/libcamera/egl.cpp | 2 +- > >>>> 1 file changed, 1 insertion(+), 1 deletion(-) > >>>> > >>>> diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp > >>>> index 3cde9040a..59a7d8cf9 100644 > >>>> --- a/src/libcamera/egl.cpp > >>>> +++ b/src/libcamera/egl.cpp > >>>> @@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage > >>>> &eglImage, int fd, bool output) > >>>> drm_format = DRM_FORMAT_R8; > >>>> break; > >>>> case GL_RG: > >>>> - drm_format = DRM_FORMAT_RG88; > >>>> + drm_format = DRM_FORMAT_GR88; > >>>> break; > >>>> case GL_RGBA: > >>>> drm_format = DRM_FORMAT_ARGB8888;
On Wed, Oct 21, 2026 at 11:13:01AM +0200, Robert Mader wrote: >Hi, thanks for the patch! > >> >>Notes: >> Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an IMX415 >> sensor (SGBRG10 unpacked, 3864x2192). >> Panfrost requires the row stride of linear dmabuf imports to be >> 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 bytes, so >> the import also needed a local rkcif change to honour the 256-byte >> aligned stride (7936) that DebayerEGL::preferredInputStride() requests. >Note that V4L2 drivers don't need to honor the bytesperline request - >you could also just align things to 64 bytes (7744) if that's enough >for Panfrost. But optimally the upstream driver would honor the >request and not hardcode any values - any chance you're looking into >working on that? :) Yes. I am planning to work on it. >> >> src/libcamera/egl.cpp | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >>diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp >>index 3cde9040a..59a7d8cf9 100644 >>--- a/src/libcamera/egl.cpp >>+++ b/src/libcamera/egl.cpp >>@@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) >> drm_format = DRM_FORMAT_R8; >> break; >> case GL_RG: >>- drm_format = DRM_FORMAT_RG88; >>+ drm_format = DRM_FORMAT_GR88; > >Good catch! > >Reviewed-by: Robert Mader <robert.mader@collabora.com> Thanks for the review. I am planning to send a two set patch for addressing the comments on this and output path (GL_RGBA).
Hi, Thank you all for the reviews and the testing. >> >>>> >> >>>> Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is >> >>>> supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the >> >>>> output path (GL_RGBA) are not affected. >> >>> >> >>> The only thing that's not entirely clear to me is why GL_RGBA is not >> >>> affected. >> >> >> >> The mapping from GL_RGBA <-> DRM_FORMAT_ARGB8888 already uses the >> >> inverted order, so that makes sense, no? >> > >> > I'd have expected DRM_FORMAT_ABGR8888, since >> > >> > /* [31:0] A:B:G:R 8:8:8:8 little endian */ >> > >> > so the memory order is RGBA. But I must be missing something. > >Here are the three relevant entries in dri2_format_table[] >(src/gallium/frontends/dri/dri_helpers.c) in Mesa: > > { DRM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888, > __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM, 1, > { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } }, > { DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888, > __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM, 1, > { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } }, > { DRM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88, > __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM, 1, > { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 } } }, > >Note that the table doesn't contain any entry for the DRM_FORMAT_RG88, >DRM_FORMAT_BGRA8888 or DRM_FORMAT_RGBA8888 formats (even though >PIPE_FORMAT_GR88_UNORM, PIPE_FORMAT_ABGR8888_UNORM and >PIPE_FORMAT_ARGB8888_UNORM exist in Mesa). > >It's also worth noting that the format_mapping[] table in >src/gallium/frontends/dri/dri_util.c contains the following entries: > > { > .image_format = __DRI_IMAGE_FORMAT_ARGB8888, > .mesa_format = MESA_FORMAT_B8G8R8A8_UNORM, > .internal_format = GL_RGBA8, > }, > { > .image_format = __DRI_IMAGE_FORMAT_ABGR8888, > .mesa_format = MESA_FORMAT_R8G8B8A8_UNORM, > .internal_format = GL_RGBA8, > }, > { > .image_format = __DRI_IMAGE_FORMAT_GR88, > .mesa_format = MESA_FORMAT_RG_UNORM8, > .internal_format = GL_RG8, > }, > { > .image_format = __DRI_IMAGE_FORMAT_GR88, > .mesa_format = MESA_FORMAT_LA_UNORM8, > .internal_format = GL_RG8, > }, > >> Urgh. I think you're right. This format is only used for the output >> buffer, not the input ones - and we require the dmabuf import to succeed >> in that case, so there's no fallback path. >> >> If we have a R-B swap here - then we most likely also have one in the >> shaders, compensating for it. > >We have > > switch (outputFormat) { > case formats::ARGB8888: > case formats::XRGB8888: > break; > case formats::ABGR8888: > case formats::XBGR8888: > egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); > break; > default: > LOG(Debayer, Error) << "Unsupported output format"; > return -EINVAL; > } > >in DebayerEGL::initBayerShaders(), and > >#if defined (SWAP_BLUE) > gl_FragColor = vec4(rgb.bgr, 1.0); >#else > gl_FragColor = vec4(rgb, 1.0); >#endif > >in the shaders. > >Unless I'm mistaken, while GL_RG and GL_RGBA may map by default to R, G, >B and A stored in bytes 0, 1, 2 and 3 respectively, the actual byte >order in memory can be overridden with EGL_LINUX_DRM_FOURCC_EXT when >calling eglCreateImageKHR(). This is documented in >https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import.txt: > > The ordering of samples within a plane is taken from the drm_fourcc > pixel_format specified for EGL_LINUX_DRM_FOURCC_EXT. > >It therefore doesn't matter much if we map GL_RGBA to >DRM_FORMAT_ARGB8888 or DRM_FORMAT_ABGR8888, as long as both are >supported by the GPU. Similarly, mapping GL_RG to DRM_FORMAT_RG88 would >be absolutely fine if it wasn't for the fact that Mesa doesn't support >that mapping (likely because no GPU supports it). > >If GL_RGBA would indeed map natively to DRM_FORMAT_ABGR8888 unless >specified otherwise, it's probably safe to consider DRM_FORMAT_ABGR8888 >as more widely supported by GPUs than DRM_FORMAT_ARGB8888. It would then >be better to use DRM_FORMAT_ABGR8888 to ensure compatibility with a >wider range of GPUs. > >Could someone test mapping GL_RGBA to GL_ABGR, and setting SWAP_BLUE for >formats::[AX]RGB8888 instead of formats::[AX]BGR8888 ? > >The commit message of this patch should probably be updated to reflect >the above (if my explanation is correct). > Yes I have tested the swap changes Barnabás Pőcze suggested and it is working. (making the drm format as DRM_FORMAT_ABGR8888 and swap changes) diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 59a7d8cf9..d7a36f232 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -187,7 +187,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) drm_format = DRM_FORMAT_GR88; break; case GL_RGBA: - drm_format = DRM_FORMAT_ARGB8888; + drm_format = DRM_FORMAT_ABGR8888; break; default: LOG(eGL, Error) << "unhandled GL format"; diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 300822f9d..cb9908e1d 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -150,10 +150,10 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm switch (outputFormat) { case formats::ARGB8888: case formats::XRGB8888: + egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); break; case formats::ABGR8888: case formats::XBGR8888: - egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); break; default: LOG(Debayer, Error) << "Unsupported output format"; Planning to send as second set of a two set patch. The first set to modify the comments to remove the 'silent' word for the initial patch. Regards Faizel
2026. 10. 22. 2:33 keltezéssel, Faizel K B írta: > Hi, > > Thank you all for the reviews and the testing. > > >>> >>>> >>> >>>> Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is >>> >>>> supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the >>> >>>> output path (GL_RGBA) are not affected. >>> >>> >>> >>> The only thing that's not entirely clear to me is why GL_RGBA is not >>> >>> affected. >>> >> >>> >> The mapping from GL_RGBA <-> DRM_FORMAT_ARGB8888 already uses the >>> >> inverted order, so that makes sense, no? >>> > >>> > I'd have expected DRM_FORMAT_ABGR8888, since >>> > >>> > /* [31:0] A:B:G:R 8:8:8:8 little endian */ >>> > >>> > so the memory order is RGBA. But I must be missing something. >> >> Here are the three relevant entries in dri2_format_table[] >> (src/gallium/frontends/dri/dri_helpers.c) in Mesa: >> >> { DRM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888, >> __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM, 1, >> { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } }, >> { DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888, >> __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM, 1, >> { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } }, >> { DRM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88, >> __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM, 1, >> { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 } } }, >> >> Note that the table doesn't contain any entry for the DRM_FORMAT_RG88, >> DRM_FORMAT_BGRA8888 or DRM_FORMAT_RGBA8888 formats (even though >> PIPE_FORMAT_GR88_UNORM, PIPE_FORMAT_ABGR8888_UNORM and >> PIPE_FORMAT_ARGB8888_UNORM exist in Mesa). >> >> It's also worth noting that the format_mapping[] table in >> src/gallium/frontends/dri/dri_util.c contains the following entries: >> >> { >> .image_format = __DRI_IMAGE_FORMAT_ARGB8888, >> .mesa_format = MESA_FORMAT_B8G8R8A8_UNORM, >> .internal_format = GL_RGBA8, >> }, >> { >> .image_format = __DRI_IMAGE_FORMAT_ABGR8888, >> .mesa_format = MESA_FORMAT_R8G8B8A8_UNORM, >> .internal_format = GL_RGBA8, >> }, >> { >> .image_format = __DRI_IMAGE_FORMAT_GR88, >> .mesa_format = MESA_FORMAT_RG_UNORM8, >> .internal_format = GL_RG8, >> }, >> { >> .image_format = __DRI_IMAGE_FORMAT_GR88, >> .mesa_format = MESA_FORMAT_LA_UNORM8, >> .internal_format = GL_RG8, >> }, >> >>> Urgh. I think you're right. This format is only used for the output >>> buffer, not the input ones - and we require the dmabuf import to succeed >>> in that case, so there's no fallback path. >>> >>> If we have a R-B swap here - then we most likely also have one in the >>> shaders, compensating for it. >> >> We have >> >> switch (outputFormat) { >> case formats::ARGB8888: >> case formats::XRGB8888: >> break; >> case formats::ABGR8888: >> case formats::XBGR8888: >> egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); >> break; >> default: >> LOG(Debayer, Error) << "Unsupported output format"; >> return -EINVAL; >> } >> >> in DebayerEGL::initBayerShaders(), and >> >> #if defined (SWAP_BLUE) >> gl_FragColor = vec4(rgb.bgr, 1.0); >> #else >> gl_FragColor = vec4(rgb, 1.0); >> #endif >> >> in the shaders. >> >> Unless I'm mistaken, while GL_RG and GL_RGBA may map by default to R, G, >> B and A stored in bytes 0, 1, 2 and 3 respectively, the actual byte >> order in memory can be overridden with EGL_LINUX_DRM_FOURCC_EXT when >> calling eglCreateImageKHR(). This is documented in >> https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import.txt: >> >> The ordering of samples within a plane is taken from the drm_fourcc >> pixel_format specified for EGL_LINUX_DRM_FOURCC_EXT. >> >> It therefore doesn't matter much if we map GL_RGBA to >> DRM_FORMAT_ARGB8888 or DRM_FORMAT_ABGR8888, as long as both are >> supported by the GPU. Similarly, mapping GL_RG to DRM_FORMAT_RG88 would >> be absolutely fine if it wasn't for the fact that Mesa doesn't support >> that mapping (likely because no GPU supports it). I'm not sure it would be fine because this is used on the input side, so using the other format "swaps" the meaning of components in the shaders. With `DRM_FORMAT_RG88`, green is byte 0, while with `DRM_FORMAT_GR88` green is byte 1. For the fallback path GL_RG + GL_UNSIGNED_BYTE is used, so green is byte 1, so I think actually only `DRM_FORMAT_GR88` is correct in this case. >> >> If GL_RGBA would indeed map natively to DRM_FORMAT_ABGR8888 unless >> specified otherwise, it's probably safe to consider DRM_FORMAT_ABGR8888 >> as more widely supported by GPUs than DRM_FORMAT_ARGB8888. It would then >> be better to use DRM_FORMAT_ABGR8888 to ensure compatibility with a >> wider range of GPUs. >> >> Could someone test mapping GL_RGBA to GL_ABGR, and setting SWAP_BLUE for >> formats::[AX]RGB8888 instead of formats::[AX]BGR8888 ? >> >> The commit message of this patch should probably be updated to reflect >> the above (if my explanation is correct). >> > > Yes I have tested the swap changes Barnabás Pőcze suggested and it is working. > (making the drm format as DRM_FORMAT_ABGR8888 and swap changes) > > > diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp > index 59a7d8cf9..d7a36f232 100644 > --- a/src/libcamera/egl.cpp > +++ b/src/libcamera/egl.cpp > @@ -187,7 +187,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) > drm_format = DRM_FORMAT_GR88; > break; > case GL_RGBA: > - drm_format = DRM_FORMAT_ARGB8888; > + drm_format = DRM_FORMAT_ABGR8888; > break; > default: > LOG(eGL, Error) << "unhandled GL format"; > diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp > index 300822f9d..cb9908e1d 100644 > --- a/src/libcamera/software_isp/debayer_egl.cpp > +++ b/src/libcamera/software_isp/debayer_egl.cpp > @@ -150,10 +150,10 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm > switch (outputFormat) { > case formats::ARGB8888: > case formats::XRGB8888: > + egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); > break; > case formats::ABGR8888: > case formats::XBGR8888: > - egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); > break; > default: > LOG(Debayer, Error) << "Unsupported output format"; > > > > > Planning to send as second set of a two set patch. The first set to modify the comments to remove the 'silent' word for the initial patch. > Regards > Faizel I think what I suggested is actually not needed. As it turns out above, it's effectively the fourcc code that determines things, and the color components are apparently remapped appropriately. Now we might still want to make this switch to always use the reverse ordering between GL_* and DRM_FORMAT_* values, but I now think it's not strictly needed.
On Thu, Oct 22, 2026 at 09:56:07AM +0200, Barnabás Pőcze wrote: > 2026. 10. 22. 2:33 keltezéssel, Faizel K B írta: > > Hi, > > > > Thank you all for the reviews and the testing. > > > >>> >>>> Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is > >>> >>>> supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the > >>> >>>> output path (GL_RGBA) are not affected. > >>> >>> > >>> >>> The only thing that's not entirely clear to me is why GL_RGBA is not > >>> >>> affected. > >>> >> > >>> >> The mapping from GL_RGBA <-> DRM_FORMAT_ARGB8888 already uses the > >>> >> inverted order, so that makes sense, no? > >>> > > >>> > I'd have expected DRM_FORMAT_ABGR8888, since > >>> > > >>> > /* [31:0] A:B:G:R 8:8:8:8 little endian */ > >>> > > >>> > so the memory order is RGBA. But I must be missing something. > >> > >> Here are the three relevant entries in dri2_format_table[] > >> (src/gallium/frontends/dri/dri_helpers.c) in Mesa: > >> > >> { DRM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888, > >> __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM, 1, > >> { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } }, > >> { DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888, > >> __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM, 1, > >> { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } }, > >> { DRM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88, > >> __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM, 1, > >> { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 } } }, > >> > >> Note that the table doesn't contain any entry for the DRM_FORMAT_RG88, > >> DRM_FORMAT_BGRA8888 or DRM_FORMAT_RGBA8888 formats (even though > >> PIPE_FORMAT_GR88_UNORM, PIPE_FORMAT_ABGR8888_UNORM and > >> PIPE_FORMAT_ARGB8888_UNORM exist in Mesa). > >> > >> It's also worth noting that the format_mapping[] table in > >> src/gallium/frontends/dri/dri_util.c contains the following entries: > >> > >> { > >> .image_format = __DRI_IMAGE_FORMAT_ARGB8888, > >> .mesa_format = MESA_FORMAT_B8G8R8A8_UNORM, > >> .internal_format = GL_RGBA8, > >> }, > >> { > >> .image_format = __DRI_IMAGE_FORMAT_ABGR8888, > >> .mesa_format = MESA_FORMAT_R8G8B8A8_UNORM, > >> .internal_format = GL_RGBA8, > >> }, > >> { > >> .image_format = __DRI_IMAGE_FORMAT_GR88, > >> .mesa_format = MESA_FORMAT_RG_UNORM8, > >> .internal_format = GL_RG8, > >> }, > >> { > >> .image_format = __DRI_IMAGE_FORMAT_GR88, > >> .mesa_format = MESA_FORMAT_LA_UNORM8, > >> .internal_format = GL_RG8, > >> }, > >> > >>> Urgh. I think you're right. This format is only used for the output > >>> buffer, not the input ones - and we require the dmabuf import to succeed > >>> in that case, so there's no fallback path. > >>> > >>> If we have a R-B swap here - then we most likely also have one in the > >>> shaders, compensating for it. > >> > >> We have > >> > >> switch (outputFormat) { > >> case formats::ARGB8888: > >> case formats::XRGB8888: > >> break; > >> case formats::ABGR8888: > >> case formats::XBGR8888: > >> egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); > >> break; > >> default: > >> LOG(Debayer, Error) << "Unsupported output format"; > >> return -EINVAL; > >> } > >> > >> in DebayerEGL::initBayerShaders(), and > >> > >> #if defined (SWAP_BLUE) > >> gl_FragColor = vec4(rgb.bgr, 1.0); > >> #else > >> gl_FragColor = vec4(rgb, 1.0); > >> #endif > >> > >> in the shaders. > >> > >> Unless I'm mistaken, while GL_RG and GL_RGBA may map by default to R, G, > >> B and A stored in bytes 0, 1, 2 and 3 respectively, the actual byte > >> order in memory can be overridden with EGL_LINUX_DRM_FOURCC_EXT when > >> calling eglCreateImageKHR(). This is documented in > >> https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import.txt: > >> > >> The ordering of samples within a plane is taken from the drm_fourcc > >> pixel_format specified for EGL_LINUX_DRM_FOURCC_EXT. > >> > >> It therefore doesn't matter much if we map GL_RGBA to > >> DRM_FORMAT_ARGB8888 or DRM_FORMAT_ABGR8888, as long as both are > >> supported by the GPU. Similarly, mapping GL_RG to DRM_FORMAT_RG88 would > >> be absolutely fine if it wasn't for the fact that Mesa doesn't support > >> that mapping (likely because no GPU supports it). > > I'm not sure it would be fine because this is used on the input side, so using the other > format "swaps" the meaning of components in the shaders. With `DRM_FORMAT_RG88`, green is > byte 0, while with `DRM_FORMAT_GR88` green is byte 1. > > For the fallback path GL_RG + GL_UNSIGNED_BYTE is used, so green is byte 1, > so I think actually only `DRM_FORMAT_GR88` is correct in this case. Yes, the shaders would of course need to be updated. My point was that it could work if Mesa (and GPUs) supported that. As they don't, it's a moot point anyway. > >> If GL_RGBA would indeed map natively to DRM_FORMAT_ABGR8888 unless > >> specified otherwise, it's probably safe to consider DRM_FORMAT_ABGR8888 > >> as more widely supported by GPUs than DRM_FORMAT_ARGB8888. It would then > >> be better to use DRM_FORMAT_ABGR8888 to ensure compatibility with a > >> wider range of GPUs. > >> > >> Could someone test mapping GL_RGBA to GL_ABGR, and setting SWAP_BLUE for > >> formats::[AX]RGB8888 instead of formats::[AX]BGR8888 ? > >> > >> The commit message of this patch should probably be updated to reflect > >> the above (if my explanation is correct). > >> > > > > Yes I have tested the swap changes Barnabás Pőcze suggested and it is working. > > (making the drm format as DRM_FORMAT_ABGR8888 and swap changes) > > > > > > diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp > > index 59a7d8cf9..d7a36f232 100644 > > --- a/src/libcamera/egl.cpp > > +++ b/src/libcamera/egl.cpp > > @@ -187,7 +187,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) > > drm_format = DRM_FORMAT_GR88; > > break; > > case GL_RGBA: > > - drm_format = DRM_FORMAT_ARGB8888; > > + drm_format = DRM_FORMAT_ABGR8888; > > break; > > default: > > LOG(eGL, Error) << "unhandled GL format"; > > diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp > > index 300822f9d..cb9908e1d 100644 > > --- a/src/libcamera/software_isp/debayer_egl.cpp > > +++ b/src/libcamera/software_isp/debayer_egl.cpp > > @@ -150,10 +150,10 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm > > switch (outputFormat) { > > case formats::ARGB8888: > > case formats::XRGB8888: > > + egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); > > break; > > case formats::ABGR8888: > > case formats::XBGR8888: > > - egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); > > break; > > default: > > LOG(Debayer, Error) << "Unsupported output format"; > > > > > > Planning to send as second set of a two set patch. The first set to modify the comments to remove the 'silent' word for the initial patch. > > Regards > > Faizel > > I think what I suggested is actually not needed. As it turns out above, it's > effectively the fourcc code that determines things, and the color components > are apparently remapped appropriately. > > Now we might still want to make this switch to always use the reverse ordering > between GL_* and DRM_FORMAT_* values, but I now think it's not strictly needed. It's not strictly needed, but I think it can provide better compatibility with a wider range of GPUs. As there's no downside (that I can see), I'd prefer using ABGR8888.
On 22/10/2026 01:33, Faizel K B wrote: > @@ -150,10 +150,10 @@ int DebayerEGL::initBayerShaders(PixelFormat > inputFormat, PixelFormat outputForm > switch (outputFormat) { > case formats::ARGB8888: > case formats::XRGB8888: > + egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); This feels wrong. --- bod
On Thu, Oct 22, 2026 at 11:13:36AM +0100, Bryan O'Donoghue wrote: > On 22/10/2026 01:33, Faizel K B wrote: > > @@ -150,10 +150,10 @@ int DebayerEGL::initBayerShaders(PixelFormat > > inputFormat, PixelFormat outputForm > > switch (outputFormat) { > > case formats::ARGB8888: > > case formats::XRGB8888: > > + egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); > > This feels wrong. How so ? It moves the SWAP_BLUE from ABGR to ARGB to match the switch from DRM_FORMAT_ARGB8888 to DRM_FORMAT_ABGR8888. That is, the GPU will now expect DRM_FORMAT_ABGR8888, and if it gets DRM_FORMAT_ARGB8888 we swap R and G in the shader. Note that we could also select DRM_FORMAT_ARGB8888 or DRM_FORMAT_ABGR8888 to match the output format and drop SWAP_BLUE.
On 22/10/2026 11:19, Laurent Pinchart wrote: > Note that we could also select DRM_FORMAT_ARGB8888 or > DRM_FORMAT_ABGR8888 to match the output format and drop SWAP_BLUE. I prefer this. My original understanding of the intent of swap-blue was well, to swap the blue because it was in a different position not to compensate for how pixels are packed by the GPU. Also - I think we look into how qcam's RAW path works ... its probably fine come to think of it because we aren't doing eglCreateImageKHR on a dma-buf handle .. --- bod
Faizel K B <faizel.kb@gmail.com> writes: > Importing unpacked 10/12-bit Bayer input buffers (e.g. SGBRG10) as > dmabufs always fails with Mesa, and DebayerEGL silently falls back to > mapping each input buffer and uploading it with glTexImage2D() on every > frame: > > INFO Debayer debayer_egl.cpp:523 Importing input DMABuf failed, falling back to upload > > The cause is the DRM format used for GL_RG textures. Unpacked Bayer > pixels are 16-bit little-endian words, loaded into a GL_RG texture with > the low byte in .r and the high byte in .g, which the shaders recombine > into a single sample. R and G here are texture channels, not colours. > GL names formats in memory byte order, while DRM fourccs describe the > components of a little-endian word from MSB to LSB: > > DRM_FORMAT_RG88 [15:0] R:G 8:8 little endian -> byte 0 = G, byte 1 = R > DRM_FORMAT_GR88 [15:0] G:R 8:8 little endian -> byte 0 = R, byte 1 = G > > The import path maps GL_RG to DRM_FORMAT_RG88, which has the opposite > byte order. Mesa has no RG88 entry in its DRI image format table, so > eglCreateImageKHR() fails. > > Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is > supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the > output path (GL_RGBA) are not affected. > > Fixes: 6e23162ddcae ("egl: Add GL format parameter to eGLImage constructor") > Signed-off-by: Faizel K B <faizel.kb@gmail.com> Tested-by: Milan Zamazal <mzamazal@redhat.com> With: INFO Camera camera.cpp:1216 configuring streams: (0) 1920x1080-ABGR8888/sRGB INFO SoftwareIsp software_isp.cpp:300 Input 2304x1296-BGGR-10 stride 4608 > --- > > Notes: > Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an IMX415 > sensor (SGBRG10 unpacked, 3864x2192). > > Panfrost requires the row stride of linear dmabuf imports to be > 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 bytes, so > the import also needed a local rkcif change to honour the 256-byte > aligned stride (7936) that DebayerEGL::preferredInputStride() requests. > > src/libcamera/egl.cpp | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp > index 3cde9040a..59a7d8cf9 100644 > --- a/src/libcamera/egl.cpp > +++ b/src/libcamera/egl.cpp > @@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) > drm_format = DRM_FORMAT_R8; > break; > case GL_RG: > - drm_format = DRM_FORMAT_RG88; > + drm_format = DRM_FORMAT_GR88; > break; > case GL_RGBA: > drm_format = DRM_FORMAT_ARGB8888;
On Thu, Oct 22, 2026 at 01:16:34PM +0100, Bryan O'Donoghue wrote: > On 22/10/2026 11:19, Laurent Pinchart wrote: > > Note that we could also select DRM_FORMAT_ARGB8888 or > > DRM_FORMAT_ABGR8888 to match the output format and drop SWAP_BLUE. > > I prefer this. My only concern is that I don't know if all GPUs we may encounter support both DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888. It feels that DRM_FORMAT_ABGR8888 would always be supported (because it maps to the native order of GL_RGBA), while DRM_FORMAT_ARGB8888 may not be universally implemented. I don't know if that's true or not. > My original understanding of the intent of swap-blue was well, to swap > the blue because it was in a different position not to compensate for > how pixels are packed by the GPU. > > Also - I think we look into how qcam's RAW path works ... its probably > fine come to think of it because we aren't doing eglCreateImageKHR on a > dma-buf handle ..
On 22.10.26 18:08, Laurent Pinchart wrote: > On Thu, Oct 22, 2026 at 01:16:34PM +0100, Bryan O'Donoghue wrote: >> On 22/10/2026 11:19, Laurent Pinchart wrote: >>> Note that we could also select DRM_FORMAT_ARGB8888 or >>> DRM_FORMAT_ABGR8888 to match the output format and drop SWAP_BLUE. >> I prefer this. > My only concern is that I don't know if all GPUs we may encounter > support both DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888. It feels that > DRM_FORMAT_ABGR8888 would always be supported (because it maps to the > native order of GL_RGBA), while DRM_FORMAT_ARGB8888 may not be > universally implemented. I don't know if that's true or not. AFAIK both are universally supported. In theory there could be GLES 2.0 drivers not supporting GL_EXT_texture_format_BGRA8888 - i.e. DRM_FORMAT_ARGB8888 - which would then only support DRM_FORMAT_ABGR8888, which is mandatory. However DRM_FORMAT_ARGB8888 - together with its opaque version - happens to be the only format essentially required for Wayland compositors (WL_SHM_FORMAT_ARGB8888). So all Linux GL drivers that are not unmaintained and ancient are pretty much guaranteed to support both if I'm not totally mistaken. If we need a bit more time to discuss this, though - should we already land the original patch with the commit message fixed during applying? > >> My original understanding of the intent of swap-blue was well, to swap >> the blue because it was in a different position not to compensate for >> how pixels are packed by the GPU. >> >> Also - I think we look into how qcam's RAW path works ... its probably >> fine come to think of it because we aren't doing eglCreateImageKHR on a >> dma-buf handle ..
On Thu, Oct 22, 2026 at 08:27:47PM +0200, Robert Mader wrote: > On 22.10.26 18:08, Laurent Pinchart wrote: > > On Thu, Oct 22, 2026 at 01:16:34PM +0100, Bryan O'Donoghue wrote: > >> On 22/10/2026 11:19, Laurent Pinchart wrote: > >>> Note that we could also select DRM_FORMAT_ARGB8888 or > >>> DRM_FORMAT_ABGR8888 to match the output format and drop SWAP_BLUE. > >> > >> I prefer this. > > > > My only concern is that I don't know if all GPUs we may encounter > > support both DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888. It feels that > > DRM_FORMAT_ABGR8888 would always be supported (because it maps to the > > native order of GL_RGBA), while DRM_FORMAT_ARGB8888 may not be > > universally implemented. I don't know if that's true or not. > > AFAIK both are universally supported. In theory there could be GLES 2.0 > drivers not supporting GL_EXT_texture_format_BGRA8888 - i.e. > DRM_FORMAT_ARGB8888 - which would then only support DRM_FORMAT_ABGR8888, > which is mandatory. However DRM_FORMAT_ARGB8888 - together with its > opaque version - happens to be the only format essentially required for > Wayland compositors (WL_SHM_FORMAT_ARGB8888). So all Linux GL drivers > that are not unmaintained and ancient are pretty much guaranteed to > support both if I'm not totally mistaken. Thank you for the information. > If we need a bit more time to discuss this, though - should we already > land the original patch with the commit message fixed during applying? Fine with me. It fixes an issue, we can address GL_RGBA in a second step. > >> My original understanding of the intent of swap-blue was well, to swap > >> the blue because it was in a different position not to compensate for > >> how pixels are packed by the GPU. > >> > >> Also - I think we look into how qcam's RAW path works ... its probably > >> fine come to think of it because we aren't doing eglCreateImageKHR on a > >> dma-buf handle ..
On Thu, Oct 22, 2026 at 09:37:46PM +0300, Laurent Pinchart wrote: >On Thu, Oct 22, 2026 at 08:27:47PM +0200, Robert Mader wrote: >> On 22.10.26 18:08, Laurent Pinchart wrote: >> > On Thu, Oct 22, 2026 at 01:16:34PM +0100, Bryan O'Donoghue wrote: >> >> On 22/10/2026 11:19, Laurent Pinchart wrote: >> >>> Note that we could also select DRM_FORMAT_ARGB8888 or >> >>> DRM_FORMAT_ABGR8888 to match the output format and drop SWAP_BLUE. >> >> >> >> I prefer this. >> > >> > My only concern is that I don't know if all GPUs we may encounter >> > support both DRM_FORMAT_ARGB8888 and DRM_FORMAT_ABGR8888. It feels that >> > DRM_FORMAT_ABGR8888 would always be supported (because it maps to the >> > native order of GL_RGBA), while DRM_FORMAT_ARGB8888 may not be >> > universally implemented. I don't know if that's true or not. >> >> AFAIK both are universally supported. In theory there could be GLES 2.0 >> drivers not supporting GL_EXT_texture_format_BGRA8888 - i.e. >> DRM_FORMAT_ARGB8888 - which would then only support DRM_FORMAT_ABGR8888, >> which is mandatory. However DRM_FORMAT_ARGB8888 - together with its >> opaque version - happens to be the only format essentially required for >> Wayland compositors (WL_SHM_FORMAT_ARGB8888). So all Linux GL drivers >> that are not unmaintained and ancient are pretty much guaranteed to >> support both if I'm not totally mistaken. > >Thank you for the information. > >> If we need a bit more time to discuss this, though - should we already >> land the original patch with the commit message fixed during applying? > >Fine with me. It fixes an issue, we can address GL_RGBA in a second >step. > Thanks all. I have sent v2 with the commit message updated and the tags collected https://patchwork.libcamera.org/patch/28567/ Regards Faizel
diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 3cde9040a..59a7d8cf9 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -184,7 +184,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) drm_format = DRM_FORMAT_R8; break; case GL_RG: - drm_format = DRM_FORMAT_RG88; + drm_format = DRM_FORMAT_GR88; break; case GL_RGBA: drm_format = DRM_FORMAT_ARGB8888;
Importing unpacked 10/12-bit Bayer input buffers (e.g. SGBRG10) as dmabufs always fails with Mesa, and DebayerEGL silently falls back to mapping each input buffer and uploading it with glTexImage2D() on every frame: INFO Debayer debayer_egl.cpp:523 Importing input DMABuf failed, falling back to upload The cause is the DRM format used for GL_RG textures. Unpacked Bayer pixels are 16-bit little-endian words, loaded into a GL_RG texture with the low byte in .r and the high byte in .g, which the shaders recombine into a single sample. R and G here are texture channels, not colours. GL names formats in memory byte order, while DRM fourccs describe the components of a little-endian word from MSB to LSB: DRM_FORMAT_RG88 [15:0] R:G 8:8 little endian -> byte 0 = G, byte 1 = R DRM_FORMAT_GR88 [15:0] G:R 8:8 little endian -> byte 0 = R, byte 1 = G The import path maps GL_RG to DRM_FORMAT_RG88, which has the opposite byte order. Mesa has no RG88 entry in its DRI image format table, so eglCreateImageKHR() fails. Map GL_RG to DRM_FORMAT_GR88, which matches the upload path and is supported by Mesa. 8-bit and CSI-2 packed input (GL_LUMINANCE) and the output path (GL_RGBA) are not affected. Fixes: 6e23162ddcae ("egl: Add GL format parameter to eGLImage constructor") Signed-off-by: Faizel K B <faizel.kb@gmail.com> --- Notes: Tested on RK3588 (Mali-G610, Panfrost, Mesa 24.3.4) with an IMX415 sensor (SGBRG10 unpacked, 3864x2192). Panfrost requires the row stride of linear dmabuf imports to be 64-byte aligned. The SGBRG10 stride at 3864 pixels is 7728 bytes, so the import also needed a local rkcif change to honour the 256-byte aligned stride (7936) that DebayerEGL::preferredInputStride() requests. src/libcamera/egl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)