Skip to content

Commit

Permalink
cuda: opengl interop
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-bin committed Sep 17, 2014
1 parent dc210db commit 346c9b3
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/codec/video/VideoDecoderCUDA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 420,7 @@ bool VideoDecoderCUDAPrivate::initCuda()
description = QString("CUDA device: %1 %2.%3 %4 MHz").arg(devname).arg(major).arg(minor).arg(clockRate/1000);

//TODO: cuD3DCtxCreate > cuGLCtxCreate > cuCtxCreate
// check user option "readBack". if not "readBack" and ctx version < 5.0, check gl or angle and run cuGLCtxCreate or cuD3DCtxCreate
checkCudaErrors(cuCtxCreate(&cuctx, CU_CTX_SCHED_BLOCKING_SYNC, cudev)); //CU_CTX_SCHED_AUTO?

unsigned int ctx_ver = 0;
Expand Down
75 changes: 75 additions & 0 deletions src/cuda/SurfaceInterop_CUDA_GL.cpp
Original file line number Diff line number Diff line change
@@ -0,0 1,75 @@
#include "SurfaceInterop_CUDA_GL.h"
#include "cuda_gl_interop.h"
namespace QtAV {
namespace cuda {

//cuda<5.0: cuGLCtxCreate to get max perf

SurfaceInterop_CUDA_GL::SurfaceInterop_CUDA_GL()
{
memset(tex_res, 0, sizeof(tex_res));
}

SurfaceInterop_CUDA_GL::~SurfaceInterop_CUDA_GL()
{
for (int i = 0; i < 2; i) {
if (tex_res[i].res)
cuGraphicsUnregisterResource(tex_res[i].res);
}
}

bool SurfaceInterop_CUDA_GL::registerTextureResource(GLuint tex, int plane)
{
TextureRes &t_r(tex_res[plane]);
if (t_r.tex == tex)
return true;
// register only once
if (t_r.tex) {
checkCudaErrors(cuGraphicsUnregisterResource(t_r.res));
}
checkCudaErrors(cuGraphicsGLRegisterImage(&t_r.res, tex, GL_TEXTURE_2D, CU_GRAPHICS_REGISTER_FLAGS_NONE)); //WO?
t_r.tex = tex;
return true;
}

void* SurfaceInterop_CUDA_GL::map(SurfaceType type, const VideoFormat& fmt, void* handle, int plane)
{
if (type != GLTextureSurface)
return 0;
Q_ASSERT(plane <= 1); //NV12
Q_ASSERT(handle); //
if (!registerTextureResource(*((GLuint*)handle), plane))
return 0;
//cuGraphicsSubResourceGetMappedPointer(CUdevicePtr) //>=0302
CUarray array;
CUresult r = cuGraphicsSubResourceGetMappedArray(&array, tex_res[plane].res, 0/*arrayIndex*/, 0 /*mipLevel*/);
if (r != CUDA_SUCCESS)
return 0;
CUDA_MEMCPY2D cp2d;
memset(&cp2d, 0, sizeof(cp2d));

r = cuMemcpy2D(&cp2d);
if (r != CUDA_SUCCESS)
return 0;
//cuGraphicsUnmapResources(1, tex_res[plane].res, 0);
return handle;
}

void SurfaceInterop_CUDA_GL::unmap(void *handle)
{
CUgraphicsResource *res = 0;
for (int i = 0; i < 2; i) {
if (tex_res[i].tex == *((GLuint*)handle)) {
res = &tex_res[i].res;
break;
}
}
if (!res)
return;
cuGraphicsUnmapResources(1, res, 0);
}

} //namespace cuda
} //namespace QtAV


36 changes: 36 additions & 0 deletions src/cuda/SurfaceInterop_CUDA_GL.h
Original file line number Diff line number Diff line change
@@ -0,0 1,36 @@
#ifndef QTAV_SURFACEINTEROP_CUDA_GL_H
#define QTAV_SURFACEINTEROP_CUDA_GL_H

#include <QtCore/QMap>
#include <QtCore/QSharedPointer>
#include "helper_cuda.h"
#include "cuda_api.h"
#include "QtAV/SurfaceInterop.h"

namespace QtAV {
namespace cuda {

class SurfaceInterop_CUDA_GL : public VideoSurfaceInterop, public cuda_api
{
public:
SurfaceInterop_CUDA_GL();
~SurfaceInterop_CUDA_GL();

bool registerTextureResource(GLuint tex, int plane);
virtual void* map(SurfaceType type, const VideoFormat& fmt, void* handle, int plane);
virtual void unmap(void *handle);

private:
typedef struct {
GLuint tex;
CUgraphicsResource res;
} TextureRes;
TextureRes tex_res[2];
// CUDA_MEMCPY2D cp2d;
CUdeviceptr src_dev;
};
typedef QSharedPointer<SurfaceInterop_CUDA_GL> SurfaceInterop_CUDA_GL_Ptr;

} //namespace cuda
} //namespace QtAV
#endif // QTAV_SURFACEINTEROP_CUDA_GL_H
1 change: 1 addition & 0 deletions src/cuda/cuda_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 28,7 @@

// high version will define cuXXX macro, so functions here will be not they look like
#if !NV_CONFIG(DLLAPI_CUDA) && !defined(CUDA_LINK)
// TODO: use driver version, here use internal version
#define CUDA_FORCE_API_VERSION 3010
#endif
#include "dllapi/nv_inc.h"
Expand Down
10 changes: 10 additions & 0 deletions src/cuda/dllapi/nv_inc.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 25,15 @@
#undef NV_CONFIG
#define NV_CONFIG(FEATURE) (defined QTAV_HAVE_##FEATURE && QTAV_HAVE_##FEATURE)

// use qt opengl to support dynamicgl
// TODO: only define needed types not include?
#include <QtGlobal>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtGui/qopengl.h>
#else
#include <QtOpenGL/qgl.h>
#endif

#if NV_CONFIG(DLLAPI_CUDA)
namespace dllapi {
namespace cuda {
Expand All @@ -34,6 43,7 @@ namespace cuda {
#endif /* __cplusplus */

#include "cuda.h"
#include "cudaGL.h"
#include "nvcuvid.h"

#if defined(__cplusplus)
Expand Down
8 changes: 5 additions & 3 deletions src/libQtAV.pro
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 187,11 @@ CONFIG = config_cuda #config_dllapi config_dllapi_cuda
#CONFIG = config_cuda_link
config_cuda {
DEFINES = QTAV_HAVE_CUDA=1
HEADERS = cuda/dllapi/nv_inc.h cuda/helper_cuda.h
SOURCES = codec/video/VideoDecoderCUDA.cpp
HEADERS = cuda/dllapi/nv_inc.h cuda/helper_cuda.h \
cuda/SurfaceInterop_CUDA_GL.h
SOURCES = \
codec/video/VideoDecoderCUDA.cpp \
cuda/SurfaceInterop_CUDA_GL.cpp
INCLUDEPATH = $$PWD/cuda cuda/dllapi
config_dllapi:config_dllapi_cuda {
DEFINES = QTAV_HAVE_DLLAPI_CUDA=1
Expand Down Expand Up @@ -401,7 404,6 @@ HEADERS *= \
QtAV/ColorTransform.h \
QtAV/VideoDecoderFFmpegHW.h


# from mkspecs/features/qt_module.prf
# OS X and iOS frameworks
mac_framework { # from common.pri
Expand Down

0 comments on commit 346c9b3

Please sign in to comment.