Skip to content

Commit

Permalink
move wgl apis. d3d11 can use them in the future
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-bin committed Apr 8, 2016
1 parent 0bc74ed commit 951761a
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 92 deletions.
102 changes: 10 additions & 92 deletions src/directx/SurfaceInteropD3D9GL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,8 @@
#include "opengl/OpenGLHelper.h"

//dynamic gl or desktop gl
#define WGL_ENSURE(x, ...) \
do { \
if (!(x)) { \
qWarning() << "WGL error " << __FILE__ << "@" << __LINE__ << " " << #x << ": " << qt_error_string(GetLastError()); \
return __VA_ARGS__; \
} \
} while(0)
#define WGL_WARN(x, ...) \
do { \
if (!(x)) { \
qWarning() << "WGL error " << __FILE__ << "@" << __LINE__ << " " << #x << ": " << qt_error_string(GetLastError()); \
} \
} while(0)

//#include <GL/wglext.h> //not found in vs2013

namespace QtAV {
namespace d3d9 {
struct WGL;
class GLInteropResource Q_DECL_FINAL: public InteropResource
{
public:
Expand All @@ -52,58 +35,27 @@ class GLInteropResource Q_DECL_FINAL: public InteropResource
bool map(IDirect3DSurface9 *surface, GLuint tex, int frame_w, int frame_h, int) Q_DECL_OVERRIDE;
bool unmap(GLuint tex) Q_DECL_OVERRIDE;
private:
bool ensureWGL();
bool ensureResource(int w, int h, GLuint tex);

HANDLE interop_dev;
HANDLE interop_obj;
WGL *wgl;
};

InteropResource* CreateInteropGL(IDirect3DDevice9 *dev)
{
return new GLInteropResource(dev);
}

#define WGL_ACCESS_READ_ONLY_NV 0x00000000
#define WGL_ACCESS_READ_WRITE_NV 0x00000001
#define WGL_ACCESS_WRITE_DISCARD_NV 0x00000002
typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void *dxObject, HANDLE shareHandle);
typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void *dxDevice);
typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice);
typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access);
typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject);
typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access);
typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects);
typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects);

//https://www.opengl.org/registry/specs/NV/DX_interop.txt
struct WGL {
PFNWGLDXSETRESOURCESHAREHANDLENVPROC DXSetResourceShareHandleNV;
PFNWGLDXOPENDEVICENVPROC DXOpenDeviceNV;
PFNWGLDXCLOSEDEVICENVPROC DXCloseDeviceNV;
PFNWGLDXREGISTEROBJECTNVPROC DXRegisterObjectNV;
PFNWGLDXUNREGISTEROBJECTNVPROC DXUnregisterObjectNV;
PFNWGLDXOBJECTACCESSNVPROC DXObjectAccessNV;
PFNWGLDXLOCKOBJECTSNVPROC DXLockObjectsNV;
PFNWGLDXUNLOCKOBJECTSNVPROC DXUnlockObjectsNV;
};

GLInteropResource::GLInteropResource(IDirect3DDevice9 *d3device)
: InteropResource(d3device)
, interop_dev(NULL)
, interop_obj(NULL)
, wgl(0)
{
}

GLInteropResource::~GLInteropResource()
{
// FIXME: why unregister/close interop obj/dev here will crash(tested on intel driver)? must be in current opengl context?
if (wgl) {
delete wgl;
wgl = NULL;
}
}

