summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/multimedia/multimedia.pro3
-rw-r--r--src/multimedia/qmediaopenglhelper_p.h117
-rw-r--r--src/multimediawidgets/qpaintervideosurface.cpp66
-rw-r--r--src/plugins/wmf/evrd3dpresentengine.cpp85
-rw-r--r--src/plugins/wmf/evrd3dpresentengine.h26
-rw-r--r--src/plugins/wmf/player/mfvideorenderercontrol.cpp32
-rw-r--r--src/plugins/wmf/player/mfvideorenderercontrol.h4
-rw-r--r--src/plugins/wmf/player/player.pri2
-rw-r--r--src/plugins/wmf/wmf.pro2
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_i420.cpp32
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_rgb.cpp30
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_texture.cpp23
-rw-r--r--tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp18
13 files changed, 330 insertions, 110 deletions
diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro
index 0f3ced913..b3bdaa874 100644
--- a/src/multimedia/multimedia.pro
+++ b/src/multimedia/multimedia.pro
@@ -22,7 +22,8 @@ PRIVATE_HEADERS += \
qmediaresourcepolicyplugin_p.h \
qmediaresourcepolicy_p.h \
qmediaresourceset_p.h \
- qmediastoragelocation_p.h
+ qmediastoragelocation_p.h \
+ qmediaopenglhelper_p.h
PUBLIC_HEADERS += \
qmediabindableinterface.h \
diff --git a/src/multimedia/qmediaopenglhelper_p.h b/src/multimedia/qmediaopenglhelper_p.h
new file mode 100644
index 000000000..298d13539
--- /dev/null
+++ b/src/multimedia/qmediaopenglhelper_p.h
@@ -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
diff --git a/src/multimediawidgets/qpaintervideosurface.cpp b/src/multimediawidgets/qpaintervideosurface.cpp
index e1dccb2bd..90e3d6063 100644
--- a/src/multimediawidgets/qpaintervideosurface.cpp
+++ b/src/multimediawidgets/qpaintervideosurface.cpp
@@ -50,10 +50,14 @@
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
#include <qglshaderprogram.h>
#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFunctions>
#include <QtGui/QWindow>
#ifndef GL_CLAMP_TO_EDGE
#define GL_CLAMP_TO_EDGE 0x812F
#endif
+#ifndef GL_RGB8
+#define GL_RGB8 0x8051
+#endif
#endif
#include <QtDebug>
@@ -97,11 +101,11 @@ QVideoSurfaceGenericPainter::QVideoSurfaceGenericPainter()
{
m_imagePixelFormats
<< 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_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(
@@ -140,13 +144,11 @@ QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::start(const QVideoSurf
const QAbstractVideoBuffer::HandleType t = format.handleType();
if (t == QAbstractVideoBuffer::NoHandle) {
- if (m_imageFormat != QImage::Format_Invalid
-#ifdef QT_OPENGL_ES
- && format.pixelFormat() != QVideoFrame::Format_RGB24
-#endif
- && !m_imageSize.isEmpty()) {
+ bool ok = m_imageFormat != QImage::Format_Invalid && !m_imageSize.isEmpty();
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES)
+ ok &= format.pixelFormat() != QVideoFrame::Format_RGB24;
+ if (ok)
return QAbstractVideoSurface::NoError;
- }
} else if (t == QAbstractVideoBuffer::QPixmapHandle) {
return QAbstractVideoSurface::NoError;
}
@@ -237,7 +239,7 @@ void QVideoSurfaceGenericPainter::updateColors(int, int, int, int)
# define GL_UNSIGNED_SHORT_5_6_5 33635
#endif
-class QVideoSurfaceGLPainter : public QVideoSurfacePainter
+class QVideoSurfaceGLPainter : public QVideoSurfacePainter, protected QOpenGLFunctions
{
public:
QVideoSurfaceGLPainter(QGLContext *context);
@@ -262,7 +264,7 @@ protected:
void initYuv420PTextureInfo(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);
_glActiveTexture glActiveTexture;
#endif
@@ -300,7 +302,7 @@ QVideoSurfaceGLPainter::QVideoSurfaceGLPainter(QGLContext *context)
, m_textureCount(0)
, m_yuv(false)
{
-#ifndef QT_OPENGL_ES
+#if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC)
glActiveTexture = (_glActiveTexture)m_context->getProcAddress(QLatin1String("glActiveTexture"));
#endif
@@ -309,6 +311,7 @@ QVideoSurfaceGLPainter::QVideoSurfaceGLPainter(QGLContext *context)
memset(m_textureHeights, 0, sizeof(m_textureHeights));
memset(m_textureOffsets, 0, sizeof(m_textureOffsets));
+ initializeOpenGLFunctions();
}
QVideoSurfaceGLPainter::~QVideoSurfaceGLPainter()
@@ -554,7 +557,7 @@ void QVideoSurfaceGLPainter::initYv12TextureInfo(const QSize &size)
m_textureOffsets[2] = bytesPerLine * size.height();
}
-#ifndef QT_OPENGL_ES
+#if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC)
# ifndef GL_FRAGMENT_PROGRAM_ARB
# define GL_FRAGMENT_PROGRAM_ARB 0x8804
@@ -945,7 +948,7 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint(
return QVideoSurfaceGLPainter::paint(target, painter, source);
}
-#endif
+#endif // !QT_OPENGL_ES && !QT_OPENGL_DYNAMIC
static const char *qt_glsl_vertexShaderProgram =
"attribute highp vec4 vertexCoordArray;\n"
@@ -1057,10 +1060,6 @@ QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context)
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_BGR32
<< QVideoFrame::Format_ARGB32
-#ifndef QT_OPENGL_ES
- << QVideoFrame::Format_RGB24
- << QVideoFrame::Format_BGR24
-#endif
<< QVideoFrame::Format_RGB565
<< QVideoFrame::Format_YUV444
<< QVideoFrame::Format_AYUV444
@@ -1069,6 +1068,11 @@ QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context)
m_glPixelFormats
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_ARGB32;
+ if (!context->contextHandle()->isOpenGLES()) {
+ m_imagePixelFormats
+ << QVideoFrame::Format_RGB24
+ << QVideoFrame::Format_BGR24;
+ }
}
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());
fragmentProgram = qt_glsl_argbShaderProgram;
break;
-#ifndef QT_OPENGL_ES
case QVideoFrame::Format_RGB24:
- initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
- fragmentProgram = qt_glsl_rgbShaderProgram;
+ if (!m_context->contextHandle()->isOpenGLES()) {
+ initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_rgbShaderProgram;
+ }
break;
case QVideoFrame::Format_BGR24:
- initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
- fragmentProgram = qt_glsl_argbShaderProgram;
+ if (!m_context->contextHandle()->isOpenGLES()) {
+ initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_argbShaderProgram;
+ }
break;
-#endif
case QVideoFrame::Format_RGB565:
initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
fragmentProgram = qt_glsl_rgbShaderProgram;
@@ -1577,14 +1583,14 @@ void QPainterVideoSurface::setGLContext(QGLContext *context)
m_glContext->makeCurrent();
- const QByteArray extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
-#ifndef QT_OPENGL_ES
-
+ const QByteArray extensions(reinterpret_cast<const char *>(
+ context->contextHandle()->functions()->glGetString(GL_EXTENSIONS)));
+#if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC)
if (extensions.contains("ARB_fragment_program"))
m_shaderTypes |= FragmentProgramShader;
#endif
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")
#endif
)
@@ -1683,13 +1689,13 @@ void QPainterVideoSurface::createPainter()
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
switch (m_shaderType) {
-#ifndef QT_OPENGL_ES
+#if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC)
case FragmentProgramShader:
Q_ASSERT(m_glContext);
m_glContext->makeCurrent();
m_painter = new QVideoSurfaceArbFpPainter(m_glContext);
break;
-#endif
+#endif // !QT_OPENGL_ES && !QT_OPENGL_DYNAMIC
case GlslShader:
Q_ASSERT(m_glContext);
m_glContext->makeCurrent();
diff --git a/src/plugins/wmf/evrd3dpresentengine.cpp b/src/plugins/wmf/evrd3dpresentengine.cpp
index 01a5c3341..8af76403e 100644
--- a/src/plugins/wmf/evrd3dpresentengine.cpp
+++ b/src/plugins/wmf/evrd3dpresentengine.cpp
@@ -51,6 +51,7 @@
#include <qvideoframe.h>
#include <QDebug>
#include <qopenglcontext.h>
+#include <qopenglfunctions.h>
#include <qwindow.h>
#include <EGL/egl.h>
@@ -88,6 +89,67 @@ private:
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()
: QObject()
@@ -104,6 +166,7 @@ D3DPresentEngine::D3DPresentEngine()
, m_eglSurface(0)
, m_glTexture(0)
, m_texture(0)
+ , m_egl(0)
{
ZeroMemory(&m_displayMode, sizeof(m_displayMode));
@@ -126,15 +189,16 @@ D3DPresentEngine::~D3DPresentEngine()
qt_wmf_safeRelease(&m_D3D9);
if (m_eglSurface) {
- eglReleaseTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER);
- eglDestroySurface(m_eglDisplay, m_eglSurface);
+ m_egl->releaseTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER);
+ m_egl->destroySurface(m_eglDisplay, m_eglSurface);
m_eglSurface = NULL;
}
if (m_glTexture)
- glDeleteTextures(1, &m_glTexture);
+ QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_glTexture);
delete m_glContext;
delete m_offscreenSurface;
+ delete m_egl;
}
void D3DPresentEngine::start()
@@ -358,14 +422,16 @@ void D3DPresentEngine::createOffscreenTexture()
if (m_glContext)
m_glContext->makeCurrent(m_offscreenSurface);
+ if (!m_egl)
+ m_egl = new EGLWrapper;
+
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
m_eglDisplay = static_cast<EGLDisplay*>(
nativeInterface->nativeResourceForContext("eglDisplay", currentContext));
m_eglConfig = static_cast<EGLDisplay*>(
nativeInterface->nativeResourceForContext("eglConfig", currentContext));
- glGenTextures(1, &m_glTexture);
-
+ currentContext->functions()->glGenTextures(1, &m_glTexture);
int w = m_surfaceFormat.frameWidth();
int h = m_surfaceFormat.frameHeight();
@@ -378,11 +444,12 @@ void D3DPresentEngine::createOffscreenTexture()
EGL_NONE
};
- EGLSurface pbuffer = eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, attribs);
+ EGLSurface pbuffer = m_egl->createPbufferSurface(m_eglDisplay, m_eglConfig, attribs);
HANDLE share_handle = 0;
PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE =
- reinterpret_cast<PFNEGLQUERYSURFACEPOINTERANGLEPROC>(eglGetProcAddress("eglQuerySurfacePointerANGLE"));
+ reinterpret_cast<PFNEGLQUERYSURFACEPOINTERANGLEPROC>(m_egl->getProcAddress("eglQuerySurfacePointerANGLE"));
+ Q_ASSERT(eglQuerySurfacePointerANGLE);
eglQuerySurfacePointerANGLE(
m_eglDisplay,
pbuffer,
@@ -410,7 +477,7 @@ bool D3DPresentEngine::updateTexture(IDirect3DSurface9 *src)
if (m_glContext)
m_glContext->makeCurrent(m_offscreenSurface);
- glBindTexture(GL_TEXTURE_2D, m_glTexture);
+ QOpenGLContext::currentContext()->functions()->glBindTexture(GL_TEXTURE_2D, m_glTexture);
IDirect3DSurface9 *dest = NULL;
@@ -424,7 +491,7 @@ bool D3DPresentEngine::updateTexture(IDirect3DSurface9 *src)
qWarning("Failed to copy D3D surface");
if (hr == S_OK)
- eglBindTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER);
+ m_egl->bindTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER);
done:
qt_wmf_safeRelease(&dest);
diff --git a/src/plugins/wmf/evrd3dpresentengine.h b/src/plugins/wmf/evrd3dpresentengine.h
index 87b3e9606..42b65f291 100644
--- a/src/plugins/wmf/evrd3dpresentengine.h
+++ b/src/plugins/wmf/evrd3dpresentengine.h
@@ -70,6 +70,31 @@ QT_BEGIN_NAMESPACE
class QAbstractVideoSurface;
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
{
Q_OBJECT
@@ -123,6 +148,7 @@ private:
EGLSurface m_eglSurface;
unsigned int m_glTexture;
IDirect3DTexture9 *m_texture;
+ EGLWrapper *m_egl;
};
QT_END_NAMESPACE
diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.cpp b/src/plugins/wmf/player/mfvideorenderercontrol.cpp
index 420473666..d4e4930ca 100644
--- a/src/plugins/wmf/player/mfvideorenderercontrol.cpp
+++ b/src/plugins/wmf/player/mfvideorenderercontrol.cpp
@@ -41,9 +41,15 @@
#include "mfvideorenderercontrol.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"
#endif
+
#include <qabstractvideosurface.h>
#include <qvideosurfaceformat.h>
#include <qtcore/qtimer.h>
@@ -53,6 +59,7 @@
#include <qtcore/qthread.h>
#include "guiddef.h"
#include <qtcore/qdebug.h>
+#include <QtMultimedia/private/qmediaopenglhelper_p.h>
//#define DEBUG_MEDIAFOUNDATION
#define PAD_TO_DWORD(x) (((x) + 3) & ~3)
@@ -2228,9 +2235,7 @@ MFVideoRendererControl::MFVideoRendererControl(QObject *parent)
, m_surface(0)
, m_currentActivate(0)
, m_callback(0)
-#ifdef QT_OPENGL_ES_2_ANGLE
, m_presenterActivate(0)
-#endif
{
}
@@ -2244,7 +2249,7 @@ void MFVideoRendererControl::clear()
if (m_surface)
m_surface->stop();
-#ifdef QT_OPENGL_ES_2_ANGLE
+#ifdef MAYBE_ANGLE
if (m_presenterActivate) {
m_presenterActivate->ShutdownObject();
m_presenterActivate->Release();
@@ -2279,7 +2284,7 @@ void MFVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged()));
}
-#ifdef QT_OPENGL_ES_2_ANGLE
+#ifdef MAYBE_ANGLE
if (m_presenterActivate)
m_presenterActivate->setSurface(m_surface);
else
@@ -2290,10 +2295,8 @@ void MFVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
void MFVideoRendererControl::customEvent(QEvent *event)
{
-#ifdef QT_OPENGL_ES_2_ANGLE
if (m_presenterActivate)
return;
-#endif
if (!m_currentActivate)
return;
@@ -2324,7 +2327,7 @@ void MFVideoRendererControl::customEvent(QEvent *event)
void MFVideoRendererControl::supportedFormatsChanged()
{
-#ifdef QT_OPENGL_ES_2_ANGLE
+#ifdef MAYBE_ANGLE
if (m_presenterActivate)
m_presenterActivate->supportedFormatsChanged();
else
@@ -2335,10 +2338,8 @@ void MFVideoRendererControl::supportedFormatsChanged()
void MFVideoRendererControl::present()
{
-#ifdef QT_OPENGL_ES_2_ANGLE
if (m_presenterActivate)
return;
-#endif
if (m_currentActivate)
static_cast<VideoRendererActivate*>(m_currentActivate)->present();
@@ -2350,20 +2351,21 @@ IMFActivate* MFVideoRendererControl::createActivate()
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
- // texture handles
- if (!m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty()) {
+ // texture handles. We also require ANGLE (due to the D3D interop).
+ if (!m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty()
+ && QMediaOpenGLHelper::isANGLE()) {
// Create the EVR media sink, but replace the presenter with our own
if (SUCCEEDED(MFCreateVideoRendererActivate(::GetShellWindow(), &m_currentActivate))) {
m_presenterActivate = new EVRCustomPresenterActivate;
m_currentActivate->SetUnknown(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, m_presenterActivate);
}
}
+#endif
if (!m_currentActivate)
-#endif
- m_currentActivate = new VideoRendererActivate(this);
+ m_currentActivate = new VideoRendererActivate(this);
setSurface(m_surface);
diff --git a/src/plugins/wmf/player/mfvideorenderercontrol.h b/src/plugins/wmf/player/mfvideorenderercontrol.h
index d796ce36d..1c05a656f 100644
--- a/src/plugins/wmf/player/mfvideorenderercontrol.h
+++ b/src/plugins/wmf/player/mfvideorenderercontrol.h
@@ -48,9 +48,7 @@
QT_BEGIN_NAMESPACE
-#ifdef QT_OPENGL_ES_2_ANGLE
class EVRCustomPresenterActivate;
-#endif
QT_END_NAMESPACE
@@ -83,9 +81,7 @@ private:
IMFActivate *m_currentActivate;
IMFSampleGrabberSinkCallback *m_callback;
-#ifdef QT_OPENGL_ES_2_ANGLE
EVRCustomPresenterActivate *m_presenterActivate;
-#endif
};
#endif
diff --git a/src/plugins/wmf/player/player.pri b/src/plugins/wmf/player/player.pri
index a72708b3f..dd5c9dc12 100644
--- a/src/plugins/wmf/player/player.pri
+++ b/src/plugins/wmf/player/player.pri
@@ -1,6 +1,6 @@
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
diff --git a/src/plugins/wmf/wmf.pro b/src/plugins/wmf/wmf.pro
index b1d157a9c..60fc3f641 100644
--- a/src/plugins/wmf/wmf.pro
+++ b/src/plugins/wmf/wmf.pro
@@ -32,7 +32,7 @@ SOURCES += \
mfactivate.cpp \
mfglobal.cpp
-contains(QT_CONFIG, angle) {
+contains(QT_CONFIG, angle)|contains(QT_CONFIG, dynamicgl) {
LIBS += -ld3d9 -ldxva2 -lwinmm -levr
QT += gui-private
diff --git a/src/qtmultimediaquicktools/qsgvideonode_i420.cpp b/src/qtmultimediaquicktools/qsgvideonode_i420.cpp
index 2d904f8eb..aac9f6d70 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_i420.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_i420.cpp
@@ -236,7 +236,7 @@ QSGVideoMaterial_YUV420::QSGVideoMaterial_YUV420(const QVideoSurfaceFormat &form
QSGVideoMaterial_YUV420::~QSGVideoMaterial_YUV420()
{
if (!m_textureSize.isEmpty())
- glDeleteTextures(Num_Texture_IDs, m_textureIds);
+ QOpenGLContext::currentContext()->functions()->glDeleteTextures(Num_Texture_IDs, m_textureIds);
}
void QSGVideoMaterial_YUV420::bind()
@@ -252,8 +252,8 @@ void QSGVideoMaterial_YUV420::bind()
// Frame has changed size, recreate textures...
if (m_textureSize != m_frame.size()) {
if (!m_textureSize.isEmpty())
- glDeleteTextures(Num_Texture_IDs, m_textureIds);
- glGenTextures(Num_Texture_IDs, m_textureIds);
+ functions->glDeleteTextures(Num_Texture_IDs, m_textureIds);
+ functions->glGenTextures(Num_Texture_IDs, m_textureIds);
m_textureSize = m_frame.size();
}
@@ -265,8 +265,8 @@ void QSGVideoMaterial_YUV420::bind()
m_uvWidth = qreal(fw) / (2 * m_frame.bytesPerLine(u));
GLint previousAlignment;
- glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
+ functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
functions->glActiveTexture(GL_TEXTURE1);
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
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();
}
@@ -283,22 +283,24 @@ void QSGVideoMaterial_YUV420::bind()
m_frame = QVideoFrame();
} else {
functions->glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
+ functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
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
- 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)
{
- glBindTexture(GL_TEXTURE_2D, id);
- 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);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
+
+ functions->glBindTexture(GL_TEXTURE_2D, id);
+ functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bits);
+ 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);
+ functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
QSGVideoNode_I420::QSGVideoNode_I420(const QVideoSurfaceFormat &format) :
diff --git a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
index ad01a08ae..5911cb19b 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp
@@ -176,7 +176,7 @@ public:
~QSGVideoMaterial_RGB()
{
if (m_textureId)
- glDeleteTextures(1, &m_textureId);
+ QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_textureId);
}
virtual QSGMaterialType *type() const {
@@ -225,8 +225,8 @@ public:
if (m_textureSize != textureSize) {
if (!m_textureSize.isEmpty())
- glDeleteTextures(1, &m_textureId);
- glGenTextures(1, &m_textureId);
+ functions->glDeleteTextures(1, &m_textureId);
+ functions->glGenTextures(1, &m_textureId);
m_textureSize = textureSize;
}
@@ -239,28 +239,28 @@ public:
}
GLint previousAlignment;
- glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
+ functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
functions->glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, m_textureId);
- glTexImage2D(GL_TEXTURE_2D, 0, dataFormat,
- m_textureSize.width(), m_textureSize.height(),
- 0, dataFormat, dataType, m_frame.bits());
+ functions->glBindTexture(GL_TEXTURE_2D, m_textureId);
+ functions->glTexImage2D(GL_TEXTURE_2D, 0, dataFormat,
+ m_textureSize.width(), m_textureSize.height(),
+ 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);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- 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_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);
+ functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_frame.unmap();
}
m_frame = QVideoFrame();
} else {
functions->glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, m_textureId);
+ functions->glBindTexture(GL_TEXTURE_2D, m_textureId);
}
}
diff --git a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
index 2320387b1..45d2736fb 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
@@ -45,6 +45,7 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
+#include <QtMultimedia/private/qmediaopenglhelper_p.h>
QT_BEGIN_NAMESPACE
@@ -120,7 +121,6 @@ protected:
" gl_FragColor = texture2D(rgbTexture, qt_TexCoord) * opacity;"
"}";
-#ifndef QT_OPENGL_ES_2_ANGLE
static const char *colorsSwapShader =
"uniform sampler2D rgbTexture;"
"uniform lowp float opacity;"
@@ -132,17 +132,17 @@ protected:
" gl_FragColor = vec4(texture2D(rgbTexture, qt_TexCoord).bgr, 1.0) * opacity;"
"}";
-
- switch (m_pixelFormat) {
+ if (!QMediaOpenGLHelper::isANGLE()) {
+ switch (m_pixelFormat) {
case QVideoFrame::Format_RGB32:
case QVideoFrame::Format_ARGB32:
return colorsSwapShader;
default:
- return shader;
+ break;
+ }
}
-#else
+
return shader;
-#endif
}
virtual void initialize() {
@@ -210,12 +210,13 @@ public:
QMutexLocker lock(&m_frameMutex);
if (m_frame.isValid()) {
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);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- 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_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);
+ functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else {
m_textureId = 0;
}
diff --git a/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp b/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp
index 183714567..1588ba245 100644
--- a/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp
+++ b/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp
@@ -50,6 +50,7 @@
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
#include <QtOpenGL/qgl.h>
#include <QtOpenGL/qglframebufferobject.h>
+#include <QtGui/qopenglfunctions.h>
#endif
QT_USE_NAMESPACE
@@ -100,12 +101,12 @@ public:
: QAbstractVideoBuffer(GLTextureHandle)
, m_textureId(0)
{
- glGenTextures(1, &m_textureId);
+ QOpenGLContext::currentContext()->functions()->glGenTextures(1, &m_textureId);
}
~QtTestGLVideoBuffer()
{
- glDeleteTextures(1, &m_textureId);
+ QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_textureId);
}
GLuint textureId() const { return m_textureId; }
@@ -1226,12 +1227,13 @@ void tst_QPainterVideoSurface::shaderPresentGLFrame()
QtTestGLVideoBuffer *buffer = new QtTestGLVideoBuffer;
- glBindTexture(GL_TEXTURE_2D, buffer->textureId());
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb32ImageData);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ f->glBindTexture(GL_TEXTURE_2D, buffer->textureId());
+ f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb32ImageData);
+ f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ f->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ 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);