# Possible causes for RGB/BGR channel swap in off-screen GPU rendering pipeline

**URL:** <https://forums.imgtec.com/t/possible-causes-for-rgb-bgr-channel-swap-in-off-screen-gpu-rendering-pipeline/4247>\
**Category:** PowerVR Insider\
**Created:** [December 17, 2025, 6:59am UTC](https://forums.imgtec.com/t/possible-causes-for-rgb-bgr-channel-swap-in-off-screen-gpu-rendering-pipeline/4247 "2025-12-17T06:59:45Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jason1](https://avatars.discourse-cdn.com/v4/letter/j/b19c9b/32.png) [@Jason1](https://forums.imgtec.com/u/Jason1)\
**Post date:** [December 17, 2025, 6:59am UTC](https://forums.imgtec.com/t/possible-causes-for-rgb-bgr-channel-swap-in-off-screen-gpu-rendering-pipeline/4247/1 "2025-12-17T06:59:45Z")

</div>

## GPU Rendering Pipeline Description

**GPU Model:** BXEP-4-32

**Input Process:**

1. **Memory Allocation:** VI (Video Input) calls SMR allocator to obtain physical memory and writes YUV422 data into this SMR.
2. **DMA Buffer Creation:** Register the SMR physical address to create a DMA buffer, then obtain a DMA file descriptor using `dma_buf_export` and `dma_buf_fd`.
3. **EGLImage Creation:** Create an EGLImage using the DMA file descriptor.
4. **Texture Creation:** Create an input texture based on the EGLImage (using `DRM_FORMAT_UYVY` format).

**Output Process:**

1. **Memory Allocation:** Call SMR API to allocate physical memory as output buffer.
2. **DMA Buffer Registration:** Register the SMR physical address to create a DMA buffer and obtain a DMA file descriptor.
3. **EGLImage Creation:** Create an EGLImage using the DMA file descriptor.
4. **Texture Creation:** Create a texture based on the EGLImage.
5. **FBO Creation:** Create a Framebuffer Object (FBO) with the texture (using `DRM_FORMAT_RGB888` format).

**Rendering Process:**

1. Bind the FBO.
2. Bind the input texture.
3. Execute `glDrawArrays` for rendering.

**Fragment Shader Code:**

```glsl
#version 320 es
#extension GL_EXT_YUV_target : enable

in highp vec2 texcoord;
out highp vec3 myFragColor;

uniform highp __samplerExternal2DY2YEXT basetexture;

void main(void)
{
    highp vec4 myFragColorYUV = texture(basetexture, texcoord);
    myFragColor = vec3(yuv_2_rgb(myFragColorYUV.xyz, itu_601));
}

```

**Issue Encountered:**  
The actual output image format appears to be **BGR888** instead of the expected **RGB888**.

**Question:**  
Is this rendering pipeline incorrect? What could be causing the RGB/BGR channel swap in the final output?

---

<div class="post-metadata">

**Author:** ![Jason1](https://avatars.discourse-cdn.com/v4/letter/j/b19c9b/32.png) [@Jason1](https://forums.imgtec.com/u/Jason1)\
**Post date:** [December 17, 2025, 7:20am UTC](https://forums.imgtec.com/t/possible-causes-for-rgb-bgr-channel-swap-in-off-screen-gpu-rendering-pipeline/4247/2 "2025-12-17T07:20:22Z")

</div>

I have verified the output format behaviors in two scenarios as follows:

#### **1. Output Format: DRM\_FORMAT\_ARGB8888**

**Fragment Shader Code** :

**glsl**

```auto
#version 320 es
#extension GL_EXT_YUV_target : enable

in highp vec2 texcoord;

out highp vec4 myFragColor;

uniform highp __samplerExternal2DY2YEXT basetexture;

void main(void)
{
	highp vec4 myFragColorYUV = texture(basetexture, texcoord);
	myFragColor = vec4(yuv_2_rgb(myFragColorYUV.xyz, itu_601), 1.0);
}

```

**Observation** : The actual output image format is RGBA8888 (instead of the expected ARGB8888).

#### **2. Output Format: DRM\_FORMAT\_BGR888**

**Fragment Shader Code** :

**glsl**

```auto
#version 320 es
#extension GL_EXT_YUV_target : enable

in highp vec2 texcoord;

out highp vec3 myFragColor;

uniform highp __samplerExternal2DY2YEXT basetexture;

void main(void)
{
	highp vec4 myFragColorYUV = texture(basetexture, texcoord);
	myFragColor = vec3(yuv_2_rgb(myFragColorYUV.xyz, itu_601));
}

```

**Findings** :

- I had to set the `EGL_DMA_BUF_PLANE0_PITCH_EXT` attribute to `output_image_width * 4`; otherwise, the `eglCreateImageKHR` function would return an error (failed to create EGLImage).

- After setting `EGL_DMA_BUF_PLANE0_PITCH_EXT = width * 4`, the saved image shows **offset (misalignment)** and **horizontal stripe artifacts**.

**3** When the fragment shader is configured to output `myFragColor = vec3(1.0, 0.0, 0.0);` (intended to produce pure red), the saved image actually appears blue instead of the expected red.

---

<div class="post-metadata">

**Author:** ![AlejandroC](https://avatars.discourse-cdn.com/v4/letter/a/97f17d/32.png) [@AlejandroC](https://forums.imgtec.com/u/AlejandroC)\
**Post date:** [January 2, 2026, 11:36am UTC](https://forums.imgtec.com/t/possible-causes-for-rgb-bgr-channel-swap-in-off-screen-gpu-rendering-pipeline/4247/3 "2026-01-02T11:36:19Z")

</div>

Hi Jason1,

Thanks for your message, and welcome to the PowerVR Developer Forum!

I would advice comparing your code with our basic PowerVR SDK OpenGL ES example _IntroducingPVRCamera_, present in [Native\_SDK/examples/OpenGLES/05\_IntroducingPVRCamera at master · powervr-graphics/Native\_SDK · GitHub](https://github.com/powervr-graphics/Native_SDK/tree/master/examples/OpenGLES/05_IntroducingPVRCamera) as there are similarities with your application.

We also have a Vulkan sample which shows how to sample different YUV textures in [Native\_SDK/examples/Vulkan/YCbCrTextureSampling at master · powervr-graphics/Native\_SDK · GitHub](https://github.com/powervr-graphics/Native_SDK/tree/master/examples/Vulkan/YCbCrTextureSampling) in case it is of any help.

Best regards,  
Alejandro

---

<div class="post-metadata">

**Author:** ![Jason1](https://avatars.discourse-cdn.com/v4/letter/j/b19c9b/32.png) [@Jason1](https://forums.imgtec.com/u/Jason1)\
**Post date:** [January 22, 2026, 2:39am UTC](https://forums.imgtec.com/t/possible-causes-for-rgb-bgr-channel-swap-in-off-screen-gpu-rendering-pipeline/4247/4 "2026-01-22T02:39:05Z")

</div>

Thank you, appreciate for your answer
