Commit cdbad6b6 authored by Pierre Lamot's avatar Pierre Lamot
Browse files

WIP: luma interop, 1/4 resolution

:(
parent 9d47f995
......@@ -3195,6 +3195,8 @@ have_xkbcommon_x11="no"
have_xcb_keysyms="no"
have_xcb_damage="no"
have_xcb_xfixes="no"
have_xcb_dri3="no"
have_xcb_present="no"
AS_IF([test "${enable_xcb}" != "no"], [
xcb_err=""
......@@ -3249,6 +3251,19 @@ AS_IF([test "${enable_xcb}" != "no"], [
])
PKG_CHECK_MODULES([XCB_PRESENT], [xcb-present], [
have_xcb_present="yes"
], [
AC_MSG_WARN([${XCB_PRESENT_PKG_ERRORS}. FIXME warning messages.])
])
PKG_CHECK_MODULES([XCB_DRI3], [xcb-dri3], [
have_xcb_dri3="yes"
], [
AC_MSG_WARN([${XCB_DRI3_PKG_ERRORS}. FIXME warning messages.])
])
have_xcb="yes"
])
AM_CONDITIONAL([HAVE_XCB], [test "${have_xcb}" = "yes"])
......@@ -3256,6 +3271,8 @@ AM_CONDITIONAL([HAVE_XKBCOMMON_X11], [test "${have_xkbcommon_x11}" = "yes"])
AM_CONDITIONAL([HAVE_XCB_KEYSYMS], [test "${have_xcb_keysyms}" = "yes"])
AM_CONDITIONAL([HAVE_XCB_DAMAGE], [test "${have_xcb_damage}" = "yes"])
AM_CONDITIONAL([HAVE_XCB_XFIXES], [test "${have_xcb_xfixes}" = "yes"])
AM_CONDITIONAL([HAVE_XCB_PRESENT], [test "${have_xcb_present}" = "yes"])
AM_CONDITIONAL([HAVE_XCB_DRI3], [test "${have_xcb_dri3}" = "yes"])
dnl
dnl VDPAU needs X11
......
......@@ -42,8 +42,6 @@
#include <vlc_filter.h>
#include <vlc_picture_pool.h>
#include <va/va_x11.h>
void
vlc_chroma_to_vaapi(int i_vlc_chroma, unsigned *va_rt_format, int *va_fourcc)
{
......@@ -99,21 +97,6 @@ vlc_vaapi_DeriveImage(vlc_object_t *o,
error: return VLC_EGENERIC;
}
int
vlc_vaapi_PutSurface(vlc_object_t *o,
VADisplay dpy, VASurfaceID surface, Drawable draw,
short srcx, short srcy, unsigned short srcw, unsigned short srch,
short destx, short desty, unsigned short destw, unsigned short desth,
VARectangle *cliprects, unsigned int number_cliprects, unsigned int flags)
{
VA_CALL(o, vaPutSurface,
dpy, surface, draw,
srcx, srcy, srcw, srch,
destx, desty, destw, desth,
cliprects, number_cliprects, flags);
return VLC_SUCCESS;
error: return VLC_EGENERIC;
}
int
vlc_vaapi_CreateImage(vlc_object_t *o, VADisplay dpy, VAImageFormat *format,
......
......@@ -26,8 +26,6 @@
# define VLC_VAAPI_H
#include <va/va.h>
#include <va/va_x11.h>
#ifndef VA_RT_FORMAT_YUV420_10BPP
# define VA_RT_FORMAT_YUV420_10BPP 0x00000100
......@@ -66,12 +64,6 @@ int
vlc_vaapi_DeriveImage(vlc_object_t *o, VADisplay dpy,
VASurfaceID surface, VAImage *image);
int
vlc_vaapi_PutSurface(vlc_object_t *o,
VADisplay dpy, VASurfaceID surface, Drawable draw,
short srcx, short srcy, unsigned short srcw, unsigned short srch,
short destx, short desty, unsigned short destw, unsigned short desth,
VARectangle *cliprects, unsigned int number_cliprects, unsigned int flags);
/* Creates a VA image */
int
......
......@@ -128,8 +128,11 @@ libglinterop_vaapi_plugin_la_LIBADD = $(LIBVA_LIBS) $(LIBVA_EGL_LIBS)
libglinterop_vaapi_glx_plugin_la_SOURCES = video_output/opengl/interop_vaapi_glx.c \
video_output/opengl/interop.h \
hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h
libglinterop_vaapi_glx_plugin_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAGS)
libglinterop_vaapi_glx_plugin_la_LIBADD = $(LIBVA_LIBS) $(GL_LIBS) $(X_LIBS) $(X_PRE_LIBS) -lX11
libglinterop_vaapi_glx_plugin_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAGS) \
$(XCB_CFLAGS) $(XCB_DRI3_CFLAGS) $(XCB_PRESENT_CFLAGS)
libglinterop_vaapi_glx_plugin_la_LIBADD = $(LIBVA_LIBS) $(GL_LIBS) \
$(XCB_LIBS) $(XCB_DRI3_LIBS) $(XCB_PRESENT_LIBS) \
$(X_LIBS) $(X_PRE_LIBS) -lX11-xcb -lX11 -lxcb
libglinterop_vdpau_plugin_la_SOURCES = video_output/opengl/interop_vdpau.c \
video_output/opengl/interop.h hw/vdpau/picture.c hw/vdpau/vlc_vdpau.h
......@@ -142,8 +145,12 @@ if HAVE_EGL
vout_LTLIBRARIES += libglinterop_vaapi_plugin.la
endif
if HAVE_XCB
if HAVE_XCB_DRI3
if HAVE_XCB_PRESENT
vout_LTLIBRARIES += libglinterop_vaapi_glx_plugin.la
endif
endif
endif
endif #HAVE_VAAPI
if HAVE_VDPAU
......
......@@ -25,12 +25,19 @@
#include <assert.h>
#include <GL/glx.h>
#include <xcb/present.h>
#include <xcb/dri3.h>
#include <xcb/xcb.h>
#include <X11/Xlib-xcb.h>
#include <va/va_drmcommon.h>
#include <vlc_common.h>
#include <vlc_window.h>
#include <vlc_codec.h>
#include <vlc_plugin.h>
#include <vlc_fs.h>
#include "gl_util.h"
#include "interop.h"
......@@ -45,7 +52,7 @@
#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
typedef struct {
Pixmap pixmap;
xcb_pixmap_t pixmap;
GLXPixmap glxpixmap;
} GLXImagePriv;
......@@ -61,11 +68,15 @@ struct priv
void (*glXReleaseTexImageEXT) (Display *dpy, GLXDrawable draw, int buffer);
GLXPixmap (*glXCreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList);
void (*glXDestroyPixmap)( Display *dpy, GLXPixmap pixmap );
} glx;
struct
{
PFNGLBINDTEXTUREPROC BindTexture;
PFNGLGENTEXTURESPROC GenTextures;
PFNGLTEXTUREVIEWPROC TextureView;
struct vlc_gl_extension_vt extension_vt;
} gl;
unsigned fourcc;
......@@ -84,12 +95,32 @@ struct priv
} last;
};
static void
vaglx_image_destroy(const struct vlc_gl_interop *interop, GLXImagePriv* imagePriv)
{
struct priv *priv = interop->priv;
if (!imagePriv)
return;
xcb_connection_t* conn = XGetXCBConnection(priv->glx.display);
if (imagePriv->glxpixmap)
priv->glx.glXDestroyPixmap(priv->glx.display, imagePriv->glxpixmap);
if (imagePriv->pixmap != XCB_PIXMAP_NONE)
xcb_free_pixmap(conn, imagePriv->pixmap);
free(imagePriv);
}
static GLXImagePriv*
vaglx_image_create(const struct vlc_gl_interop *interop, int w, int h)
vaglx_image_create(const struct vlc_gl_interop *interop, int w, int h, int fd, uint32_t offset, uint32_t pitch, uint32_t size, uint64_t modifiers)
{
struct priv *priv = interop->priv;
xcb_connection_t* conn = XGetXCBConnection(priv->glx.display);
GLXImagePriv* img = (GLXImagePriv*)malloc(sizeof(GLXImagePriv));
img->glxpixmap = 0;
img->pixmap = XCB_PIXMAP_NONE;
int attribs[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
......@@ -109,42 +140,74 @@ vaglx_image_create(const struct vlc_gl_interop *interop, int w, int h)
int fbcount;
GLXFBConfig *fbcs = glXChooseFBConfig(priv->glx.display, DefaultScreen(priv->glx.display), attribs, &fbcount);
if (!fbcount) {
msg_Err(interop->gl, "can't find glx config");
XFree(fbcs);
free(img);
return NULL;
goto error;
}
GLXFBConfig fbc = fbcs[0];
XFree(fbcs);
XWindowAttributes xwa;
XGetWindowAttributes(priv->glx.display, DefaultRootWindow(priv->glx.display), &xwa);
img->pixmap = XCreatePixmap(priv->glx.display, DefaultRootWindow(priv->glx.display), w, h, xwa.depth);
msg_Info(interop->gl, "create pixmap from buffer, size %u, %ix%i, pitch %u, offset %u", size, w, h, pitch, offset);
img->pixmap = xcb_generate_id(conn);
//xcb_void_cookie_t cookie = xcb_dri3_pixmap_from_buffer_checked(conn,
// img->pixmap, DefaultRootWindow(priv->glx.display),
// size, w/4, h, pitch,
// 32, 32, fd);
int fdarray[4];
fdarray[0] = vlc_dup(fd);
fdarray[1] = vlc_dup(fd);
fdarray[2] = vlc_dup(fd);
fdarray[3] = vlc_dup(fd);
xcb_void_cookie_t cookie = xcb_dri3_pixmap_from_buffers_checked(conn,
img->pixmap, DefaultRootWindow(priv->glx.display),
1, w/4, h,
pitch, offset,
pitch, 0,
pitch, 0,
pitch, 0,
32, 32, modifiers,
fdarray );
xcb_generic_error_t* err = xcb_request_check(conn, cookie);
if (err)
{
msg_Err(interop->gl, "can't create DRI3 pixmap (%u) %u:%u", err->error_code, err->major_code, err->minor_code);
free(err);
goto error;
return NULL;
}
xcb_flush(conn);
const int attribs_pixmap[] = {
GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
GLX_TEXTURE_FORMAT_EXT, xwa.depth == 32 ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT,
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
GLX_MIPMAP_TEXTURE_EXT, False,
None,
};
img->glxpixmap = priv->glx.glXCreatePixmap(priv->glx.display, fbc, img->pixmap, attribs_pixmap);
GLenum glErr = priv->gl.extension_vt.GetError();
if (glErr != GL_NO_ERROR)
{
msg_Err(interop->gl, "can't create GLX pixmap (%u)", glErr);
goto error;
}
return img;
}
static void
vaglx_image_destroy(const struct vlc_gl_interop *interop, GLXImagePriv* imagePriv)
{
struct priv *priv = interop->priv;
if (!imagePriv)
return;
if (imagePriv->glxpixmap)
priv->glx.glXDestroyPixmap(priv->glx.display, imagePriv->glxpixmap);
if (imagePriv->pixmap)
XFreePixmap(priv->glx.display, imagePriv->pixmap);
free(imagePriv);
error:
vaglx_image_destroy(interop, img);
return NULL;
}
static void
vaglx_release_last_pic(const struct vlc_gl_interop *interop, struct priv *priv)
{
......@@ -153,13 +216,7 @@ vaglx_release_last_pic(const struct vlc_gl_interop *interop, struct priv *priv)
for (unsigned i = 0; i < priv->last.va_image.num_planes; ++i)
vaglx_image_destroy(interop, priv->last.glx_images[i]);
#if VA_CHECK_VERSION(1, 1, 0)
for (unsigned i = 0; i < priv->last.va_surface_descriptor.num_objects; ++i)
close(priv->last.va_surface_descriptor.objects[i].fd);
#else
vlc_vaapi_ReleaseBufferHandle(o, priv->vadpy, priv->last.va_image.buf);
#endif
vlc_vaapi_DestroyImage(o, priv->vadpy, priv->last.va_image.image_id);
picture_Release(priv->last.pic);
......@@ -189,8 +246,6 @@ tc_vaglx_update(const struct vlc_gl_interop *interop, uint32_t textures[],
const int32_t tex_width[], const int32_t tex_height[],
picture_t *pic, const size_t *plane_offset)
{
msg_Err(interop->gl, "tc_vaglx_update");
(void) plane_offset;
struct priv *priv = interop->priv;
vlc_object_t *o = VLC_OBJECT(interop->gl);
......@@ -214,10 +269,6 @@ tc_vaglx_update(const struct vlc_gl_interop *interop, uint32_t textures[],
}
else
{
vlc_vaapi_PutSurface(o, priv->vadpy, vlc_vaapi_PicGetSurface(pic), NULL,
0, 0, pic->format.i_width, pic->format.i_height,
0, 0, pic->format.i_width, pic->format.i_height,
NULL, 0, 0);
if (vlc_vaapi_DeriveImage(o, priv->vadpy, vlc_vaapi_PicGetSurface(pic),
&va_image))
goto error;
......@@ -242,7 +293,7 @@ tc_vaglx_update(const struct vlc_gl_interop *interop, uint32_t textures[],
}
#if VA_CHECK_VERSION(1, 1, 0)
for (unsigned i = 0; i < va_surface_descriptor.num_layers; ++i)
for (unsigned i = 0; i < 1 /* va_surface_descriptor.num_layers */; ++i)
{
unsigned obj_idx = va_surface_descriptor.layers[i].object_index[0];
......@@ -252,21 +303,39 @@ tc_vaglx_update(const struct vlc_gl_interop *interop, uint32_t textures[],
if (va_surface_descriptor.layers[i].num_planes > 1)
goto error;
glx_images[i] =
vaglx_image_create(interop, tex_width[i], tex_height[i]);
if (glx_images[i] == 0)
goto error;
glx_images[i] = vaglx_image_create(interop, tex_width[i], tex_height[i],
va_surface_descriptor.objects[obj_idx].fd,
va_surface_descriptor.layers[i].offset[0],
va_surface_descriptor.layers[i].pitch[0],
va_surface_descriptor.objects[obj_idx].size,
va_surface_descriptor.objects[obj_idx].drm_format_modifier
);
#define CHECK_GL(reason) { \
GLenum glErr = priv->gl.extension_vt.GetError(); \
if (glErr != GL_NO_ERROR) \
{ \
msg_Err(interop->gl, "can't %s pixmap (%x)", reason, glErr); \
goto error; \
} \
}
priv->gl.BindTexture(interop->tex_target, textures[i]);
if (glx_images[i] == NULL)
goto error;
priv->gl.BindTexture(GL_TEXTURE_2D, textures[i]);
priv->glx.glXBindTexImageEXT(priv->glx.display, glx_images[i]->glxpixmap, GLX_FRONT_EXT, NULL);
}
#else
for (unsigned i = 0; i < va_image.num_planes; ++i)
{
glx_images[i] =
vaglx_image_create(interop, tex_width[i], tex_height[i]);
if (glx_images[i] == NULL)
glx_images[i] = vaglx_image_create(interop, tex_width[i], tex_height[i],
va_buffer_info.handle,
va_image.offsets[i],
va_image.pitches[i],
42);
if (egl_images[i] == NULL)
goto error;
priv->gl.BindTexture(interop->tex_target, textures[i]);
......@@ -306,7 +375,7 @@ error:
#endif
}
for (unsigned i = 0; i < 3 && glx_images[i] != 0; ++i)
for (unsigned i = 0; i < 3 && glx_images[i] != NULL; ++i)
vaglx_image_destroy(interop, glx_images[i]);
vlc_vaapi_DestroyImage(o, priv->vadpy, va_image.image_id);
......@@ -393,21 +462,20 @@ tc_va_check_derive_image(const struct vlc_gl_interop *interop)
for (unsigned i = 0; i < image_desc->plane_count; ++i)
{
unsigned w_num = image_desc->p[i].w.num;
if (image_desc->plane_count == 2 && i == 1)
// for NV12/P010 the second plane uses GL_RG which has a double pitch
w_num /= 2;
int w = (va_image.width * w_num) / image_desc->p[i].w.den;
int h = (va_image.height * image_desc->p[i].h.num) / image_desc->p[i].h.den;
GLXPixmap glx_image =
vaglx_image_create(interop, w, h);
if (glx_image == 0)
{
msg_Warn(o, "Can't create Image KHR: kernel too old ?");
ret = VLC_EGENERIC;
goto done;
}
vaglx_image_destroy(interop, glx_image);
//unsigned w_num = image_desc->p[i].w.num;
//if (image_desc->plane_count == 2 && i == 1)
// // for NV12/P010 the second plane uses GL_RG which has a double pitch
// w_num /= 2;
//int w = (va_image.width * w_num) / image_desc->p[i].w.den;
//int h = (va_image.height * image_desc->p[i].h.num) / image_desc->p[i].h.den;
//GLXPixmap glx_image = vaglx_image_create(interop, w, h);
//if (glx_image == 0)
//{
// msg_Warn(o, "Can't create Image KHR: kernel too old ?");
// ret = VLC_EGENERIC;
// goto done;
//}
//vaglx_image_destroy(interop, glx_image);
}
done:
......@@ -438,14 +506,13 @@ Open(vlc_object_t *obj)
goto error;
}
struct vlc_gl_extension_vt extension_vt;
vlc_gl_LoadExtensionFunctions(interop->gl, &extension_vt);
priv = interop->priv = calloc(1, sizeof(struct priv));
if (unlikely(priv == NULL))
goto error;
priv->fourcc = 0;
vlc_gl_LoadExtensionFunctions(interop->gl, &priv->gl.extension_vt);
int va_fourcc;
int vlc_sw_chroma;
switch (interop->fmt_in.i_chroma)
......@@ -538,6 +605,14 @@ Open(vlc_object_t *obj)
if (priv->gl.BindTexture == NULL)
goto error;
priv->gl.GenTextures = vlc_gl_GetProcAddress(interop->gl, "GenTextures");
if (priv->gl.GenTextures == NULL)
goto error;
priv->gl.TextureView = vlc_gl_GetProcAddress(interop->gl, "glTextureView");
if (priv->gl.TextureView == NULL)
goto error;
priv->vadpy = dec_device->opaque;
assert(priv->vadpy != NULL);
......@@ -548,7 +623,7 @@ Open(vlc_object_t *obj)
goto error;
///* The pictures are uploaded upside-down */
//video_format_TransformBy(&interop->fmt_out, TRANSFORM_VFLIP);
video_format_TransformBy(&interop->fmt_out, TRANSFORM_VFLIP);
interop->tex_target = GL_TEXTURE_2D;
interop->fmt_out.i_chroma = vlc_sw_chroma;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment