From 06eac9ba70ace125ea2835ef9aec854f231405b2 Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Tue, 24 Oct 2017 14:45:29 +0200 Subject: Windows: Fix EVR's rendering of GLTextureHandle frames When ANGLE is used and video frames have GLTextureHandle handle type black screen is shown while audio is working correctly. Fixed a bug when opengl texture has not been ever creating. Fixed a crash when releasing resources due to empty QOpenGLContext. Also moved gl initialization related code to OpenGLResources. Task-number: QTBUG-61407 Change-Id: Ifc92a4a2fa2e769494ef962203446a9b3e7dd86d Reviewed-by: Christian Stromme --- src/plugins/common/evr/evrd3dpresentengine.cpp | 159 +++++++++++++------------ 1 file changed, 86 insertions(+), 73 deletions(-) (limited to 'src/plugins/common/evr/evrd3dpresentengine.cpp') diff --git a/src/plugins/common/evr/evrd3dpresentengine.cpp b/src/plugins/common/evr/evrd3dpresentengine.cpp index 043d0ad73..754faef2d 100644 --- a/src/plugins/common/evr/evrd3dpresentengine.cpp +++ b/src/plugins/common/evr/evrd3dpresentengine.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #ifdef MAYBE_ANGLE # include @@ -128,11 +129,65 @@ class OpenGLResources : public QObject { public: OpenGLResources() - : egl(new EGLWrapper) - , eglDisplay(0) - , eglSurface(0) - , glTexture(0) - {} + : m_egl(new EGLWrapper) + , m_eglDisplay(nullptr) + , m_eglSurface(nullptr) + , m_glTexture(0) + , m_glContext(QOpenGLContext::currentContext()) + { + Q_ASSERT(m_glContext); + } + + unsigned int glTexture() const + { + return m_glTexture; + } + + bool createTexture(const QVideoSurfaceFormat &format, IDirect3DDevice9Ex *device, + IDirect3DTexture9 **texture) + { + if (!m_glContext) + return false; + + m_glContext->functions()->glGenTextures(1, &m_glTexture); + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + m_eglDisplay = static_cast( + nativeInterface->nativeResourceForContext("eglDisplay", m_glContext)); + EGLConfig *eglConfig = static_cast( + nativeInterface->nativeResourceForContext("eglConfig", m_glContext)); + + const bool hasAlpha = m_glContext->format().hasAlpha(); + + EGLint attribs[] = { + EGL_WIDTH, format.frameWidth(), + EGL_HEIGHT, format.frameHeight(), + EGL_TEXTURE_FORMAT, (hasAlpha ? EGL_TEXTURE_RGBA : EGL_TEXTURE_RGB), + EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, + EGL_NONE + }; + + m_eglSurface = m_egl->createPbufferSurface(m_eglDisplay, eglConfig, attribs); + + HANDLE share_handle = 0; + PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE = + reinterpret_cast( + m_egl->getProcAddress("eglQuerySurfacePointerANGLE")); + Q_ASSERT(eglQuerySurfacePointerANGLE); + eglQuerySurfacePointerANGLE( + m_eglDisplay, + m_eglSurface, + EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &share_handle); + + device->CreateTexture(format.frameWidth(), format.frameHeight(), 1, + D3DUSAGE_RENDERTARGET, + (hasAlpha ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8), + D3DPOOL_DEFAULT, texture, &share_handle); + + m_glContext->functions()->glBindTexture(GL_TEXTURE_2D, m_glTexture); + m_egl->bindTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER); + + return texture != NULL; + } void release() { @@ -142,24 +197,32 @@ public: deleteLater(); } - EGLWrapper *egl; - EGLDisplay *eglDisplay; - EGLSurface eglSurface; - unsigned int glTexture; - private: + EGLWrapper *m_egl; + EGLDisplay *m_eglDisplay; + EGLSurface m_eglSurface; + unsigned int m_glTexture; + QOpenGLContext *m_glContext; + ~OpenGLResources() { - Q_ASSERT(QOpenGLContext::currentContext() != NULL); + QScopedPointer surface; + if (m_glContext != QOpenGLContext::currentContext()) { + surface.reset(new QOffscreenSurface); + surface->create(); + m_glContext->makeCurrent(surface.data()); + } - if (eglSurface && egl) { - egl->releaseTexImage(eglDisplay, eglSurface, EGL_BACK_BUFFER); - egl->destroySurface(eglDisplay, eglSurface); + if (m_eglSurface && m_egl) { + m_egl->releaseTexImage(m_eglDisplay, m_eglSurface, EGL_BACK_BUFFER); + m_egl->destroySurface(m_eglDisplay, m_eglSurface); } - if (glTexture) - QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &glTexture); + if (m_glTexture) + m_glContext->functions()->glDeleteTextures(1, &m_glTexture); - delete egl; + delete m_egl; + if (surface) + m_glContext->doneCurrent(); } }; @@ -257,9 +320,9 @@ QVariant IMFSampleVideoBuffer::handle() const if (handleType() != GLTextureHandle) return handle; - if (m_engine->m_glResources && (m_textureUpdated || m_engine->updateTexture(m_surface))) { + if (m_textureUpdated || m_engine->updateTexture(m_surface)) { m_textureUpdated = true; - handle = QVariant::fromValue(m_engine->m_glResources->glTexture); + handle = QVariant::fromValue(m_engine->m_glResources->glTexture()); } #endif @@ -553,61 +616,11 @@ QVideoFrame D3DPresentEngine::makeVideoFrame(IMFSample *sample) bool D3DPresentEngine::createRenderTexture() { - if (m_texture) - return true; - - Q_ASSERT(QOpenGLContext::currentContext() != NULL); - - if (!m_glResources) - m_glResources = new OpenGLResources; - - QOpenGLContext *currentContext = QOpenGLContext::currentContext(); - if (!currentContext) - return false; - - QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - m_glResources->eglDisplay = static_cast( - nativeInterface->nativeResourceForContext("eglDisplay", currentContext)); - EGLConfig *eglConfig = static_cast( - nativeInterface->nativeResourceForContext("eglConfig", currentContext)); - - currentContext->functions()->glGenTextures(1, &m_glResources->glTexture); - - bool hasAlpha = currentContext->format().hasAlpha(); - - EGLint attribs[] = { - EGL_WIDTH, m_surfaceFormat.frameWidth(), - EGL_HEIGHT, m_surfaceFormat.frameHeight(), - EGL_TEXTURE_FORMAT, hasAlpha ? EGL_TEXTURE_RGBA : EGL_TEXTURE_RGB, - EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, - EGL_NONE - }; - - EGLSurface pbuffer = m_glResources->egl->createPbufferSurface(m_glResources->eglDisplay, eglConfig, attribs); - - HANDLE share_handle = 0; - PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE = - reinterpret_cast(m_glResources->egl->getProcAddress("eglQuerySurfacePointerANGLE")); - Q_ASSERT(eglQuerySurfacePointerANGLE); - eglQuerySurfacePointerANGLE( - m_glResources->eglDisplay, - pbuffer, - EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &share_handle); - - - m_device->CreateTexture(m_surfaceFormat.frameWidth(), m_surfaceFormat.frameHeight(), 1, - D3DUSAGE_RENDERTARGET, - hasAlpha ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8, - D3DPOOL_DEFAULT, - &m_texture, - &share_handle); - - m_glResources->eglSurface = pbuffer; - - QOpenGLContext::currentContext()->functions()->glBindTexture(GL_TEXTURE_2D, m_glResources->glTexture); - m_glResources->egl->bindTexImage(m_glResources->eglDisplay, m_glResources->eglSurface, EGL_BACK_BUFFER); + if (m_glResources) + m_glResources->release(); - return m_texture != NULL; + m_glResources = new OpenGLResources; + return m_glResources->createTexture(m_surfaceFormat, m_device, &m_texture); } bool D3DPresentEngine::updateTexture(IDirect3DSurface9 *src) -- cgit v1.2.3