[libcamera-devel,v5,1/4] qcam: add OpenGL shader code as Qt resource

Message ID 20200904084316.7319-2-show.liu@linaro.org
State Superseded
Headers show
Series
  • qcam: accelerate format conversion by OpenGL shader
Related show

Commit Message

Show Liu Sept. 4, 2020, 8:43 a.m. UTC
qcam: add OpenGL shader code as Qt resource

Signed-off-by: Show Liu <show.liu@linaro.org>
---
 src/qcam/assets/shader/NV_2_planes_UV_f.glsl | 32 +++++++++++++++++++
 src/qcam/assets/shader/NV_2_planes_VU_f.glsl | 32 +++++++++++++++++++
 src/qcam/assets/shader/NV_3_planes_UV_f.glsl | 33 ++++++++++++++++++++
 src/qcam/assets/shader/NV_3_planes_VU_f.glsl | 33 ++++++++++++++++++++
 src/qcam/assets/shader/NV_vertex_shader.glsl | 16 ++++++++++
 src/qcam/assets/shader/shaders.qrc           | 10 ++++++
 src/qcam/meson.build                         |  1 +
 7 files changed, 157 insertions(+)
 create mode 100644 src/qcam/assets/shader/NV_2_planes_UV_f.glsl
 create mode 100644 src/qcam/assets/shader/NV_2_planes_VU_f.glsl
 create mode 100644 src/qcam/assets/shader/NV_3_planes_UV_f.glsl
 create mode 100644 src/qcam/assets/shader/NV_3_planes_VU_f.glsl
 create mode 100644 src/qcam/assets/shader/NV_vertex_shader.glsl
 create mode 100644 src/qcam/assets/shader/shaders.qrc

Comments

Laurent Pinchart Sept. 6, 2020, 12:56 a.m. UTC | #1
Hi Show,

Thank you for the patch.

