[libcamera-devel] qcam: Support OpenGL ES 2.0
diff mbox series

Message ID 20210803092310.11956-1-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • [libcamera-devel] qcam: Support OpenGL ES 2.0
Related show

Commit Message

Laurent Pinchart Aug. 3, 2021, 9:23 a.m. UTC
The GL_RG and GL_RED texture formats are not supported in OpenGL ES
prior to 3.0. In order to be compatible with OpenGL ES 2.0, use
GL_LUMINANCE_ALPHA and GL_LUMINANCE instead. The shader code needs to be
updated accordingly for GL_RG, as the second component is now stored in
alpha component instead of the green component. Usage of the red
component is fine, the luminance value is stored in the red, green and
blue components.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Tested with vivid, using NV12, YV420, YVU420 and SGRBG8, which should
cover all code paths.
---
 src/qcam/assets/shader/YUV_2_planes.frag |  4 +--
 src/qcam/viewfinder_gl.cpp               | 40 ++++++++++++------------
 2 files changed, 22 insertions(+), 22 deletions(-)

Comments

Kieran Bingham Aug. 3, 2021, 9:31 a.m. UTC | #1
Hi Laurent,

On 03/08/2021 10:23, Laurent Pinchart wrote:
> The GL_RG and GL_RED texture formats are not supported in OpenGL ES
> prior to 3.0. In order to be compatible with OpenGL ES 2.0, use
> GL_LUMINANCE_ALPHA and GL_LUMINANCE instead. The shader code needs to be
> updated accordingly for GL_RG, as the second component is now stored in

/in alpha/in the alpha/

> alpha component instead of the green component. Usage of the red
> component is fine, the luminance value is stored in the red, green and
> blue components.
> 

So these seem to be just fairly arbitrary identifiers of the texture
maps to use, which as long as they are consistently referenced that's
all that matters?


> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Tested with vivid, using NV12, YV420, YVU420 and SGRBG8, which should
> cover all code paths.
> ---
>  src/qcam/assets/shader/YUV_2_planes.frag |  4 +--
>  src/qcam/viewfinder_gl.cpp               | 40 ++++++++++++------------
>  2 files changed, 22 insertions(+), 22 deletions(-)
> 
> diff --git a/src/qcam/assets/shader/YUV_2_planes.frag b/src/qcam/assets/shader/YUV_2_planes.frag
> index 125f1c850a33..254463c05cac 100644
> --- a/src/qcam/assets/shader/YUV_2_planes.frag
> +++ b/src/qcam/assets/shader/YUV_2_planes.frag
> @@ -26,9 +26,9 @@ void main(void)
>  	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
>  #if defined(YUV_PATTERN_UV)
>  	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
> -	yuv.z = texture2D(tex_u, textureOut).g - 0.500;
> +	yuv.z = texture2D(tex_u, textureOut).a - 0.500;
>  #elif defined(YUV_PATTERN_VU)
> -	yuv.y = texture2D(tex_u, textureOut).g - 0.500;
> +	yuv.y = texture2D(tex_u, textureOut).a - 0.500;
>  	yuv.z = texture2D(tex_u, textureOut).r - 0.500;
>  #else
>  #error Invalid pattern
> diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
> index e7c8620c7024..77a6437e56fd 100644
> --- a/src/qcam/viewfinder_gl.cpp
> +++ b/src/qcam/viewfinder_gl.cpp
> @@ -481,11 +481,11 @@ void ViewFinderGL::doRender()
>  		configureTexture(*textures_[0]);
>  		glTexImage2D(GL_TEXTURE_2D,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     size_.width(),
>  			     size_.height(),
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     GL_UNSIGNED_BYTE,
>  			     data_);
>  		shaderProgram_.setUniformValue(textureUniformY_, 0);
> @@ -495,11 +495,11 @@ void ViewFinderGL::doRender()
>  		configureTexture(*textures_[1]);
>  		glTexImage2D(GL_TEXTURE_2D,
>  			     0,
> -			     GL_RG,
> +			     GL_LUMINANCE_ALPHA,
>  			     size_.width() / horzSubSample_,
>  			     size_.height() / vertSubSample_,
>  			     0,
> -			     GL_RG,
> +			     GL_LUMINANCE_ALPHA,
>  			     GL_UNSIGNED_BYTE,
>  			     data_ + size_.width() * size_.height());
>  		shaderProgram_.setUniformValue(textureUniformU_, 1);
> @@ -511,11 +511,11 @@ void ViewFinderGL::doRender()
>  		configureTexture(*textures_[0]);
>  		glTexImage2D(GL_TEXTURE_2D,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     size_.width(),
>  			     size_.height(),
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     GL_UNSIGNED_BYTE,
>  			     data_);
>  		shaderProgram_.setUniformValue(textureUniformY_, 0);
> @@ -525,11 +525,11 @@ void ViewFinderGL::doRender()
>  		configureTexture(*textures_[1]);
>  		glTexImage2D(GL_TEXTURE_2D,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     size_.width() / horzSubSample_,
>  			     size_.height() / vertSubSample_,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     GL_UNSIGNED_BYTE,
>  			     data_ + size_.width() * size_.height());
>  		shaderProgram_.setUniformValue(textureUniformU_, 1);
> @@ -539,11 +539,11 @@ void ViewFinderGL::doRender()
>  		configureTexture(*textures_[2]);
>  		glTexImage2D(GL_TEXTURE_2D,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     size_.width() / horzSubSample_,
>  			     size_.height() / vertSubSample_,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     GL_UNSIGNED_BYTE,
>  			     data_ + size_.width() * size_.height() * 5 / 4);
>  		shaderProgram_.setUniformValue(textureUniformV_, 2);
> @@ -555,11 +555,11 @@ void ViewFinderGL::doRender()
>  		configureTexture(*textures_[0]);
>  		glTexImage2D(GL_TEXTURE_2D,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     size_.width(),
>  			     size_.height(),
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     GL_UNSIGNED_BYTE,
>  			     data_);
>  		shaderProgram_.setUniformValue(textureUniformY_, 0);
> @@ -569,11 +569,11 @@ void ViewFinderGL::doRender()
>  		configureTexture(*textures_[2]);
>  		glTexImage2D(GL_TEXTURE_2D,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     size_.width() / horzSubSample_,
>  			     size_.height() / vertSubSample_,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     GL_UNSIGNED_BYTE,
>  			     data_ + size_.width() * size_.height());
>  		shaderProgram_.setUniformValue(textureUniformV_, 2);
> @@ -583,11 +583,11 @@ void ViewFinderGL::doRender()
>  		configureTexture(*textures_[1]);
>  		glTexImage2D(GL_TEXTURE_2D,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     size_.width() / horzSubSample_,
>  			     size_.height() / vertSubSample_,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     GL_UNSIGNED_BYTE,
>  			     data_ + size_.width() * size_.height() * 5 / 4);
>  		shaderProgram_.setUniformValue(textureUniformU_, 1);
> @@ -674,18 +674,18 @@ void ViewFinderGL::doRender()
>  	case libcamera::formats::SRGGB12_CSI2P:
>  		/*
>  		 * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats
> -		 * are stored in GL_RED texture.
> -		 * The texture width is equal to the stride.
> +		 * are stored in GL_LUMINANCE texture. The texture width is

I know you're modifying an existing sentence, but should this read either:

 - are stored in a GL_LUMINANCE texture
or
 - are stored in the GL_LUMINANCE texture

depending on if there is only one GL_LUMINANCE texture, or if there
might be more and this is specifically allocated.

(That extra clarification would help me understand those identifiers
too... such power from a single word addition).

Anyway, aside from / with that:

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>


> +		 * equal to the stride.
>  		 */
>  		glActiveTexture(GL_TEXTURE0);
>  		configureTexture(*textures_[0]);
>  		glTexImage2D(GL_TEXTURE_2D,
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     stride_,
>  			     size_.height(),
>  			     0,
> -			     GL_RED,
> +			     GL_LUMINANCE,
>  			     GL_UNSIGNED_BYTE,
>  			     data_);
>  		shaderProgram_.setUniformValue(textureUniformY_, 0);
>
Laurent Pinchart Aug. 3, 2021, 9:41 a.m. UTC | #2
Hi Kieran,

On Tue, Aug 03, 2021 at 10:31:23AM +0100, Kieran Bingham wrote:
> On 03/08/2021 10:23, Laurent Pinchart wrote:
> > The GL_RG and GL_RED texture formats are not supported in OpenGL ES
> > prior to 3.0. In order to be compatible with OpenGL ES 2.0, use
> > GL_LUMINANCE_ALPHA and GL_LUMINANCE instead. The shader code needs to be
> > updated accordingly for GL_RG, as the second component is now stored in
> 
> /in alpha/in the alpha/
> 
> > alpha component instead of the green component. Usage of the red
> > component is fine, the luminance value is stored in the red, green and
> > blue components.
> 
> So these seem to be just fairly arbitrary identifiers of the texture
> maps to use, which as long as they are consistently referenced that's
> all that matters?

They describe how the texture is stored in memory, and how it's
converted to RGBA before going through the shaders. See
https://docs.gl/es2/glTexImage2D for more information. In particular,

GL_LUMINANCE

    Each element is a single luminance value. The GL converts it to
    floating point, then assembles it into an RGBA element by
    replicating the luminance value three times for red, green, and blue
    and attaching 1 for alpha. Each component is then clamped to the
    range [0,1].

GL_LUMINANCE_ALPHA

    Each element is a luminance/alpha pair. The GL converts it to
    floating point, then assembles it into an RGBA element by
    replicating the luminance value three times for red, green, and
    blue. Each component is then clamped to the range [0,1].

In ES3, we additionally have
(https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml),

GL_RED

    Each element is a single red component. For fixed point normalized
    components, the GL converts it to floating point, clamps to the
    range [0,1], and assembles it into an RGBA element by attaching 0.0
    for green and blue, and 1.0 for alpha.

GL_RG

    Each element is a red/green double. For fixed point normalized
    components, the GL converts each component to floating point, clamps
    to the range [0,1], and assembles them into an RGBA element by
    attaching 0.0 for blue, and 1.0 for alpha.

GL_RED maps the value to [v, 0.0, 0.0, 1.0] while GL_LUMINANCE maps it
to [v, v, v, 1.0]. As the shaders use the red component only, they're
equivalent. For GL_RG, however, when moving to GL_LUMINANCE_ALPHA, we
need to replace usage for the green component with the alpha component.

> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > Tested with vivid, using NV12, YV420, YVU420 and SGRBG8, which should
> > cover all code paths.
> > ---
> >  src/qcam/assets/shader/YUV_2_planes.frag |  4 +--
> >  src/qcam/viewfinder_gl.cpp               | 40 ++++++++++++------------
> >  2 files changed, 22 insertions(+), 22 deletions(-)
> > 
> > diff --git a/src/qcam/assets/shader/YUV_2_planes.frag b/src/qcam/assets/shader/YUV_2_planes.frag
> > index 125f1c850a33..254463c05cac 100644
> > --- a/src/qcam/assets/shader/YUV_2_planes.frag
> > +++ b/src/qcam/assets/shader/YUV_2_planes.frag
> > @@ -26,9 +26,9 @@ void main(void)
> >  	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
> >  #if defined(YUV_PATTERN_UV)
> >  	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
> > -	yuv.z = texture2D(tex_u, textureOut).g - 0.500;
> > +	yuv.z = texture2D(tex_u, textureOut).a - 0.500;
> >  #elif defined(YUV_PATTERN_VU)
> > -	yuv.y = texture2D(tex_u, textureOut).g - 0.500;
> > +	yuv.y = texture2D(tex_u, textureOut).a - 0.500;
> >  	yuv.z = texture2D(tex_u, textureOut).r - 0.500;
> >  #else
> >  #error Invalid pattern
> > diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
> > index e7c8620c7024..77a6437e56fd 100644
> > --- a/src/qcam/viewfinder_gl.cpp
> > +++ b/src/qcam/viewfinder_gl.cpp
> > @@ -481,11 +481,11 @@ void ViewFinderGL::doRender()
> >  		configureTexture(*textures_[0]);
> >  		glTexImage2D(GL_TEXTURE_2D,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     size_.width(),
> >  			     size_.height(),
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     GL_UNSIGNED_BYTE,
> >  			     data_);
> >  		shaderProgram_.setUniformValue(textureUniformY_, 0);
> > @@ -495,11 +495,11 @@ void ViewFinderGL::doRender()
> >  		configureTexture(*textures_[1]);
> >  		glTexImage2D(GL_TEXTURE_2D,
> >  			     0,
> > -			     GL_RG,
> > +			     GL_LUMINANCE_ALPHA,
> >  			     size_.width() / horzSubSample_,
> >  			     size_.height() / vertSubSample_,
> >  			     0,
> > -			     GL_RG,
> > +			     GL_LUMINANCE_ALPHA,
> >  			     GL_UNSIGNED_BYTE,
> >  			     data_ + size_.width() * size_.height());
> >  		shaderProgram_.setUniformValue(textureUniformU_, 1);
> > @@ -511,11 +511,11 @@ void ViewFinderGL::doRender()
> >  		configureTexture(*textures_[0]);
> >  		glTexImage2D(GL_TEXTURE_2D,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     size_.width(),
> >  			     size_.height(),
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     GL_UNSIGNED_BYTE,
> >  			     data_);
> >  		shaderProgram_.setUniformValue(textureUniformY_, 0);
> > @@ -525,11 +525,11 @@ void ViewFinderGL::doRender()
> >  		configureTexture(*textures_[1]);
> >  		glTexImage2D(GL_TEXTURE_2D,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     size_.width() / horzSubSample_,
> >  			     size_.height() / vertSubSample_,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     GL_UNSIGNED_BYTE,
> >  			     data_ + size_.width() * size_.height());
> >  		shaderProgram_.setUniformValue(textureUniformU_, 1);
> > @@ -539,11 +539,11 @@ void ViewFinderGL::doRender()
> >  		configureTexture(*textures_[2]);
> >  		glTexImage2D(GL_TEXTURE_2D,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     size_.width() / horzSubSample_,
> >  			     size_.height() / vertSubSample_,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     GL_UNSIGNED_BYTE,
> >  			     data_ + size_.width() * size_.height() * 5 / 4);
> >  		shaderProgram_.setUniformValue(textureUniformV_, 2);
> > @@ -555,11 +555,11 @@ void ViewFinderGL::doRender()
> >  		configureTexture(*textures_[0]);
> >  		glTexImage2D(GL_TEXTURE_2D,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     size_.width(),
> >  			     size_.height(),
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     GL_UNSIGNED_BYTE,
> >  			     data_);
> >  		shaderProgram_.setUniformValue(textureUniformY_, 0);
> > @@ -569,11 +569,11 @@ void ViewFinderGL::doRender()
> >  		configureTexture(*textures_[2]);
> >  		glTexImage2D(GL_TEXTURE_2D,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     size_.width() / horzSubSample_,
> >  			     size_.height() / vertSubSample_,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     GL_UNSIGNED_BYTE,
> >  			     data_ + size_.width() * size_.height());
> >  		shaderProgram_.setUniformValue(textureUniformV_, 2);
> > @@ -583,11 +583,11 @@ void ViewFinderGL::doRender()
> >  		configureTexture(*textures_[1]);
> >  		glTexImage2D(GL_TEXTURE_2D,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     size_.width() / horzSubSample_,
> >  			     size_.height() / vertSubSample_,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     GL_UNSIGNED_BYTE,
> >  			     data_ + size_.width() * size_.height() * 5 / 4);
> >  		shaderProgram_.setUniformValue(textureUniformU_, 1);
> > @@ -674,18 +674,18 @@ void ViewFinderGL::doRender()
> >  	case libcamera::formats::SRGGB12_CSI2P:
> >  		/*
> >  		 * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats
> > -		 * are stored in GL_RED texture.
> > -		 * The texture width is equal to the stride.
> > +		 * are stored in GL_LUMINANCE texture. The texture width is
> 
> I know you're modifying an existing sentence, but should this read either:
> 
>  - are stored in a GL_LUMINANCE texture
> or
>  - are stored in the GL_LUMINANCE texture
> 
> depending on if there is only one GL_LUMINANCE texture, or if there
> might be more and this is specifically allocated.

I'll fix it, using "a GL_LUMINANCE texture".

> (That extra clarification would help me understand those identifiers
> too... such power from a single word addition).
> 
> Anyway, aside from / with that:
> 
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> > +		 * equal to the stride.
> >  		 */
> >  		glActiveTexture(GL_TEXTURE0);
> >  		configureTexture(*textures_[0]);
> >  		glTexImage2D(GL_TEXTURE_2D,
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     stride_,
> >  			     size_.height(),
> >  			     0,
> > -			     GL_RED,
> > +			     GL_LUMINANCE,
> >  			     GL_UNSIGNED_BYTE,
> >  			     data_);
> >  		shaderProgram_.setUniformValue(textureUniformY_, 0);
> >
Andrey Konovalov Aug. 3, 2021, 8:28 p.m. UTC | #3
Hi Laurent,

