| Message ID | 20261021065624.153207-1-faizel.kb@gmail.com |
|---|---|
| State | New |
| 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;
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(-)