bool GLInteropResource::map(IDirect3DSurface9 *surface, GLuint tex, int w, int h, int)
Expand All @@ -114,15 +66,15 @@ bool GLInteropResource::map(IDirect3DSurface9 *surface, GLuint tex, int w, int h
}
// open/close and register/unregster in every map/unmap to ensure called in current context and avoid crash (tested on intel driver)
// interop operations begin
WGL_ENSURE((interop_dev = wgl->DXOpenDeviceNV(d3ddev)) != NULL, false);
WGL_ENSURE((interop_dev = gl().DXOpenDeviceNV(d3ddev)) != NULL, false);
// call in ensureResource or in map?
WGL_ENSURE((interop_obj = wgl->DXRegisterObjectNV(interop_dev, dx_surface, tex, GL_TEXTURE_2D, WGL_ACCESS_READ_ONLY_NV)) != NULL, false);
WGL_ENSURE((interop_obj = gl().DXRegisterObjectNV(interop_dev, dx_surface, tex, GL_TEXTURE_2D, WGL_ACCESS_READ_ONLY_NV)) != NULL, false);
// prepare dx resources for gl
const RECT src = { 0, 0, w, h};
DX_ENSURE_OK(d3ddev->StretchRect(surface, &src, dx_surface, NULL, D3DTEXF_NONE), false);
// lock dx resources
WGL_ENSURE(wgl->DXLockObjectsNV(interop_dev, 1, &interop_obj), false);
WGL_ENSURE(wgl->DXObjectAccessNV(interop_obj, WGL_ACCESS_READ_ONLY_NV), false);
WGL_ENSURE(gl().DXLockObjectsNV(interop_dev, 1, &interop_obj), false);
WGL_ENSURE(gl().DXObjectAccessNV(interop_obj, WGL_ACCESS_READ_ONLY_NV), false);
DYGL(glBindTexture(GL_TEXTURE_2D, tex));
return true;
}
Expand All @@ -133,55 +85,21 @@ bool GLInteropResource::unmap(GLuint tex)
if (!interop_obj || !interop_dev)
return false;
DYGL(glBindTexture(GL_TEXTURE_2D, 0));
WGL_ENSURE(wgl->DXUnlockObjectsNV(interop_dev, 1, &interop_obj), false);
WGL_WARN(wgl->DXUnregisterObjectNV(interop_dev, interop_obj));
WGL_ENSURE(gl().DXUnlockObjectsNV(interop_dev, 1, &interop_obj), false);
WGL_WARN(gl().DXUnregisterObjectNV(interop_dev, interop_obj));
// interop operations end
WGL_WARN(wgl->DXCloseDeviceNV(interop_dev));
WGL_WARN(gl().DXCloseDeviceNV(interop_dev));
interop_obj = NULL;
interop_dev = NULL;
return true;
}

// IDirect3DDevice9 can not be used on WDDM OSes(>=vista)
bool GLInteropResource::ensureWGL()
{
if (wgl)
return true;
static const char* ext[] = {
"WGL_NV_DX_interop2",
"WGL_NV_DX_interop",
NULL,
};
if (!OpenGLHelper::hasExtension(ext)) { // TODO: use wgl getprocaddress function (for qt4)
qWarning("WGL_NV_DX_interop is required");
}
wgl = new WGL();
memset(wgl, 0, sizeof(*wgl));
const QOpenGLContext *ctx = QOpenGLContext::currentContext(); //const for qt4
// QGLContext::getProcAddress(const QByteArray&), QOpenGLContext::getProcAddress(const QString&). So to work with QT_NO_CAST_FROM_ASCII we need a wrapper
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#define QB(x) x
#else
#define QB(x) QString::fromLatin1(x)
#endif
wgl->DXSetResourceShareHandleNV = (PFNWGLDXSETRESOURCESHAREHANDLENVPROC)ctx->getProcAddress(QB("wglDXSetResourceShareHandleNV"));
wgl->DXOpenDeviceNV = (PFNWGLDXOPENDEVICENVPROC)ctx->getProcAddress(QB("wglDXOpenDeviceNV"));
wgl->DXCloseDeviceNV = (PFNWGLDXCLOSEDEVICENVPROC)ctx->getProcAddress(QB("wglDXCloseDeviceNV"));
wgl->DXRegisterObjectNV = (PFNWGLDXREGISTEROBJECTNVPROC)ctx->getProcAddress(QB("wglDXRegisterObjectNV"));
wgl->DXUnregisterObjectNV = (PFNWGLDXUNREGISTEROBJECTNVPROC)ctx->getProcAddress(QB("wglDXUnregisterObjectNV"));
wgl->DXObjectAccessNV = (PFNWGLDXOBJECTACCESSNVPROC)ctx->getProcAddress(QB("wglDXObjectAccessNV"));
wgl->DXLockObjectsNV = (PFNWGLDXLOCKOBJECTSNVPROC)ctx->getProcAddress(QB("wglDXLockObjectsNV"));
wgl->DXUnlockObjectsNV = (PFNWGLDXUNLOCKOBJECTSNVPROC)ctx->getProcAddress(QB("wglDXUnlockObjectsNV"));
#undef QB
Q_ASSERT(wgl->DXRegisterObjectNV);
return true;
}

bool GLInteropResource::ensureResource(int w, int h, GLuint tex)
{
Q_UNUSED(tex);
if (!ensureWGL())
return false;
Q_ASSERT(gl().DXRegisterObjectNV && "WGL_NV_DX_interop is required");

if (dx_surface && width == w && height == h)
return true;
releaseDX();
Expand All @@ -200,7 +118,7 @@ bool GLInteropResource::ensureResource(int w, int h, GLuint tex)
&share_handle) , false);
DX_ENSURE_OK(dx_texture->GetSurfaceLevel(0, &dx_surface), false);
// required by d3d9 not d3d10&11: https://www.opengl.org/registry/specs/NV/DX_interop2.txt
WGL_WARN(wgl->DXSetResourceShareHandleNV(dx_surface, share_handle));
WGL_WARN(gl().DXSetResourceShareHandleNV(dx_surface, share_handle));
width = w;
height = h;
return true;
Expand Down
15 changes: 15 additions & 0 deletions src/opengl/OpenGLHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@
} \
} while(0)