Making qcam to work with OpenGL ES 2.0 is a nice improvement!

On 03.08.2021 12:41, Laurent Pinchart wrote:
> Hi Kieran,
> 
> On Tue, Aug 03, 2021 at 10:31:23AM +0100, Kieran Bingham wrote:
>> On 03/08/2021 10:23, Laurent Pinchart wrote:
>>> The GL_RG and GL_RED texture formats are not supported in OpenGL ES
>>> prior to 3.0. In order to be compatible with OpenGL ES 2.0, use
>>> GL_LUMINANCE_ALPHA and GL_LUMINANCE instead. The shader code needs to be
>>> updated accordingly for GL_RG, as the second component is now stored in
>>
>> /in alpha/in the alpha/
>>
>>> alpha component instead of the green component. Usage of the red
>>> component is fine, the luminance value is stored in the red, green and
>>> blue components.
>>
>> So these seem to be just fairly arbitrary identifiers of the texture
>> maps to use, which as long as they are consistently referenced that's
>> all that matters?
> 
> They describe how the texture is stored in memory, and how it's
> converted to RGBA before going through the shaders. See
> https://docs.gl/es2/glTexImage2D for more information. In particular,
> 
> GL_LUMINANCE
> 
>      Each element is a single luminance value. The GL converts it to
>      floating point, then assembles it into an RGBA element by
>      replicating the luminance value three times for red, green, and blue
>      and attaching 1 for alpha. Each component is then clamped to the
>      range [0,1].
> 
> GL_LUMINANCE_ALPHA
> 
>      Each element is a luminance/alpha pair. The GL converts it to
>      floating point, then assembles it into an RGBA element by
>      replicating the luminance value three times for red, green, and
>      blue. Each component is then clamped to the range [0,1].
> 
> In ES3, we additionally have
> (https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml),
> 
> GL_RED
> 
>      Each element is a single red component. For fixed point normalized
>      components, the GL converts it to floating point, clamps to the
>      range [0,1], and assembles it into an RGBA element by attaching 0.0
>      for green and blue, and 1.0 for alpha.
> 
> GL_RG
> 
>      Each element is a red/green double. For fixed point normalized
>      components, the GL converts each component to floating point, clamps
>      to the range [0,1], and assembles them into an RGBA element by
>      attaching 0.0 for blue, and 1.0 for alpha.
> 
> GL_RED maps the value to [v, 0.0, 0.0, 1.0] while GL_LUMINANCE maps it
> to [v, v, v, 1.0]. As the shaders use the red component only, they're
> equivalent. For GL_RG, however, when moving to GL_LUMINANCE_ALPHA, we
> need to replace usage for the green component with the alpha component.

Thanks for the explanation and the docs links!

>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> ---
>>> Tested with vivid, using NV12, YV420, YVU420 and SGRBG8, which should
>>> cover all code paths.

Reviewed-by: Andrey Konovalov <andrey.konovalov@linaro.org>

(Tested on RB3 board with camss using SGRBG10_CSI2P - just in case)

Thanks,
Andrey

