mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
x11: implement pixmap rendering with RENDER extension.
Use hardware accelerated XRenderComposite() function, from the RENDER extension, to blit a pixmap to screen. Besides, this can also support cropping and scaling.
This commit is contained in:
parent
373329e6ff
commit
0af0849a92
6 changed files with 176 additions and 5 deletions
17
configure.ac
17
configure.ac
|
@ -470,6 +470,23 @@ if test $HAVE_XRANDR -eq 1; then
|
|||
[Defined to 1 if the XRandR extension exists.])
|
||||
fi
|
||||
|
||||
dnl Check for XRender
|
||||
HAVE_XRENDER=0
|
||||
if test $USE_X11 -eq 1; then
|
||||
HAVE_XRENDER=1
|
||||
PKG_CHECK_MODULES([XRENDER], [xrender], [:], [HAVE_XRENDER=0])
|
||||
if test $HAVE_XRENDER -eq 1; then
|
||||
saved_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $XRENDER_CFLAGS"
|
||||
AC_CHECK_HEADERS([X11/extensions/Xrender.h], [:], [HAVE_XRENDER=0])
|
||||
CPPFLAGS="$saved_CPPFLAGS"
|
||||
fi
|
||||
fi
|
||||
if test $HAVE_XRENDER -eq 1; then
|
||||
AC_DEFINE_UNQUOTED([HAVE_XRENDER], [1],
|
||||
[Defined to 1 if the XRender extension exists.])
|
||||
fi
|
||||
|
||||
dnl OpenGL
|
||||
enable_opengl="no"
|
||||
if test "$enable_glx" = "yes"; then
|
||||
|
|
|
@ -289,6 +289,7 @@ libgstvaapi_x11_@GST_API_VERSION@_la_CFLAGS = \
|
|||
$(GST_BASE_CFLAGS) \
|
||||
$(X11_CFLAGS) \
|
||||
$(XRANDR_CFLAGS) \
|
||||
$(XRENDER_CFLAGS) \
|
||||
$(LIBVA_X11_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
|
@ -296,6 +297,7 @@ libgstvaapi_x11_@GST_API_VERSION@_la_LIBADD = \
|
|||
$(GLIB_LIBS) \
|
||||
$(X11_LIBS) \
|
||||
$(XRANDR_LIBS) \
|
||||
$(XRENDER_LIBS) \
|
||||
$(LIBVA_X11_LIBS) \
|
||||
libgstvaapi-$(GST_API_VERSION).la \
|
||||
$(NULL)
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
# include <X11/extensions/Xrandr.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XRENDER
|
||||
# include <X11/extensions/Xrender.h>
|
||||
#endif
|
||||
|
||||
#define DEBUG 1
|
||||
#include "gstvaapidebug.h"
|
||||
|
||||
|
@ -130,18 +134,22 @@ set_synchronous(GstVaapiDisplayX11 *display, gboolean synchronous)
|
|||
}
|
||||
}
|
||||
|
||||
/* Check whether XRANDR extension is available */
|
||||
/* Check for display server extensions */
|
||||
static void
|
||||
check_xrandr(GstVaapiDisplayX11 *display)
|
||||
check_extensions(GstVaapiDisplayX11 *display)
|
||||
{
|
||||
#ifdef HAVE_XRANDR
|
||||
GstVaapiDisplayX11Private * const priv =
|
||||
GST_VAAPI_DISPLAY_X11_PRIVATE(display);
|
||||
int evt_base, err_base;
|
||||
|
||||
#ifdef HAVE_XRANDR
|
||||
priv->use_xrandr = XRRQueryExtension(priv->x11_display,
|
||||
&evt_base, &err_base);
|
||||
#endif
|
||||
#ifdef HAVE_XRENDER
|
||||
priv->has_xrender = XRenderQueryExtension(priv->x11_display,
|
||||
&evt_base, &err_base);
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -156,7 +164,7 @@ gst_vaapi_display_x11_bind_display(GstVaapiDisplay *base_display,
|
|||
priv->x11_screen = DefaultScreen(native_display);
|
||||
priv->use_foreign_display = TRUE;
|
||||
|
||||
check_xrandr(display);
|
||||
check_extensions(display);
|
||||
|
||||
if (!set_display_name(display, XDisplayString(priv->x11_display)))
|
||||
return FALSE;
|
||||
|
@ -193,7 +201,7 @@ gst_vaapi_display_x11_open_display(GstVaapiDisplay *base_display,
|
|||
}
|
||||
priv->x11_screen = DefaultScreen(priv->x11_display);
|
||||
|
||||
check_xrandr(display);
|
||||
check_extensions(display);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,17 @@ typedef struct _GstVaapiDisplayX11Class GstVaapiDisplayX11Class;
|
|||
#define GST_VAAPI_DISPLAY_XSCREEN(display) \
|
||||
GST_VAAPI_DISPLAY_X11_PRIVATE(display)->x11_screen
|
||||
|
||||
/**
|
||||
* GST_VAAPI_DISPLAY_HAS_XRENDER:
|
||||
* @display: a #GstVaapiDisplay
|
||||
*
|
||||
* Macro that evaluates to the existence of the XRender extension on
|
||||
* @display server.
|
||||
*/
|
||||
#undef GST_VAAPI_DISPLAY_HAS_XRENDER
|
||||
#define GST_VAAPI_DISPLAY_HAS_XRENDER(display) \
|
||||
(GST_VAAPI_DISPLAY_X11_PRIVATE(display)->has_xrender)
|
||||
|
||||
struct _GstVaapiDisplayX11Private {
|
||||
gchar *display_name;
|
||||
Display *x11_display;
|
||||
|
@ -70,6 +81,7 @@ struct _GstVaapiDisplayX11Private {
|
|||
GArray *pixmap_formats;
|
||||
guint use_foreign_display : 1; // Foreign native_display?
|
||||
guint use_xrandr : 1;
|
||||
guint has_xrender : 1; // Has XRender extension?
|
||||
guint synchronous : 1;
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "gstvaapicompat.h"
|
||||
#include "gstvaapiwindow_x11.h"
|
||||
#include "gstvaapiwindow_x11_priv.h"
|
||||
#include "gstvaapipixmap_x11.h"
|
||||
#include "gstvaapipixmap_priv.h"
|
||||
#include "gstvaapidisplay_x11.h"
|
||||
#include "gstvaapidisplay_x11_priv.h"
|
||||
#include "gstvaapiutils.h"
|
||||
|
@ -223,6 +225,9 @@ gst_vaapi_window_x11_create(GstVaapiWindow *window, guint *width, guint *height)
|
|||
"_NET_WM_STATE_FULLSCREEN",
|
||||
};
|
||||
|
||||
priv->has_xrender = GST_VAAPI_DISPLAY_HAS_XRENDER(
|
||||
GST_VAAPI_OBJECT_DISPLAY(window));
|
||||
|
||||
if (window->use_foreign_window && xid) {
|
||||
GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
|
||||
XGetWindowAttributes(dpy, xid, &wattr);
|
||||
|
@ -266,6 +271,17 @@ gst_vaapi_window_x11_destroy(GstVaapiWindow *window)
|
|||
Display * const dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
|
||||
const Window xid = GST_VAAPI_OBJECT_ID(window);
|
||||
|
||||
#ifdef HAVE_XRENDER
|
||||
GstVaapiWindowX11Private * const priv =
|
||||
GST_VAAPI_WINDOW_X11_GET_PRIVATE(window);
|
||||
if (priv->picture) {
|
||||
GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
|
||||
XRenderFreePicture(dpy, priv->picture);
|
||||
GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
|
||||
priv->picture = None;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (xid) {
|
||||
if (!window->use_foreign_window) {
|
||||
GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
|
||||
|
@ -434,6 +450,113 @@ gst_vaapi_window_x11_render(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vaapi_window_x11_render_pixmap_xrender(
|
||||
GstVaapiWindow *window,
|
||||
GstVaapiPixmap *pixmap,
|
||||
const GstVaapiRectangle *src_rect,
|
||||
const GstVaapiRectangle *dst_rect
|
||||
)
|
||||
{
|
||||
#ifdef HAVE_XRENDER
|
||||
GstVaapiWindowX11Private * const priv =
|
||||
GST_VAAPI_WINDOW_X11_GET_PRIVATE(window);
|
||||
Display * const dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
|
||||
const Window win = GST_VAAPI_OBJECT_ID(window);
|
||||
const Pixmap pix = GST_VAAPI_OBJECT_ID(pixmap);
|
||||
Picture picture;
|
||||
XRenderPictFormat *pic_fmt;
|
||||
XWindowAttributes wattr;
|
||||
int fmt, op;
|
||||
gboolean success = FALSE;
|
||||
|
||||
/* Ensure Picture for window is created */
|
||||
if (!priv->picture) {
|
||||
GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
|
||||
XGetWindowAttributes(dpy, win, &wattr);
|
||||
pic_fmt = XRenderFindVisualFormat(dpy, wattr.visual);
|
||||
if (pic_fmt)
|
||||
priv->picture = XRenderCreatePicture(dpy, win, pic_fmt, 0, NULL);
|
||||
GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
|
||||
if (!priv->picture)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check pixmap format */
|
||||
switch (GST_VAAPI_PIXMAP_FORMAT(pixmap)) {
|
||||
case GST_VIDEO_FORMAT_xRGB:
|
||||
fmt = PictStandardRGB24;
|
||||
op = PictOpSrc;
|
||||
goto get_pic_fmt;
|
||||
case GST_VIDEO_FORMAT_ARGB:
|
||||
fmt = PictStandardARGB32;
|
||||
op = PictOpOver;
|
||||
get_pic_fmt:
|
||||
GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
|
||||
pic_fmt = XRenderFindStandardFormat(dpy, fmt);
|
||||
GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
|
||||
break;
|
||||
default:
|
||||
pic_fmt = NULL;
|
||||
break;
|
||||
}
|
||||
if (!pic_fmt)
|
||||
return FALSE;
|
||||
|
||||
GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
|
||||
do {
|
||||
const double sx = (double)src_rect->width / dst_rect->width;
|
||||
const double sy = (double)src_rect->height / dst_rect->height;
|
||||
XTransform xform;
|
||||
|
||||
picture = XRenderCreatePicture(dpy, pix, pic_fmt, 0, NULL);
|
||||
if (!picture)
|
||||
break;
|
||||
|
||||
xform.matrix[0][0] = XDoubleToFixed(sx);
|
||||
xform.matrix[0][1] = XDoubleToFixed(0.0);
|
||||
xform.matrix[0][2] = XDoubleToFixed(src_rect->x);
|
||||
xform.matrix[1][0] = XDoubleToFixed(0.0);
|
||||
xform.matrix[1][1] = XDoubleToFixed(sy);
|
||||
xform.matrix[1][2] = XDoubleToFixed(src_rect->y);
|
||||
xform.matrix[2][0] = XDoubleToFixed(0.0);
|
||||
xform.matrix[2][1] = XDoubleToFixed(0.0);
|
||||
xform.matrix[2][2] = XDoubleToFixed(1.0);
|
||||
XRenderSetPictureTransform(dpy, picture, &xform);
|
||||
|
||||
XRenderComposite(dpy, op, picture, None, priv->picture,
|
||||
0, 0, 0, 0, dst_rect->x, dst_rect->y,
|
||||
dst_rect->width, dst_rect->height);
|
||||
XSync(dpy, False);
|
||||
success = TRUE;
|
||||
} while (0);
|
||||
if (picture)
|
||||
XRenderFreePicture(dpy, picture);
|
||||
GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
|
||||
return success;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vaapi_window_x11_render_pixmap(
|
||||
GstVaapiWindow *window,
|
||||
GstVaapiPixmap *pixmap,
|
||||
const GstVaapiRectangle *src_rect,
|
||||
const GstVaapiRectangle *dst_rect
|
||||
)
|
||||
{
|
||||
GstVaapiWindowX11Private * const priv =
|
||||
GST_VAAPI_WINDOW_X11_GET_PRIVATE(window);
|
||||
|
||||
if (priv->has_xrender)
|
||||
return gst_vaapi_window_x11_render_pixmap_xrender(window, pixmap,
|
||||
src_rect, dst_rect);
|
||||
|
||||
/* XXX: only X RENDER extension is supported for now */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gst_vaapi_window_x11_class_init(GstVaapiWindowX11Class *klass)
|
||||
{
|
||||
|
@ -452,6 +575,7 @@ gst_vaapi_window_x11_class_init(GstVaapiWindowX11Class *klass)
|
|||
window_class->set_fullscreen = gst_vaapi_window_x11_set_fullscreen;
|
||||
window_class->resize = gst_vaapi_window_x11_resize;
|
||||
window_class->render = gst_vaapi_window_x11_render;
|
||||
window_class->render_pixmap = gst_vaapi_window_x11_render_pixmap;
|
||||
}
|
||||
|
||||
#define gst_vaapi_window_x11_finalize \
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
|
||||
#include "gstvaapiwindow_priv.h"
|
||||
|
||||
#ifdef HAVE_XRENDER
|
||||
# include <X11/extensions/Xrender.h>
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_VAAPI_WINDOW_X11_GET_PRIVATE(obj) \
|
||||
|
@ -42,8 +46,12 @@ typedef struct _GstVaapiWindowX11Class GstVaapiWindowX11Class;
|
|||
struct _GstVaapiWindowX11Private {
|
||||
Atom atom_NET_WM_STATE;
|
||||
Atom atom_NET_WM_STATE_FULLSCREEN;
|
||||
#ifdef HAVE_XRENDER
|
||||
Picture picture;
|
||||
#endif
|
||||
guint is_mapped : 1;
|
||||
guint fullscreen_on_map : 1;
|
||||
guint has_xrender : 1;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue