From 66ba21971b24942c7481eeb4a4ff156f54ea658a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 5 Feb 2014 15:54:36 +0100 Subject: Support dynamic opengl32 - ANGLE switching on Windows Change-Id: I38532db3ab0ad4fcb8dbabd0cbb528f7d8e4ba06 Reviewed-by: Andrew Knight Reviewed-by: Friedemann Kleint --- src/multimedia/multimedia.pro | 3 +- src/multimedia/qmediaopenglhelper_p.h | 117 +++++++++++++++++++++ src/multimediawidgets/qpaintervideosurface.cpp | 66 ++++++------ src/plugins/wmf/evrd3dpresentengine.cpp | 85 +++++++++++++-- src/plugins/wmf/evrd3dpresentengine.h | 26 +++++ src/plugins/wmf/player/mfvideorenderercontrol.cpp | 32 +++--- src/plugins/wmf/player/mfvideorenderercontrol.h | 4 - src/plugins/wmf/player/player.pri | 2 +- src/plugins/wmf/wmf.pro | 2 +- src/qtmultimediaquicktools/qsgvideonode_i420.cpp | 32 +++--- src/qtmultimediaquicktools/qsgvideonode_rgb.cpp | 30 +++--- .../qsgvideonode_texture.cpp | 23 ++-- 12 files changed, 320 insertions(+), 102 deletions(-) create mode 100644 src/multimedia/qmediaopenglhelper_p.h (limited to 'src') 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 + +#if defined(Q_OS_WIN) && (defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)) +#include +#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 #include +#include #include #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif +#ifndef GL_RGB8 +#define GL_RGB8 0x8051 +#endif #endif #include @@ -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 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(glGetString(GL_EXTENSIONS))); -#ifndef QT_OPENGL_ES - + const QByteArray extensions(reinterpret_cast( + 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 #include #include +#include #include #include @@ -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( nativeInterface->nativeResourceForContext("eglDisplay", currentContext)); m_eglConfig = static_cast( 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(eglGetProcAddress("eglQuerySurfacePointerANGLE")); + reinterpret_cast(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 #include #include @@ -53,6 +59,7 @@ #include #include "guiddef.h" #include +#include //#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(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 #include #include +#include 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; } -- cgit v1.2.3