vaapi: va-x11 + glx tfp

sometimes ui blocks, why?
This commit is contained in:
wang-bin
2015-05-31 11:55:01 +08:00
parent 99ac697b12
commit 580fbca4cb
3 changed files with 218 additions and 7 deletions
+142 -1
View File
@@ -1,5 +1,7 @@
#include "SurfaceInteropVAAPI.h"
#include "utils/OpenGLHelper.h"
#include <GL/glx.h>
#include <va/va_x11.h>
namespace QtAV {
namespace vaapi {
@@ -23,6 +25,8 @@ void* SurfaceInteropVAAPI::map(SurfaceType type, const VideoFormat &fmt, void *h
{
if (!fmt.isRGB())
return 0;
QMutexLocker lock(&mutex);
if (!handle)
handle = createHandle(type, fmt, plane);
if (type == GLTextureSurface) {
@@ -37,7 +41,7 @@ void* SurfaceInteropVAAPI::map(SurfaceType type, const VideoFormat &fmt, void *h
glx->set(m_surface);
if (!glx->copy())
return 0;
glx->sync();
VAWARN(vaSyncSurface(m_surface->display(), m_surface->get()));
return handle;
} else
if (type == HostMemorySurface) {
@@ -78,6 +82,143 @@ void* SurfaceInteropVAAPI::createHandle(SurfaceType type, const VideoFormat &fmt
return 0;
}
#ifndef QT_OPENGL_ES_2
VAAPI_X_GLX_Interop::glXReleaseTexImage_t VAAPI_X_GLX_Interop::glXReleaseTexImage = 0;
VAAPI_X_GLX_Interop::glXBindTexImage_t VAAPI_X_GLX_Interop::glXBindTexImage = 0;
VAAPI_X_GLX_Interop::VAAPI_X_GLX_Interop()
: xdisplay(0)
, fbc(0)
, pixmap(0)
, glxpixmap(0)
, width(0)
, height(0)
{}
VAAPI_X_GLX_Interop::~VAAPI_X_GLX_Interop()
{
if (glxpixmap) {
glXReleaseTexImage(xdisplay, glxpixmap, GLX_FRONT_EXT);
XSync((::Display*)xdisplay, False);
glXDestroyPixmap((::Display*)xdisplay, glxpixmap);
}
glxpixmap = 0;
if (pixmap)
XFreePixmap((::Display*)xdisplay, pixmap);
pixmap = 0;
}
bool VAAPI_X_GLX_Interop::ensureGLX()
{
if (fbc)
return true;
xdisplay = (Display*)glXGetCurrentDisplay();
if (!xdisplay)
return false;
int xscr = DefaultScreen(xdisplay);
const char *glxext = glXQueryExtensionsString((::Display*)xdisplay, xscr);
if (!glxext || !strstr(glxext, "GLX_EXT_texture_from_pixmap"))
return false;
glXBindTexImage = (glXBindTexImage_t)glXGetProcAddressARB((const GLubyte*)"glXBindTexImageEXT");
if (!glXBindTexImage) {
qWarning("glXBindTexImage not found");
return false;
}
glXReleaseTexImage = (glXReleaseTexImage_t)glXGetProcAddressARB((const GLubyte*)"glXReleaseTexImageEXT");
if (!glXReleaseTexImage) {
qWarning("glXReleaseTexImage not found");
return false;
}
int attribs[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT, //xbmc
GLX_X_RENDERABLE, True, //xbmc
GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
GLX_Y_INVERTED_EXT, True,
GLX_DOUBLEBUFFER, False,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
None
};
int fbcount;
GLXFBConfig *fbcs = glXChooseFBConfig((::Display*)xdisplay, xscr, attribs, &fbcount);
if (!fbcount) {
qWarning("No texture-from-pixmap support");
return false;
}
if (fbcount)
fbc = fbcs[0];
XFree(fbcs);
return true;
}
bool VAAPI_X_GLX_Interop::ensurePixmaps(int w, int h)
{
if (pixmap && width == w && height == h)
return true;
if (!ensureGLX()) {
return false;
}
pixmap = XCreatePixmap((::Display*)xdisplay, RootWindow((::Display*)xdisplay, DefaultScreen((::Display*)xdisplay)), w, h, 24);
if (!pixmap) {
qWarning("VAAPI_X_GLX_Interop could not create pixmap");
return false;
}
int attribs[] = {
GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
GLX_MIPMAP_TEXTURE_EXT, False,
None,
};
glxpixmap = glXCreatePixmap((::Display*)xdisplay, fbc, pixmap, attribs);
return true;
}
void* VAAPI_X_GLX_Interop::map(SurfaceType type, const VideoFormat &fmt, void *handle, int plane)
{
Q_UNUSED(plane);
if (!handle)
return 0;
QMutexLocker lock(&mutex);
if (!m_surface)
return 0;
if (type != GLTextureSurface)
return 0;
if (!fmt.isRGB()) {
return 0;
}
if (!ensurePixmaps(m_surface->width(), m_surface->height()))
return 0;
VA_ENSURE_TRUE(vaPutSurface(m_surface->display(), m_surface->get(), pixmap
, 0, 0, m_surface->width(), m_surface->height()
, 0, 0, m_surface->width(), m_surface->height()
, NULL, 0, VA_FRAME_PICTURE | VA_SRC_BT709)
, NULL);
XSync((::Display*)xdisplay, False);
VAWARN(vaSyncSurface(m_surface->display(), m_surface->get()));
DYGL(glBindTexture(GL_TEXTURE_2D, *((GLuint*)handle)));
glXBindTexImage(xdisplay, glxpixmap, GLX_FRONT_EXT, NULL);
DYGL(glBindTexture(GL_TEXTURE_2D, 0));
return handle;
}
void VAAPI_X_GLX_Interop::unmap(void *handle)
{
DYGL(glBindTexture(GL_TEXTURE_2D, *((GLuint*)handle)));
glXReleaseTexImage(xdisplay, glxpixmap, GLX_FRONT_EXT);
DYGL(glBindTexture(GL_TEXTURE_2D, 0));
}
#endif //QT_OPENGL_ES_2
} //namespace QtAV
} //namespace vaapi
+57 -3
View File
@@ -3,28 +3,82 @@
#include <QtCore/QMap>
#include <QtCore/QSharedPointer>
#include "vaapi_helper.h"
#include <QtCore/QMutex>
#include "QtAV/SurfaceInterop.h"
#include "vaapi_helper.h"
#if defined(QT_OPENGL_ES_2)
#include <EGL/egl.h>
#else
#include <GL/glx.h>
#endif //defined(QT_OPENGL_ES_2)
#ifdef Bool
#undef Bool
#endif //Bool
#ifdef CursorShape
#undef CursorShape //used in qvariant and x11
#endif //CursorShape
#ifdef Status
#undef Status // qtextstream
#endif //Status
namespace QtAV {
namespace vaapi {
// TODO: move create glx surface to decoder, interop only map/unmap, 1 interop per frame
// load/resolve symbols only once in decoder and pass a VAAPI_XXX ptr
// or use pool
class SurfaceInteropVAAPI : public VideoSurfaceInterop, public VAAPI_GLX
{
public:
SurfaceInteropVAAPI();
void setSurface(const surface_ptr& surface) { m_surface = surface; }
void setSurface(const surface_ptr& surface) {
QMutexLocker lock(&mutex);
m_surface = surface;
}
// return glx surface
surface_glx_ptr createGLXSurface(void* handle);
virtual void* map(SurfaceType type, const VideoFormat& fmt, void* handle, int plane);
virtual void unmap(void *handle);
virtual void* createHandle(SurfaceType type, const VideoFormat& fmt, int plane = 0);
private:
surface_ptr m_surface;
QMap<GLuint*,surface_glx_ptr> glx_surfaces, tmp_surfaces;
surface_ptr m_surface;
QMutex mutex;
};
typedef QSharedPointer<SurfaceInteropVAAPI> SurfaceInteropVAAPIPtr;
#ifndef QT_OPENGL_ES_2
class VAAPI_X_GLX_Interop Q_DECL_FINAL: public VideoSurfaceInterop, public VAAPI_X11
{
public:
VAAPI_X_GLX_Interop();
~VAAPI_X_GLX_Interop();
void setSurface(const surface_ptr& surface) {
QMutexLocker lock(&mutex);
m_surface = surface;
}
void* map(SurfaceType type, const VideoFormat& fmt, void* handle, int plane) Q_DECL_OVERRIDE;
void unmap(void *handle) Q_DECL_OVERRIDE;
private:
bool ensureGLX();
bool ensurePixmaps(int w, int h);
Display *xdisplay;
GLXFBConfig fbc;
Pixmap pixmap;
GLXPixmap glxpixmap;
int width, height;
surface_ptr m_surface;
QMutex mutex;
typedef void (*glXBindTexImage_t)(Display *dpy, GLXDrawable draw, int buffer, int *a);
typedef void (*glXReleaseTexImage_t)(Display *dpy, GLXDrawable draw, int buffer);
static glXBindTexImage_t glXBindTexImage;
static glXReleaseTexImage_t glXReleaseTexImage;
};
#endif //QT_OPENGL_ES_2
} //namespace QtAV
} //namespace vaapi
//Q_DECLARE_METATYPE(QtAV::vaapi::SurfaceInteropVAAPIPtr)
+19 -3
View File
@@ -33,7 +33,9 @@
#elif defined(QT_OPENGL_LIB)
#include <qgl.h>
#else
#if !defined(QT_OPENGL_ES_2)
#include <GL/gl.h>
#endif //!defined(QT_OPENGL_ES_2)
#endif
#include "utils/SharedPtr.h"
@@ -117,16 +119,33 @@ private:
};
class VAAPI_X11 : public dll_helper {
public:
typedef unsigned long Drawable;
typedef VADisplay vaGetDisplay_t(Display *);
typedef VAStatus vaPutSurface_t(VADisplay, VASurfaceID, Drawable,
short, short, unsigned short, unsigned short,
short, short, unsigned short, unsigned short,
VARectangle *, unsigned int, unsigned int);
VAAPI_X11(): dll_helper("va-x11",1) {
fp_vaGetDisplay = (vaGetDisplay_t*)resolve("vaGetDisplay");
fp_vaPutSurface = (vaPutSurface_t*)resolve("vaPutSurface");
}
VADisplay vaGetDisplay(Display *dpy) {
assert(fp_vaGetDisplay);
return fp_vaGetDisplay(dpy);
}
VAStatus vaPutSurface (VADisplay dpy, VASurfaceID surface, Drawable draw, /* X Drawable */
short srcx, short srcy, unsigned short srcw, unsigned short srch,
short destx, short desty, unsigned short destw, unsigned short desth,
VARectangle *cliprects, /* client supplied destination clip list */
unsigned int number_cliprects, /* number of clip rects in the clip list */
unsigned int flags /* PutSurface flags */
) {
assert(fp_vaPutSurface);
return fp_vaPutSurface(dpy, surface, draw, srcx, srcy, srcw, srch, destx, desty, destw, desth, cliprects, number_cliprects, flags);
}
private:
vaGetDisplay_t* fp_vaGetDisplay;
vaPutSurface_t* fp_vaPutSurface;
};
class VAAPI_GLX : public dll_helper {
public:
@@ -244,9 +263,6 @@ public:
VA_ENSURE_TRUE(vaCopySurfaceGLX(display(), m_glx, m_surface->get(), VA_FRAME_PICTURE | VA_SRC_BT709), false);
return true;
}
void sync() {
VAWARN(vaSyncSurface(display(), m_surface->get()));
}
VADisplay display() const { return m_surface->display();}
surface_t* surface() { return m_surface.get();}
void* glxSurface() { return m_glx;}