summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac47
-rw-r--r--gst-libs/gst/vaapi/Makefile.am49
-rw-r--r--gst-libs/gst/vaapi/gstvaapidisplay_glx.c99
-rw-r--r--gst-libs/gst/vaapi/gstvaapidisplay_glx.h90
-rw-r--r--gst-libs/gst/vaapi/gstvaapiutils_glx.c183
-rw-r--r--gst-libs/gst/vaapi/gstvaapiutils_glx.h57
-rw-r--r--gst-libs/gst/vaapi/gstvaapiwindow_glx.c488
-rw-r--r--gst-libs/gst/vaapi/gstvaapiwindow_glx.h100
-rw-r--r--pkgconfig/Makefile.am16
-rw-r--r--pkgconfig/gstreamer-vaapi-glx.pc.in12
-rw-r--r--tests/Makefile.am21
-rw-r--r--tests/test-textures.c141
12 files changed, 1289 insertions, 14 deletions
diff --git a/configure.ac b/configure.ac
index a8d73a08..3b73507b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,6 +70,11 @@ AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_LIBTOOL
+AC_ARG_ENABLE(glx,
+ AC_HELP_STRING([--enable-glx],
+ [enable OpenGL/X11 @<:@default=yes@:>@]),
+ [], [enable_glx="yes"])
+
dnl Check for __attribute__((visibility()))
AC_CACHE_CHECK([whether __attribute__((visibility())) is supported],
vaapi_cv_visibility_attribute,
@@ -150,11 +155,28 @@ AC_SUBST(plugindir)
dnl Check for X11
PKG_CHECK_MODULES(X11, [x11])
+dnl Check for OpenGL
+USE_GLX=1
+if test "$enable_glx" != "yes"; then
+ USE_GLX=0
+fi
+OPENGL_CFLAGS=""
+OPENGL_LIBS=""
+AC_CHECK_HEADERS([GL/gl.h GL/glext.h GL/glx.h], [], [USE_GLX=0], [
+#ifdef HAVE_GL_GL_H
+# include <GL/gl.h>
+#endif
+])
+AC_CHECK_LIB(GL, glXCreateContext, [OPENGL_LIBS="-lGL -ldl"], [USE_GLX=0])
+AC_SUBST(OPENGL_CFLAGS)
+AC_SUBST(OPENGL_LIBS)
+
dnl Check for VA-API
LIBVA_PKGNAME="libva"
PKG_CHECK_MODULES(LIBVA, [$LIBVA_PKGNAME])
AC_SUBST(LIBVA_PKGNAME)
+dnl ... original VA-API 0.29
AC_CACHE_CHECK([for old VA-API 0.29],
ac_cv_have_vaapi_old, [
saved_CFLAGS="$CFLAGS"
@@ -173,6 +195,7 @@ if test "$ac_cv_have_vaapi_old" = "yes"; then
LIBVA_EXTRA_CFLAGS="$LIBVA_CFLAGS -DGST_VAAPI_USE_OLD_VAAPI_0_29"
fi
+dnl ... VA-API >= 0.31 or -sds
LIBVA_X11_PKGNAME="libva-x11"
PKG_CHECK_MODULES(LIBVA_X11, [$LIBVA_X11_PKGNAME],
[ac_cv_have_vaapi_x11="yes"],
@@ -189,9 +212,24 @@ if test "$ac_cv_have_vaapi_x11" = "no"; then
fi
AC_SUBST(LIBVA_X11_PKGNAME)
+dnl ... VA-API >= 0.31 or -sds
+LIBVA_GLX_PKGNAME="libva-glx"
+PKG_CHECK_MODULES(LIBVA_GLX, [$LIBVA_GLX_PKGNAME],
+ [ac_cv_have_vaapi_glx="yes"],
+ [ac_cv_have_vaapi_glx="no"]
+)
+if test "$ac_cv_have_vaapi_glx" = "no"; then
+ AC_MSG_WARN([could not find VA/GLX extensions. Disabling GLX support])
+ USE_GLX=0
+fi
+AC_SUBST(LIBVA_GLX_PKGNAME)
+
AC_SUBST(LIBVA_EXTRA_CFLAGS)
AC_SUBST(LIBVA_EXTRA_LIBS)
+AC_DEFINE_UNQUOTED(USE_GLX, $USE_GLX, [Defined to 1 if GLX is enabled])
+AM_CONDITIONAL(USE_GLX, test $USE_GLX -eq 1)
+
VA_VERSION=`$PKG_CONFIG --modversion libva`
VA_MAJOR_VERSION=`echo "$VA_VERSION" | cut -d'.' -f1`
VA_MINOR_VERSION=`echo "$VA_VERSION" | cut -d'.' -f2`
@@ -231,8 +269,12 @@ debian.upstream/libgstvaapi-x11.install.in
gst-libs/gst/Makefile
gst-libs/gst/vaapi/Makefile
pkgconfig/Makefile
- pkgconfig/gstreamer-vaapi.pc
- pkgconfig/gstreamer-vaapi-x11.pc
+ pkgconfig/gstreamer-vaapi-$GST_MAJORMINOR.pc:\
+pkgconfig/gstreamer-vaapi.pc.in
+ pkgconfig/gstreamer-vaapi-glx-$GST_MAJORMINOR.pc:\
+pkgconfig/gstreamer-vaapi-glx.pc.in
+ pkgconfig/gstreamer-vaapi-x11-$GST_MAJORMINOR.pc:\
+pkgconfig/gstreamer-vaapi-x11.pc.in
sys/Makefile
sys/vaapiconvert/Makefile
sys/vaapisink/Makefile
@@ -244,4 +286,5 @@ echo
echo $PACKAGE configuration summary:
echo
echo VA-API version ................... : $VA_VERSION_STR
+echo GLX support ...................... : $(test $USE_GLX -eq 1 && echo yes || echo no)
echo
diff --git a/gst-libs/gst/vaapi/Makefile.am b/gst-libs/gst/vaapi/Makefile.am
index b1bef04e..d9626f9a 100644
--- a/gst-libs/gst/vaapi/Makefile.am
+++ b/gst-libs/gst/vaapi/Makefile.am
@@ -3,6 +3,10 @@ lib_LTLIBRARIES = \
libgstvaapi-x11-@GST_MAJORMINOR@.la \
$(NULL)
+if USE_GLX
+lib_LTLIBRARIES += libgstvaapi-glx-@GST_MAJORMINOR@.la
+endif
+
libgstvaapi_includedir = \
$(includedir)/gstreamer-@GST_MAJORMINOR@/gst/vaapi
@@ -68,6 +72,26 @@ libgstvaapi_x11_source_priv_h = \
gstvaapiutils_x11.h \
$(NULL)
+libgstvaapi_glx_source_c = \
+ gstvaapidisplay_glx.c \
+ gstvaapiutils.c \
+ gstvaapiutils_glx.c \
+ gstvaapiutils_x11.c \
+ gstvaapiwindow_glx.c \
+ $(NULL)
+
+libgstvaapi_glx_source_h = \
+ gstvaapicompat.h \
+ gstvaapidisplay_glx.h \
+ gstvaapiwindow_glx.h \
+ $(NULL)
+
+libgstvaapi_glx_source_priv_h = \
+ gstvaapiutils.h \
+ gstvaapiutils_glx.h \
+ gstvaapiutils_x11.h \
+ $(NULL)
+
libgstvaapi_@GST_MAJORMINOR@_la_SOURCES = \
$(libgstvaapi_source_c) \
$(libgstvaapi_source_priv_h) \
@@ -118,6 +142,31 @@ libgstvaapi_x11_@GST_MAJORMINOR@_la_LIBADD = \
libgstvaapi-@GST_MAJORMINOR@.la \
$(NULL)
+libgstvaapi_glx_@GST_MAJORMINOR@_la_SOURCES = \
+ $(libgstvaapi_glx_source_c) \
+ $(libgstvaapi_glx_source_priv_h) \
+ $(NULL)
+
+libgstvaapi_glx_@GST_MAJORMINOR@include_HEADERS = \
+ $(libgstvaapi_glx_source_h) \
+ $(NULL)
+
+libgstvaapi_glx_@GST_MAJORMINOR@includedir = \
+ $(libgstvaapi_includedir)
+
+libgstvaapi_glx_@GST_MAJORMINOR@_la_CFLAGS = \
+ -I$(top_srcdir)/gst-libs \
+ $(GLIB_CFLAGS) \
+ $(GST_BASE_CFLAGS) \
+ $(LIBVA_GLX_CFLAGS) \
+ $(NULL)
+
+libgstvaapi_glx_@GST_MAJORMINOR@_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(LIBVA_GLX_LIBS) \
+ libgstvaapi-x11-@GST_MAJORMINOR@.la \
+ $(NULL)
+
# Extra clean files so that maintainer-clean removes *everything*
MAINTAINERCLEANFILES = Makefile.in
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_glx.c b/gst-libs/gst/vaapi/gstvaapidisplay_glx.c
new file mode 100644
index 00000000..7a078cf7
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapidisplay_glx.c
@@ -0,0 +1,99 @@
+/*
+ * gstvaapidisplay_glx.c - VA/GLX display abstraction
+ *
+ * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * SECTION:gstvaapidisplay_glx
+ * @short_description: VA/GLX display abstraction
+ */
+
+#include "config.h"
+#include "gstvaapiutils.h"
+#include "gstvaapidisplay_glx.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDisplayGLX,
+ gst_vaapi_display_glx,
+ GST_VAAPI_TYPE_DISPLAY_X11);
+
+static void
+gst_vaapi_display_glx_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gst_vaapi_display_glx_parent_class)->finalize(object);
+}
+
+static VADisplay
+gst_vaapi_display_glx_get_va_display(GstVaapiDisplay *display)
+{
+ return vaGetDisplayGLX(GST_VAAPI_DISPLAY_XDISPLAY(display));
+}
+
+static void
+gst_vaapi_display_glx_class_init(GstVaapiDisplayGLXClass *klass)
+{
+ GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+ GstVaapiDisplayClass * const dpy_class = GST_VAAPI_DISPLAY_CLASS(klass);
+
+ object_class->finalize = gst_vaapi_display_glx_finalize;
+ dpy_class->get_display = gst_vaapi_display_glx_get_va_display;
+}
+
+static void
+gst_vaapi_display_glx_init(GstVaapiDisplayGLX *display)
+{
+}
+
+/**
+ * gst_vaapi_display_glx_new:
+ * @display_name: the X11 display name
+ *
+ * Opens an X11 #Display using @display_name and returns a newly
+ * allocated #GstVaapiDisplay object. The X11 display will be cloed
+ * when the reference count of the object reaches zero.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_glx_new(const gchar *display_name)
+{
+ return g_object_new(GST_VAAPI_TYPE_DISPLAY_GLX,
+ "display-name", display_name,
+ NULL);
+}
+
+/**
+ * gst_vaapi_display_glx_new_with_display:
+ * @x11_display: an X11 #Display
+ *
+ * Creates a #GstVaapiDisplay based on the X11 @x11_display
+ * display. The caller still owns the display and must call
+ * XCloseDisplay() when all #GstVaapiDisplay references are
+ * released. Doing so too early can yield undefined behaviour.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_glx_new_with_display(Display *x11_display)
+{
+ return g_object_new(GST_VAAPI_TYPE_DISPLAY_GLX,
+ "x11-display", x11_display,
+ NULL);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_glx.h b/gst-libs/gst/vaapi/gstvaapidisplay_glx.h
new file mode 100644
index 00000000..6206f1e9
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapidisplay_glx.h
@@ -0,0 +1,90 @@
+/*
+ * gstvaapidisplay_glx.h - VA/GLX display abstraction
+ *
+ * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_GLX_H
+#define GST_VAAPI_DISPLAY_GLX_H
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <va/va_glx.h>
+#include <gst/vaapi/gstvaapidisplay_x11.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DISPLAY_GLX \
+ (gst_vaapi_display_glx_get_type())
+
+#define GST_VAAPI_DISPLAY_GLX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ GST_VAAPI_TYPE_DISPLAY_GLX, \
+ GstVaapiDisplayGLX))
+
+#define GST_VAAPI_DISPLAY_GLX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), \
+ GST_VAAPI_TYPE_DISPLAY_GLX, \
+ GstVaapiDisplayGLXClass))
+
+#define GST_VAAPI_IS_DISPLAY_GLX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DISPLAY_GLX))
+
+#define GST_VAAPI_IS_DISPLAY_GLX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DISPLAY_GLX))
+
+#define GST_VAAPI_DISPLAY_GLX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ GST_VAAPI_TYPE_DISPLAY_GLX, \
+ GstVaapiDisplayGLXClass))
+
+typedef struct _GstVaapiDisplayGLX GstVaapiDisplayGLX;
+typedef struct _GstVaapiDisplayGLXClass GstVaapiDisplayGLXClass;
+
+/**
+ * GstVaapiDisplayGLX:
+ *
+ * VA/GLX display wrapper.
+ */
+struct _GstVaapiDisplayGLX {
+ /*< private >*/
+ GstVaapiDisplayX11 parent_instance;
+};
+
+
+/**
+ * GstVaapiDisplayGLXClass:
+ *
+ * VA/GLX display wrapper clas.
+ */
+struct _GstVaapiDisplayGLXClass {
+ /*< private >*/
+ GstVaapiDisplayX11Class parent_class;
+};
+
+GType
+gst_vaapi_display_glx_get_type(void);
+
+GstVaapiDisplay *
+gst_vaapi_display_glx_new(const gchar *display_name);
+
+GstVaapiDisplay *
+gst_vaapi_display_glx_new_with_display(Display *x11_display);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_GLX_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiutils_glx.c b/gst-libs/gst/vaapi/gstvaapiutils_glx.c
new file mode 100644
index 00000000..8053a54a
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapiutils_glx.c
@@ -0,0 +1,183 @@
+/*
+ * gstvaapiutils_glx.c - GLX utilties
+ *
+ * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "gstvaapiutils_glx.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+/**
+ * gl_get_error_string:
+ * @error: an OpenGL error enumeration
+ *
+ * Retrieves the string representation the OpenGL @error.
+ *
+ * Return error: the static string representing the OpenGL @error
+ */
+const char *
+gl_get_error_string(GLenum error)
+{
+ static const struct {
+ GLenum val;
+ const char *str;
+ }
+ gl_errors[] = {
+ { GL_NO_ERROR, "no error" },
+ { GL_INVALID_ENUM, "invalid enumerant" },
+ { GL_INVALID_VALUE, "invalid value" },
+ { GL_INVALID_OPERATION, "invalid operation" },
+ { GL_STACK_OVERFLOW, "stack overflow" },
+ { GL_STACK_UNDERFLOW, "stack underflow" },
+ { GL_OUT_OF_MEMORY, "out of memory" },
+#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
+ { GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "invalid framebuffer operation" },
+#endif
+ { ~0, NULL }
+ };
+
+ guint i;
+ for (i = 0; gl_errors[i].str; i++) {
+ if (gl_errors[i].val == error)
+ return gl_errors[i].str;
+ }
+ return "unknown";
+}
+
+/**
+ * gl_purge_errors:
+ *
+ * Purges all OpenGL errors. This function is generally useful to
+ * clear up the pending errors prior to calling gl_check_error().
+ */
+void
+gl_purge_errors(void)
+{
+ while (glGetError() != GL_NO_ERROR)
+ ; /* nothing */
+}
+
+/**
+ * gl_check_error:
+ *
+ * Checks whether there is any OpenGL error pending.
+ *
+ * Return value: %TRUE if an error was encountered
+ */
+gboolean
+gl_check_error(void)
+{
+ GLenum error;
+ gboolean has_errors = FALSE;
+
+ while ((error = glGetError()) != GL_NO_ERROR) {
+ GST_DEBUG("glError: %s caught", gl_get_error_string(error));
+ has_errors = TRUE;
+ }
+ return has_errors;
+}
+
+/**
+ * gl_get_param:
+ * @param: the parameter name
+ * @pval: return location for the value
+ *
+ * This function is a wrapper around glGetIntegerv() that does extra
+ * error checking.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_get_param(GLenum param, guint *pval)
+{
+ GLint val;
+
+ gl_purge_errors();
+ glGetIntegerv(param, &val);
+ if (gl_check_error())
+ return FALSE;
+
+ if (pval)
+ *pval = val;
+ return TRUE;
+}
+
+/**
+ * gl_get_param:
+ * @param: the parameter name
+ * @pval: return location for the value
+ *
+ * This function is a wrapper around glGetTexLevelParameteriv() that
+ * does extra error checking.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_get_texture_param(GLenum param, guint *pval)
+{
+ GLint val;
+
+ gl_purge_errors();
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, param, &val);
+ if (gl_check_error())
+ return FALSE;
+
+ if (pval)
+ *pval = val;
+ return TRUE;
+}
+
+/**
+ * gl_set_bgcolor:
+ * @color: the requested RGB color
+ *
+ * Sets background color to the RGB @color. This basically is a
+ * wrapper around glClearColor().
+ */
+void
+gl_set_bgcolor(guint32 color)
+{
+ glClearColor(
+ ((color >> 16) & 0xff) / 255.0f,
+ ((color >> 8) & 0xff) / 255.0f,
+ ( color & 0xff) / 255.0f,
+ 1.0f
+ );
+}
+
+/**
+ * gl_resize:
+ * @width: the requested width, in pixels
+ * @height: the requested height, in pixels
+ *
+ * Resizes the OpenGL viewport to the specified dimensions, using an
+ * orthogonal projection. (0,0) represents the top-left corner of the
+ * window.
+ */
+void
+gl_resize(guint width, guint height)
+{
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, width, height, 0, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiutils_glx.h b/gst-libs/gst/vaapi/gstvaapiutils_glx.h
new file mode 100644
index 00000000..79328e72
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapiutils_glx.h
@@ -0,0 +1,57 @@
+/*
+ * gstvaapiutils_glx.h - GLX utilties
+ *
+ * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef GST_VAAPI_UTILS_GLX_H
+#define GST_VAAPI_UTILS_GLX_H
+
+#include "config.h"
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <glib/gtypes.h>
+
+const char *
+gl_get_error_string(GLenum error)
+ attribute_hidden;
+
+void
+gl_purge_errors(void)
+ attribute_hidden;
+
+gboolean
+gl_check_error(void)
+ attribute_hidden;
+
+gboolean
+gl_get_param(GLenum param, guint *pval)
+ attribute_hidden;
+
+gboolean
+gl_get_texture_param(GLenum param, guint *pval)
+ attribute_hidden;
+
+void
+gl_set_bgcolor(guint32 color)
+ attribute_hidden;
+
+void
+gl_resize(guint width, guint height)
+ attribute_hidden;
+
+#endif /* GST_VAAPI_UTILS_GLX_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_glx.c b/gst-libs/gst/vaapi/gstvaapiwindow_glx.c
new file mode 100644
index 00000000..5d91116f
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapiwindow_glx.c
@@ -0,0 +1,488 @@
+/*
+ * gstvaapiwindow_glx.c - VA/GLX window abstraction
+ *
+ * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * SECTION:gstvaapiwindow_glx
+ * @short_description: VA/GLX window abstraction
+ */
+
+#include "config.h"
+#include "gstvaapiwindow_glx.h"
+#include "gstvaapidisplay_x11.h"
+#include "gstvaapiutils_x11.h"
+#include "gstvaapiutils_glx.h"
+#include "gstvaapiobject_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiWindowGLX,
+ gst_vaapi_window_glx,
+ GST_VAAPI_TYPE_WINDOW_X11);
+
+#define GST_VAAPI_WINDOW_GLX_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
+ GST_VAAPI_TYPE_WINDOW_GLX, \
+ GstVaapiWindowGLXPrivate))
+
+struct _GstVaapiWindowGLXPrivate {
+ XVisualInfo *vi;
+ XVisualInfo vi_static;
+ Colormap cmap;
+ GLXContext context;
+ guint foreign_context : 1;
+ guint foreign_window : 1;
+};
+
+enum {
+ PROP_0,
+
+ PROP_GLX_CONTEXT
+};
+
+static XVisualInfo *
+gst_vaapi_window_glx_create_visual(GstVaapiWindowGLX *window);
+
+static inline void
+_gst_vaapi_window_glx_set_context(
+ GstVaapiWindowGLX *window,
+ GLXContext context,
+ gboolean is_foreign
+)
+{
+ GstVaapiWindowGLXPrivate * const priv = window->priv;
+
+ priv->context = context;
+ priv->foreign_context = is_foreign;
+}
+
+static void
+gst_vaapi_window_glx_destroy_context(GstVaapiWindowGLX *window)
+{
+ GstVaapiWindowGLXPrivate * const priv = window->priv;
+ Display * const dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
+
+ if (priv->context) {
+ if (!priv->foreign_context) {
+ GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+ if (glXGetCurrentContext() == priv->context)
+ glXMakeCurrent(dpy, None, NULL);
+ glXDestroyContext(dpy, priv->context);
+ GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+ }
+ priv->context = NULL;
+ priv->foreign_context = FALSE;
+ }
+}
+
+static gboolean
+gst_vaapi_window_glx_create_context(GstVaapiWindowGLX *window)
+{
+ GstVaapiWindowGLXPrivate * const priv = window->priv;
+ Display * const dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
+ GLXContext ctx = NULL;
+ guint width, height;
+ gboolean has_errors = TRUE;
+
+ if (!gst_vaapi_window_glx_create_visual(window))
+ return FALSE;
+
+ GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+ ctx = glXCreateContext(dpy, priv->vi, NULL, True);
+ if (ctx && glXIsDirect(dpy, ctx)) {
+ _gst_vaapi_window_glx_set_context(window, ctx, FALSE);
+ if (glXMakeCurrent(dpy, GST_VAAPI_OBJECT_ID(window), ctx)) {
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_CULL_FACE);
+ glDrawBuffer(GL_BACK);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ gst_vaapi_window_get_size(GST_VAAPI_WINDOW(window), &width, &height);
+ gl_resize(width, height);
+
+ gl_set_bgcolor(0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ has_errors = FALSE;
+ }
+ }
+ else if (ctx)
+ glXDestroyContext(dpy, ctx);
+ GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+
+ return !has_errors;
+}
+
+static inline void
+gst_vaapi_window_glx_destroy_visual(GstVaapiWindowGLX *window)
+{
+ GstVaapiWindowGLXPrivate * const priv = window->priv;
+
+ if (priv->vi) {
+ if (priv->vi != &priv->vi_static)
+ XFree(priv->vi);
+ priv->vi = NULL;
+ }
+}
+
+static XVisualInfo *
+gst_vaapi_window_glx_create_visual(GstVaapiWindowGLX *window)
+{
+ GstVaapiWindowGLXPrivate * const priv = window->priv;
+ Display * const dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
+ XWindowAttributes wattr;
+ int screen;
+ gboolean has_errors;
+
+ /* XXX: add and use a GstVaapiWindow:double-buffer property? */
+ static GLint gl_visual_attr[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ GL_NONE
+ };
+
+ if (!priv->vi) {
+ /* XXX: add and use a GstVaapiDisplayX11:x11-screen property? */
+ screen = DefaultScreen(dpy);
+
+ GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+ x11_trap_errors();
+ if (!priv->foreign_window)
+ priv->vi = glXChooseVisual(dpy, screen, gl_visual_attr);
+ else {
+ XGetWindowAttributes(dpy, GST_VAAPI_OBJECT_ID(window), &wattr);
+ if (XMatchVisualInfo(dpy, screen, wattr.depth, wattr.visual->class,
+ &priv->vi_static))
+ priv->vi = &priv->vi_static;
+ }
+ has_errors = x11_untrap_errors() != 0;
+ GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+
+ if (has_errors)
+ return NULL;
+ }
+ return priv->vi;
+}
+
+static Visual *
+gst_vaapi_window_glx_get_visual(GstVaapiWindow *window)
+{
+ XVisualInfo *vi;
+
+ vi = gst_vaapi_window_glx_create_visual(GST_VAAPI_WINDOW_GLX(window));
+ if (!vi)
+ return NULL;
+ return vi->visual;
+}
+
+static void
+gst_vaapi_window_glx_destroy_colormap(GstVaapiWindowGLX *window)
+{
+ GstVaapiWindowGLXPrivate * const priv = window->priv;
+ Display * const dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
+
+ if (priv->cmap) {
+ if (!priv->foreign_window) {
+ GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+ XFreeColormap(dpy, priv->cmap);
+ GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+ }
+ priv->cmap = None;
+ }
+}
+
+static Colormap
+gst_vaapi_window_glx_create_colormap(GstVaapiWindowGLX *window)
+{
+ GstVaapiWindowGLXPrivate * const priv = window->priv;
+ Display * const dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
+ int screen;
+ XWindowAttributes wattr;
+ XVisualInfo *vi;
+ gboolean has_errors;
+
+ if (!priv->cmap) {
+ GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+ x11_trap_errors();
+ if (!priv->foreign_window) {
+ vi = gst_vaapi_window_glx_create_visual(window);
+ if (vi) {
+ /* XXX: add a GstVaapiDisplayX11:x11-screen property? */
+ screen = DefaultScreen(dpy);
+ priv->cmap = XCreateColormap(
+ dpy,
+ RootWindow(dpy, screen),
+ vi->visual,
+ AllocNone
+ );
+ }
+ }
+ else {
+ XGetWindowAttributes(dpy, GST_VAAPI_OBJECT_ID(window), &wattr);
+ priv->cmap = wattr.colormap;
+ }
+ has_errors = x11_untrap_errors() != 0;
+ GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+
+ if (has_errors)
+ return None;
+ }
+ return priv->cmap;
+}
+
+static Colormap
+gst_vaapi_window_glx_get_colormap(GstVaapiWindow *window)
+{
+ return gst_vaapi_window_glx_create_colormap(GST_VAAPI_WINDOW_GLX(window));
+}
+
+static void
+gst_vaapi_window_glx_finalize(GObject *object)
+{
+ GstVaapiWindowGLX * const window = GST_VAAPI_WINDOW_GLX(object);
+
+ gst_vaapi_window_glx_destroy_context(window);
+ gst_vaapi_window_glx_destroy_visual(window);
+ gst_vaapi_window_glx_destroy_colormap(window);
+
+ G_OBJECT_CLASS(gst_vaapi_window_glx_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_window_glx_set_property(
+ GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec
+)
+{
+ GstVaapiWindowGLX * const window = GST_VAAPI_WINDOW_GLX(object);
+
+ switch (prop_id) {
+ case PROP_GLX_CONTEXT:
+ gst_vaapi_window_glx_set_context(window, g_value_get_pointer(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_vaapi_window_glx_get_property(
+ GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec
+)
+{
+ GstVaapiWindowGLX * const window = GST_VAAPI_WINDOW_GLX(object);
+
+ switch (prop_id) {
+ case PROP_GLX_CONTEXT:
+ g_value_set_pointer(value, gst_vaapi_window_glx_get_context(window));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_vaapi_window_glx_constructed(GObject *object)
+{
+ GstVaapiWindowGLXPrivate * const priv = GST_VAAPI_WINDOW_GLX(object)->priv;
+ GObjectClass *parent_class;
+
+ priv->foreign_context = priv->context != NULL;
+
+ parent_class = G_OBJECT_CLASS(gst_vaapi_window_glx_parent_class);
+ if (parent_class->constructed)
+ parent_class->constructed(object);
+
+ priv->foreign_window =
+ gst_vaapi_window_x11_is_foreign_xid(GST_VAAPI_WINDOW_X11(object));
+
+ if (!priv->foreign_context)
+ gst_vaapi_window_glx_create_context(GST_VAAPI_WINDOW_GLX(object));
+}
+
+static void
+gst_vaapi_window_glx_class_init(GstVaapiWindowGLXClass *klass)
+{
+ GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+ GstVaapiWindowX11Class * const xwin_class = GST_VAAPI_WINDOW_X11_CLASS(klass);
+
+ g_type_class_add_private(klass, sizeof(GstVaapiWindowGLXPrivate));
+
+ object_class->finalize = gst_vaapi_window_glx_finalize;
+ object_class->set_property = gst_vaapi_window_glx_set_property;
+ object_class->get_property = gst_vaapi_window_glx_get_property;
+ object_class->constructed = gst_vaapi_window_glx_constructed;
+
+ xwin_class->get_visual = gst_vaapi_window_glx_get_visual;
+ xwin_class->get_colormap = gst_vaapi_window_glx_get_colormap;
+
+ /**
+ * GstVaapiDisplayGLX:glx-context:
+ *
+ * The GLX context that was created by gst_vaapi_window_glx_new()
+ * or that was bound from gst_vaapi_window_glx_set_context().
+ */
+ g_object_class_install_property
+ (object_class,
+ PROP_GLX_CONTEXT,
+ g_param_spec_pointer("glx-context",
+ "GLX context",
+ "GLX context",
+ G_PARAM_READWRITE));
+}
+
+static void
+gst_vaapi_window_glx_init(GstVaapiWindowGLX *window)
+{
+ GstVaapiWindowGLXPrivate *priv = GST_VAAPI_WINDOW_GLX_GET_PRIVATE(window);
+
+ window->priv = priv;
+ priv->vi = NULL;
+ priv->cmap = None;
+ priv->context = NULL;
+ priv->foreign_context = FALSE;
+}
+
+/**
+ * gst_vaapi_window_glx_new:
+ * @display: a #GstVaapiDisplay
+ * @width: the requested window width, in pixels
+ * @height: the requested windo height, in pixels
+ *
+ * Creates a window with the specified @width and @height. The window
+ * will be attached to the @display and remains invisible to the user
+ * until gst_vaapi_window_show() is called.
+ *
+ * Return value: the newly allocated #GstVaapiWindow object
+ */
+GstVaapiWindow *
+gst_vaapi_window_glx_new(GstVaapiDisplay *display, guint width, guint height)
+{
+ g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+ g_return_val_if_fail(width > 0, NULL);
+ g_return_val_if_fail(height > 0, NULL);
+
+ return g_object_new(GST_VAAPI_TYPE_WINDOW_GLX,
+ "display", display,
+ "id", GST_VAAPI_ID(None),
+ "width", width,
+ "height", height,
+ NULL);
+}
+
+/**
+ * gst_vaapi_window_glx_new_with_xid:
+ * @display: a #GstVaapiDisplay
+ * @xid: an X11 #Window id
+ *
+ * Creates a #GstVaapiWindow using the X11 #Window @xid. The caller
+ * still owns the window and must call XDestroyWindow() when all
+ * #GstVaapiWindow references are released. Doing so too early can
+ * yield undefined behaviour.
+ *
+ * Return value: the newly allocated #GstVaapiWindow object
+ */
+GstVaapiWindow *
+gst_vaapi_window_glx_new_with_xid(GstVaapiDisplay *display, Window xid)
+{
+ GST_DEBUG("new window from xid 0x%08x", xid);
+
+ g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+ g_return_val_if_fail(xid != None, NULL);
+
+ return g_object_new(GST_VAAPI_TYPE_WINDOW_GLX,
+ "display", display,
+ "id", GST_VAAPI_ID(xid),
+ NULL);
+}
+
+/**
+ * gst_vaapi_window_glx_get_context:
+ * @window: a #GstVaapiWindow
+ *
+ * Returns the #GLXContext bound to the @window.
+ *
+ * Return value: the #GLXContext bound to the @window
+ */
+GLXContext
+gst_vaapi_window_glx_get_context(GstVaapiWindowGLX *window)
+{
+ g_return_val_if_fail(GST_VAAPI_IS_WINDOW_GLX(window), NULL);
+
+ return window->priv->context;
+}
+
+/**
+ * gst_vaapi_window_glx_set_context:
+ * @window: a #GstVaapiWindow
+ * @ctx: a GLX context
+ *
+ * Binds GLX context @ctx to @window. If @ctx is non %NULL, the caller
+ * is responsible to making sure it has compatible visual with that of
+ * the underlying X window. If @ctx is %NULL, a new context is created
+ * and the @window owns it.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_window_glx_set_context(GstVaapiWindowGLX *window, GLXContext ctx)
+{
+ g_return_val_if_fail(GST_VAAPI_IS_WINDOW_GLX(window), FALSE);
+
+ gst_vaapi_window_glx_destroy_context(window);
+
+ if (ctx) {
+ _gst_vaapi_window_glx_set_context(window, ctx, TRUE);
+ return TRUE;
+ }
+ return gst_vaapi_window_glx_create_context(window);
+}
+
+/**
+ * gst_vaapi_window_glx_swap_buffers:
+ * @window: a #GstVaapiWindowGLX
+ *
+ * Promotes the contents of the back buffer of @window to become the
+ * contents of the front buffer of @window. This simply is wrapper
+ * around glXSwapBuffers().
+ */
+void
+gst_vaapi_window_glx_swap_buffers(GstVaapiWindowGLX *window)
+{
+ g_return_if_fail(GST_VAAPI_IS_WINDOW_GLX(window));
+
+ glXSwapBuffers(
+ GST_VAAPI_OBJECT_XDISPLAY(window),
+ GST_VAAPI_OBJECT_ID(window)
+ );
+ glClear(GL_COLOR_BUFFER_BIT);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_glx.h b/gst-libs/gst/vaapi/gstvaapiwindow_glx.h
new file mode 100644
index 00000000..b10fcd4d
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapiwindow_glx.h
@@ -0,0 +1,100 @@
+/*
+ * gstvaapiwindow_glx.h - VA/GLX window abstraction
+ *
+ * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef GST_VAAPI_WINDOW_GLX_H
+#define GST_VAAPI_WINDOW_GLX_H
+
+#include <GL/glx.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiwindow_x11.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_WINDOW_GLX \
+ (gst_vaapi_window_glx_get_type())
+
+#define GST_VAAPI_WINDOW_GLX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ GST_VAAPI_TYPE_WINDOW_GLX, \
+ GstVaapiWindowGLX))
+
+#define GST_VAAPI_WINDOW_GLX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), \
+ GST_VAAPI_TYPE_WINDOW_GLX, \
+ GstVaapiWindowGLXClass))
+
+#define GST_VAAPI_IS_WINDOW_GLX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_WINDOW_GLX))
+
+#define GST_VAAPI_IS_WINDOW_GLX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_WINDOW_GLX))
+
+#define GST_VAAPI_WINDOW_GLX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ GST_VAAPI_TYPE_WINDOW_GLX, \
+ GstVaapiWindowGLXClass))
+
+typedef struct _GstVaapiWindowGLX GstVaapiWindowGLX;
+typedef struct _GstVaapiWindowGLXPrivate GstVaapiWindowGLXPrivate;
+typedef struct _GstVaapiWindowGLXClass GstVaapiWindowGLXClass;
+
+/**
+ * GstVaapiWindowGLX:
+ *
+ * An X11 #Window suitable for GLX rendering.
+ */
+struct _GstVaapiWindowGLX {
+ /*< private >*/
+ GstVaapiWindowX11 parent_instance;
+
+ GstVaapiWindowGLXPrivate *priv;
+};
+
+/**
+ * GstVaapiWindowGLXClass:
+ *
+ * An X11 #Window suitable for GLX rendering.
+ */
+struct _GstVaapiWindowGLXClass {
+ /*< private >*/
+ GstVaapiWindowX11Class parent_class;
+};
+
+GType
+gst_vaapi_window_glx_get_type(void);
+
+GstVaapiWindow *
+gst_vaapi_window_glx_new(GstVaapiDisplay *display, guint width, guint height);
+
+GstVaapiWindow *
+gst_vaapi_window_glx_new_with_xid(GstVaapiDisplay *display, Window xid);
+
+GLXContext
+gst_vaapi_window_glx_get_context(GstVaapiWindowGLX *window);
+
+gboolean
+gst_vaapi_window_glx_set_context(GstVaapiWindowGLX *window, GLXContext ctx);
+
+void
+gst_vaapi_window_glx_swap_buffers(GstVaapiWindowGLX *window);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_WINDOW_GLX_H */
diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am
index 1e772a68..b98888c1 100644
--- a/pkgconfig/Makefile.am
+++ b/pkgconfig/Makefile.am
@@ -1,21 +1,21 @@
-AUTOMAKE_OPTIONS = -Wno-portability
+pcfiles_in = gstreamer-vaapi.pc.in
+pcfiles_in += gstreamer-vaapi-x11.pc.in
+if USE_GLX
+pcfiles_in += gstreamer-vaapi-glx.pc.in
+endif
-pcfiles = gstreamer-vaapi-@GST_MAJORMINOR@.pc
-pcfiles += gstreamer-vaapi-x11-@GST_MAJORMINOR@.pc
+pcfiles = $(pcfiles_in:%.pc.in=%-@GST_MAJORMINOR@.pc)
pkgconfigdir = @pkgconfigdir@
pkgconfig_DATA = $(pcfiles)
EXTRA_DIST = \
gstreamer-vaapi.pc.in \
+ gstreamer-vaapi-glx.pc.in \
gstreamer-vaapi-x11.pc.in \
$(NULL)
-CLEANFILES = $(pcfiles)
-
-# XXX: this is a GNU make extension
-%-@GST_MAJORMINOR@.pc: %.pc
- cp $< $@
+DISTCLEANFILES = $(pcfiles)
# Extra clean files so that maintainer-clean removes *everything*
MAINTAINERCLEANFILES = Makefile.in
diff --git a/pkgconfig/gstreamer-vaapi-glx.pc.in b/pkgconfig/gstreamer-vaapi-glx.pc.in
new file mode 100644
index 00000000..73b4c1bd
--- /dev/null
+++ b/pkgconfig/gstreamer-vaapi-glx.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/gstreamer-@GST_MAJORMINOR@
+pluginsdir=@libdir@/gstreamer-@GST_MAJORMINOR@
+
+Name: GStreamer VA-API (glx) Plugins Libraries
+Description: Streaming media framework, VA-API (glx) plugins libraries
+Requires: gstreamer-vaapi-@GST_MAJORMINOR@ @LIBVA_GLX_PKGNAME@
+Version: @VERSION@
+Libs: -L${libdir} -lgstvaapi-glx-@GST_MAJORMINOR@ @LIBVA_EXTRA_LIBS@
+Cflags: -I${includedir} @LIBVA_EXTRA_CFLAGS@
diff --git a/tests/Makefile.am b/tests/Makefile.am
index de69c18d..ed9ca0a6 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -4,26 +4,39 @@ noinst_PROGRAMS = \
test-windows \
$(NULL)
+noinst_PROGRAMS += \
+ test-textures \
+ $(NULL)
+
TEST_CFLAGS = \
$(GST_CFLAGS) \
-I$(top_srcdir)/gst-libs \
$(X11_CFLAGS)
TEST_LIBS = \
- $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-x11-@GST_MAJORMINOR@.la \
$(X11_LIBS)
+TEST_GLX_LIBS = \
+ $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-glx-@GST_MAJORMINOR@.la
+
+TEST_X11_LIBS = \
+ $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-x11-@GST_MAJORMINOR@.la
+
test_display_SOURCES = test-display.c
test_display_CFLAGS = $(TEST_CFLAGS)
-test_display_LDADD = $(TEST_LIBS)
+test_display_LDADD = $(TEST_LIBS) $(TEST_X11_LIBS)
test_surfaces_SOURCES = test-surfaces.c
test_surfaces_CFLAGS = $(TEST_CFLAGS)
-test_surfaces_LDADD = $(TEST_LIBS)
+test_surfaces_LDADD = $(TEST_LIBS) $(TEST_X11_LIBS)
test_windows_SOURCES = test-windows.c
test_windows_CFLAGS = $(TEST_CFLAGS)
-test_windows_LDADD = $(TEST_LIBS)
+test_windows_LDADD = $(TEST_LIBS) $(TEST_X11_LIBS)
+
+test_textures_SOURCES = test-textures.c
+test_textures_CFLAGS = $(TEST_CFLAGS)
+test_textures_LDADD = $(TEST_LIBS) $(TEST_GLX_LIBS)
# Extra clean files so that maintainer-clean removes *everything*
MAINTAINERCLEANFILES = Makefile.in
diff --git a/tests/test-textures.c b/tests/test-textures.c
new file mode 100644
index 00000000..493faa21
--- /dev/null
+++ b/tests/test-textures.c
@@ -0,0 +1,141 @@
+/*
+ * test-textures.c - Test GstVaapiTexture
+ *
+ * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <gst/vaapi/gstvaapidisplay_glx.h>
+#include <gst/vaapi/gstvaapiwindow_glx.h>
+
+static inline void pause(void)
+{
+ g_print("Press any key to continue...\n");
+ getchar();
+}
+
+static void
+print_caps(GstCaps *caps, const gchar *name)
+{
+ guint i, n_caps = gst_caps_get_size(caps);
+
+ g_print("%u %s caps\n", n_caps, name);
+
+ for (i = 0; i < gst_caps_get_size(caps); i++) {
+ GstStructure * const structure = gst_caps_get_structure(caps, i);
+ if (!structure)
+ g_error("could not get caps structure %d", i);
+
+ g_print(" %s:", gst_structure_get_name(structure));
+
+ if (gst_structure_has_name(structure, "video/x-raw-yuv")) {
+ guint32 fourcc;
+
+ gst_structure_get_fourcc(structure, "format", &fourcc);
+
+ g_print(" fourcc '%c%c%c%c'",
+ fourcc & 0xff,
+ (fourcc >> 8) & 0xff,
+ (fourcc >> 16) & 0xff,
+ (fourcc >> 24) & 0xff);
+ }
+ else {
+ gint bpp, endian, rmask, gmask, bmask, amask;
+ gboolean has_alpha;
+
+ gst_structure_get_int(structure, "bpp", &bpp);
+ gst_structure_get_int(structure, "endianness", &endian);
+ gst_structure_get_int(structure, "red_mask", &rmask);
+ gst_structure_get_int(structure, "blue_mask", &bmask);
+ gst_structure_get_int(structure, "green_mask", &gmask);
+ has_alpha = gst_structure_get_int(structure, "alpha_mask", &amask);
+
+ g_print(" %d bits per pixel, %s endian,",
+ bpp, endian == G_BIG_ENDIAN ? "big" : "little");
+ g_print(" %s masks", has_alpha ? "rgba" : "rgb");
+ g_print(" 0x%08x 0x%08x 0x%08x", rmask, gmask, bmask);
+ if (has_alpha)
+ g_print(" 0x%08x", amask);
+ }
+ g_print("\n");
+ }
+}
+
+static void
+dump_caps(GstVaapiDisplay *display)
+{
+ GstCaps *caps;
+
+ caps = gst_vaapi_display_get_image_caps(display);
+ if (!caps)
+ g_error("could not get VA image caps");
+
+ print_caps(caps, "image");
+ gst_caps_unref(caps);
+
+ caps = gst_vaapi_display_get_subpicture_caps(display);
+ if (!caps)
+ g_error("could not get VA subpicture caps");
+
+ print_caps(caps, "subpicture");
+ gst_caps_unref(caps);
+}
+
+int
+main(int argc, char *argv[])
+{
+ GstVaapiDisplay *display;
+ GstVaapiWindow *window;
+ GstVaapiWindowGLX *glx_window;
+ GLXContext glx_context;
+ Display *x11_display;
+ Window x11_window;
+
+ static const GstVaapiChromaType chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
+ static const guint width = 320;
+ static const guint height = 240;
+ static const guint win_width = 640;
+ static const guint win_height = 480;
+
+ gst_init(&argc, &argv);
+
+ display = gst_vaapi_display_glx_new(NULL);
+ if (!display)
+ g_error("could not create Gst/VA display");
+
+ dump_caps(display);
+
+ window = gst_vaapi_window_glx_new(display, win_width, win_height);
+ if (!window)
+ g_error("could not create window");
+
+ gst_vaapi_window_show(window);
+
+ glx_window = GST_VAAPI_WINDOW_GLX(window);
+ glx_context = gst_vaapi_window_glx_get_context(glx_window);
+ x11_display = gst_vaapi_display_x11_get_display(GST_VAAPI_DISPLAY_X11(display));
+ x11_window = gst_vaapi_object_get_id(GST_VAAPI_OBJECT(window));
+
+ if (!glXMakeCurrent(x11_display, x11_window, glx_context))
+ g_error("could not make VA/GLX window context current");
+
+ pause();
+
+ g_object_unref(window);
+ g_object_unref(display);
+ gst_deinit();
+ return 0;
+}