From: Kerem Karabay <kekrby@gmail.com>
Add XRGB8888 emulation helper for devices that only support BGR888.
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
---
v2 -> Fix incorrect description
v3 -> No change in this patch
v4 -> No change in this patch
drivers/gpu/drm/drm_format_helper.c | 54 +++++++++++++
.../gpu/drm/tests/drm_format_helper_test.c | 81 +++++++++++++++++++
include/drm/drm_format_helper.h | 3 +
3 files changed, 138 insertions(+)
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index b1be458ed..4f60c8d8f 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -702,6 +702,57 @@ void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pi
}
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888);
+static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
+{
+ u8 *dbuf8 = dbuf;
+ const __le32 *sbuf32 = sbuf;
+ unsigned int x;
+ u32 pix;
+
+ for (x = 0; x < pixels; x++) {
+ pix = le32_to_cpu(sbuf32[x]);
+ /* write red-green-blue to output in little endianness */
+ *dbuf8++ = (pix & 0x00ff0000) >> 16;
+ *dbuf8++ = (pix & 0x0000ff00) >> 8;
+ *dbuf8++ = (pix & 0x000000ff) >> 0;
+ }
+}
+
+/**
+ * drm_fb_xrgb8888_to_bgr888 - Convert XRGB8888 to BGR888 clip buffer
+ * @dst: Array of BGR888 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ * within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffers
+ * @fb: DRM framebuffer
+ * @clip: Clip rectangle area to copy
+ * @state: Transform and conversion state
+ *
+ * This function copies parts of a framebuffer to display memory and converts the
+ * color format during the process. Destination and framebuffer formats must match. The
+ * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
+ * least as many entries as there are planes in @fb's format. Each entry stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
+ *
+ * Drivers can use this function for BGR888 devices that don't natively
+ * support XRGB8888.
+ */
+void drm_fb_xrgb8888_to_bgr888(struct iosys_map *dst, const unsigned int *dst_pitch,
+ const struct iosys_map *src, const struct drm_framebuffer *fb,
+ const struct drm_rect *clip, struct drm_format_conv_state *state)
+{
+ static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+ 3,
+ };
+
+ drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
+ drm_fb_xrgb8888_to_bgr888_line);
+}
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgr888);
+
static void drm_fb_xrgb8888_to_argb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
{
__le32 *dbuf32 = dbuf;
@@ -1035,6 +1086,9 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d
} else if (dst_format == DRM_FORMAT_RGB888) {
drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip, state);
return 0;
+ } else if (dst_format == DRM_FORMAT_BGR888) {
+ drm_fb_xrgb8888_to_bgr888(dst, dst_pitch, src, fb, clip, state);
+ return 0;
} else if (dst_format == DRM_FORMAT_ARGB8888) {
drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip, state);
return 0;
diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c
index 08992636e..35cd3405d 100644
--- a/drivers/gpu/drm/tests/drm_format_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_format_helper_test.c
@@ -60,6 +60,11 @@ struct convert_to_rgb888_result {
const u8 expected[TEST_BUF_SIZE];
};
+struct convert_to_bgr888_result {
+ unsigned int dst_pitch;
+ const u8 expected[TEST_BUF_SIZE];
+};
+
struct convert_to_argb8888_result {
unsigned int dst_pitch;
const u32 expected[TEST_BUF_SIZE];
@@ -107,6 +112,7 @@ struct convert_xrgb8888_case {
struct convert_to_argb1555_result argb1555_result;
struct convert_to_rgba5551_result rgba5551_result;
struct convert_to_rgb888_result rgb888_result;
+ struct convert_to_bgr888_result bgr888_result;
struct convert_to_argb8888_result argb8888_result;
struct convert_to_xrgb2101010_result xrgb2101010_result;
struct convert_to_argb2101010_result argb2101010_result;
@@ -151,6 +157,10 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
.dst_pitch = TEST_USE_DEFAULT_PITCH,
.expected = { 0x00, 0x00, 0xFF },
},
+ .bgr888_result = {
+ .dst_pitch = TEST_USE_DEFAULT_PITCH,
+ .expected = { 0xFF, 0x00, 0x00 },
+ },
.argb8888_result = {
.dst_pitch = TEST_USE_DEFAULT_PITCH,
.expected = { 0xFFFF0000 },
@@ -217,6 +227,10 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
.dst_pitch = TEST_USE_DEFAULT_PITCH,
.expected = { 0x00, 0x00, 0xFF },
},
+ .bgr888_result = {
+ .dst_pitch = TEST_USE_DEFAULT_PITCH,
+ .expected = { 0xFF, 0x00, 0x00 },
+ },
.argb8888_result = {
.dst_pitch = TEST_USE_DEFAULT_PITCH,
.expected = { 0xFFFF0000 },
@@ -330,6 +344,15 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
},
},
+ .bgr888_result = {
+ .dst_pitch = TEST_USE_DEFAULT_PITCH,
+ .expected = {
+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
+ 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF,
+ 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+ },
+ },
.argb8888_result = {
.dst_pitch = TEST_USE_DEFAULT_PITCH,
.expected = {
@@ -468,6 +491,17 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
},
+ .bgr888_result = {
+ .dst_pitch = 15,
+ .expected = {
+ 0x0E, 0x44, 0x9C, 0x11, 0x4D, 0x05, 0xA8, 0xF3, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x6C, 0xF0, 0x73, 0x0E, 0x44, 0x9C, 0x11, 0x4D, 0x05,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xA8, 0x03, 0x03, 0x6C, 0xF0, 0x73, 0x0E, 0x44, 0x9C,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ },
.argb8888_result = {
.dst_pitch = 20,
.expected = {
@@ -914,6 +948,52 @@ static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
}
+static void drm_test_fb_xrgb8888_to_bgr888(struct kunit *test)
+{
+ const struct convert_xrgb8888_case *params = test->param_value;
+ const struct convert_to_bgr888_result *result = ¶ms->bgr888_result;
+ size_t dst_size;
+ u8 *buf = NULL;
+ __le32 *xrgb8888 = NULL;
+ struct iosys_map dst, src;
+
+ struct drm_framebuffer fb = {
+ .format = drm_format_info(DRM_FORMAT_XRGB8888),
+ .pitches = { params->pitch, 0, 0 },
+ };
+
+ dst_size = conversion_buf_size(DRM_FORMAT_BGR888, result->dst_pitch,
+ ¶ms->clip, 0);
+ KUNIT_ASSERT_GT(test, dst_size, 0);
+
+ buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
+ iosys_map_set_vaddr(&dst, buf);
+
+ xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
+ iosys_map_set_vaddr(&src, xrgb8888);
+
+ /*
+ * BGR888 expected results are already in little-endian
+ * order, so there's no need to convert the test output.
+ */
+ drm_fb_xrgb8888_to_bgr888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip,
+ &fmtcnv_state);
+ KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
+
+ buf = dst.vaddr; /* restore original value of buf */
+ memset(buf, 0, dst_size);
+
+ int blit_result = 0;
+
+ blit_result = drm_fb_blit(&dst, &result->dst_pitch, DRM_FORMAT_BGR888, &src, &fb, ¶ms->clip,
+ &fmtcnv_state);
+
+ KUNIT_EXPECT_FALSE(test, blit_result);
+ KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
+}
+
static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test)
{
const struct convert_xrgb8888_case *params = test->param_value;
@@ -1851,6 +1931,7 @@ static struct kunit_case drm_format_helper_test_cases[] = {
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb1555, convert_xrgb8888_gen_params),
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgba5551, convert_xrgb8888_gen_params),
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb888, convert_xrgb8888_gen_params),
+ KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_bgr888, convert_xrgb8888_gen_params),
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb8888, convert_xrgb8888_gen_params),
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params),
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb2101010, convert_xrgb8888_gen_params),
diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
index 428d81afe..aa1604d92 100644
--- a/include/drm/drm_format_helper.h
+++ b/include/drm/drm_format_helper.h
@@ -96,6 +96,9 @@ void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_
void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch,
const struct iosys_map *src, const struct drm_framebuffer *fb,
const struct drm_rect *clip, struct drm_format_conv_state *state);
+void drm_fb_xrgb8888_to_bgr888(struct iosys_map *dst, const unsigned int *dst_pitch,
+ const struct iosys_map *src, const struct drm_framebuffer *fb,
+ const struct drm_rect *clip, struct drm_format_conv_state *state);
void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
const struct iosys_map *src, const struct drm_framebuffer *fb,
const struct drm_rect *clip, struct drm_format_conv_state *state);
--
2.43.0
On Mon, Feb 24, 2025 at 01:38:32PM +0000, Aditya Garg wrote:
> From: Kerem Karabay <kekrby@gmail.com>
>
> Add XRGB8888 emulation helper for devices that only support BGR888.
...
> +static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
Okay the xrgb8888 is the actual pixel format independently on
the CPU endianess.
> +{
> + u8 *dbuf8 = dbuf;
> + const __le32 *sbuf32 = sbuf;
But here we assume that sbuf is __le32.
And I think we may benefit from the __be32 there.
> + unsigned int x;
> + u32 pix;
> +
> + for (x = 0; x < pixels; x++) {
> + pix = le32_to_cpu(sbuf32[x]);
> + /* write red-green-blue to output in little endianness */
> + *dbuf8++ = (pix & 0x00ff0000) >> 16;
> + *dbuf8++ = (pix & 0x0000ff00) >> 8;
> + *dbuf8++ = (pix & 0x000000ff) >> 0;
pix = be32_to_cpu(sbuf[4 * x]) >> 8;
put_unaligned_le24(pix, &dbuf[3 * x]);
> + }
Or, after all, this __le32 magic might be not needed at all. Wouldn't the below
be the equivalent
static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
{
unsigned int x;
u32 pix;
for (x = 0; x < pixels; x++) {
/* Read red-green-blue from input in big endianess and... */
pix = get_unaligned_be24(sbuf + x * 4 + 1);
/* ...write it to output in little endianness. */
put_unaligned_le24(pix, dbuf + x * 3);
}
}
The comments can even be dropped as the code quite clear about what's going on.
> +}
But it's up to you. I don't know which solution gives better code generation
either.
--
With Best Regards,
Andy Shevchenko
Hi
Am 24.02.25 um 15:29 schrieb andriy.shevchenko@linux.intel.com:
> On Mon, Feb 24, 2025 at 01:38:32PM +0000, Aditya Garg wrote:
>> From: Kerem Karabay <kekrby@gmail.com>
>>
>> Add XRGB8888 emulation helper for devices that only support BGR888.
> ...
>
>> +static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
> Okay the xrgb8888 is the actual pixel format independently on
> the CPU endianess.
>
>> +{
>> + u8 *dbuf8 = dbuf;
>> + const __le32 *sbuf32 = sbuf;
> But here we assume that sbuf is __le32.
> And I think we may benefit from the __be32 there.
No, please. XRGB is the logical order. The raw physical byte order for
DRM formats is always* little endian, hence reversed from the logical
one. sbuf points to raw memory and is therefore __le32. DRM-format byte
order is impossible to understand, I know. But that code is correct.
Best regards
Thomas
*) White lie: there's a DRM format flag signalling physical big
endianess. That isn't the case here. So nothing here should ever
indicate big endianess.
>
>> + unsigned int x;
>> + u32 pix;
>> +
>> + for (x = 0; x < pixels; x++) {
>> + pix = le32_to_cpu(sbuf32[x]);
>> + /* write red-green-blue to output in little endianness */
>> + *dbuf8++ = (pix & 0x00ff0000) >> 16;
>> + *dbuf8++ = (pix & 0x0000ff00) >> 8;
>> + *dbuf8++ = (pix & 0x000000ff) >> 0;
> pix = be32_to_cpu(sbuf[4 * x]) >> 8;
> put_unaligned_le24(pix, &dbuf[3 * x]);
>
>> + }
> Or, after all, this __le32 magic might be not needed at all. Wouldn't the below
> be the equivalent
>
> static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
> {
> unsigned int x;
> u32 pix;
>
> for (x = 0; x < pixels; x++) {
> /* Read red-green-blue from input in big endianess and... */
> pix = get_unaligned_be24(sbuf + x * 4 + 1);
> /* ...write it to output in little endianness. */
> put_unaligned_le24(pix, dbuf + x * 3);
> }
> }
>
> The comments can even be dropped as the code quite clear about what's going on.
>
>> +}
> But it's up to you. I don't know which solution gives better code generation
> either.
>
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)
On Tue, Feb 25, 2025 at 08:37:32AM +0100, Thomas Zimmermann wrote:
> Am 24.02.25 um 15:29 schrieb andriy.shevchenko@linux.intel.com:
> > On Mon, Feb 24, 2025 at 01:38:32PM +0000, Aditya Garg wrote:
...
> > > +static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
> > Okay the xrgb8888 is the actual pixel format independently on
> > the CPU endianess.
> >
> > > +{
> > > + u8 *dbuf8 = dbuf;
> > > + const __le32 *sbuf32 = sbuf;
> > But here we assume that sbuf is __le32.
> > And I think we may benefit from the __be32 there.
>
> No, please. XRGB is the logical order. The raw physical byte order for DRM
> formats is always* little endian, hence reversed from the logical one. sbuf
> points to raw memory and is therefore __le32. DRM-format byte order is
> impossible to understand, I know. But that code is correct.
Okay, so it's only about the colour (top-level) layout, the input and output
data is always in little endian?
> *) White lie: there's a DRM format flag signalling physical big endianess.
> That isn't the case here. So nothing here should ever indicate big
> endianess.
But should it indicate the little? To me sounds like neither...
> > > + unsigned int x;
> > > + u32 pix;
> > > +
> > > + for (x = 0; x < pixels; x++) {
> > > + pix = le32_to_cpu(sbuf32[x]);
> > > + /* write red-green-blue to output in little endianness */
> > > + *dbuf8++ = (pix & 0x00ff0000) >> 16;
> > > + *dbuf8++ = (pix & 0x0000ff00) >> 8;
> > > + *dbuf8++ = (pix & 0x000000ff) >> 0;
> > pix = be32_to_cpu(sbuf[4 * x]) >> 8;
> > put_unaligned_le24(pix, &dbuf[3 * x]);
> >
> > > + }
> > Or, after all, this __le32 magic might be not needed at all. Wouldn't the below
> > be the equivalent
> >
> > static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
> > {
> > unsigned int x;
> > u32 pix;
> >
> > for (x = 0; x < pixels; x++) {
> > /* Read red-green-blue from input in big endianess and... */
> > pix = get_unaligned_be24(sbuf + x * 4 + 1);
> > /* ...write it to output in little endianness. */
> > put_unaligned_le24(pix, dbuf + x * 3);
> > }
> > }
> >
> > The comments can even be dropped as the code quite clear about what's going on.
> >
> > > +}
> > But it's up to you. I don't know which solution gives better code generation
> > either.
--
With Best Regards,
Andy Shevchenko
This conversion helper mimics the existing drm_fb_xrgb8888_to_rgb888 helper
> On 24 Feb 2025, at 7:59 PM, andriy.shevchenko@linux.intel.com wrote:
>
> On Mon, Feb 24, 2025 at 01:38:32PM +0000, Aditya Garg wrote:
>> From: Kerem Karabay <kekrby@gmail.com>
>>
>> Add XRGB8888 emulation helper for devices that only support BGR888.
>
> ...
>
>> +static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
>
> Okay the xrgb8888 is the actual pixel format independently on
> the CPU endianess.
>
>> +{
>> + u8 *dbuf8 = dbuf;
>> + const __le32 *sbuf32 = sbuf;
>
> But here we assume that sbuf is __le32.
> And I think we may benefit from the __be32 there.
So, like drm_fb_xrgb8888_to_rgb888, we are using __le32
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n657
>
>> + unsigned int x;
>> + u32 pix;
>> +
>> + for (x = 0; x < pixels; x++) {
>> + pix = le32_to_cpu(sbuf32[x]);
>> + /* write red-green-blue to output in little endianness */
>> + *dbuf8++ = (pix & 0x00ff0000) >> 16;
>> + *dbuf8++ = (pix & 0x0000ff00) >> 8;
>> + *dbuf8++ = (pix & 0x000000ff) >> 0;
>
> pix = be32_to_cpu(sbuf[4 * x]) >> 8;
> put_unaligned_le24(pix, &dbuf[3 * x]);
Again,
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n664
>
>> + }
>
> Or, after all, this __le32 magic might be not needed at all. Wouldn't the below
> be the equivalent
>
> static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
> {
> unsigned int x;
> u32 pix;
>
> for (x = 0; x < pixels; x++) {
> /* Read red-green-blue from input in big endianess and... */
> pix = get_unaligned_be24(sbuf + x * 4 + 1);
> /* ...write it to output in little endianness. */
> put_unaligned_le24(pix, dbuf + x * 3);
> }
> }
>
> The comments can even be dropped as the code quite clear about what's going on.
These comments are literally rewritten :
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n663
>
>> +}
>
> But it's up to you. I don't know which solution gives better code generation
> either.
I don't really mind any code change tbh, but I’d prefer that as an improvement to existing code, and not a part of this patchset.
On Mon, Feb 24, 2025 at 02:54:07PM +0000, Aditya Garg wrote:
> This conversion helper mimics the existing drm_fb_xrgb8888_to_rgb888 helper
Not really. See below.
> > On 24 Feb 2025, at 7:59 PM, andriy.shevchenko@linux.intel.com wrote:
> > On Mon, Feb 24, 2025 at 01:38:32PM +0000, Aditya Garg wrote:
...
> >> +static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
> >
> > Okay the xrgb8888 is the actual pixel format independently on
> > the CPU endianess.
> >
> >> +{
> >> + u8 *dbuf8 = dbuf;
> >> + const __le32 *sbuf32 = sbuf;
> >
> > But here we assume that sbuf is __le32.
> > And I think we may benefit from the __be32 there.
>
> So, like drm_fb_xrgb8888_to_rgb888, we are using __le32
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n657
The rgb888 != bgr888, that's where the byte swapping happens. So, one should
use __be32 if the other has already been using __le32.
> >> + unsigned int x;
> >> + u32 pix;
> >> +
> >> + for (x = 0; x < pixels; x++) {
> >> + pix = le32_to_cpu(sbuf32[x]);
> >> + /* write red-green-blue to output in little endianness */
> >> + *dbuf8++ = (pix & 0x00ff0000) >> 16;
> >> + *dbuf8++ = (pix & 0x0000ff00) >> 8;
> >> + *dbuf8++ = (pix & 0x000000ff) >> 0;
> >
> > pix = be32_to_cpu(sbuf[4 * x]) >> 8;
> > put_unaligned_le24(pix, &dbuf[3 * x]);
>
> Again,
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n664
As per above.
> >> + }
> >
> > Or, after all, this __le32 magic might be not needed at all. Wouldn't the below
> > be the equivalent
> >
> > static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
> > {
> > unsigned int x;
> > u32 pix;
> >
> > for (x = 0; x < pixels; x++) {
> > /* Read red-green-blue from input in big endianess and... */
> > pix = get_unaligned_be24(sbuf + x * 4 + 1);
> > /* ...write it to output in little endianness. */
> > put_unaligned_le24(pix, dbuf + x * 3);
> > }
> > }
> >
> > The comments can even be dropped as the code quite clear about what's going on.
>
> These comments are literally rewritten :
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n663
>
> >> +}
> >
> > But it's up to you. I don't know which solution gives better code generation
> > either.
>
> I don't really mind any code change tbh, but I’d prefer that as an
> improvement to existing code, and not a part of this patchset.
Right, but see my argumentation above.
--
With Best Regards,
Andy Shevchenko
On Mon, Feb 24, 2025 at 05:00:50PM +0200, andriy.shevchenko@linux.intel.com wrote:
> On Mon, Feb 24, 2025 at 02:54:07PM +0000, Aditya Garg wrote:
> > This conversion helper mimics the existing drm_fb_xrgb8888_to_rgb888 helper
>
> Not really. See below.
>
> > > On 24 Feb 2025, at 7:59 PM, andriy.shevchenko@linux.intel.com wrote:
> > > On Mon, Feb 24, 2025 at 01:38:32PM +0000, Aditya Garg wrote:
...
> > >> +static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
> > >
> > > Okay the xrgb8888 is the actual pixel format independently on
> > > the CPU endianess.
> > >
> > >> +{
> > >> + u8 *dbuf8 = dbuf;
> > >> + const __le32 *sbuf32 = sbuf;
> > >
> > > But here we assume that sbuf is __le32.
> > > And I think we may benefit from the __be32 there.
> >
> > So, like drm_fb_xrgb8888_to_rgb888, we are using __le32
> >
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n657
>
> The rgb888 != bgr888, that's where the byte swapping happens. So, one should
> use __be32 if the other has already been using __le32.
But in both cases it's actually the 24-bit format in 4-byte packets.
I would rewrite both to remove these types as they are just confusing. But it's
probably not your call. So, if you want to stick with __le32, fine, not my call
either :-)
> > >> + unsigned int x;
> > >> + u32 pix;
> > >> +
> > >> + for (x = 0; x < pixels; x++) {
> > >> + pix = le32_to_cpu(sbuf32[x]);
> > >> + /* write red-green-blue to output in little endianness */
> > >> + *dbuf8++ = (pix & 0x00ff0000) >> 16;
> > >> + *dbuf8++ = (pix & 0x0000ff00) >> 8;
> > >> + *dbuf8++ = (pix & 0x000000ff) >> 0;
> > >
> > > pix = be32_to_cpu(sbuf[4 * x]) >> 8;
> > > put_unaligned_le24(pix, &dbuf[3 * x]);
> >
> > Again,
> >
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n664
>
> As per above.
>
> > >> + }
> > >
> > > Or, after all, this __le32 magic might be not needed at all. Wouldn't the below
> > > be the equivalent
> > >
> > > static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
> > > {
> > > unsigned int x;
> > > u32 pix;
> > >
> > > for (x = 0; x < pixels; x++) {
> > > /* Read red-green-blue from input in big endianess and... */
> > > pix = get_unaligned_be24(sbuf + x * 4 + 1);
> > > /* ...write it to output in little endianness. */
> > > put_unaligned_le24(pix, dbuf + x * 3);
> > > }
> > > }
> > >
> > > The comments can even be dropped as the code quite clear about what's going on.
--
With Best Regards,
Andy Shevchenko
> On 24 Feb 2025, at 8:30 PM, andriy.shevchenko@linux.intel.com wrote:
>
> On Mon, Feb 24, 2025 at 02:54:07PM +0000, Aditya Garg wrote:
>> This conversion helper mimics the existing drm_fb_xrgb8888_to_rgb888 helper
>
> Not really. See below.
>
>>> On 24 Feb 2025, at 7:59 PM, andriy.shevchenko@linux.intel.com wrote:
>>> On Mon, Feb 24, 2025 at 01:38:32PM +0000, Aditya Garg wrote:
>
> ...
>
>>>> +static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
>>>
>>> Okay the xrgb8888 is the actual pixel format independently on
>>> the CPU endianess.
>>>
>>>> +{
>>>> + u8 *dbuf8 = dbuf;
>>>> + const __le32 *sbuf32 = sbuf;
>>>
>>> But here we assume that sbuf is __le32.
>>> And I think we may benefit from the __be32 there.
>>
>> So, like drm_fb_xrgb8888_to_rgb888, we are using __le32
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n657
>
> The rgb888 != bgr888, that's where the byte swapping happens. So, one should
> use __be32 if the other has already been using __le32.
>
>>>> + unsigned int x;
>>>> + u32 pix;
>>>> +
>>>> + for (x = 0; x < pixels; x++) {
>>>> + pix = le32_to_cpu(sbuf32[x]);
>>>> + /* write red-green-blue to output in little endianness */
>>>> + *dbuf8++ = (pix & 0x00ff0000) >> 16;
>>>> + *dbuf8++ = (pix & 0x0000ff00) >> 8;
>>>> + *dbuf8++ = (pix & 0x000000ff) >> 0;
>>>
>>> pix = be32_to_cpu(sbuf[4 * x]) >> 8;
>>> put_unaligned_le24(pix, &dbuf[3 * x]);
>>
>> Again,
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n664
>
> As per above.
>
>>>> + }
>>>
>>> Or, after all, this __le32 magic might be not needed at all. Wouldn't the below
>>> be the equivalent
>>>
>>> static void drm_fb_xrgb8888_to_bgr888_line(void *dbuf, const void *sbuf, unsigned int pixels)
>>> {
>>> unsigned int x;
>>> u32 pix;
>>>
>>> for (x = 0; x < pixels; x++) {
>>> /* Read red-green-blue from input in big endianess and... */
>>> pix = get_unaligned_be24(sbuf + x * 4 + 1);
>>> /* ...write it to output in little endianness. */
>>> put_unaligned_le24(pix, dbuf + x * 3);
>>> }
>>> }
>>>
>>> The comments can even be dropped as the code quite clear about what's going on.
>>
>> These comments are literally rewritten :
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_format_helper.c?h=v6.14-rc4#n663
>>
>>>> +}
>>>
>>> But it's up to you. I don't know which solution gives better code generation
>>> either.
>>
>> I don't really mind any code change tbh, but I’d prefer that as an
>> improvement to existing code, and not a part of this patchset.
>
> Right, but see my argumentation above.
Guess what, I’ll just wait for Thomas to reply here. He knows more DRM than me.
>
> --
> With Best Regards,
> Andy Shevchenko
© 2016 - 2025 Red Hat, Inc.