Support dynamic opengl32 - ANGLE switching on Windows
Change-Id: I38532db3ab0ad4fcb8dbabd0cbb528f7d8e4ba06 Reviewed-by: Andrew Knight <andrew.knight@digia.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
This commit is contained in:
@@ -22,7 +22,8 @@ PRIVATE_HEADERS += \
|
|||||||
qmediaresourcepolicyplugin_p.h \
|
qmediaresourcepolicyplugin_p.h \
|
||||||
qmediaresourcepolicy_p.h \
|
qmediaresourcepolicy_p.h \
|
||||||
qmediaresourceset_p.h \
|
qmediaresourceset_p.h \
|
||||||
qmediastoragelocation_p.h
|
qmediastoragelocation_p.h \
|
||||||
|
qmediaopenglhelper_p.h
|
||||||
|
|
||||||
PUBLIC_HEADERS += \
|
PUBLIC_HEADERS += \
|
||||||
qmediabindableinterface.h \
|
qmediabindableinterface.h \
|
||||||
|
|||||||
117
src/multimedia/qmediaopenglhelper_p.h
Normal file
117
src/multimedia/qmediaopenglhelper_p.h
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://qt.digia.com/licensing. For further information
|
||||||
|
** use the contact form at http://qt.digia.com/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3.0 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU General Public License version 3.0 requirements will be
|
||||||
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QMEDIAOPENGLHELPER_P_H
|
||||||
|
#define QMEDIAOPENGLHELPER_P_H
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G
|
||||||
|
// -------------
|
||||||
|
//
|
||||||
|
// This file is not part of the Qt API. It exists purely as an
|
||||||
|
// implementation detail. This header file may change from version to
|
||||||
|
// version without notice, or even be removed.
|
||||||
|
//
|
||||||
|
// We mean it.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <QtGui/QOpenGLContext>
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN) && (defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC))
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QMediaOpenGLHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool isANGLE();
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool QMediaOpenGLHelper::isANGLE()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WINRT
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
bool isANGLE = false;
|
||||||
|
|
||||||
|
# if defined(Q_OS_WIN) && (defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC))
|
||||||
|
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
|
||||||
|
// Although unlikely, technically LibGLES could mean a non-ANGLE EGL/GLES2 implementation too.
|
||||||
|
// Verify that it is indeed ANGLE.
|
||||||
|
# ifdef QT_OPENGL_ES_2_ANGLE_STATIC
|
||||||
|
// ANGLE linked-in statically.
|
||||||
|
isANGLE = true;
|
||||||
|
# else
|
||||||
|
// Qt configured with either -opengl es2 or -opengl desktop.
|
||||||
|
# ifdef QT_DEBUG
|
||||||
|
HMODULE eglHandle = LoadLibraryW(L"libEGLd.dll");
|
||||||
|
# else
|
||||||
|
HMODULE eglHandle = LoadLibraryW(L"libEGL.dll");
|
||||||
|
# endif // QT_DEBUG
|
||||||
|
if (eglHandle) {
|
||||||
|
typedef EGLDisplay (EGLAPIENTRYP EglGetDisplay)(EGLNativeDisplayType display_id);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRYP EglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||||
|
typedef const char * (EGLAPIENTRYP EglQueryString)(EGLDisplay dpy, EGLint name);
|
||||||
|
EglGetDisplay eglGetDisplay = (EglGetDisplay) GetProcAddress(eglHandle, "eglGetDisplay");
|
||||||
|
EglInitialize eglInitialize = (EglInitialize) GetProcAddress(eglHandle, "eglInitialize");
|
||||||
|
EglQueryString eglQueryString = (EglQueryString) GetProcAddress(eglHandle, "eglQueryString");
|
||||||
|
if (eglGetDisplay && eglInitialize && eglQueryString) {
|
||||||
|
// EGL may not be initialized at this stage.
|
||||||
|
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
|
eglInitialize(dpy, 0, 0);
|
||||||
|
const char *vendorStr = eglQueryString(dpy, EGL_VERSION);
|
||||||
|
isANGLE = vendorStr && strstr(vendorStr, "ANGLE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif // QT_OPENGL_ES_2_ANGLE_STATIC
|
||||||
|
|
||||||
|
}
|
||||||
|
# endif // Q_OS_WIN && (QT_OPENGL_ES_2 || QT_OPENGL_DYNAMIC)
|
||||||
|
|
||||||
|
return isANGLE;
|
||||||
|
#endif // Q_OS_WINRT
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -50,10 +50,14 @@
|
|||||||
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
|
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
|
||||||
#include <qglshaderprogram.h>
|
#include <qglshaderprogram.h>
|
||||||
#include <QtGui/QOpenGLContext>
|
#include <QtGui/QOpenGLContext>
|
||||||
|
#include <QtGui/QOpenGLFunctions>
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
#ifndef GL_CLAMP_TO_EDGE
|
#ifndef GL_CLAMP_TO_EDGE
|
||||||
#define GL_CLAMP_TO_EDGE 0x812F
|
#define GL_CLAMP_TO_EDGE 0x812F
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef GL_RGB8
|
||||||
|
#define GL_RGB8 0x8051
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
@@ -97,11 +101,11 @@ QVideoSurfaceGenericPainter::QVideoSurfaceGenericPainter()
|
|||||||
{
|
{
|
||||||
m_imagePixelFormats
|
m_imagePixelFormats
|
||||||
<< QVideoFrame::Format_RGB32
|
<< QVideoFrame::Format_RGB32
|
||||||
#ifndef QT_OPENGL_ES // The raster formats should be a subset of the GL formats.
|
|
||||||
<< QVideoFrame::Format_RGB24
|
|
||||||
#endif
|
|
||||||
<< QVideoFrame::Format_ARGB32
|
<< QVideoFrame::Format_ARGB32
|
||||||
<< QVideoFrame::Format_RGB565;
|
<< QVideoFrame::Format_RGB565;
|
||||||
|
// The raster formats should be a subset of the GL formats.
|
||||||
|
if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES)
|
||||||
|
m_imagePixelFormats << QVideoFrame::Format_RGB24;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QVideoFrame::PixelFormat> QVideoSurfaceGenericPainter::supportedPixelFormats(
|
QList<QVideoFrame::PixelFormat> QVideoSurfaceGenericPainter::supportedPixelFormats(
|
||||||
@@ -140,13 +144,11 @@ QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::start(const QVideoSurf
|
|||||||
|
|
||||||
const QAbstractVideoBuffer::HandleType t = format.handleType();
|
const QAbstractVideoBuffer::HandleType t = format.handleType();
|
||||||
if (t == QAbstractVideoBuffer::NoHandle) {
|
if (t == QAbstractVideoBuffer::NoHandle) {
|
||||||
if (m_imageFormat != QImage::Format_Invalid
|
bool ok = m_imageFormat != QImage::Format_Invalid && !m_imageSize.isEmpty();
|
||||||
#ifdef QT_OPENGL_ES
|
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES)
|
||||||
&& format.pixelFormat() != QVideoFrame::Format_RGB24
|
ok &= format.pixelFormat() != QVideoFrame::Format_RGB24;
|
||||||
#endif
|
if (ok)
|
||||||
&& !m_imageSize.isEmpty()) {
|
|
||||||
return QAbstractVideoSurface::NoError;
|
return QAbstractVideoSurface::NoError;
|
||||||
}
|
|
||||||
} else if (t == QAbstractVideoBuffer::QPixmapHandle) {
|
} else if (t == QAbstractVideoBuffer::QPixmapHandle) {
|
||||||
return QAbstractVideoSurface::NoError;
|
return QAbstractVideoSurface::NoError;
|
||||||
}
|
}
|
||||||
@@ -237,7 +239,7 @@ void QVideoSurfaceGenericPainter::updateColors(int, int, int, int)
|
|||||||
# define GL_UNSIGNED_SHORT_5_6_5 33635
|
# define GL_UNSIGNED_SHORT_5_6_5 33635
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class QVideoSurfaceGLPainter : public QVideoSurfacePainter
|
class QVideoSurfaceGLPainter : public QVideoSurfacePainter, protected QOpenGLFunctions
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QVideoSurfaceGLPainter(QGLContext *context);
|
QVideoSurfaceGLPainter(QGLContext *context);
|
||||||
@@ -262,7 +264,7 @@ protected:
|
|||||||
void initYuv420PTextureInfo(const QSize &size);
|
void initYuv420PTextureInfo(const QSize &size);
|
||||||
void initYv12TextureInfo(const QSize &size);
|
void initYv12TextureInfo(const QSize &size);
|
||||||
|
|
||||||
#ifndef QT_OPENGL_ES
|
#if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC)
|
||||||
typedef void (APIENTRY *_glActiveTexture) (GLenum);
|
typedef void (APIENTRY *_glActiveTexture) (GLenum);
|
||||||
_glActiveTexture glActiveTexture;
|
_glActiveTexture glActiveTexture;
|
||||||
#endif
|
#endif
|
||||||
@@ -300,7 +302,7 @@ QVideoSurfaceGLPainter::QVideoSurfaceGLPainter(QGLContext *context)
|
|||||||
, m_textureCount(0)
|
, m_textureCount(0)
|
||||||
, m_yuv(false)
|
, m_yuv(false)
|
||||||
{
|
{
|
||||||
#ifndef QT_OPENGL_ES
|
#if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC)
|
||||||
glActiveTexture = (_glActiveTexture)m_context->getProcAddress(QLatin1String("glActiveTexture"));
|
glActiveTexture = (_glActiveTexture)m_context->getProcAddress(QLatin1String("glActiveTexture"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -309,6 +311,7 @@ QVideoSurfaceGLPainter::QVideoSurfaceGLPainter(QGLContext *context)
|
|||||||
memset(m_textureHeights, 0, sizeof(m_textureHeights));
|
memset(m_textureHeights, 0, sizeof(m_textureHeights));
|
||||||
memset(m_textureOffsets, 0, sizeof(m_textureOffsets));
|
memset(m_textureOffsets, 0, sizeof(m_textureOffsets));
|
||||||
|
|
||||||
|
initializeOpenGLFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVideoSurfaceGLPainter::~QVideoSurfaceGLPainter()
|
QVideoSurfaceGLPainter::~QVideoSurfaceGLPainter()
|
||||||
@@ -554,7 +557,7 @@ void QVideoSurfaceGLPainter::initYv12TextureInfo(const QSize &size)
|
|||||||
m_textureOffsets[2] = bytesPerLine * size.height();
|
m_textureOffsets[2] = bytesPerLine * size.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_OPENGL_ES
|
#if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC)
|
||||||
|
|
||||||
# ifndef GL_FRAGMENT_PROGRAM_ARB
|
# ifndef GL_FRAGMENT_PROGRAM_ARB
|
||||||
# define GL_FRAGMENT_PROGRAM_ARB 0x8804
|
# define GL_FRAGMENT_PROGRAM_ARB 0x8804
|
||||||
@@ -945,7 +948,7 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint(
|
|||||||
return QVideoSurfaceGLPainter::paint(target, painter, source);
|
return QVideoSurfaceGLPainter::paint(target, painter, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // !QT_OPENGL_ES && !QT_OPENGL_DYNAMIC
|
||||||
|
|
||||||
static const char *qt_glsl_vertexShaderProgram =
|
static const char *qt_glsl_vertexShaderProgram =
|
||||||
"attribute highp vec4 vertexCoordArray;\n"
|
"attribute highp vec4 vertexCoordArray;\n"
|
||||||
@@ -1057,10 +1060,6 @@ QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context)
|
|||||||
<< QVideoFrame::Format_RGB32
|
<< QVideoFrame::Format_RGB32
|
||||||
<< QVideoFrame::Format_BGR32
|
<< QVideoFrame::Format_BGR32
|
||||||
<< QVideoFrame::Format_ARGB32
|
<< QVideoFrame::Format_ARGB32
|
||||||
#ifndef QT_OPENGL_ES
|
|
||||||
<< QVideoFrame::Format_RGB24
|
|
||||||
<< QVideoFrame::Format_BGR24
|
|
||||||
#endif
|
|
||||||
<< QVideoFrame::Format_RGB565
|
<< QVideoFrame::Format_RGB565
|
||||||
<< QVideoFrame::Format_YUV444
|
<< QVideoFrame::Format_YUV444
|
||||||
<< QVideoFrame::Format_AYUV444
|
<< QVideoFrame::Format_AYUV444
|
||||||
@@ -1069,6 +1068,11 @@ QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context)
|
|||||||
m_glPixelFormats
|
m_glPixelFormats
|
||||||
<< QVideoFrame::Format_RGB32
|
<< QVideoFrame::Format_RGB32
|
||||||
<< QVideoFrame::Format_ARGB32;
|
<< QVideoFrame::Format_ARGB32;
|
||||||
|
if (!context->contextHandle()->isOpenGLES()) {
|
||||||
|
m_imagePixelFormats
|
||||||
|
<< QVideoFrame::Format_RGB24
|
||||||
|
<< QVideoFrame::Format_BGR24;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurfaceFormat &format)
|
QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurfaceFormat &format)
|
||||||
@@ -1095,16 +1099,18 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurface
|
|||||||
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
|
initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
|
||||||
fragmentProgram = qt_glsl_argbShaderProgram;
|
fragmentProgram = qt_glsl_argbShaderProgram;
|
||||||
break;
|
break;
|
||||||
#ifndef QT_OPENGL_ES
|
|
||||||
case QVideoFrame::Format_RGB24:
|
case QVideoFrame::Format_RGB24:
|
||||||
initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
|
if (!m_context->contextHandle()->isOpenGLES()) {
|
||||||
fragmentProgram = qt_glsl_rgbShaderProgram;
|
initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
|
||||||
|
fragmentProgram = qt_glsl_rgbShaderProgram;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case QVideoFrame::Format_BGR24:
|
case QVideoFrame::Format_BGR24:
|
||||||
initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
|
if (!m_context->contextHandle()->isOpenGLES()) {
|
||||||
fragmentProgram = qt_glsl_argbShaderProgram;
|
initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
|
||||||
|
fragmentProgram = qt_glsl_argbShaderProgram;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case QVideoFrame::Format_RGB565:
|
case QVideoFrame::Format_RGB565:
|
||||||
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
|
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
|
||||||
fragmentProgram = qt_glsl_rgbShaderProgram;
|
fragmentProgram = qt_glsl_rgbShaderProgram;
|
||||||
@@ -1577,14 +1583,14 @@ void QPainterVideoSurface::setGLContext(QGLContext *context)
|
|||||||
|
|
||||||
m_glContext->makeCurrent();
|
m_glContext->makeCurrent();
|
||||||
|
|
||||||
const QByteArray extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
|
const QByteArray extensions(reinterpret_cast<const char *>(
|
||||||
#ifndef QT_OPENGL_ES
|
context->contextHandle()->functions()->glGetString(GL_EXTENSIONS)));
|
||||||
|
#if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC)
|
||||||
if (extensions.contains("ARB_fragment_program"))
|
if (extensions.contains("ARB_fragment_program"))
|
||||||
m_shaderTypes |= FragmentProgramShader;
|
m_shaderTypes |= FragmentProgramShader;
|
||||||
#endif
|
#endif
|
||||||
if (QGLShaderProgram::hasOpenGLShaderPrograms(m_glContext)
|
if (QGLShaderProgram::hasOpenGLShaderPrograms(m_glContext)
|
||||||
#ifndef QT_OPENGL_ES_2
|
#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_DYNAMIC)
|
||||||
&& extensions.contains("ARB_shader_objects")
|
&& extensions.contains("ARB_shader_objects")
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
@@ -1683,13 +1689,13 @@ void QPainterVideoSurface::createPainter()
|
|||||||
|
|
||||||
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
|
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
|
||||||
switch (m_shaderType) {
|
switch (m_shaderType) {
|
||||||
#ifndef QT_OPENGL_ES
|
#if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC)
|
||||||
case FragmentProgramShader:
|
case FragmentProgramShader:
|
||||||
Q_ASSERT(m_glContext);
|
Q_ASSERT(m_glContext);
|
||||||
m_glContext->makeCurrent();
|
m_glContext->makeCurrent();
|
||||||
m_painter = new QVideoSurfaceArbFpPainter(m_glContext);
|
m_painter = new QVideoSurfaceArbFpPainter(m_glContext);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif // !QT_OPENGL_ES && !QT_OPENGL_DYNAMIC
|
||||||
case GlslShader:
|
case GlslShader:
|
||||||
Q_ASSERT(m_glContext);
|
Q_ASSERT(m_glContext);
|
||||||
m_glContext->makeCurrent();
|
m_glContext->makeCurrent();
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
#include <qvideoframe.h>
|
#include <qvideoframe.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <qopenglcontext.h>
|
#include <qopenglcontext.h>
|
||||||
|
#include <qopenglfunctions.h>
|
||||||
#include <qwindow.h>
|
#include <qwindow.h>
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
@@ -88,6 +89,67 @@ private:
|
|||||||
GLuint m_textureId;
|
GLuint m_textureId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EGLWrapper::EGLWrapper()
|
||||||
|
{
|
||||||
|
#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
|
||||||
|
// Resolve the EGL functions we use. When configured for dynamic OpenGL, no
|
||||||
|
// component in Qt will link to libEGL.lib and libGLESv2.lib. We know
|
||||||
|
// however that libEGL is loaded for sure, since this is an ANGLE-only path.
|
||||||
|
|
||||||
|
# ifdef QT_DEBUG
|
||||||
|
HMODULE eglHandle = GetModuleHandle(L"libEGLd.dll");
|
||||||
|
# else
|
||||||
|
HMODULE eglHandle = GetModuleHandle(L"libEGL.dll");
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (!eglHandle)
|
||||||
|
qWarning("No EGL library loaded");
|
||||||
|
|
||||||
|
m_eglGetProcAddress = (EglGetProcAddress) GetProcAddress(eglHandle, "eglGetProcAddress");
|
||||||
|
m_eglCreatePbufferSurface = (EglCreatePbufferSurface) GetProcAddress(eglHandle, "eglCreatePbufferSurface");
|
||||||
|
m_eglDestroySurface = (EglDestroySurface) GetProcAddress(eglHandle, "eglDestroySurface");
|
||||||
|
m_eglBindTexImage = (EglBindTexImage) GetProcAddress(eglHandle, "eglBindTexImage");
|
||||||
|
m_eglReleaseTexImage = (EglReleaseTexImage) GetProcAddress(eglHandle, "eglReleaseTexImage");
|
||||||
|
#else
|
||||||
|
// Static ANGLE-only build. There is no libEGL.dll in use.
|
||||||
|
|
||||||
|
m_eglGetProcAddress = ::eglGetProcAddress;
|
||||||
|
m_eglCreatePbufferSurface = ::eglCreatePbufferSurface;
|
||||||
|
m_eglDestroySurface = ::eglDestroySurface;
|
||||||
|
m_eglBindTexImage = ::eglBindTexImage;
|
||||||
|
m_eglReleaseTexImage = ::eglReleaseTexImage;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__eglMustCastToProperFunctionPointerType EGLWrapper::getProcAddress(const char *procname)
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_eglGetProcAddress);
|
||||||
|
return m_eglGetProcAddress(procname);
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLSurface EGLWrapper::createPbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_eglCreatePbufferSurface);
|
||||||
|
return m_eglCreatePbufferSurface(dpy, config, attrib_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLBoolean EGLWrapper::destroySurface(EGLDisplay dpy, EGLSurface surface)
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_eglDestroySurface);
|
||||||
|
return m_eglDestroySurface(dpy, surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLBoolean EGLWrapper::bindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_eglBindTexImage);
|
||||||
|
return m_eglBindTexImage(dpy, surface, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLBoolean EGLWrapper::releaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_eglReleaseTexImage);
|
||||||
|
return m_eglReleaseTexImage(dpy, surface, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
D3DPresentEngine::D3DPresentEngine()
|
D3DPresentEngine::D3DPresentEngine()
|
||||||
: QObject()
|
: QObject()
|
||||||
@@ -104,6 +166,7 @@ D3DPresentEngine::D3DPresentEngine()
|
|||||||
, m_eglSurface(0)
|
, m_eglSurface(0)
|
||||||
, m_glTexture(0)
|
, m_glTexture(0)
|
||||||
, m_texture(0)
|
, m_texture(0)
|
||||||
|
, m_egl(0)
|
||||||
{
|
{
|
||||||
ZeroMemory(&m_displayMode, sizeof(m_displayMode));
|
ZeroMemory(&m_displayMode, sizeof(m_displayMode));
|
||||||
|
|
||||||
@@ -126,15 +189,16 @@ D3DPresentEngine::~D3DPresentEngine()
|
|||||||
qt_wmf_safeRelease(&m_D3D9);
|
qt_wmf_safeRelease(&m_D3D9);
|
||||||
|
|
||||||
if (m_eglSurface) {
|
if (m_eglSurface) {
|
||||||
eglReleaseTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER);
|
m_egl->releaseTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER);
|
||||||
eglDestroySurface(m_eglDisplay, m_eglSurface);
|
m_egl->destroySurface(m_eglDisplay, m_eglSurface);
|
||||||
m_eglSurface = NULL;
|
m_eglSurface = NULL;
|
||||||
}
|
}
|
||||||
if (m_glTexture)
|
if (m_glTexture)
|
||||||
glDeleteTextures(1, &m_glTexture);
|
QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_glTexture);
|
||||||
|
|
||||||
delete m_glContext;
|
delete m_glContext;
|
||||||
delete m_offscreenSurface;
|
delete m_offscreenSurface;
|
||||||
|
delete m_egl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3DPresentEngine::start()
|
void D3DPresentEngine::start()
|
||||||
@@ -358,14 +422,16 @@ void D3DPresentEngine::createOffscreenTexture()
|
|||||||
if (m_glContext)
|
if (m_glContext)
|
||||||
m_glContext->makeCurrent(m_offscreenSurface);
|
m_glContext->makeCurrent(m_offscreenSurface);
|
||||||
|
|
||||||
|
if (!m_egl)
|
||||||
|
m_egl = new EGLWrapper;
|
||||||
|
|
||||||
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
|
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
|
||||||
m_eglDisplay = static_cast<EGLDisplay*>(
|
m_eglDisplay = static_cast<EGLDisplay*>(
|
||||||
nativeInterface->nativeResourceForContext("eglDisplay", currentContext));
|
nativeInterface->nativeResourceForContext("eglDisplay", currentContext));
|
||||||
m_eglConfig = static_cast<EGLDisplay*>(
|
m_eglConfig = static_cast<EGLDisplay*>(
|
||||||
nativeInterface->nativeResourceForContext("eglConfig", currentContext));
|
nativeInterface->nativeResourceForContext("eglConfig", currentContext));
|
||||||
|
|
||||||
glGenTextures(1, &m_glTexture);
|
currentContext->functions()->glGenTextures(1, &m_glTexture);
|
||||||
|
|
||||||
|
|
||||||
int w = m_surfaceFormat.frameWidth();
|
int w = m_surfaceFormat.frameWidth();
|
||||||
int h = m_surfaceFormat.frameHeight();
|
int h = m_surfaceFormat.frameHeight();
|
||||||
@@ -378,11 +444,12 @@ void D3DPresentEngine::createOffscreenTexture()
|
|||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
EGLSurface pbuffer = eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, attribs);
|
EGLSurface pbuffer = m_egl->createPbufferSurface(m_eglDisplay, m_eglConfig, attribs);
|
||||||
|
|
||||||
HANDLE share_handle = 0;
|
HANDLE share_handle = 0;
|
||||||
PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE =
|
PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE =
|
||||||
reinterpret_cast<PFNEGLQUERYSURFACEPOINTERANGLEPROC>(eglGetProcAddress("eglQuerySurfacePointerANGLE"));
|
reinterpret_cast<PFNEGLQUERYSURFACEPOINTERANGLEPROC>(m_egl->getProcAddress("eglQuerySurfacePointerANGLE"));
|
||||||
|
Q_ASSERT(eglQuerySurfacePointerANGLE);
|
||||||
eglQuerySurfacePointerANGLE(
|
eglQuerySurfacePointerANGLE(
|
||||||
m_eglDisplay,
|
m_eglDisplay,
|
||||||
pbuffer,
|
pbuffer,
|
||||||
@@ -410,7 +477,7 @@ bool D3DPresentEngine::updateTexture(IDirect3DSurface9 *src)
|
|||||||
if (m_glContext)
|
if (m_glContext)
|
||||||
m_glContext->makeCurrent(m_offscreenSurface);
|
m_glContext->makeCurrent(m_offscreenSurface);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_glTexture);
|
QOpenGLContext::currentContext()->functions()->glBindTexture(GL_TEXTURE_2D, m_glTexture);
|
||||||
|
|
||||||
IDirect3DSurface9 *dest = NULL;
|
IDirect3DSurface9 *dest = NULL;
|
||||||
|
|
||||||
@@ -424,7 +491,7 @@ bool D3DPresentEngine::updateTexture(IDirect3DSurface9 *src)
|
|||||||
qWarning("Failed to copy D3D surface");
|
qWarning("Failed to copy D3D surface");
|
||||||
|
|
||||||
if (hr == S_OK)
|
if (hr == S_OK)
|
||||||
eglBindTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER);
|
m_egl->bindTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
qt_wmf_safeRelease(&dest);
|
qt_wmf_safeRelease(&dest);
|
||||||
|
|||||||
@@ -70,6 +70,31 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QAbstractVideoSurface;
|
class QAbstractVideoSurface;
|
||||||
class QOpenGLContext;
|
class QOpenGLContext;
|
||||||
|
|
||||||
|
class EGLWrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EGLWrapper();
|
||||||
|
|
||||||
|
__eglMustCastToProperFunctionPointerType getProcAddress(const char *procname);
|
||||||
|
EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||||
|
EGLBoolean destroySurface(EGLDisplay dpy, EGLSurface surface);
|
||||||
|
EGLBoolean bindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||||
|
EGLBoolean releaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef __eglMustCastToProperFunctionPointerType (EGLAPIENTRYP EglGetProcAddress)(const char *procname);
|
||||||
|
typedef EGLSurface (EGLAPIENTRYP EglCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRYP EglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRYP EglBindTexImage)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRYP EglReleaseTexImage)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||||
|
|
||||||
|
EglGetProcAddress m_eglGetProcAddress;
|
||||||
|
EglCreatePbufferSurface m_eglCreatePbufferSurface;
|
||||||
|
EglDestroySurface m_eglDestroySurface;
|
||||||
|
EglBindTexImage m_eglBindTexImage;
|
||||||
|
EglReleaseTexImage m_eglReleaseTexImage;
|
||||||
|
};
|
||||||
|
|
||||||
class D3DPresentEngine : public QObject
|
class D3DPresentEngine : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -123,6 +148,7 @@ private:
|
|||||||
EGLSurface m_eglSurface;
|
EGLSurface m_eglSurface;
|
||||||
unsigned int m_glTexture;
|
unsigned int m_glTexture;
|
||||||
IDirect3DTexture9 *m_texture;
|
IDirect3DTexture9 *m_texture;
|
||||||
|
EGLWrapper *m_egl;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|||||||
@@ -41,9 +41,15 @@
|
|||||||
|
|
||||||
#include "mfvideorenderercontrol.h"
|
#include "mfvideorenderercontrol.h"
|
||||||
#include "mfglobal.h"
|
#include "mfglobal.h"
|
||||||
#ifdef QT_OPENGL_ES_2_ANGLE
|
|
||||||
|
#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
|
||||||
|
#define MAYBE_ANGLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAYBE_ANGLE
|
||||||
#include "evrcustompresenter.h"
|
#include "evrcustompresenter.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <qabstractvideosurface.h>
|
#include <qabstractvideosurface.h>
|
||||||
#include <qvideosurfaceformat.h>
|
#include <qvideosurfaceformat.h>
|
||||||
#include <qtcore/qtimer.h>
|
#include <qtcore/qtimer.h>
|
||||||
@@ -53,6 +59,7 @@
|
|||||||
#include <qtcore/qthread.h>
|
#include <qtcore/qthread.h>
|
||||||
#include "guiddef.h"
|
#include "guiddef.h"
|
||||||
#include <qtcore/qdebug.h>
|
#include <qtcore/qdebug.h>
|
||||||
|
#include <QtMultimedia/private/qmediaopenglhelper_p.h>
|
||||||
|
|
||||||
//#define DEBUG_MEDIAFOUNDATION
|
//#define DEBUG_MEDIAFOUNDATION
|
||||||
#define PAD_TO_DWORD(x) (((x) + 3) & ~3)
|
#define PAD_TO_DWORD(x) (((x) + 3) & ~3)
|
||||||
@@ -2228,9 +2235,7 @@ MFVideoRendererControl::MFVideoRendererControl(QObject *parent)
|
|||||||
, m_surface(0)
|
, m_surface(0)
|
||||||
, m_currentActivate(0)
|
, m_currentActivate(0)
|
||||||
, m_callback(0)
|
, m_callback(0)
|
||||||
#ifdef QT_OPENGL_ES_2_ANGLE
|
|
||||||
, m_presenterActivate(0)
|
, m_presenterActivate(0)
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2244,7 +2249,7 @@ void MFVideoRendererControl::clear()
|
|||||||
if (m_surface)
|
if (m_surface)
|
||||||
m_surface->stop();
|
m_surface->stop();
|
||||||
|
|
||||||
#ifdef QT_OPENGL_ES_2_ANGLE
|
#ifdef MAYBE_ANGLE
|
||||||
if (m_presenterActivate) {
|
if (m_presenterActivate) {
|
||||||
m_presenterActivate->ShutdownObject();
|
m_presenterActivate->ShutdownObject();
|
||||||
m_presenterActivate->Release();
|
m_presenterActivate->Release();
|
||||||
@@ -2279,7 +2284,7 @@ void MFVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
|
|||||||
connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged()));
|
connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef QT_OPENGL_ES_2_ANGLE
|
#ifdef MAYBE_ANGLE
|
||||||
if (m_presenterActivate)
|
if (m_presenterActivate)
|
||||||
m_presenterActivate->setSurface(m_surface);
|
m_presenterActivate->setSurface(m_surface);
|
||||||
else
|
else
|
||||||
@@ -2290,10 +2295,8 @@ void MFVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
|
|||||||
|
|
||||||
void MFVideoRendererControl::customEvent(QEvent *event)
|
void MFVideoRendererControl::customEvent(QEvent *event)
|
||||||
{
|
{
|
||||||
#ifdef QT_OPENGL_ES_2_ANGLE
|
|
||||||
if (m_presenterActivate)
|
if (m_presenterActivate)
|
||||||
return;
|
return;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!m_currentActivate)
|
if (!m_currentActivate)
|
||||||
return;
|
return;
|
||||||
@@ -2324,7 +2327,7 @@ void MFVideoRendererControl::customEvent(QEvent *event)
|
|||||||
|
|
||||||
void MFVideoRendererControl::supportedFormatsChanged()
|
void MFVideoRendererControl::supportedFormatsChanged()
|
||||||
{
|
{
|
||||||
#ifdef QT_OPENGL_ES_2_ANGLE
|
#ifdef MAYBE_ANGLE
|
||||||
if (m_presenterActivate)
|
if (m_presenterActivate)
|
||||||
m_presenterActivate->supportedFormatsChanged();
|
m_presenterActivate->supportedFormatsChanged();
|
||||||
else
|
else
|
||||||
@@ -2335,10 +2338,8 @@ void MFVideoRendererControl::supportedFormatsChanged()
|
|||||||
|
|
||||||
void MFVideoRendererControl::present()
|
void MFVideoRendererControl::present()
|
||||||
{
|
{
|
||||||
#ifdef QT_OPENGL_ES_2_ANGLE
|
|
||||||
if (m_presenterActivate)
|
if (m_presenterActivate)
|
||||||
return;
|
return;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (m_currentActivate)
|
if (m_currentActivate)
|
||||||
static_cast<VideoRendererActivate*>(m_currentActivate)->present();
|
static_cast<VideoRendererActivate*>(m_currentActivate)->present();
|
||||||
@@ -2350,20 +2351,21 @@ IMFActivate* MFVideoRendererControl::createActivate()
|
|||||||
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
#ifdef QT_OPENGL_ES_2_ANGLE
|
#ifdef MAYBE_ANGLE
|
||||||
// We can use the EVR with our custom presenter only if the surface supports OpenGL
|
// We can use the EVR with our custom presenter only if the surface supports OpenGL
|
||||||
// texture handles
|
// texture handles. We also require ANGLE (due to the D3D interop).
|
||||||
if (!m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty()) {
|
if (!m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty()
|
||||||
|
&& QMediaOpenGLHelper::isANGLE()) {
|
||||||
// Create the EVR media sink, but replace the presenter with our own
|
// Create the EVR media sink, but replace the presenter with our own
|
||||||
if (SUCCEEDED(MFCreateVideoRendererActivate(::GetShellWindow(), &m_currentActivate))) {
|
if (SUCCEEDED(MFCreateVideoRendererActivate(::GetShellWindow(), &m_currentActivate))) {
|
||||||
m_presenterActivate = new EVRCustomPresenterActivate;
|
m_presenterActivate = new EVRCustomPresenterActivate;
|
||||||
m_currentActivate->SetUnknown(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, m_presenterActivate);
|
m_currentActivate->SetUnknown(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, m_presenterActivate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!m_currentActivate)
|
if (!m_currentActivate)
|
||||||
#endif
|
m_currentActivate = new VideoRendererActivate(this);
|
||||||
m_currentActivate = new VideoRendererActivate(this);
|
|
||||||
|
|
||||||
setSurface(m_surface);
|
setSurface(m_surface);
|
||||||
|
|
||||||
|
|||||||
@@ -48,9 +48,7 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
#ifdef QT_OPENGL_ES_2_ANGLE
|
|
||||||
class EVRCustomPresenterActivate;
|
class EVRCustomPresenterActivate;
|
||||||
#endif
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
@@ -83,9 +81,7 @@ private:
|
|||||||
IMFActivate *m_currentActivate;
|
IMFActivate *m_currentActivate;
|
||||||
IMFSampleGrabberSinkCallback *m_callback;
|
IMFSampleGrabberSinkCallback *m_callback;
|
||||||
|
|
||||||
#ifdef QT_OPENGL_ES_2_ANGLE
|
|
||||||
EVRCustomPresenterActivate *m_presenterActivate;
|
EVRCustomPresenterActivate *m_presenterActivate;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
INCLUDEPATH += $$PWD
|
INCLUDEPATH += $$PWD
|
||||||
|
|
||||||
LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lMf -lMfuuid -lMfplat -lPropsys
|
LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lgdi32 -luser32 -lole32 -loleaut32 -lMf -lMfuuid -lMfplat -lPropsys
|
||||||
|
|
||||||
DEFINES += QMEDIA_MEDIAFOUNDATION_PLAYER
|
DEFINES += QMEDIA_MEDIAFOUNDATION_PLAYER
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ SOURCES += \
|
|||||||
mfactivate.cpp \
|
mfactivate.cpp \
|
||||||
mfglobal.cpp
|
mfglobal.cpp
|
||||||
|
|
||||||
contains(QT_CONFIG, angle) {
|
contains(QT_CONFIG, angle)|contains(QT_CONFIG, dynamicgl) {
|
||||||
LIBS += -ld3d9 -ldxva2 -lwinmm -levr
|
LIBS += -ld3d9 -ldxva2 -lwinmm -levr
|
||||||
QT += gui-private
|
QT += gui-private
|
||||||
|
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ QSGVideoMaterial_YUV420::QSGVideoMaterial_YUV420(const QVideoSurfaceFormat &form
|
|||||||
QSGVideoMaterial_YUV420::~QSGVideoMaterial_YUV420()
|
QSGVideoMaterial_YUV420::~QSGVideoMaterial_YUV420()
|
||||||
{
|
{
|
||||||
if (!m_textureSize.isEmpty())
|
if (!m_textureSize.isEmpty())
|
||||||
glDeleteTextures(Num_Texture_IDs, m_textureIds);
|
QOpenGLContext::currentContext()->functions()->glDeleteTextures(Num_Texture_IDs, m_textureIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSGVideoMaterial_YUV420::bind()
|
void QSGVideoMaterial_YUV420::bind()
|
||||||
@@ -252,8 +252,8 @@ void QSGVideoMaterial_YUV420::bind()
|
|||||||
// Frame has changed size, recreate textures...
|
// Frame has changed size, recreate textures...
|
||||||
if (m_textureSize != m_frame.size()) {
|
if (m_textureSize != m_frame.size()) {
|
||||||
if (!m_textureSize.isEmpty())
|
if (!m_textureSize.isEmpty())
|
||||||
glDeleteTextures(Num_Texture_IDs, m_textureIds);
|
functions->glDeleteTextures(Num_Texture_IDs, m_textureIds);
|
||||||
glGenTextures(Num_Texture_IDs, m_textureIds);
|
functions->glGenTextures(Num_Texture_IDs, m_textureIds);
|
||||||
m_textureSize = m_frame.size();
|
m_textureSize = m_frame.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,8 +265,8 @@ void QSGVideoMaterial_YUV420::bind()
|
|||||||
m_uvWidth = qreal(fw) / (2 * m_frame.bytesPerLine(u));
|
m_uvWidth = qreal(fw) / (2 * m_frame.bytesPerLine(u));
|
||||||
|
|
||||||
GLint previousAlignment;
|
GLint previousAlignment;
|
||||||
glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
|
functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
functions->glActiveTexture(GL_TEXTURE1);
|
functions->glActiveTexture(GL_TEXTURE1);
|
||||||
bindTexture(m_textureIds[1], m_frame.bytesPerLine(u), fh / 2, m_frame.bits(u));
|
bindTexture(m_textureIds[1], m_frame.bytesPerLine(u), fh / 2, m_frame.bits(u));
|
||||||
@@ -275,7 +275,7 @@ void QSGVideoMaterial_YUV420::bind()
|
|||||||
functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
|
functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
|
||||||
bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y));
|
bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y));
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, previousAlignment);
|
functions->glPixelStorei(GL_UNPACK_ALIGNMENT, previousAlignment);
|
||||||
|
|
||||||
m_frame.unmap();
|
m_frame.unmap();
|
||||||
}
|
}
|
||||||
@@ -283,22 +283,24 @@ void QSGVideoMaterial_YUV420::bind()
|
|||||||
m_frame = QVideoFrame();
|
m_frame = QVideoFrame();
|
||||||
} else {
|
} else {
|
||||||
functions->glActiveTexture(GL_TEXTURE1);
|
functions->glActiveTexture(GL_TEXTURE1);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
|
functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
|
||||||
functions->glActiveTexture(GL_TEXTURE2);
|
functions->glActiveTexture(GL_TEXTURE2);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
|
functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
|
||||||
functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
|
functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
|
||||||
glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
|
functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSGVideoMaterial_YUV420::bindTexture(int id, int w, int h, const uchar *bits)
|
void QSGVideoMaterial_YUV420::bindTexture(int id, int w, int h, const uchar *bits)
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bits);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
functions->glBindTexture(GL_TEXTURE_2D, id);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bits);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGVideoNode_I420::QSGVideoNode_I420(const QVideoSurfaceFormat &format) :
|
QSGVideoNode_I420::QSGVideoNode_I420(const QVideoSurfaceFormat &format) :
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ public:
|
|||||||
~QSGVideoMaterial_RGB()
|
~QSGVideoMaterial_RGB()
|
||||||
{
|
{
|
||||||
if (m_textureId)
|
if (m_textureId)
|
||||||
glDeleteTextures(1, &m_textureId);
|
QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_textureId);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual QSGMaterialType *type() const {
|
virtual QSGMaterialType *type() const {
|
||||||
@@ -225,8 +225,8 @@ public:
|
|||||||
|
|
||||||
if (m_textureSize != textureSize) {
|
if (m_textureSize != textureSize) {
|
||||||
if (!m_textureSize.isEmpty())
|
if (!m_textureSize.isEmpty())
|
||||||
glDeleteTextures(1, &m_textureId);
|
functions->glDeleteTextures(1, &m_textureId);
|
||||||
glGenTextures(1, &m_textureId);
|
functions->glGenTextures(1, &m_textureId);
|
||||||
m_textureSize = textureSize;
|
m_textureSize = textureSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,28 +239,28 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLint previousAlignment;
|
GLint previousAlignment;
|
||||||
glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
|
functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
functions->glActiveTexture(GL_TEXTURE0);
|
functions->glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_textureId);
|
functions->glBindTexture(GL_TEXTURE_2D, m_textureId);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, dataFormat,
|
functions->glTexImage2D(GL_TEXTURE_2D, 0, dataFormat,
|
||||||
m_textureSize.width(), m_textureSize.height(),
|
m_textureSize.width(), m_textureSize.height(),
|
||||||
0, dataFormat, dataType, m_frame.bits());
|
0, dataFormat, dataType, m_frame.bits());
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, previousAlignment);
|
functions->glPixelStorei(GL_UNPACK_ALIGNMENT, previousAlignment);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
m_frame.unmap();
|
m_frame.unmap();
|
||||||
}
|
}
|
||||||
m_frame = QVideoFrame();
|
m_frame = QVideoFrame();
|
||||||
} else {
|
} else {
|
||||||
functions->glActiveTexture(GL_TEXTURE0);
|
functions->glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_textureId);
|
functions->glBindTexture(GL_TEXTURE_2D, m_textureId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
#include <QtGui/QOpenGLContext>
|
#include <QtGui/QOpenGLContext>
|
||||||
#include <QtGui/QOpenGLFunctions>
|
#include <QtGui/QOpenGLFunctions>
|
||||||
#include <QtGui/QOpenGLShaderProgram>
|
#include <QtGui/QOpenGLShaderProgram>
|
||||||
|
#include <QtMultimedia/private/qmediaopenglhelper_p.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@@ -120,7 +121,6 @@ protected:
|
|||||||
" gl_FragColor = texture2D(rgbTexture, qt_TexCoord) * opacity;"
|
" gl_FragColor = texture2D(rgbTexture, qt_TexCoord) * opacity;"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
#ifndef QT_OPENGL_ES_2_ANGLE
|
|
||||||
static const char *colorsSwapShader =
|
static const char *colorsSwapShader =
|
||||||
"uniform sampler2D rgbTexture;"
|
"uniform sampler2D rgbTexture;"
|
||||||
"uniform lowp float opacity;"
|
"uniform lowp float opacity;"
|
||||||
@@ -132,17 +132,17 @@ protected:
|
|||||||
" gl_FragColor = vec4(texture2D(rgbTexture, qt_TexCoord).bgr, 1.0) * opacity;"
|
" gl_FragColor = vec4(texture2D(rgbTexture, qt_TexCoord).bgr, 1.0) * opacity;"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
|
if (!QMediaOpenGLHelper::isANGLE()) {
|
||||||
switch (m_pixelFormat) {
|
switch (m_pixelFormat) {
|
||||||
case QVideoFrame::Format_RGB32:
|
case QVideoFrame::Format_RGB32:
|
||||||
case QVideoFrame::Format_ARGB32:
|
case QVideoFrame::Format_ARGB32:
|
||||||
return colorsSwapShader;
|
return colorsSwapShader;
|
||||||
default:
|
default:
|
||||||
return shader;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
return shader;
|
return shader;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void initialize() {
|
virtual void initialize() {
|
||||||
@@ -210,12 +210,13 @@ public:
|
|||||||
QMutexLocker lock(&m_frameMutex);
|
QMutexLocker lock(&m_frameMutex);
|
||||||
if (m_frame.isValid()) {
|
if (m_frame.isValid()) {
|
||||||
m_textureId = m_frame.handle().toUInt();
|
m_textureId = m_frame.handle().toUInt();
|
||||||
glBindTexture(GL_TEXTURE_2D, m_textureId);
|
QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
|
||||||
|
functions->glBindTexture(GL_TEXTURE_2D, m_textureId);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
} else {
|
} else {
|
||||||
m_textureId = 0;
|
m_textureId = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
|
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
|
||||||
#include <QtOpenGL/qgl.h>
|
#include <QtOpenGL/qgl.h>
|
||||||
#include <QtOpenGL/qglframebufferobject.h>
|
#include <QtOpenGL/qglframebufferobject.h>
|
||||||
|
#include <QtGui/qopenglfunctions.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QT_USE_NAMESPACE
|
QT_USE_NAMESPACE
|
||||||
@@ -100,12 +101,12 @@ public:
|
|||||||
: QAbstractVideoBuffer(GLTextureHandle)
|
: QAbstractVideoBuffer(GLTextureHandle)
|
||||||
, m_textureId(0)
|
, m_textureId(0)
|
||||||
{
|
{
|
||||||
glGenTextures(1, &m_textureId);
|
QOpenGLContext::currentContext()->functions()->glGenTextures(1, &m_textureId);
|
||||||
}
|
}
|
||||||
|
|
||||||
~QtTestGLVideoBuffer()
|
~QtTestGLVideoBuffer()
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &m_textureId);
|
QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_textureId);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint textureId() const { return m_textureId; }
|
GLuint textureId() const { return m_textureId; }
|
||||||
@@ -1226,12 +1227,13 @@ void tst_QPainterVideoSurface::shaderPresentGLFrame()
|
|||||||
|
|
||||||
QtTestGLVideoBuffer *buffer = new QtTestGLVideoBuffer;
|
QtTestGLVideoBuffer *buffer = new QtTestGLVideoBuffer;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, buffer->textureId());
|
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb32ImageData);
|
f->glBindTexture(GL_TEXTURE_2D, buffer->textureId());
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb32ImageData);
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
QVideoFrame frame(buffer, QSize(2, 2), QVideoFrame::Format_RGB32);
|
QVideoFrame frame(buffer, QSize(2, 2), QVideoFrame::Format_RGB32);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user