From f844a2acbb7ecc4d7b1776d1d6eeb8feab7044f1 Mon Sep 17 00:00:00 2001 From: Massimo Callegari Date: Fri, 24 Aug 2018 23:41:13 +0200 Subject: Add OpenGL core profile support to QtMultimediaQuickTools When requesting a OGL Core profile via QSurfaceFormat::setDefaultFormat (e.g. to use Qt3D advanced features), it is no longer possible to render QML Video items. This is because the requested shaders should be _core versions. This patch adds the core shaders so QtMultimedia stops whining, and bind textures with the proper format, since GL_LUMINANCE and GL_LUMINANCE_ALPHA are no longer valid in OGL 4. Task-number: QTBUG-51064 Change-Id: I909e01e7dc7be07549e9ecf0a6425b309af38ea1 Reviewed-by: VaL Doroshchuk Reviewed-by: Christian Stromme --- src/qtmultimediaquicktools/qsgvideonode_yuv.cpp | 47 +++++++++++++++++++++---- 1 file changed, 41 insertions(+), 6 deletions(-) (limited to 'src/qtmultimediaquicktools/qsgvideonode_yuv.cpp') diff --git a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp index 9eff9dbd6..43cd5a2b2 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp +++ b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp @@ -44,6 +44,28 @@ #include #include +#ifndef GL_RED +#define GL_RED 0x1903 +#endif +#ifndef GL_GREEN +#define GL_GREEN 0x1904 +#endif +#ifndef GL_RG +#define GL_RG 0x8227 +#endif +#ifndef GL_TEXTURE_SWIZZLE_R +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#endif +#ifndef GL_TEXTURE_SWIZZLE_G +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#endif +#ifndef GL_TEXTURE_SWIZZLE_B +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#endif +#ifndef GL_TEXTURE_SWIZZLE_A +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#endif + QT_BEGIN_NAMESPACE QList QSGVideoNodeFactory_YUV::supportedPixelFormats( @@ -335,6 +357,8 @@ QSGVideoMaterial_YUV::~QSGVideoMaterial_YUV() void QSGVideoMaterial_YUV::bind() { QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions(); + QSurfaceFormat::OpenGLContextProfile profile = QOpenGLContext::currentContext()->format().profile(); + QMutexLocker lock(&m_frameMutex); if (m_frame.isValid()) { if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) { @@ -350,12 +374,16 @@ void QSGVideoMaterial_YUV::bind() } GLint previousAlignment; + const GLenum texFormat1 = (profile == QSurfaceFormat::CoreProfile) ? GL_RED : GL_LUMINANCE; + const GLenum texFormat2 = (profile == QSurfaceFormat::CoreProfile) ? GL_RG : GL_LUMINANCE_ALPHA; + functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment); functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if (m_format.pixelFormat() == QVideoFrame::Format_UYVY || m_format.pixelFormat() == QVideoFrame::Format_YUYV) { int fw = m_frame.width(); + m_planeWidth[0] = fw; // In YUYV texture the UV plane appears with the 1/2 of image and Y width. m_planeWidth[1] = fw / 2; @@ -367,7 +395,7 @@ void QSGVideoMaterial_YUV::bind() bindTexture(m_textureIds[1], m_planeWidth[1], m_frame.height(), m_frame.bits(), GL_RGBA); functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit // Either red (YUYV) or alpha (UYVY) values are used as source of Y - bindTexture(m_textureIds[0], m_planeWidth[0], m_frame.height(), m_frame.bits(), GL_LUMINANCE_ALPHA); + bindTexture(m_textureIds[0], m_planeWidth[0], m_frame.height(), m_frame.bits(), texFormat2); } else if (m_format.pixelFormat() == QVideoFrame::Format_NV12 || m_format.pixelFormat() == QVideoFrame::Format_NV21) { const int y = 0; @@ -376,9 +404,9 @@ void QSGVideoMaterial_YUV::bind() m_planeWidth[0] = m_planeWidth[1] = qreal(fw) / m_frame.bytesPerLine(y); functions->glActiveTexture(GL_TEXTURE1); - bindTexture(m_textureIds[1], m_frame.bytesPerLine(uv) / 2, fh / 2, m_frame.bits(uv), GL_LUMINANCE_ALPHA); + bindTexture(m_textureIds[1], m_frame.bytesPerLine(uv) / 2, fh / 2, m_frame.bits(uv), texFormat2); functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit - bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y), GL_LUMINANCE); + bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y), texFormat1); } else { // YUV420P || YV12 const int y = 0; @@ -389,11 +417,11 @@ void QSGVideoMaterial_YUV::bind() m_planeWidth[1] = m_planeWidth[2] = qreal(fw) / (2 * m_frame.bytesPerLine(u)); functions->glActiveTexture(GL_TEXTURE1); - bindTexture(m_textureIds[1], m_frame.bytesPerLine(u), fh / 2, m_frame.bits(u), GL_LUMINANCE); + bindTexture(m_textureIds[1], m_frame.bytesPerLine(u), fh / 2, m_frame.bits(u), texFormat1); functions->glActiveTexture(GL_TEXTURE2); - bindTexture(m_textureIds[2], m_frame.bytesPerLine(v), fh / 2, m_frame.bits(v), GL_LUMINANCE); + bindTexture(m_textureIds[2], m_frame.bytesPerLine(v), fh / 2, m_frame.bits(v), texFormat1); functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit - bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y), GL_LUMINANCE); + bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y), texFormat1); } functions->glPixelStorei(GL_UNPACK_ALIGNMENT, previousAlignment); @@ -415,6 +443,13 @@ void QSGVideoMaterial_YUV::bindTexture(int id, int w, int h, const uchar *bits, QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions(); functions->glBindTexture(GL_TEXTURE_2D, id); functions->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, bits); + // replacement for GL_LUMINANCE_ALPHA in core profile + if (format == GL_RG) { + functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED); + functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED); + functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); + functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_GREEN); + } functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -- cgit v1.2.3