>>> ---
>>>   src/qcam/assets/shader/YUV_2_planes.frag |  4 +--
>>>   src/qcam/viewfinder_gl.cpp               | 40 ++++++++++++------------
>>>   2 files changed, 22 insertions(+), 22 deletions(-)
>>>
>>> diff --git a/src/qcam/assets/shader/YUV_2_planes.frag b/src/qcam/assets/shader/YUV_2_planes.frag
>>> index 125f1c850a33..254463c05cac 100644
>>> --- a/src/qcam/assets/shader/YUV_2_planes.frag
>>> +++ b/src/qcam/assets/shader/YUV_2_planes.frag
>>> @@ -26,9 +26,9 @@ void main(void)
>>>   	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
>>>   #if defined(YUV_PATTERN_UV)
>>>   	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
>>> -	yuv.z = texture2D(tex_u, textureOut).g - 0.500;
>>> +	yuv.z = texture2D(tex_u, textureOut).a - 0.500;
>>>   #elif defined(YUV_PATTERN_VU)
>>> -	yuv.y = texture2D(tex_u, textureOut).g - 0.500;
>>> +	yuv.y = texture2D(tex_u, textureOut).a - 0.500;
>>>   	yuv.z = texture2D(tex_u, textureOut).r - 0.500;
>>>   #else
>>>   #error Invalid pattern
>>> diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
>>> index e7c8620c7024..77a6437e56fd 100644
>>> --- a/src/qcam/viewfinder_gl.cpp
>>> +++ b/src/qcam/viewfinder_gl.cpp
>>> @@ -481,11 +481,11 @@ void ViewFinderGL::doRender()
>>>   		configureTexture(*textures_[0]);
>>>   		glTexImage2D(GL_TEXTURE_2D,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     size_.width(),
>>>   			     size_.height(),
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     GL_UNSIGNED_BYTE,
>>>   			     data_);
>>>   		shaderProgram_.setUniformValue(textureUniformY_, 0);
>>> @@ -495,11 +495,11 @@ void ViewFinderGL::doRender()
>>>   		configureTexture(*textures_[1]);
>>>   		glTexImage2D(GL_TEXTURE_2D,
>>>   			     0,
>>> -			     GL_RG,
>>> +			     GL_LUMINANCE_ALPHA,
>>>   			     size_.width() / horzSubSample_,
>>>   			     size_.height() / vertSubSample_,
>>>   			     0,
>>> -			     GL_RG,
>>> +			     GL_LUMINANCE_ALPHA,
>>>   			     GL_UNSIGNED_BYTE,
>>>   			     data_ + size_.width() * size_.height());
>>>   		shaderProgram_.setUniformValue(textureUniformU_, 1);
>>> @@ -511,11 +511,11 @@ void ViewFinderGL::doRender()
>>>   		configureTexture(*textures_[0]);
>>>   		glTexImage2D(GL_TEXTURE_2D,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     size_.width(),
>>>   			     size_.height(),
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     GL_UNSIGNED_BYTE,
>>>   			     data_);
>>>   		shaderProgram_.setUniformValue(textureUniformY_, 0);
>>> @@ -525,11 +525,11 @@ void ViewFinderGL::doRender()
>>>   		configureTexture(*textures_[1]);
>>>   		glTexImage2D(GL_TEXTURE_2D,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     size_.width() / horzSubSample_,
>>>   			     size_.height() / vertSubSample_,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     GL_UNSIGNED_BYTE,
>>>   			     data_ + size_.width() * size_.height());
>>>   		shaderProgram_.setUniformValue(textureUniformU_, 1);
>>> @@ -539,11 +539,11 @@ void ViewFinderGL::doRender()
>>>   		configureTexture(*textures_[2]);
>>>   		glTexImage2D(GL_TEXTURE_2D,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     size_.width() / horzSubSample_,
>>>   			     size_.height() / vertSubSample_,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     GL_UNSIGNED_BYTE,
>>>   			     data_ + size_.width() * size_.height() * 5 / 4);
>>>   		shaderProgram_.setUniformValue(textureUniformV_, 2);
>>> @@ -555,11 +555,11 @@ void ViewFinderGL::doRender()
>>>   		configureTexture(*textures_[0]);
>>>   		glTexImage2D(GL_TEXTURE_2D,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     size_.width(),
>>>   			     size_.height(),
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     GL_UNSIGNED_BYTE,
>>>   			     data_);
>>>   		shaderProgram_.setUniformValue(textureUniformY_, 0);
>>> @@ -569,11 +569,11 @@ void ViewFinderGL::doRender()
>>>   		configureTexture(*textures_[2]);
>>>   		glTexImage2D(GL_TEXTURE_2D,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     size_.width() / horzSubSample_,
>>>   			     size_.height() / vertSubSample_,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     GL_UNSIGNED_BYTE,
>>>   			     data_ + size_.width() * size_.height());
>>>   		shaderProgram_.setUniformValue(textureUniformV_, 2);
>>> @@ -583,11 +583,11 @@ void ViewFinderGL::doRender()
>>>   		configureTexture(*textures_[1]);
>>>   		glTexImage2D(GL_TEXTURE_2D,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     size_.width() / horzSubSample_,
>>>   			     size_.height() / vertSubSample_,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     GL_UNSIGNED_BYTE,
>>>   			     data_ + size_.width() * size_.height() * 5 / 4);
>>>   		shaderProgram_.setUniformValue(textureUniformU_, 1);
>>> @@ -674,18 +674,18 @@ void ViewFinderGL::doRender()
>>>   	case libcamera::formats::SRGGB12_CSI2P:
>>>   		/*
>>>   		 * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats
>>> -		 * are stored in GL_RED texture.
>>> -		 * The texture width is equal to the stride.
>>> +		 * are stored in GL_LUMINANCE texture. The texture width is
>>
>> I know you're modifying an existing sentence, but should this read either:
>>
>>   - are stored in a GL_LUMINANCE texture
>> or
>>   - are stored in the GL_LUMINANCE texture
>>
>> depending on if there is only one GL_LUMINANCE texture, or if there
>> might be more and this is specifically allocated.
> 
> I'll fix it, using "a GL_LUMINANCE texture".
> 
>> (That extra clarification would help me understand those identifiers
>> too... such power from a single word addition).
>>
>> Anyway, aside from / with that:
>>
>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>
>>> +		 * equal to the stride.
>>>   		 */
>>>   		glActiveTexture(GL_TEXTURE0);
>>>   		configureTexture(*textures_[0]);
>>>   		glTexImage2D(GL_TEXTURE_2D,
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     stride_,
>>>   			     size_.height(),
>>>   			     0,
>>> -			     GL_RED,
>>> +			     GL_LUMINANCE,
>>>   			     GL_UNSIGNED_BYTE,
>>>   			     data_);
>>>   		shaderProgram_.setUniformValue(textureUniformY_, 0);
>>>
>
Laurent Pinchart Aug. 3, 2021, 8:38 p.m. UTC | #4
Hi Andrey,

