diff --git a/src/capi/egl_api.cpp b/src/capi/egl_api.cpp index 74b9034c..e4a07060 100644 --- a/src/capi/egl_api.cpp +++ b/src/capi/egl_api.cpp @@ -50,7 +50,7 @@ public: explicit EGLLib(const QString& fileName, int verNum) : m_lib(fileName, verNum) {} void* resolve(const char *symbol) { // from qwindowseglcontext.cpp -#ifdef Q_CC_MINGW +#ifdef __MINGW32__ QString baseNameStr = QString::fromLatin1(symbol); QString nameStr; void *proc = 0; diff --git a/src/codec/video/SurfaceInteropDXVA.cpp b/src/codec/video/SurfaceInteropDXVA.cpp index 934716a8..793d9b78 100644 --- a/src/codec/video/SurfaceInteropDXVA.cpp +++ b/src/codec/video/SurfaceInteropDXVA.cpp @@ -18,20 +18,9 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ******************************************************************************/ -#include "QtAV/VideoFrame.h" -// no need to check qt4 because no ANGLE there -#if defined(QT_OPENGL_DYNAMIC) || defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES_2_ANGLE) -#define QTAV_HAVE_DXVA_EGL 1 -#endif -#if QTAV_HAVE(DXVA_EGL) -# if QTAV_HAVE(GUI_PRIVATE) -#include -#include -# endif //QTAV_HAVE(GUI_PRIVATE) -#endif -#include "utils/Logger.h" -#define WGL_WGLEXT_PROTOTYPES #include "SurfaceInteropDXVA.h" +#include "QtAV/VideoFrame.h" +#include "utils/Logger.h" namespace QtAV { extern VideoFormat::PixelFormat pixelFormatFromD3D(D3DFORMAT format); @@ -60,6 +49,28 @@ template void SafeRelease(T **ppT) } \ } while (0) +InteropResource::InteropResource(IDirect3DDevice9 *d3device) + : d3ddev(d3device) + , dx_texture(NULL) + , dx_surface(NULL) + , width(0) + , height(0) +{ + d3ddev->AddRef(); +} + +InteropResource::~InteropResource() +{ + releaseDX(); + SafeRelease(&d3ddev); +} + +void InteropResource::releaseDX() +{ + SafeRelease(&dx_surface); + SafeRelease(&dx_texture); +} + SurfaceInteropDXVA::~SurfaceInteropDXVA() { SafeRelease(&m_surface); @@ -154,6 +165,8 @@ void* SurfaceInteropDXVA::mapToHost(const VideoFormat &format, void *handle, int *f = frame; return f; } +} //namespace dxva +} //namespace QtAV #if QTAV_HAVE(DXVA_EGL) #define EGL_ENSURE(x, ...) \ @@ -165,32 +178,47 @@ void* SurfaceInteropDXVA::mapToHost(const VideoFormat &format, void *handle, int } \ } while(0) +#if QTAV_HAVE(GUI_PRIVATE) +#include +#include +#endif //QTAV_HAVE(GUI_PRIVATE) +#ifdef QT_OPENGL_ES_2_ANGLE_STATIC +#define CAPI_LINK_EGL +#else +#define EGL_CAPI_NS +#endif //QT_OPENGL_ES_2_ANGLE_STATIC +#include "capi/egl_api.h" +#include //include after egl_capi.h to match types + +namespace QtAV { +namespace dxva { +class EGL { +public: + EGL() : dpy(EGL_NO_DISPLAY), surface(EGL_NO_SURFACE) {} + EGLDisplay dpy; + EGLSurface surface; +}; + EGLInteropResource::EGLInteropResource(IDirect3DDevice9 * d3device) - : InteropResource() - , d3ddev(d3device) - , dx_texture(NULL) - , dx_surface(NULL) - , egl_dpy(EGL_NO_DISPLAY) - , egl_surface(EGL_NO_SURFACE) - , width(0) - , height(0) + : InteropResource(d3device) + , egl(new EGL()) { - d3ddev->AddRef(); } EGLInteropResource::~EGLInteropResource() { - releaseResource(); - SafeRelease(&d3ddev); + releaseEGL(); + if (egl) { + delete egl; + egl = NULL; + } } -void EGLInteropResource::releaseResource() { - SafeRelease(&dx_surface); - SafeRelease(&dx_texture); - if (egl_surface != EGL_NO_SURFACE) { - eglReleaseTexImage(egl_dpy, egl_surface, EGL_BACK_BUFFER); - eglDestroySurface(egl_dpy, egl_surface); - egl_surface = EGL_NO_SURFACE; +void EGLInteropResource::releaseEGL() { + if (egl->surface != EGL_NO_SURFACE) { + eglReleaseTexImage(egl->dpy, egl->surface, EGL_BACK_BUFFER); + eglDestroySurface(egl->dpy, egl->surface); + egl->surface = EGL_NO_SURFACE; } } @@ -199,7 +227,7 @@ bool EGLInteropResource::ensureSurface(int w, int h) { return true; #if QTAV_HAVE(GUI_PRIVATE) QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - egl_dpy = static_cast(nativeInterface->nativeResourceForContext("eglDisplay", QOpenGLContext::currentContext())); + egl->dpy = static_cast(nativeInterface->nativeResourceForContext("eglDisplay", QOpenGLContext::currentContext())); EGLConfig egl_cfg = static_cast(nativeInterface->nativeResourceForContext("eglConfig", QOpenGLContext::currentContext())); #else #ifdef Q_OS_WIN @@ -212,26 +240,26 @@ bool EGLInteropResource::ensureSurface(int w, int h) { #endif #endif //Q_OS_WIN // eglQueryContext() added (Feb 2015): https://github.com/google/angle/commit/8310797003c44005da4143774293ea69671b0e2a - egl_dpy = eglGetCurrentDisplay(); + egl->dpy = eglGetCurrentDisplay(); EGLint cfg_id = 0; - EGL_ENSURE(eglQueryContext(egl_dpy, eglGetCurrentContext(), EGL_CONFIG_ID , &cfg_id) == EGL_TRUE, false); + EGL_ENSURE(eglQueryContext(egl->dpy, eglGetCurrentContext(), EGL_CONFIG_ID , &cfg_id) == EGL_TRUE, false); qDebug("egl config id: %d", cfg_id); EGLint nb_cfg = 0; - EGL_ENSURE(eglGetConfigs(egl_dpy, NULL, 0, &nb_cfg) == EGL_TRUE, false); + EGL_ENSURE(eglGetConfigs(egl->dpy, NULL, 0, &nb_cfg) == EGL_TRUE, false); qDebug("eglGetConfigs number: %d", nb_cfg); QVector cfgs(nb_cfg); //check > 0 - EGL_ENSURE(eglGetConfigs(egl_dpy, cfgs.data(), cfgs.size(), &nb_cfg) == EGL_TRUE, false); + EGL_ENSURE(eglGetConfigs(egl->dpy, cfgs.data(), cfgs.size(), &nb_cfg) == EGL_TRUE, false); EGLConfig egl_cfg = NULL; for (int i = 0; i < nb_cfg; ++i) { EGLint id = 0; - eglGetConfigAttrib(egl_dpy, cfgs[i], EGL_CONFIG_ID, &id); + eglGetConfigAttrib(egl->dpy, cfgs[i], EGL_CONFIG_ID, &id); if (id == cfg_id) { egl_cfg = cfgs[i]; break; } } #endif - qDebug("egl display:%p config: %p", egl_dpy, egl_cfg); + qDebug("egl display:%p config: %p", egl->dpy, egl_cfg); EGLint attribs[] = { EGL_WIDTH, w, @@ -240,8 +268,8 @@ bool EGLInteropResource::ensureSurface(int w, int h) { EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, EGL_NONE }; - EGL_ENSURE((egl_surface = eglCreatePbufferSurface(egl_dpy, egl_cfg, attribs)) != EGL_NO_SURFACE, false); - qDebug("pbuffer surface: %p", egl_surface); + EGL_ENSURE((egl->surface = eglCreatePbufferSurface(egl->dpy, egl_cfg, attribs)) != EGL_NO_SURFACE, false); + qDebug("pbuffer surface: %p", egl->surface); // create dx resources PFNEGLQUERYSURFACEPOINTERANGLEPROC eglQuerySurfacePointerANGLE = reinterpret_cast(eglGetProcAddress("eglQuerySurfacePointerANGLE")); @@ -250,10 +278,9 @@ bool EGLInteropResource::ensureSurface(int w, int h) { return false; } HANDLE share_handle = NULL; - EGL_ENSURE(eglQuerySurfacePointerANGLE(egl_dpy, egl_surface, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &share_handle), false); + EGL_ENSURE(eglQuerySurfacePointerANGLE(egl->dpy, egl->surface, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &share_handle), false); - SafeRelease(&dx_surface); - SafeRelease(&dx_texture); + releaseDX(); // _A8 for a yuv plane DX_ENSURE_OK(d3ddev->CreateTexture(w, h, 1, D3DUSAGE_RENDERTARGET, @@ -272,21 +299,24 @@ bool EGLInteropResource::map(IDirect3DSurface9* surface, GLuint tex, int) D3DSURFACE_DESC dxvaDesc; surface->GetDesc(&dxvaDesc); if (!ensureSurface(dxvaDesc.Width, dxvaDesc.Height)) { - releaseResource(); + releaseEGL(); + releaseDX(); return false; } DYGL(glBindTexture(GL_TEXTURE_2D, tex)); if (SUCCEEDED(d3ddev->StretchRect(surface, NULL, dx_surface, NULL, D3DTEXF_NONE))) - eglBindTexImage(egl_dpy, egl_surface, EGL_BACK_BUFFER); + eglBindTexImage(egl->dpy, egl->surface, EGL_BACK_BUFFER); // Flush the draw command now, so that by the time we come to draw this - // image, we're less likely to need to wait for the draw operation to - // complete. - IDirect3DQuery9 *query = NULL; - DX_ENSURE_OK(d3ddev->CreateQuery(D3DQUERYTYPE_EVENT, &query), false); - DX_ENSURE_OK(query->Issue(D3DISSUE_END), false); + // image, we're less likely to need to wait for the draw operation to + // complete. + //IDirect3DQuery9 *query = NULL; + //DX_ENSURE_OK(d3ddev->CreateQuery(D3DQUERYTYPE_EVENT, &query), false); + //DX_ENSURE_OK(query->Issue(D3DISSUE_END), false); DYGL(glBindTexture(GL_TEXTURE_2D, 0)); return true; } +} //namespace dxva +} //namespace QtAV #endif //QTAV_HAVE(DXVA_EGL) #if QTAV_HAVE(DXVA_GL) @@ -307,6 +337,8 @@ bool EGLInteropResource::map(IDirect3DSurface9* surface, GLuint tex, int) } while(0) //#include //not found in vs2013 +namespace QtAV { +namespace dxva { #define WGL_ACCESS_READ_ONLY_NV 0x00000000 #define WGL_ACCESS_READ_WRITE_NV 0x00000001 #define WGL_ACCESS_WRITE_DISCARD_NV 0x00000002 @@ -332,17 +364,11 @@ struct WGL { }; GLInteropResource::GLInteropResource(IDirect3DDevice9 *d3device) - : InteropResource() - , d3ddev(d3device) - , dx_texture(NULL) - , dx_surface(NULL) + : InteropResource(d3device) , interop_dev(NULL) , interop_obj(NULL) - , width(0) - , height(0) , wgl(0) { - d3ddev->AddRef(); } GLInteropResource::~GLInteropResource() @@ -352,13 +378,6 @@ GLInteropResource::~GLInteropResource() delete wgl; wgl = NULL; } - releaseResource(); - SafeRelease(&d3ddev); -} - -void GLInteropResource::releaseResource() { - SafeRelease(&dx_surface); - SafeRelease(&dx_texture); } bool GLInteropResource::map(IDirect3DSurface9 *surface, GLuint tex, int) @@ -366,7 +385,7 @@ bool GLInteropResource::map(IDirect3DSurface9 *surface, GLuint tex, int) D3DSURFACE_DESC dxvaDesc; surface->GetDesc(&dxvaDesc); if (!ensureResource(dxvaDesc.Width, dxvaDesc.Height, tex)) { - releaseResource(); + releaseDX(); return false; } // open/close and register/unregster in every map/unmap to ensure called in current context and avoid crash (tested on intel driver) @@ -423,9 +442,6 @@ bool GLInteropResource::ensureWGL() wgl->DXUnlockObjectsNV = (PFNWGLDXUNLOCKOBJECTSNVPROC)ctx->getProcAddress("wglDXUnlockObjectsNV"); Q_ASSERT(wgl->DXRegisterObjectNV); - Q_ASSERT(wgl->DXSetResourceShareHandleNV); - Q_ASSERT(wgl->DXLockObjectsNV); - Q_ASSERT(wgl->DXObjectAccessNV); return true; } @@ -436,8 +452,7 @@ bool GLInteropResource::ensureResource(int w, int h, GLuint tex) return false; if (dx_surface && width == w && height == h) return true; - SafeRelease(&dx_surface); - SafeRelease(&dx_texture); + releaseDX(); HANDLE share_handle = NULL; // _A8 for a yuv plane DX_ENSURE_OK(d3ddev->CreateTexture(w, h, 1, @@ -454,6 +469,6 @@ bool GLInteropResource::ensureResource(int w, int h, GLuint tex) height = h; return true; } -#endif //QTAV_HAVE(DXVA_GL) } //namespace dxva } //namespace QtAV +#endif //QTAV_HAVE(DXVA_GL) diff --git a/src/codec/video/SurfaceInteropDXVA.h b/src/codec/video/SurfaceInteropDXVA.h index 633757d0..affbd7d5 100644 --- a/src/codec/video/SurfaceInteropDXVA.h +++ b/src/codec/video/SurfaceInteropDXVA.h @@ -31,26 +31,24 @@ #if defined(QT_OPENGL_DYNAMIC) || !defined(QT_OPENGL_ES_2) #define QTAV_HAVE_DXVA_GL 1 #endif -#if QTAV_HAVE(DXVA_EGL) -# ifdef QT_OPENGL_ES_2_ANGLE_STATIC -# define CAPI_LINK_EGL -# else -# define EGL_CAPI_NS -# endif //QT_OPENGL_ES_2_ANGLE_STATIC -#include "capi/egl_api.h" -#include //include after egl_capi.h to match types -#endif //QTAV_HAVE(DXVA_EGL) namespace QtAV { namespace dxva { - class InteropResource { public: - virtual ~InteropResource() {} + InteropResource(IDirect3DDevice9 * d3device); + virtual ~InteropResource(); virtual bool map(IDirect3DSurface9* surface, GLuint tex, int plane) = 0; virtual bool unmap(GLuint tex) { Q_UNUSED(tex); return true;} +protected: + void releaseDX(); + + IDirect3DDevice9 *d3ddev; + IDirect3DTexture9 *dx_texture; + IDirect3DSurface9 *dx_surface; + int width, height; }; typedef QSharedPointer InteropResourcePtr; @@ -70,10 +68,8 @@ private: }; #if QTAV_HAVE(DXVA_EGL) +class EGL; class EGLInteropResource Q_DECL_FINAL: public InteropResource -#ifndef EGL_CAPI_NS - , public egl::api -#endif //EGL_CAPI_NS { public: EGLInteropResource(IDirect3DDevice9 * d3device); @@ -81,15 +77,10 @@ public: bool map(IDirect3DSurface9 *surface, GLuint tex, int) Q_DECL_OVERRIDE; private: - void releaseResource(); + void releaseEGL(); bool ensureSurface(int w, int h); - IDirect3DDevice9 *d3ddev; - IDirect3DTexture9 *dx_texture; - IDirect3DSurface9 *dx_surface; - EGLDisplay egl_dpy; - EGLSurface egl_surface; - int width, height; + EGL* egl; }; #endif //QTAV_HAVE(DXVA_EGL) @@ -103,16 +94,11 @@ public: bool map(IDirect3DSurface9 *surface, GLuint tex, int) Q_DECL_OVERRIDE; bool unmap(GLuint tex) Q_DECL_OVERRIDE; private: - void releaseResource(); bool ensureWGL(); bool ensureResource(int w, int h, GLuint tex); - IDirect3DDevice9 *d3ddev; - IDirect3DTexture9 *dx_texture; - IDirect3DSurface9 *dx_surface; // convert nv12 to rgb surface HANDLE interop_dev; HANDLE interop_obj; - int width, height; WGL *wgl; }; #endif //QTAV_HAVE(DXVA_GL)