#define WGL_ENSURE(x, ...) \
do { \
if (!(x)) { \
qWarning() << "WGL error " << __FILE__ << "@" << __LINE__ << " " << #x << ": " << qt_error_string(GetLastError()); \
return __VA_ARGS__; \
} \
} while(0)
#define WGL_WARN(x, ...) \
do { \
if (!(x)) { \
qWarning() << "WGL error " << __FILE__ << "@" << __LINE__ << " " << #x << ": " << qt_error_string(GetLastError()); \
} \
} while(0)

QT_BEGIN_NAMESPACE
class QMatrix4x4;
QT_END_NAMESPACE
Expand Down
27 changes: 27 additions & 0 deletions src/opengl/gl_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
#include "gl_api.h"
#include "OpenGLHelper.h"

namespace QtAV {
typedef void *(*GetProcAddress_t)(const char *);
Expand Down Expand Up @@ -82,6 +83,11 @@ void* GetProcAddress_Qt(const char *name)
} while(0)
#endif

#define WGL_RESOLVE(name) do {\
void** fp = (void**)(&name); \
*fp = sGetProcAddress("wgl" # name); \
} while(0)

void api::resolve()
{
//memset(g, 0, sizeof(g));
Expand All @@ -107,6 +113,27 @@ void api::resolve()
GL_RESOLVE(UniformMatrix4fv);

GL_RESOLVE_ES_3_1(GetTexLevelParameteriv);

#ifdef Q_OS_WIN32
if (!OpenGLHelper::isOpenGLES()) {
static const char* ext[] = {
"WGL_NV_DX_interop2",
"WGL_NV_DX_interop",
NULL,
};
if (OpenGLHelper::hasExtension(ext)) { // TODO: use wgl getprocaddress function (for qt4)
qDebug("resolving WGL_NV_DX_interop...");
WGL_RESOLVE(DXSetResourceShareHandleNV);
WGL_RESOLVE(DXOpenDeviceNV);
WGL_RESOLVE(DXCloseDeviceNV);
WGL_RESOLVE(DXRegisterObjectNV);
WGL_RESOLVE(DXUnregisterObjectNV);
WGL_RESOLVE(DXObjectAccessNV);
WGL_RESOLVE(DXLockObjectsNV);
WGL_RESOLVE(DXUnlockObjectsNV);
}
}
#endif //Q_OS_WIN32
}

api& gl() {
Expand Down
18 changes: 18 additions & 0 deletions src/opengl/gl_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,24 @@ struct api {
// Before using the following members, check null ptr first because they are not valid everywhere
// ES3.1
void (GL_APIENTRY *GetTexLevelParameteriv)(GLenum, GLint, GLenum, GLint *);

#if defined(Q_OS_WIN32)
//#include <GL/wglext.h> //not found in vs2013
//https://www.opengl.org/registry/specs/NV/DX_interop.txt
#ifndef WGL_ACCESS_READ_ONLY_NV
#define WGL_ACCESS_READ_ONLY_NV 0x00000000
#define WGL_ACCESS_READ_WRITE_NV 0x00000001
#define WGL_ACCESS_WRITE_DISCARD_NV 0x00000002
#endif
BOOL (WINAPI* DXSetResourceShareHandleNV)(void *dxObject, HANDLE shareHandle);
HANDLE (WINAPI* DXOpenDeviceNV)(void *dxDevice);
BOOL (WINAPI* DXCloseDeviceNV)(HANDLE hDevice);
HANDLE (WINAPI* DXRegisterObjectNV)(HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access);
BOOL (WINAPI* DXUnregisterObjectNV)(HANDLE hDevice, HANDLE hObject);
BOOL (WINAPI* DXObjectAccessNV)(HANDLE hObject, GLenum access);
BOOL (WINAPI* DXLockObjectsNV)(HANDLE hDevice, GLint count, HANDLE *hObjects);
BOOL (WINAPI* DXUnlockObjectsNV)(HANDLE hDevice, GLint count, HANDLE *hObjects);
#endif
};
} //namespace QtAV
#endif //QT_NO_OPENGL
Expand Down

0 comments on commit 951761a

Please sign in to comment.