On Tue, Aug 03, 2021 at 11:28:30PM +0300, Andrey Konovalov wrote:
> Hi Laurent,
> 
> Making qcam to work with OpenGL ES 2.0 is a nice improvement!
> 
> On 03.08.2021 12:41, Laurent Pinchart wrote:
> > On Tue, Aug 03, 2021 at 10:31:23AM +0100, Kieran Bingham wrote:
> >> On 03/08/2021 10:23, Laurent Pinchart wrote:
> >>> The GL_RG and GL_RED texture formats are not supported in OpenGL ES
> >>> prior to 3.0. In order to be compatible with OpenGL ES 2.0, use
> >>> GL_LUMINANCE_ALPHA and GL_LUMINANCE instead. The shader code needs to be
> >>> updated accordingly for GL_RG, as the second component is now stored in
> >>
> >> /in alpha/in the alpha/
> >>
> >>> alpha component instead of the green component. Usage of the red
> >>> component is fine, the luminance value is stored in the red, green and
> >>> blue components.
> >>
> >> So these seem to be just fairly arbitrary identifiers of the texture
> >> maps to use, which as long as they are consistently referenced that's
> >> all that matters?
> > 
> > They describe how the texture is stored in memory, and how it's
> > converted to RGBA before going through the shaders. See
> > https://docs.gl/es2/glTexImage2D for more information. In particular,
> > 
> > GL_LUMINANCE
> > 
> >      Each element is a single luminance value. The GL converts it to
> >      floating point, then assembles it into an RGBA element by
> >      replicating the luminance value three times for red, green, and blue
> >      and attaching 1 for alpha. Each component is then clamped to the
> >      range [0,1].
> > 
> > GL_LUMINANCE_ALPHA
> > 
> >      Each element is a luminance/alpha pair. The GL converts it to
> >      floating point, then assembles it into an RGBA element by
> >      replicating the luminance value three times for red, green, and
> >      blue. Each component is then clamped to the range [0,1].
> > 
> > In ES3, we additionally have
> > (https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml),
> > 
> > GL_RED
> > 
> >      Each element is a single red component. For fixed point normalized
> >      components, the GL converts it to floating point, clamps to the
> >      range [0,1], and assembles it into an RGBA element by attaching 0.0
> >      for green and blue, and 1.0 for alpha.
> > 
> > GL_RG
> > 
> >      Each element is a red/green double. For fixed point normalized
> >      components, the GL converts each component to floating point, clamps
> >      to the range [0,1], and assembles them into an RGBA element by
> >      attaching 0.0 for blue, and 1.0 for alpha.
> > 
> > GL_RED maps the value to [v, 0.0, 0.0, 1.0] while GL_LUMINANCE maps it
> > to [v, v, v, 1.0]. As the shaders use the red component only, they're
> > equivalent. For GL_RG, however, when moving to GL_LUMINANCE_ALPHA, we
> > need to replace usage for the green component with the alpha component.
> 
> Thanks for the explanation and the docs links!
> 
> >>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>> ---
> >>> Tested with vivid, using NV12, YV420, YVU420 and SGRBG8, which should
> >>> cover all code paths.
> 
> Reviewed-by: Andrey Konovalov <andrey.konovalov@linaro.org>
> 
> (Tested on RB3 board with camss using SGRBG10_CSI2P - just in case)

That's the only format family that I haven't been able to test :-)
Thanks.