On Fri, Sep 04, 2020 at 04:43:12PM +0800, Show Liu wrote:
> qcam: add OpenGL shader code as Qt resource
> 
> Signed-off-by: Show Liu <show.liu@linaro.org>
> ---
>  src/qcam/assets/shader/NV_2_planes_UV_f.glsl | 32 +++++++++++++++++++
>  src/qcam/assets/shader/NV_2_planes_VU_f.glsl | 32 +++++++++++++++++++
>  src/qcam/assets/shader/NV_3_planes_UV_f.glsl | 33 ++++++++++++++++++++
>  src/qcam/assets/shader/NV_3_planes_VU_f.glsl | 33 ++++++++++++++++++++
>  src/qcam/assets/shader/NV_vertex_shader.glsl | 16 ++++++++++
>  src/qcam/assets/shader/shaders.qrc           | 10 ++++++
>  src/qcam/meson.build                         |  1 +
>  7 files changed, 157 insertions(+)
>  create mode 100644 src/qcam/assets/shader/NV_2_planes_UV_f.glsl
>  create mode 100644 src/qcam/assets/shader/NV_2_planes_VU_f.glsl
>  create mode 100644 src/qcam/assets/shader/NV_3_planes_UV_f.glsl
>  create mode 100644 src/qcam/assets/shader/NV_3_planes_VU_f.glsl
>  create mode 100644 src/qcam/assets/shader/NV_vertex_shader.glsl
>  create mode 100644 src/qcam/assets/shader/shaders.qrc
> 
> diff --git a/src/qcam/assets/shader/NV_2_planes_UV_f.glsl b/src/qcam/assets/shader/NV_2_planes_UV_f.glsl
> new file mode 100644
> index 0000000..54bb459
> --- /dev/null
> +++ b/src/qcam/assets/shader/NV_2_planes_UV_f.glsl
> @@ -0,0 +1,32 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2020, Linaro
> + *
> + * NV_2_planes_UV_f.glsl - Fragment shader code for NV12, NV16 and NV24 formats
> + */
> +
> +#ifdef GL_ES
> +precision mediump float;
> +#endif
> +
> +varying vec2 textureOut;
> +uniform sampler2D tex_y;
> +uniform sampler2D tex_u;
> +
> +void main(void)
> +{
> +	vec3 yuv;
> +	vec3 rgb;
> +	mat3 yuv2rgb_bt601_mat = mat3(
> +				      vec3(1.164,  1.164, 1.164),
> +				      vec3(0.000, -0.392, 2.017),
> +				      vec3(1.596, -0.813, 0.000)
> +				 );
> +
> +	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
> +	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
> +	yuv.z = texture2D(tex_u, textureOut).g - 0.500;
> +
> +	rgb = yuv2rgb_bt601_mat * yuv;
> +	gl_FragColor = vec4(rgb, 1.0);
> +}
> diff --git a/src/qcam/assets/shader/NV_2_planes_VU_f.glsl b/src/qcam/assets/shader/NV_2_planes_VU_f.glsl
> new file mode 100644
> index 0000000..6571ed6
> --- /dev/null
> +++ b/src/qcam/assets/shader/NV_2_planes_VU_f.glsl
> @@ -0,0 +1,32 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2020, Linaro
> + *
> + * NV_2_planes_VU_f.glsl - Fragment shader code for NV21, NV61 and NV42 formats
> + */
> +
> +#ifdef GL_ES
> +precision mediump float;
> +#endif
> +
> +varying vec2 textureOut;
> +uniform sampler2D tex_y;
> +uniform sampler2D tex_u;
> +
> +void main(void)
> +{
> +	vec3 yuv;
> +	vec3 rgb;
> +	mat3 yuv2rgb_bt601_mat = mat3(
> +				      vec3(1.164,  1.164, 1.164),
> +				      vec3(0.000, -0.392, 2.017),
> +				      vec3(1.596, -0.813, 0.000)
> +				 );
> +
> +	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
> +	yuv.y = texture2D(tex_u, textureOut).g - 0.500;
> +	yuv.z = texture2D(tex_u, textureOut).r - 0.500;
> +
> +	rgb = yuv2rgb_bt601_mat * yuv;
> +	gl_FragColor = vec4(rgb, 1.0);
> +}
> diff --git a/src/qcam/assets/shader/NV_3_planes_UV_f.glsl b/src/qcam/assets/shader/NV_3_planes_UV_f.glsl
> new file mode 100644
> index 0000000..9d104fd
> --- /dev/null
> +++ b/src/qcam/assets/shader/NV_3_planes_UV_f.glsl
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2020, Linaro
> + *
> + * NV_3_planes_UV_f.glsl - Fragment shader code for YUV420 format
> + */
> +
> +#ifdef GL_ES
> +precision mediump float;
> +#endif
> +
> +varying vec2 textureOut;
> +uniform sampler2D tex_y;
> +uniform sampler2D tex_u;
> +uniform sampler2D tex_v;
> +
> +void main(void)
> +{
> +	vec3 yuv;
> +	vec3 rgb;
> +	mat3 yuv2rgb_bt601_mat = mat3(
> +				      vec3(1.164,  1.164, 1.164),
> +				      vec3(0.000, -0.392, 2.017),
> +				      vec3(1.596, -0.813, 0.000)
> +				 );
> +
> +	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
> +	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
> +	yuv.z = texture2D(tex_v, textureOut).r - 0.500;
> +
> +	rgb = yuv2rgb_bt601_mat * yuv;
> +	gl_FragColor = vec4(rgb, 1.0);
> +}
> diff --git a/src/qcam/assets/shader/NV_3_planes_VU_f.glsl b/src/qcam/assets/shader/NV_3_planes_VU_f.glsl
> new file mode 100644
> index 0000000..245a619
> --- /dev/null
> +++ b/src/qcam/assets/shader/NV_3_planes_VU_f.glsl
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2020, Linaro
> + *
> + * NV_3_planes_VU_f.glsl - Fragment shader code for YVU420 format
> + */
> +
> +#ifdef GL_ES
> +precision mediump float;
> +#endif
> +
> +varying vec2 textureOut;
> +uniform sampler2D tex_y;
> +uniform sampler2D tex_u;
> +uniform sampler2D tex_v;
> +
> +void main(void)
> +{
> +	vec3 yuv;
> +	vec3 rgb;
> +	mat3 yuv2rgb_bt601_mat = mat3(
> +				      vec3(1.164,  1.164, 1.164),
> +				      vec3(0.000, -0.392, 2.017),
> +				      vec3(1.596, -0.813, 0.000)
> +				 );
> +
> +	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
> +	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
> +	yuv.z = texture2D(tex_v, textureOut).r - 0.500;

Shouldn't this be

	yuv.y = texture2D(tex_v, textureOut).r - 0.500;
	yuv.z = texture2D(tex_u, textureOut).r - 0.500;

?

Apart from that,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +
> +	rgb = yuv2rgb_bt601_mat * yuv;
> +	gl_FragColor = vec4(rgb, 1.0);
> +}
> diff --git a/src/qcam/assets/shader/NV_vertex_shader.glsl b/src/qcam/assets/shader/NV_vertex_shader.glsl
> new file mode 100644
> index 0000000..403b791
> --- /dev/null
> +++ b/src/qcam/assets/shader/NV_vertex_shader.glsl
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2020, Linaro
> + *
> + * NV_vertex_shader.glsl - Vertex shader code for NV family
> + */
> +
> +attribute vec4 vertexIn;
> +attribute vec2 textureIn;
> +varying vec2 textureOut;
> +
> +void main(void)
> +{
> +	gl_Position = vertexIn;
> +	textureOut = textureIn;
> +}
> diff --git a/src/qcam/assets/shader/shaders.qrc b/src/qcam/assets/shader/shaders.qrc
> new file mode 100644
> index 0000000..6fe4c7f
> --- /dev/null
> +++ b/src/qcam/assets/shader/shaders.qrc
> @@ -0,0 +1,10 @@
> +<!-- SPDX-License-Identifier: GPL-2.0-or-later -->
> +<!DOCTYPE RCC><RCC version="1.0">
> +<qresource>
> +<file>./NV_vertex_shader.glsl</file>
> +<file>./NV_2_planes_UV_f.glsl</file>
> +<file>./NV_2_planes_VU_f.glsl</file>
> +<file>./NV_3_planes_UV_f.glsl</file>
> +<file>./NV_3_planes_VU_f.glsl</file>
> +</qresource>
> +</RCC>
> diff --git a/src/qcam/meson.build b/src/qcam/meson.build
> index 6ea886a..e0c6f26 100644
> --- a/src/qcam/meson.build
> +++ b/src/qcam/meson.build
> @@ -16,6 +16,7 @@ qcam_moc_headers = files([
>  
>  qcam_resources = files([
>      'assets/feathericons/feathericons.qrc',
> +    'assets/shader/shaders.qrc'
>  ])
>  
>  qt5 = import('qt5')
Laurent Pinchart Sept. 6, 2020, 1 a.m. UTC | #2
On Sun, Sep 06, 2020 at 03:56:45AM +0300, Laurent Pinchart wrote:
> Hi Show,
> 
> Thank you for the patch.
> 
> On Fri, Sep 04, 2020 at 04:43:12PM +0800, Show Liu wrote:
> > qcam: add OpenGL shader code as Qt resource

Maybe with a bit more detailed commit message actually, this just
duplicates the subject line. How about the following ?

Add OpenGL fragment and vertex shaders to convert two- and tri-planar
YUV formats to RGB. This will be used to accelerate YUV image rendering.

> > Signed-off-by: Show Liu <show.liu@linaro.org>
> > ---
> >  src/qcam/assets/shader/NV_2_planes_UV_f.glsl | 32 +++++++++++++++++++
> >  src/qcam/assets/shader/NV_2_planes_VU_f.glsl | 32 +++++++++++++++++++
> >  src/qcam/assets/shader/NV_3_planes_UV_f.glsl | 33 ++++++++++++++++++++
> >  src/qcam/assets/shader/NV_3_planes_VU_f.glsl | 33 ++++++++++++++++++++
> >  src/qcam/assets/shader/NV_vertex_shader.glsl | 16 ++++++++++
> >  src/qcam/assets/shader/shaders.qrc           | 10 ++++++
> >  src/qcam/meson.build                         |  1 +
> >  7 files changed, 157 insertions(+)
> >  create mode 100644 src/qcam/assets/shader/NV_2_planes_UV_f.glsl
> >  create mode 100644 src/qcam/assets/shader/NV_2_planes_VU_f.glsl
> >  create mode 100644 src/qcam/assets/shader/NV_3_planes_UV_f.glsl
> >  create mode 100644 src/qcam/assets/shader/NV_3_planes_VU_f.glsl
> >  create mode 100644 src/qcam/assets/shader/NV_vertex_shader.glsl
> >  create mode 100644 src/qcam/assets/shader/shaders.qrc
> > 
> > diff --git a/src/qcam/assets/shader/NV_2_planes_UV_f.glsl b/src/qcam/assets/shader/NV_2_planes_UV_f.glsl
> > new file mode 100644
> > index 0000000..54bb459
> > --- /dev/null
> > +++ b/src/qcam/assets/shader/NV_2_planes_UV_f.glsl
> > @@ -0,0 +1,32 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Copyright (C) 2020, Linaro
> > + *
> > + * NV_2_planes_UV_f.glsl - Fragment shader code for NV12, NV16 and NV24 formats
> > + */
> > +
> > +#ifdef GL_ES
> > +precision mediump float;
> > +#endif
> > +
> > +varying vec2 textureOut;
> > +uniform sampler2D tex_y;
> > +uniform sampler2D tex_u;
> > +
> > +void main(void)
> > +{
> > +	vec3 yuv;
> > +	vec3 rgb;
> > +	mat3 yuv2rgb_bt601_mat = mat3(
> > +				      vec3(1.164,  1.164, 1.164),
> > +				      vec3(0.000, -0.392, 2.017),
> > +				      vec3(1.596, -0.813, 0.000)
> > +				 );
> > +
> > +	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
> > +	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
> > +	yuv.z = texture2D(tex_u, textureOut).g - 0.500;
> > +
> > +	rgb = yuv2rgb_bt601_mat * yuv;
> > +	gl_FragColor = vec4(rgb, 1.0);
> > +}
> > diff --git a/src/qcam/assets/shader/NV_2_planes_VU_f.glsl b/src/qcam/assets/shader/NV_2_planes_VU_f.glsl
> > new file mode 100644
> > index 0000000..6571ed6
> > --- /dev/null
> > +++ b/src/qcam/assets/shader/NV_2_planes_VU_f.glsl
> > @@ -0,0 +1,32 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Copyright (C) 2020, Linaro
> > + *
> > + * NV_2_planes_VU_f.glsl - Fragment shader code for NV21, NV61 and NV42 formats
> > + */
> > +
> > +#ifdef GL_ES
> > +precision mediump float;
> > +#endif
> > +
> > +varying vec2 textureOut;
> > +uniform sampler2D tex_y;
> > +uniform sampler2D tex_u;
> > +
> > +void main(void)
> > +{
> > +	vec3 yuv;
> > +	vec3 rgb;
> > +	mat3 yuv2rgb_bt601_mat = mat3(
> > +				      vec3(1.164,  1.164, 1.164),
> > +				      vec3(0.000, -0.392, 2.017),
> > +				      vec3(1.596, -0.813, 0.000)
> > +				 );
> > +
> > +	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
> > +	yuv.y = texture2D(tex_u, textureOut).g - 0.500;
> > +	yuv.z = texture2D(tex_u, textureOut).r - 0.500;
> > +
> > +	rgb = yuv2rgb_bt601_mat * yuv;
> > +	gl_FragColor = vec4(rgb, 1.0);
> > +}
> > diff --git a/src/qcam/assets/shader/NV_3_planes_UV_f.glsl b/src/qcam/assets/shader/NV_3_planes_UV_f.glsl
> > new file mode 100644
> > index 0000000..9d104fd
> > --- /dev/null
> > +++ b/src/qcam/assets/shader/NV_3_planes_UV_f.glsl
> > @@ -0,0 +1,33 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Copyright (C) 2020, Linaro
> > + *
> > + * NV_3_planes_UV_f.glsl - Fragment shader code for YUV420 format
> > + */
> > +
> > +#ifdef GL_ES
> > +precision mediump float;
> > +#endif
> > +
> > +varying vec2 textureOut;
> > +uniform sampler2D tex_y;
> > +uniform sampler2D tex_u;
> > +uniform sampler2D tex_v;
> > +
> > +void main(void)
> > +{
> > +	vec3 yuv;
> > +	vec3 rgb;
> > +	mat3 yuv2rgb_bt601_mat = mat3(
> > +				      vec3(1.164,  1.164, 1.164),
> > +				      vec3(0.000, -0.392, 2.017),
> > +				      vec3(1.596, -0.813, 0.000)
> > +				 );
> > +
> > +	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
> > +	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
> > +	yuv.z = texture2D(tex_v, textureOut).r - 0.500;
> > +
> > +	rgb = yuv2rgb_bt601_mat * yuv;
> > +	gl_FragColor = vec4(rgb, 1.0);
> > +}
> > diff --git a/src/qcam/assets/shader/NV_3_planes_VU_f.glsl b/src/qcam/assets/shader/NV_3_planes_VU_f.glsl
> > new file mode 100644
> > index 0000000..245a619
> > --- /dev/null
> > +++ b/src/qcam/assets/shader/NV_3_planes_VU_f.glsl
> > @@ -0,0 +1,33 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Copyright (C) 2020, Linaro
> > + *
> > + * NV_3_planes_VU_f.glsl - Fragment shader code for YVU420 format
> > + */
> > +
> > +#ifdef GL_ES
> > +precision mediump float;
> > +#endif
> > +
> > +varying vec2 textureOut;
> > +uniform sampler2D tex_y;
> > +uniform sampler2D tex_u;
> > +uniform sampler2D tex_v;
> > +
> > +void main(void)
> > +{
> > +	vec3 yuv;
> > +	vec3 rgb;
> > +	mat3 yuv2rgb_bt601_mat = mat3(
> > +				      vec3(1.164,  1.164, 1.164),
> > +				      vec3(0.000, -0.392, 2.017),
> > +				      vec3(1.596, -0.813, 0.000)
> > +				 );
> > +
> > +	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
> > +	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
> > +	yuv.z = texture2D(tex_v, textureOut).r - 0.500;
> 
> Shouldn't this be
> 
> 	yuv.y = texture2D(tex_v, textureOut).r - 0.500;
> 	yuv.z = texture2D(tex_u, textureOut).r - 0.500;
> 
> ?
> 
> Apart from that,
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> > +
> > +	rgb = yuv2rgb_bt601_mat * yuv;
> > +	gl_FragColor = vec4(rgb, 1.0);
> > +}
> > diff --git a/src/qcam/assets/shader/NV_vertex_shader.glsl b/src/qcam/assets/shader/NV_vertex_shader.glsl
> > new file mode 100644
> > index 0000000..403b791
> > --- /dev/null
> > +++ b/src/qcam/assets/shader/NV_vertex_shader.glsl
> > @@ -0,0 +1,16 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Copyright (C) 2020, Linaro
> > + *
> > + * NV_vertex_shader.glsl - Vertex shader code for NV family
> > + */
> > +
> > +attribute vec4 vertexIn;
> > +attribute vec2 textureIn;
> > +varying vec2 textureOut;
> > +
> > +void main(void)
> > +{
> > +	gl_Position = vertexIn;
> > +	textureOut = textureIn;
> > +}
> > diff --git a/src/qcam/assets/shader/shaders.qrc b/src/qcam/assets/shader/shaders.qrc
> > new file mode 100644
> > index 0000000..6fe4c7f
> > --- /dev/null
> > +++ b/src/qcam/assets/shader/shaders.qrc
> > @@ -0,0 +1,10 @@
> > +<!-- SPDX-License-Identifier: GPL-2.0-or-later -->
> > +<!DOCTYPE RCC><RCC version="1.0">
> > +<qresource>
> > +<file>./NV_vertex_shader.glsl</file>
> > +<file>./NV_2_planes_UV_f.glsl</file>
> > +<file>./NV_2_planes_VU_f.glsl</file>
> > +<file>./NV_3_planes_UV_f.glsl</file>
> > +<file>./NV_3_planes_VU_f.glsl</file>
> > +</qresource>
> > +</RCC>
> > diff --git a/src/qcam/meson.build b/src/qcam/meson.build
> > index 6ea886a..e0c6f26 100644
> > --- a/src/qcam/meson.build
> > +++ b/src/qcam/meson.build
> > @@ -16,6 +16,7 @@ qcam_moc_headers = files([
> >  
> >  qcam_resources = files([
> >      'assets/feathericons/feathericons.qrc',
> > +    'assets/shader/shaders.qrc'
> >  ])
> >  
> >  qt5 = import('qt5')
> 
> -- 
> Regards,
> 
> Laurent Pinchart

Patch

diff --git a/src/qcam/assets/shader/NV_2_planes_UV_f.glsl b/src/qcam/assets/shader/NV_2_planes_UV_f.glsl
new file mode 100644
index 0000000..54bb459
--- /dev/null
+++ b/src/qcam/assets/shader/NV_2_planes_UV_f.glsl
@@ -0,0 +1,32 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020, Linaro
+ *
+ * NV_2_planes_UV_f.glsl - Fragment shader code for NV12, NV16 and NV24 formats
+ */
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+varying vec2 textureOut;
+uniform sampler2D tex_y;
+uniform sampler2D tex_u;
+
+void main(void)
+{
+	vec3 yuv;
+	vec3 rgb;
+	mat3 yuv2rgb_bt601_mat = mat3(
+				      vec3(1.164,  1.164, 1.164),
+				      vec3(0.000, -0.392, 2.017),
+				      vec3(1.596, -0.813, 0.000)
+				 );
+
+	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
+	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
+	yuv.z = texture2D(tex_u, textureOut).g - 0.500;
+
+	rgb = yuv2rgb_bt601_mat * yuv;
+	gl_FragColor = vec4(rgb, 1.0);
+}
diff --git a/src/qcam/assets/shader/NV_2_planes_VU_f.glsl b/src/qcam/assets/shader/NV_2_planes_VU_f.glsl
new file mode 100644
index 0000000..6571ed6
--- /dev/null
+++ b/src/qcam/assets/shader/NV_2_planes_VU_f.glsl
@@ -0,0 +1,32 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020, Linaro
+ *
+ * NV_2_planes_VU_f.glsl - Fragment shader code for NV21, NV61 and NV42 formats
+ */
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+varying vec2 textureOut;
+uniform sampler2D tex_y;
+uniform sampler2D tex_u;
+
+void main(void)
+{
+	vec3 yuv;
+	vec3 rgb;
+	mat3 yuv2rgb_bt601_mat = mat3(
+				      vec3(1.164,  1.164, 1.164),
+				      vec3(0.000, -0.392, 2.017),
+				      vec3(1.596, -0.813, 0.000)
+				 );
+
+	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
+	yuv.y = texture2D(tex_u, textureOut).g - 0.500;
+	yuv.z = texture2D(tex_u, textureOut).r - 0.500;
+
+	rgb = yuv2rgb_bt601_mat * yuv;
+	gl_FragColor = vec4(rgb, 1.0);
+}
diff --git a/src/qcam/assets/shader/NV_3_planes_UV_f.glsl b/src/qcam/assets/shader/NV_3_planes_UV_f.glsl
new file mode 100644
index 0000000..9d104fd
--- /dev/null
+++ b/src/qcam/assets/shader/NV_3_planes_UV_f.glsl
@@ -0,0 +1,33 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020, Linaro
+ *
+ * NV_3_planes_UV_f.glsl - Fragment shader code for YUV420 format
+ */
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+varying vec2 textureOut;
+uniform sampler2D tex_y;
+uniform sampler2D tex_u;
+uniform sampler2D tex_v;
+
+void main(void)
+{
+	vec3 yuv;
+	vec3 rgb;
+	mat3 yuv2rgb_bt601_mat = mat3(
+				      vec3(1.164,  1.164, 1.164),
+				      vec3(0.000, -0.392, 2.017),
+				      vec3(1.596, -0.813, 0.000)
+				 );
+
+	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
+	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
+	yuv.z = texture2D(tex_v, textureOut).r - 0.500;
+
+	rgb = yuv2rgb_bt601_mat * yuv;
+	gl_FragColor = vec4(rgb, 1.0);
+}
diff --git a/src/qcam/assets/shader/NV_3_planes_VU_f.glsl b/src/qcam/assets/shader/NV_3_planes_VU_f.glsl
new file mode 100644
index 0000000..245a619
--- /dev/null
+++ b/src/qcam/assets/shader/NV_3_planes_VU_f.glsl
@@ -0,0 +1,33 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020, Linaro
+ *
+ * NV_3_planes_VU_f.glsl - Fragment shader code for YVU420 format
+ */
+
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+varying vec2 textureOut;
+uniform sampler2D tex_y;
+uniform sampler2D tex_u;
+uniform sampler2D tex_v;
+
+void main(void)
+{
+	vec3 yuv;
+	vec3 rgb;
+	mat3 yuv2rgb_bt601_mat = mat3(
+				      vec3(1.164,  1.164, 1.164),
+				      vec3(0.000, -0.392, 2.017),
+				      vec3(1.596, -0.813, 0.000)
+				 );
+
+	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
+	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
+	yuv.z = texture2D(tex_v, textureOut).r - 0.500;
+
+	rgb = yuv2rgb_bt601_mat * yuv;
+	gl_FragColor = vec4(rgb, 1.0);
+}
diff --git a/src/qcam/assets/shader/NV_vertex_shader.glsl b/src/qcam/assets/shader/NV_vertex_shader.glsl
new file mode 100644
index 0000000..403b791
--- /dev/null
+++ b/src/qcam/assets/shader/NV_vertex_shader.glsl
@@ -0,0 +1,16 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020, Linaro
+ *
+ * NV_vertex_shader.glsl - Vertex shader code for NV family
+ */
+
+attribute vec4 vertexIn;
+attribute vec2 textureIn;
+varying vec2 textureOut;
+
+void main(void)
+{
+	gl_Position = vertexIn;
+	textureOut = textureIn;
+}
diff --git a/src/qcam/assets/shader/shaders.qrc b/src/qcam/assets/shader/shaders.qrc
new file mode 100644
index 0000000..6fe4c7f
--- /dev/null
+++ b/src/qcam/assets/shader/shaders.qrc
@@ -0,0 +1,10 @@ 
+<!-- SPDX-License-Identifier: GPL-2.0-or-later -->
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+<file>./NV_vertex_shader.glsl</file>
+<file>./NV_2_planes_UV_f.glsl</file>
+<file>./NV_2_planes_VU_f.glsl</file>
+<file>./NV_3_planes_UV_f.glsl</file>
+<file>./NV_3_planes_VU_f.glsl</file>
+</qresource>
+</RCC>
diff --git a/src/qcam/meson.build b/src/qcam/meson.build
index 6ea886a..e0c6f26 100644
--- a/src/qcam/meson.build
+++ b/src/qcam/meson.build
@@ -16,6 +16,7 @@  qcam_moc_headers = files([
 
 qcam_resources = files([
     'assets/feathericons/feathericons.qrc',
+    'assets/shader/shaders.qrc'
 ])
 
 qt5 = import('qt5')