> >>> ---
> >>>   src/qcam/assets/shader/YUV_2_planes.frag |  4 +--
> >>>   src/qcam/viewfinder_gl.cpp               | 40 ++++++++++++------------
> >>>   2 files changed, 22 insertions(+), 22 deletions(-)
> >>>
> >>> diff --git a/src/qcam/assets/shader/YUV_2_planes.frag b/src/qcam/assets/shader/YUV_2_planes.frag
> >>> index 125f1c850a33..254463c05cac 100644
> >>> --- a/src/qcam/assets/shader/YUV_2_planes.frag
> >>> +++ b/src/qcam/assets/shader/YUV_2_planes.frag
> >>> @@ -26,9 +26,9 @@ void main(void)
> >>>   	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
> >>>   #if defined(YUV_PATTERN_UV)
> >>>   	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
> >>> -	yuv.z = texture2D(tex_u, textureOut).g - 0.500;
> >>> +	yuv.z = texture2D(tex_u, textureOut).a - 0.500;
> >>>   #elif defined(YUV_PATTERN_VU)
> >>> -	yuv.y = texture2D(tex_u, textureOut).g - 0.500;
> >>> +	yuv.y = texture2D(tex_u, textureOut).a - 0.500;
> >>>   	yuv.z = texture2D(tex_u, textureOut).r - 0.500;
> >>>   #else
> >>>   #error Invalid pattern
> >>> diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
> >>> index e7c8620c7024..77a6437e56fd 100644
> >>> --- a/src/qcam/viewfinder_gl.cpp
> >>> +++ b/src/qcam/viewfinder_gl.cpp
> >>> @@ -481,11 +481,11 @@ void ViewFinderGL::doRender()
> >>>   		configureTexture(*textures_[0]);
> >>>   		glTexImage2D(GL_TEXTURE_2D,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     size_.width(),
> >>>   			     size_.height(),
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     GL_UNSIGNED_BYTE,
> >>>   			     data_);
> >>>   		shaderProgram_.setUniformValue(textureUniformY_, 0);
> >>> @@ -495,11 +495,11 @@ void ViewFinderGL::doRender()
> >>>   		configureTexture(*textures_[1]);
> >>>   		glTexImage2D(GL_TEXTURE_2D,
> >>>   			     0,
> >>> -			     GL_RG,
> >>> +			     GL_LUMINANCE_ALPHA,
> >>>   			     size_.width() / horzSubSample_,
> >>>   			     size_.height() / vertSubSample_,
> >>>   			     0,
> >>> -			     GL_RG,
> >>> +			     GL_LUMINANCE_ALPHA,
> >>>   			     GL_UNSIGNED_BYTE,
> >>>   			     data_ + size_.width() * size_.height());
> >>>   		shaderProgram_.setUniformValue(textureUniformU_, 1);
> >>> @@ -511,11 +511,11 @@ void ViewFinderGL::doRender()
> >>>   		configureTexture(*textures_[0]);
> >>>   		glTexImage2D(GL_TEXTURE_2D,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     size_.width(),
> >>>   			     size_.height(),
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     GL_UNSIGNED_BYTE,
> >>>   			     data_);
> >>>   		shaderProgram_.setUniformValue(textureUniformY_, 0);
> >>> @@ -525,11 +525,11 @@ void ViewFinderGL::doRender()
> >>>   		configureTexture(*textures_[1]);
> >>>   		glTexImage2D(GL_TEXTURE_2D,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     size_.width() / horzSubSample_,
> >>>   			     size_.height() / vertSubSample_,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     GL_UNSIGNED_BYTE,
> >>>   			     data_ + size_.width() * size_.height());
> >>>   		shaderProgram_.setUniformValue(textureUniformU_, 1);
> >>> @@ -539,11 +539,11 @@ void ViewFinderGL::doRender()
> >>>   		configureTexture(*textures_[2]);
> >>>   		glTexImage2D(GL_TEXTURE_2D,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     size_.width() / horzSubSample_,
> >>>   			     size_.height() / vertSubSample_,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     GL_UNSIGNED_BYTE,
> >>>   			     data_ + size_.width() * size_.height() * 5 / 4);
> >>>   		shaderProgram_.setUniformValue(textureUniformV_, 2);
> >>> @@ -555,11 +555,11 @@ void ViewFinderGL::doRender()
> >>>   		configureTexture(*textures_[0]);
> >>>   		glTexImage2D(GL_TEXTURE_2D,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     size_.width(),
> >>>   			     size_.height(),
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     GL_UNSIGNED_BYTE,
> >>>   			     data_);
> >>>   		shaderProgram_.setUniformValue(textureUniformY_, 0);
> >>> @@ -569,11 +569,11 @@ void ViewFinderGL::doRender()
> >>>   		configureTexture(*textures_[2]);
> >>>   		glTexImage2D(GL_TEXTURE_2D,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     size_.width() / horzSubSample_,
> >>>   			     size_.height() / vertSubSample_,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     GL_UNSIGNED_BYTE,
> >>>   			     data_ + size_.width() * size_.height());
> >>>   		shaderProgram_.setUniformValue(textureUniformV_, 2);
> >>> @@ -583,11 +583,11 @@ void ViewFinderGL::doRender()
> >>>   		configureTexture(*textures_[1]);
> >>>   		glTexImage2D(GL_TEXTURE_2D,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     size_.width() / horzSubSample_,
> >>>   			     size_.height() / vertSubSample_,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     GL_UNSIGNED_BYTE,
> >>>   			     data_ + size_.width() * size_.height() * 5 / 4);
> >>>   		shaderProgram_.setUniformValue(textureUniformU_, 1);
> >>> @@ -674,18 +674,18 @@ void ViewFinderGL::doRender()
> >>>   	case libcamera::formats::SRGGB12_CSI2P:
> >>>   		/*
> >>>   		 * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats
> >>> -		 * are stored in GL_RED texture.
> >>> -		 * The texture width is equal to the stride.
> >>> +		 * are stored in GL_LUMINANCE texture. The texture width is
> >>
> >> I know you're modifying an existing sentence, but should this read either:
> >>
> >>   - are stored in a GL_LUMINANCE texture
> >> or
> >>   - are stored in the GL_LUMINANCE texture
> >>
> >> depending on if there is only one GL_LUMINANCE texture, or if there
> >> might be more and this is specifically allocated.
> > 
> > I'll fix it, using "a GL_LUMINANCE texture".
> > 
> >> (That extra clarification would help me understand those identifiers
> >> too... such power from a single word addition).
> >>
> >> Anyway, aside from / with that:
> >>
> >> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> >>
> >>> +		 * equal to the stride.
> >>>   		 */
> >>>   		glActiveTexture(GL_TEXTURE0);
> >>>   		configureTexture(*textures_[0]);
> >>>   		glTexImage2D(GL_TEXTURE_2D,
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     stride_,
> >>>   			     size_.height(),
> >>>   			     0,
> >>> -			     GL_RED,
> >>> +			     GL_LUMINANCE,
> >>>   			     GL_UNSIGNED_BYTE,
> >>>   			     data_);
> >>>   		shaderProgram_.setUniformValue(textureUniformY_, 0);
> >>>

Patch
diff mbox series

diff --git a/src/qcam/assets/shader/YUV_2_planes.frag b/src/qcam/assets/shader/YUV_2_planes.frag
index 125f1c850a33..254463c05cac 100644
--- a/src/qcam/assets/shader/YUV_2_planes.frag
+++ b/src/qcam/assets/shader/YUV_2_planes.frag
@@ -26,9 +26,9 @@  void main(void)
 	yuv.x = texture2D(tex_y, textureOut).r - 0.063;
 #if defined(YUV_PATTERN_UV)
 	yuv.y = texture2D(tex_u, textureOut).r - 0.500;
-	yuv.z = texture2D(tex_u, textureOut).g - 0.500;
+	yuv.z = texture2D(tex_u, textureOut).a - 0.500;
 #elif defined(YUV_PATTERN_VU)
-	yuv.y = texture2D(tex_u, textureOut).g - 0.500;
+	yuv.y = texture2D(tex_u, textureOut).a - 0.500;
 	yuv.z = texture2D(tex_u, textureOut).r - 0.500;
 #else
 #error Invalid pattern
diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
index e7c8620c7024..77a6437e56fd 100644
--- a/src/qcam/viewfinder_gl.cpp
+++ b/src/qcam/viewfinder_gl.cpp
@@ -481,11 +481,11 @@  void ViewFinderGL::doRender()
 		configureTexture(*textures_[0]);
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     size_.width(),
 			     size_.height(),
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     GL_UNSIGNED_BYTE,
 			     data_);
 		shaderProgram_.setUniformValue(textureUniformY_, 0);
@@ -495,11 +495,11 @@  void ViewFinderGL::doRender()
 		configureTexture(*textures_[1]);
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
-			     GL_RG,
+			     GL_LUMINANCE_ALPHA,
 			     size_.width() / horzSubSample_,
 			     size_.height() / vertSubSample_,
 			     0,
-			     GL_RG,
+			     GL_LUMINANCE_ALPHA,
 			     GL_UNSIGNED_BYTE,
 			     data_ + size_.width() * size_.height());
 		shaderProgram_.setUniformValue(textureUniformU_, 1);
@@ -511,11 +511,11 @@  void ViewFinderGL::doRender()
 		configureTexture(*textures_[0]);
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     size_.width(),
 			     size_.height(),
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     GL_UNSIGNED_BYTE,
 			     data_);
 		shaderProgram_.setUniformValue(textureUniformY_, 0);
@@ -525,11 +525,11 @@  void ViewFinderGL::doRender()
 		configureTexture(*textures_[1]);
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     size_.width() / horzSubSample_,
 			     size_.height() / vertSubSample_,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     GL_UNSIGNED_BYTE,
 			     data_ + size_.width() * size_.height());
 		shaderProgram_.setUniformValue(textureUniformU_, 1);
@@ -539,11 +539,11 @@  void ViewFinderGL::doRender()
 		configureTexture(*textures_[2]);
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     size_.width() / horzSubSample_,
 			     size_.height() / vertSubSample_,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     GL_UNSIGNED_BYTE,
 			     data_ + size_.width() * size_.height() * 5 / 4);
 		shaderProgram_.setUniformValue(textureUniformV_, 2);
@@ -555,11 +555,11 @@  void ViewFinderGL::doRender()
 		configureTexture(*textures_[0]);
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     size_.width(),
 			     size_.height(),
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     GL_UNSIGNED_BYTE,
 			     data_);
 		shaderProgram_.setUniformValue(textureUniformY_, 0);
@@ -569,11 +569,11 @@  void ViewFinderGL::doRender()
 		configureTexture(*textures_[2]);
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     size_.width() / horzSubSample_,
 			     size_.height() / vertSubSample_,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     GL_UNSIGNED_BYTE,
 			     data_ + size_.width() * size_.height());
 		shaderProgram_.setUniformValue(textureUniformV_, 2);
@@ -583,11 +583,11 @@  void ViewFinderGL::doRender()
 		configureTexture(*textures_[1]);
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     size_.width() / horzSubSample_,
 			     size_.height() / vertSubSample_,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     GL_UNSIGNED_BYTE,
 			     data_ + size_.width() * size_.height() * 5 / 4);
 		shaderProgram_.setUniformValue(textureUniformU_, 1);
@@ -674,18 +674,18 @@  void ViewFinderGL::doRender()
 	case libcamera::formats::SRGGB12_CSI2P:
 		/*
 		 * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats
-		 * are stored in GL_RED texture.
-		 * The texture width is equal to the stride.
+		 * are stored in GL_LUMINANCE texture. The texture width is
+		 * equal to the stride.
 		 */
 		glActiveTexture(GL_TEXTURE0);
 		configureTexture(*textures_[0]);
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     stride_,
 			     size_.height(),
 			     0,
-			     GL_RED,
+			     GL_LUMINANCE,
 			     GL_UNSIGNED_BYTE,
 			     data_);
 		shaderProgram_.setUniformValue(textureUniformY_, 0);