summaryrefslogtreecommitdiffstats
path: root/sys/glsink
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2007-12-21 00:03:11 +0000
committerDavid Schleef <ds@schleef.org>2007-12-21 00:03:11 +0000
commitbb4e1d10e99c206fdf0ca22a43ef20efa24236ef (patch)
tree5d99e25822404edf4c91fd1e96ee33be00cee66b /sys/glsink
parent1bc2202132e729b40e002eb98520ee7b2a788149 (diff)
downloadgst-plugins-bad-bb4e1d10e99c206fdf0ca22a43ef20efa24236ef.tar.gz
gst-plugins-bad-bb4e1d10e99c206fdf0ca22a43ef20efa24236ef.tar.bz2
gst-plugins-bad-bb4e1d10e99c206fdf0ca22a43ef20efa24236ef.zip
sys/glsink/: Switch to using framebuffer_objects instead of GLXPixmaps, because that's what my driver supports. Remo...
Original commit message from CVS: * sys/glsink/Makefile.am: * sys/glsink/glextensions.c: * sys/glsink/glextensions.h: * sys/glsink/glimagesink.c: * sys/glsink/glimagesink.h: * sys/glsink/glvideo.c: * sys/glsink/glvideo.h: * sys/glsink/gstglbuffer.c: * sys/glsink/gstglbuffer.h: * sys/glsink/gstgldownload.c: * sys/glsink/gstglfilter.c: * sys/glsink/gstglupload.c: * sys/glsink/gstopengl.c: Switch to using framebuffer_objects instead of GLXPixmaps, because that's what my driver supports. Remove GLDrawable, since GstGLDisplay now has a default drawable and context.
Diffstat (limited to 'sys/glsink')
-rw-r--r--sys/glsink/Makefile.am4
-rw-r--r--sys/glsink/glextensions.c57
-rw-r--r--sys/glsink/glextensions.h24
-rw-r--r--sys/glsink/glimagesink.c29
-rw-r--r--sys/glsink/glimagesink.h1
-rw-r--r--sys/glsink/glvideo.c285
-rw-r--r--sys/glsink/glvideo.h62
-rw-r--r--sys/glsink/gstglbuffer.c239
-rw-r--r--sys/glsink/gstglbuffer.h47
-rw-r--r--sys/glsink/gstgldownload.c294
-rw-r--r--sys/glsink/gstglfilter.c416
-rw-r--r--sys/glsink/gstglupload.c112
-rw-r--r--sys/glsink/gstopengl.c12
13 files changed, 1394 insertions, 188 deletions
diff --git a/sys/glsink/Makefile.am b/sys/glsink/Makefile.am
index 43e60378..49d8ac4f 100644
--- a/sys/glsink/Makefile.am
+++ b/sys/glsink/Makefile.am
@@ -7,7 +7,9 @@ libgstglimagesink_la_SOURCES = \
gstopengl.c \
glextensions.c \
gstglbuffer.c \
- gstglupload.c
+ gstglupload.c \
+ gstgldownload.c \
+ gstglfilter.c
libgstglimagesink_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) $(GST_BASE_CFLAGS) \
$(GST_PLUGINS_BASE_CFLAGS)
libgstglimagesink_la_LIBADD = $(X_LIBS) $(XSHM_LIBS) -lGL \
diff --git a/sys/glsink/glextensions.c b/sys/glsink/glextensions.c
index 31b862e3..6c48e8b2 100644
--- a/sys/glsink/glextensions.c
+++ b/sys/glsink/glextensions.c
@@ -122,3 +122,60 @@ DEFINE_FUNC_RET (glXWaitForSbcOML, Bool,
DEFINE_FUNC_RET (glXSwapIntervalSGI, int, (int interval), (interval));
DEFINE_FUNC_RET (glXSwapIntervalMESA, int, (unsigned int interval), (interval));
+
+#if 0
+DEFINE_FUNC (glBindFramebufferEXT, (int target, uint framebuffer),
+ (target, framebuffer));
+
+DEFINE_FUNC (glDeleteRenderbuffersEXT, (int n, unsigned int *renderbuffers),
+ (n, renderbuffers));
+DEFINE_FUNC (glGenRenderbuffersEXT, (int n, unsigned int *renderbuffers),
+ (n, renderbuffers));
+DEFINE_FUNC (glRenderbufferStorageEXT, (int target, int internalformat,
+ int width, int height), (target, internalformat, width, height));
+DEFINE_FUNC (glBindRenderbufferEXT, (int target, unsigned int renderbuffer),
+ (target, renderbuffer));
+DEFINE_FUNC (glFramebufferRenderbufferEXT,
+ (int target, int attachment, int renderbuffertarget,
+ unsigned int renderbuffer), (target, attachment, renderbuffertarget,
+ renderbuffer));
+#endif
+
+/* EXT_framebuffer_object */
+DEFINE_FUNC_RET (glIsRenderbufferEXT, Bool,
+ (GLuint renderbuffer), (renderbuffer));
+DEFINE_FUNC (glBindRenderbufferEXT,
+ (GLenum target, GLuint renderbuffer), (target, renderbuffer));
+DEFINE_FUNC (glDeleteRenderbuffersEXT,
+ (GLsizei n, GLuint * renderbuffers), (n, renderbuffers));
+DEFINE_FUNC (glGenRenderbuffersEXT,
+ (GLsizei n, GLuint * renderbuffers), (n, renderbuffers));
+DEFINE_FUNC (glRenderbufferStorageEXT,
+ (GLenum target, GLenum internalformat, GLsizei width, GLsizei height),
+ (target, internalformat, width, height));
+DEFINE_FUNC (glGetRenderbufferParameterivEXT,
+ (GLenum target, GLenum pname, GLint * params), (target, pname, params));
+DEFINE_FUNC_RET (glIsFramebufferEXT, Bool, (GLuint framebuffer), (framebuffer));
+DEFINE_FUNC (glBindFramebufferEXT,
+ (GLenum target, GLuint framebuffer), (target, framebuffer));
+DEFINE_FUNC (glDeleteFramebuffersEXT,
+ (GLsizei n, GLuint * framebuffers), (n, framebuffers));
+DEFINE_FUNC (glGenFramebuffersEXT,
+ (GLsizei n, GLuint * framebuffers), (n, framebuffers));
+DEFINE_FUNC_RET (glCheckFramebufferStatusEXT, GLenum,
+ (GLenum target), (target));
+DEFINE_FUNC (glFramebufferTexture1DEXT,
+ (GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
+ GLint level), (target, attachment, textarget, texture, level));
+DEFINE_FUNC (glFramebufferTexture2DEXT, (GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level), (target, attachment,
+ textarget, texture, level));
+DEFINE_FUNC (glFramebufferTexture3DEXT, (GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level, GLint zoffset), (target,
+ attachment, textarget, texture, level, zoffset));
+DEFINE_FUNC (glFramebufferRenderbufferEXT, (GLenum target, GLenum attachment,
+ GLenum renderbuffertarget, GLuint renderbuffer), (target, attachment,
+ renderbuffertarget, renderbuffer));
+DEFINE_FUNC (glGetFramebufferAttachmentParameterivEXT, (GLenum target,
+ GLenum pname, GLint * params), (target, pname, params));
+DEFINE_FUNC (glGenerateMipmapEXT, (GLenum target), (target));
diff --git a/sys/glsink/glextensions.h b/sys/glsink/glextensions.h
index fd3f8ea7..48161c49 100644
--- a/sys/glsink/glextensions.h
+++ b/sys/glsink/glextensions.h
@@ -29,6 +29,30 @@ Bool glXWaitForSbcOML (Display *, GLXDrawable, int64_t, int64_t *, int64_t *, in
int glXSwapIntervalSGI (int);
int glXSwapIntervalMESA (unsigned int);
+/* EXT_framebuffer_object */
+Bool glIsRenderbufferEXT (GLuint renderbuffer);
+void glBindRenderbufferEXT (GLenum target, GLuint renderbuffer);
+void glDeleteRenderbuffersEXT (GLsizei n, GLuint *renderbuffers);
+void glGenRenderbuffersEXT (GLsizei n, GLuint *renderbuffers);
+void glRenderbufferStorageEXT (GLenum target, GLenum internalformat,
+ GLsizei width, GLsizei height);
+void glGetRenderbufferParameterivEXT (GLenum target, GLenum pname, GLint *params);
+Bool glIsFramebufferEXT (GLuint framebuffer);
+void glBindFramebufferEXT (GLenum target, GLuint framebuffer);
+void glDeleteFramebuffersEXT (GLsizei n, GLuint *framebuffers);
+void glGenFramebuffersEXT (GLsizei n, GLuint *framebuffers);
+GLenum glCheckFramebufferStatusEXT (GLenum target);
+void glFramebufferTexture1DEXT (GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level);
+void glFramebufferTexture2DEXT (GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level);
+void glFramebufferTexture3DEXT (GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+void glFramebufferRenderbufferEXT (GLenum target, GLenum attachment,
+ GLenum renderbuffertarget, GLuint renderbuffer);
+void glGetFramebufferAttachmentParameterivEXT (GLenum target, GLenum pname,
+ GLint *params);
+void glGenerateMipmapEXT (GLenum target);
#endif
diff --git a/sys/glsink/glimagesink.c b/sys/glsink/glimagesink.c
index 8df11e00..560a523f 100644
--- a/sys/glsink/glimagesink.c
+++ b/sys/glsink/glimagesink.c
@@ -282,27 +282,22 @@ static gboolean
gst_glimage_sink_start (GstBaseSink * bsink)
{
GstGLImageSink *glimage_sink;
+ gboolean ret;
GST_DEBUG ("start");
glimage_sink = GST_GLIMAGE_SINK (bsink);
- glimage_sink->display = gst_gl_display_new (glimage_sink->display_name);
- if (glimage_sink->display == NULL) {
+ glimage_sink->display = gst_gl_display_new ();
+ ret = gst_gl_display_connect (glimage_sink->display,
+ glimage_sink->display_name);
+ if (!ret) {
GST_ERROR ("failed to open display");
return FALSE;
}
if (glimage_sink->window_id) {
- glimage_sink->drawable =
- gst_gl_drawable_new_from_window (glimage_sink->display,
- glimage_sink->window_id);
- } else {
- glimage_sink->drawable = gst_gl_drawable_new_window (glimage_sink->display);
- }
- if (glimage_sink->drawable == NULL) {
- GST_ERROR ("failed to create window");
- return FALSE;
+ gst_gl_display_set_window (glimage_sink->display, glimage_sink->window_id);
}
GST_DEBUG ("start done");
@@ -319,11 +314,9 @@ gst_glimage_sink_stop (GstBaseSink * bsink)
glimage_sink = GST_GLIMAGE_SINK (bsink);
- gst_gl_drawable_free (glimage_sink->drawable);
- gst_gl_display_free (glimage_sink->display);
+ g_object_unref (glimage_sink->display);
glimage_sink->display = NULL;
- glimage_sink->drawable = NULL;
return TRUE;
}
@@ -461,7 +454,7 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf)
glimage_sink = GST_GLIMAGE_SINK (bsink);
- gst_gl_drawable_draw_image (glimage_sink->drawable,
+ gst_gl_display_draw_image (glimage_sink->display,
glimage_sink->type, GST_BUFFER_DATA (buf),
GST_VIDEO_SINK_WIDTH (glimage_sink),
GST_VIDEO_SINK_HEIGHT (glimage_sink));
@@ -495,11 +488,7 @@ gst_glimage_sink_set_xwindow_id (GstXOverlay * overlay, XID window_id)
return;
}
glimage_sink->window_id = window_id;
- if (glimage_sink->drawable) {
- gst_gl_drawable_free (glimage_sink->drawable);
- glimage_sink->drawable =
- gst_gl_drawable_new_from_window (glimage_sink->display, window_id);
- }
+ gst_gl_display_set_window (glimage_sink->display, glimage_sink->window_id);
}
static void
diff --git a/sys/glsink/glimagesink.h b/sys/glsink/glimagesink.h
index 9d8294b1..7eee7f3b 100644
--- a/sys/glsink/glimagesink.h
+++ b/sys/glsink/glimagesink.h
@@ -58,7 +58,6 @@ struct _GstGLImageSink
int par_n, par_d;
GstGLDisplay *display;
- GstGLDrawable *drawable;
GstGLImageType type;
XID window_id;
diff --git a/sys/glsink/glvideo.c b/sys/glsink/glvideo.c
index 5b4e222d..f7328153 100644
--- a/sys/glsink/glvideo.c
+++ b/sys/glsink/glvideo.c
@@ -27,33 +27,115 @@
#include <string.h>
+static void gst_gl_display_finalize (GObject * object);
+static void gst_gl_display_init_tmp_window (GstGLDisplay * display);
-static gboolean gst_gl_display_check_features (GstGLDisplay * display);
+GST_BOILERPLATE (GstGLDisplay, gst_gl_display, GObject, G_TYPE_OBJECT);
+
+static void
+gst_gl_display_base_init (gpointer g_class)
+{
+
+}
+
+static void
+gst_gl_display_class_init (GstGLDisplayClass * klass)
+{
+ G_OBJECT_CLASS (klass)->finalize = gst_gl_display_finalize;
+}
+
+static void
+gst_gl_display_init (GstGLDisplay * display, GstGLDisplayClass * klass)
+{
+
+ display->lock = g_mutex_new ();
+}
+
+static void
+gst_gl_display_finalize (GObject * object)
+{
+ GstGLDisplay *display = GST_GL_DISPLAY (object);
+
+ if (display->assigned_window == None) {
+ XDestroyWindow (display->display, display->window);
+ }
+ if (display->context) {
+ glXDestroyContext (display->display, display->context);
+ }
+ if (display->visinfo) {
+ XFree (display->visinfo);
+ }
+ if (display->display) {
+ XCloseDisplay (display->display);
+ }
+
+ if (display->lock) {
+ g_mutex_free (display->lock);
+ }
+}
+
+static gboolean gst_gl_display_check_features (GstGLDisplay * display);
GstGLDisplay *
-gst_gl_display_new (const char *display_name)
+gst_gl_display_new (void)
{
- GstGLDisplay *display;
- gboolean usable;
+ return g_object_new (GST_TYPE_GL_DISPLAY, NULL);
+}
- display = g_malloc0 (sizeof (GstGLDisplay));
+#define HANDLE_X_ERRORS
+#ifdef HANDLE_X_ERRORS
+static int
+x_error_handler (Display * display, XErrorEvent * event)
+{
+ g_assert_not_reached ();
+}
+#endif
+
+gboolean
+gst_gl_display_connect (GstGLDisplay * display, const char *display_name)
+{
+ gboolean usable;
+ XGCValues values;
+ XPixmapFormatValues *px_formats;
+ int n_formats;
+ int i;
display->display = XOpenDisplay (display_name);
if (display->display == NULL) {
- g_free (display);
- return NULL;
+ return FALSE;
}
+#ifdef HANDLE_X_ERRORS
+ XSynchronize (display->display, True);
+ XSetErrorHandler (x_error_handler);
+#endif
usable = gst_gl_display_check_features (display);
if (!usable) {
- g_free (display);
- return NULL;
+ return FALSE;
}
- display->lock = g_mutex_new ();
+ display->screen = DefaultScreenOfDisplay (display->display);
+ display->screen_num = DefaultScreen (display->display);
+ display->visual = DefaultVisual (display->display, display->screen_num);
+ display->root = DefaultRootWindow (display->display);
+ display->white = XWhitePixel (display->display, display->screen_num);
+ display->black = XBlackPixel (display->display, display->screen_num);
+ display->depth = DefaultDepthOfScreen (display->screen);
+
+ display->gc = XCreateGC (display->display,
+ DefaultRootWindow (display->display), 0, &values);
+
+ px_formats = XListPixmapFormats (display->display, &n_formats);
+ for (i = 0; i < n_formats; i++) {
+ GST_DEBUG ("%d: depth %d bpp %d pad %d", i,
+ px_formats[i].depth,
+ px_formats[i].bits_per_pixel, px_formats[i].scanline_pad);
+ }
+
+ gst_gl_display_init_tmp_window (display);
- return display;
+ return TRUE;
}
static gboolean
@@ -161,56 +243,29 @@ gst_gl_display_can_handle_type (GstGLDisplay * display, GstGLImageType type)
}
void
-gst_gl_display_free (GstGLDisplay * display)
-{
- /* sure hope nobody is using it as it's being freed */
- g_mutex_lock (display->lock);
- g_mutex_unlock (display->lock);
-
- if (display->context) {
- glXDestroyContext (display->display, display->context);
- }
- if (display->visinfo) {
- XFree (display->visinfo);
- }
- if (display->display) {
- XCloseDisplay (display->display);
- }
-
- g_mutex_free (display->lock);
-
- g_free (display);
-}
-
-void
gst_gl_display_lock (GstGLDisplay * display)
{
g_mutex_lock (display->lock);
+ glXMakeCurrent (display->display, display->window, display->context);
}
void
gst_gl_display_unlock (GstGLDisplay * display)
{
+ glXMakeCurrent (display->display, None, NULL);
g_mutex_unlock (display->lock);
}
-
-/* drawable */
-
-GstGLDrawable *
-gst_gl_drawable_new_window (GstGLDisplay * display)
+static void
+gst_gl_display_init_tmp_window (GstGLDisplay * display)
{
- GstGLDrawable *drawable;
XSetWindowAttributes attr = { 0 };
int scrnum;
int mask;
Window root;
Screen *screen;
- drawable = g_malloc0 (sizeof (GstGLDrawable));
-
- g_mutex_lock (display->lock);
- drawable->display = display;
+ GST_ERROR ("creating temp window");
screen = XDefaultScreenOfDisplay (display->display);
scrnum = XScreenNumberOfScreen (screen);
@@ -229,114 +284,72 @@ gst_gl_drawable_new_window (GstGLDisplay * display)
mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect;
- drawable->window = XCreateWindow (display->display,
+ display->window = XCreateWindow (display->display,
root, 0, 0, 100, 100,
0, display->visinfo->depth, InputOutput,
display->visinfo->visual, mask, &attr);
- XMapWindow (display->display, drawable->window);
- drawable->destroy_on_free = TRUE;
-
- g_mutex_unlock (display->lock);
-
- return drawable;
-}
-
-GstGLDrawable *
-gst_gl_drawable_new_root_window (GstGLDisplay * display)
-{
- GstGLDrawable *drawable;
- int scrnum;
- Screen *screen;
-
- drawable = g_malloc0 (sizeof (GstGLDrawable));
-
- g_mutex_lock (display->lock);
- drawable->display = display;
-
- screen = XDefaultScreenOfDisplay (display->display);
- scrnum = XScreenNumberOfScreen (screen);
-
- drawable->window = XRootWindow (display->display, scrnum);
- drawable->destroy_on_free = FALSE;
- g_mutex_unlock (display->lock);
-
- return drawable;
+ XMapWindow (display->display, display->window);
+ XSync (display->display, FALSE);
}
-GstGLDrawable *
-gst_gl_drawable_new_from_window (GstGLDisplay * display, Window window)
+static void
+gst_gl_display_destroy_tmp_window (GstGLDisplay * display)
{
- GstGLDrawable *drawable;
-
- drawable = g_malloc0 (sizeof (GstGLDrawable));
-
- g_mutex_lock (display->lock);
- drawable->display = display;
-
- drawable->window = window;
- drawable->destroy_on_free = FALSE;
-
- g_mutex_unlock (display->lock);
- return drawable;
+ XDestroyWindow (display->display, display->window);
}
void
-gst_gl_drawable_free (GstGLDrawable * drawable)
+gst_gl_display_set_window (GstGLDisplay * display, Window window)
{
+ g_mutex_lock (display->lock);
- g_mutex_lock (drawable->display->lock);
- if (drawable->destroy_on_free) {
- XDestroyWindow (drawable->display->display, drawable->window);
+ if (window != display->assigned_window) {
+ if (display->assigned_window == None) {
+ gst_gl_display_destroy_tmp_window (display);
+ }
+ display->assigned_window = window;
+ if (display->assigned_window == None) {
+ gst_gl_display_init_tmp_window (display);
+ } else {
+ display->window = window;
+ }
}
- g_mutex_unlock (drawable->display->lock);
-
- g_free (drawable);
-}
-
-void
-gst_gl_drawable_lock (GstGLDrawable * drawable)
-{
- g_mutex_lock (drawable->display->lock);
- glXMakeCurrent (drawable->display->display, drawable->window,
- drawable->display->context);
-}
-void
-gst_gl_drawable_unlock (GstGLDrawable * drawable)
-{
- glXMakeCurrent (drawable->display->display, None, NULL);
- g_mutex_unlock (drawable->display->lock);
+ g_mutex_unlock (display->lock);
}
void
-gst_gl_drawable_update_attributes (GstGLDrawable * drawable)
+gst_gl_display_update_attributes (GstGLDisplay * display)
{
XWindowAttributes attr;
- XGetWindowAttributes (drawable->display->display, drawable->window, &attr);
- drawable->win_width = attr.width;
- drawable->win_height = attr.height;
-
+ if (display->window != None) {
+ XGetWindowAttributes (display->display, display->window, &attr);
+ display->win_width = attr.width;
+ display->win_height = attr.height;
+ } else {
+ display->win_width = 0;
+ display->win_height = 0;
+ }
}
void
-gst_gl_drawable_clear (GstGLDrawable * drawable)
+gst_gl_display_clear (GstGLDisplay * display)
{
-
- gst_gl_drawable_lock (drawable);
+ gst_gl_display_lock (display);
glDepthFunc (GL_LESS);
glEnable (GL_DEPTH_TEST);
glClearColor (0.2, 0.2, 0.2, 1.0);
- glViewport (0, 0, drawable->win_width, drawable->win_height);
+ glViewport (0, 0, display->win_width, display->win_height);
- gst_gl_drawable_unlock (drawable);
+ gst_gl_display_unlock (display);
}
static void
-draw_rect_texture (GstGLDrawable * drawable, GstGLImageType type,
+draw_rect_texture (GstGLDisplay * display, GstGLImageType type,
void *data, int width, int height)
{
GLuint texture;
@@ -437,7 +450,7 @@ draw_rect_texture (GstGLDrawable * drawable, GstGLImageType type,
}
static void
-draw_pow2_texture (GstGLDrawable * drawable, GstGLImageType type,
+draw_pow2_texture (GstGLDisplay * display, GstGLImageType type,
void *data, int width, int height)
{
int pow2_width;
@@ -544,14 +557,14 @@ draw_pow2_texture (GstGLDrawable * drawable, GstGLImageType type,
}
void
-gst_gl_drawable_draw_image (GstGLDrawable * drawable, GstGLImageType type,
+gst_gl_display_draw_image (GstGLDisplay * display, GstGLImageType type,
void *data, int width, int height)
{
g_return_if_fail (data != NULL);
g_return_if_fail (width > 0);
g_return_if_fail (height > 0);
- gst_gl_drawable_lock (drawable);
+ gst_gl_display_lock (display);
#if 0
/* Doesn't work */
@@ -561,9 +574,9 @@ gst_gl_drawable_draw_image (GstGLDrawable * drawable, GstGLImageType type,
int64_t sbc = 1234;
gboolean ret;
- ret = glXGetSyncValuesOML (drawable->display->display, drawable->window,
+ ret = glXGetSyncValuesOML (display->display, display->window,
&ust, &mst, &sbc);
- GST_ERROR ("sync values %d %lld %lld %lld", ret, ust, mst, sbc);
+ GST_DEBUG ("sync values %d %lld %lld %lld", ret, ust, mst, sbc);
}
#endif
@@ -574,16 +587,15 @@ gst_gl_drawable_draw_image (GstGLDrawable * drawable, GstGLImageType type,
int32_t den = 1234;
gboolean ret;
- ret = glXGetMscRateOML (drawable->display->display, drawable->window,
- &num, &den);
- GST_ERROR ("rate %d %d %d", ret, num, den);
+ ret = glXGetMscRateOML (display->display, display->window, &num, &den);
+ GST_DEBUG ("rate %d %d %d", ret, num, den);
}
#endif
- gst_gl_drawable_update_attributes (drawable);
+ gst_gl_display_update_attributes (display);
- glXSwapIntervalSGI (1);
- glViewport (0, 0, drawable->win_width, drawable->win_height);
+ //glXSwapIntervalSGI (1);
+ glViewport (0, 0, display->win_width, display->win_height);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -598,23 +610,22 @@ gst_gl_drawable_draw_image (GstGLDrawable * drawable, GstGLImageType type,
glColor4f (1, 1, 1, 1);
- if (drawable->display->have_texture_rectangle) {
- draw_rect_texture (drawable, type, data, width, height);
+ if (display->have_texture_rectangle) {
+ draw_rect_texture (display, type, data, width, height);
} else {
- draw_pow2_texture (drawable, type, data, width, height);
+ draw_pow2_texture (display, type, data, width, height);
}
- glXSwapBuffers (drawable->display->display, drawable->window);
+ glXSwapBuffers (display->display, display->window);
#if 0
/* Doesn't work */
{
- ret = glXSwapBuffersMscOML (drawable->display->display, drawable->window,
- 0, 1, 0);
+ ret = glXSwapBuffersMscOML (display->display, display->window, 0, 1, 0);
if (ret == 0) {
- GST_ERROR ("glXSwapBuffersMscOML failed");
+ GST_DEBUG ("glXSwapBuffersMscOML failed");
}
}
#endif
- gst_gl_drawable_unlock (drawable);
+ gst_gl_display_unlock (display);
}
diff --git a/sys/glsink/glvideo.h b/sys/glsink/glvideo.h
index e1bdfe92..aef064e3 100644
--- a/sys/glsink/glvideo.h
+++ b/sys/glsink/glvideo.h
@@ -6,9 +6,6 @@
#include <GL/gl.h>
#include <gst/gst.h>
-typedef struct _GstGLDisplay GstGLDisplay;
-typedef struct _GstGLDrawable GstGLDrawable;
-
typedef enum {
GST_GL_IMAGE_TYPE_RGBx,
GST_GL_IMAGE_TYPE_BGRx,
@@ -19,54 +16,71 @@ typedef enum {
GST_GL_IMAGE_TYPE_AYUV,
} GstGLImageType;
+typedef struct _GstGLDisplay GstGLDisplay;
+typedef struct _GstGLDisplayClass GstGLDisplayClass;
+
+#define GST_TYPE_GL_DISPLAY \
+ (gst_gl_display_get_type())
+#define GST_GL_DISPLAY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DISPLAY,GstGLDisplay))
+#define GST_GL_DISPLAY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_DISPLAY,GstGLDisplayClass))
+#define GST_IS_GL_DISPLAY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DISPLAY))
+#define GST_IS_GL_DISPLAY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_DISPLAY))
+
struct _GstGLDisplay {
+ GObject object;
+
Display *display;
+ GC gc;
XVisualInfo *visinfo;
GLXContext context;
GMutex *lock;
Screen *screen;
- int scrnum;
+ int screen_num;
+ Visual *visual;
Window root;
+ guint32 white;
+ guint32 black;
+ int depth;
int max_texture_size;
gboolean have_ycbcr_texture;
gboolean have_texture_rectangle;
gboolean have_color_matrix;
-};
-
-struct _GstGLDrawable {
- GstGLDisplay *display;
Window window;
-
- gboolean destroy_on_free;
+ Window assigned_window;
int win_width;
int win_height;
+
+};
+
+struct _GstGLDisplayClass {
+ GObjectClass object_class;
};
+GType gst_gl_display_get_type (void);
+
-GstGLDisplay *gst_gl_display_new (const char *display_name);
+GstGLDisplay *gst_gl_display_new (void);
+gboolean gst_gl_display_connect (GstGLDisplay *display,
+ const char *display_name);
gboolean gst_gl_display_can_handle_type (GstGLDisplay *display,
GstGLImageType type);
-void gst_gl_display_free (GstGLDisplay *display);
void gst_gl_display_lock (GstGLDisplay *display);
void gst_gl_display_unlock (GstGLDisplay *display);
-
-/* drawable */
-
-GstGLDrawable * gst_gl_drawable_new_window (GstGLDisplay *display);
-GstGLDrawable * gst_gl_drawable_new_root_window (GstGLDisplay *display);
-GstGLDrawable * gst_gl_drawable_new_from_window (GstGLDisplay *display, Window window);
-void gst_gl_drawable_free (GstGLDrawable *drawable);
-void gst_gl_drawable_lock (GstGLDrawable *drawable);
-void gst_gl_drawable_unlock (GstGLDrawable *drawable);
-void gst_gl_drawable_update_attributes (GstGLDrawable *drawable);
-void gst_gl_drawable_clear (GstGLDrawable *drawable);
-void gst_gl_drawable_draw_image (GstGLDrawable *drawable, GstGLImageType type, void *data, int width, int height);
+void gst_gl_display_set_window (GstGLDisplay *display, Window window);
+void gst_gl_display_update_attributes (GstGLDisplay *display);
+void gst_gl_display_clear (GstGLDisplay *display);
+void gst_gl_display_draw_image (GstGLDisplay * display, GstGLImageType type,
+ void *data, int width, int height);
#endif
diff --git a/sys/glsink/gstglbuffer.c b/sys/glsink/gstglbuffer.c
new file mode 100644
index 00000000..04421ce7
--- /dev/null
+++ b/sys/glsink/gstglbuffer.c
@@ -0,0 +1,239 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gstglbuffer.h>
+#include <glvideo.h>
+#include "glextensions.h"
+
+#include <string.h>
+
+static GObjectClass *gst_gl_buffer_parent_class;
+
+static void
+gst_gl_buffer_finalize (GstGLBuffer * buffer)
+{
+ gst_gl_display_lock (buffer->display);
+
+ switch (buffer->type) {
+ case GST_GL_BUFFER_XIMAGE:
+ GST_DEBUG ("freeing pixmap %ld", buffer->pixmap);
+ XFreeGC (buffer->display->display, buffer->gc);
+ XFreePixmap (buffer->display->display, buffer->pixmap);
+ break;
+ case GST_GL_BUFFER_RBO:
+ glDeleteRenderbuffersEXT (1, &buffer->rbo);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ gst_gl_display_unlock (buffer->display);
+ g_object_unref (buffer->display);
+
+ GST_MINI_OBJECT_CLASS (gst_gl_buffer_parent_class)->
+ finalize (GST_MINI_OBJECT (buffer));
+}
+
+static void
+gst_gl_buffer_init (GstGLBuffer * buffer, gpointer g_class)
+{
+
+}
+
+static void
+gst_gl_buffer_class_init (gpointer g_class, gpointer class_data)
+{
+ GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+
+ gst_gl_buffer_parent_class = g_type_class_peek_parent (g_class);
+
+ mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
+ gst_gl_buffer_finalize;
+}
+
+
+GType
+gst_gl_buffer_get_type (void)
+{
+ static GType _gst_gl_buffer_type;
+
+ if (G_UNLIKELY (_gst_gl_buffer_type == 0)) {
+ static const GTypeInfo info = {
+ sizeof (GstBufferClass),
+ NULL,
+ NULL,
+ gst_gl_buffer_class_init,
+ NULL,
+ NULL,
+ sizeof (GstGLBuffer),
+ 0,
+ (GInstanceInitFunc) gst_gl_buffer_init,
+ NULL
+ };
+ _gst_gl_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
+ "GstGLBuffer", &info, 0);
+ }
+ return _gst_gl_buffer_type;
+}
+
+
+GstGLBuffer *
+gst_gl_buffer_new (GstGLDisplay * display, GstVideoFormat format,
+ int width, int height)
+{
+ GstGLBuffer *buffer;
+ XGCValues values = { 0 };
+
+ g_return_val_if_fail (format == GST_VIDEO_FORMAT_BGRx, NULL);
+ g_return_val_if_fail (width > 0, NULL);
+ g_return_val_if_fail (height > 0, NULL);
+
+ buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
+
+ buffer->display = g_object_ref (display);
+ buffer->type = GST_GL_BUFFER_RBO;
+
+ buffer->width = width;
+ buffer->height = height;
+
+ switch (buffer->type) {
+ case GST_GL_BUFFER_XIMAGE:
+ {
+ buffer->pixmap = XCreatePixmap (display->display,
+ DefaultRootWindow (display->display), width, height, 32);
+ XSync (display->display, False);
+
+ buffer->gc = XCreateGC (display->display, buffer->pixmap, 0, &values);
+
+ GST_DEBUG ("new pixmap %dx%d xid %ld", width, height, buffer->pixmap);
+ break;
+ }
+ case GST_GL_BUFFER_RBO:
+ {
+ gst_gl_display_lock (buffer->display);
+
+ glGenRenderbuffersEXT (1, &buffer->rbo);
+ glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, buffer->rbo);
+
+ glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, buffer->rbo);
+ glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_RGB,
+ buffer->width, buffer->height);
+
+
+
+ gst_gl_display_unlock (buffer->display);
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ }
+
+ return buffer;
+}
+
+void
+gst_gl_buffer_upload (GstGLBuffer * buffer, void *data)
+{
+ Display *display = buffer->display->display;
+
+ GST_DEBUG ("uploading %p %dx%d", data, buffer->width, buffer->height);
+
+ gst_gl_display_lock (buffer->display);
+
+ switch (buffer->type) {
+ case GST_GL_BUFFER_XIMAGE:
+ {
+ XImage *image;
+ Visual *visual;
+ int depth;
+ int bpp;
+
+ visual = DefaultVisual (display, 0);
+ depth = 32;
+ bpp = 32;
+
+ image = XCreateImage (display, visual, depth, ZPixmap, 0, NULL,
+ buffer->width, buffer->height, bpp, 0);
+ GST_DEBUG ("image %p", image);
+ image->data = data;
+
+ XPutImage (display, buffer->pixmap, buffer->gc,
+ image, 0, 0, 0, 0, buffer->width, buffer->height);
+
+ XDestroyImage (image);
+ break;
+ }
+ case GST_GL_BUFFER_RBO:
+ {
+ unsigned int fbo;
+
+ glGenFramebuffersEXT (1, &fbo);
+ glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
+
+ glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, buffer->rbo);
+
+ glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT);
+ //glWindowPos2iARB(0, 0);
+ glDrawPixels (buffer->width, buffer->height, GL_RGBA,
+ GL_UNSIGNED_BYTE, data);
+
+ glDeleteFramebuffersEXT (1, &fbo);
+
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ }
+
+ gst_gl_display_unlock (buffer->display);
+}
+
+
+void
+gst_gl_buffer_download (GstGLBuffer * buffer, void *data)
+{
+ gst_gl_display_lock (buffer->display);
+
+ GST_DEBUG ("downloading");
+
+ switch (buffer->type) {
+ case GST_GL_BUFFER_XIMAGE:
+ {
+ XImage *image;
+
+ image = XGetImage (buffer->display->display, buffer->pixmap,
+ 0, 0, buffer->width, buffer->height, 0xffffffff, ZPixmap);
+
+ memcpy (data, image->data, buffer->width * buffer->height * 4);
+
+ XDestroyImage (image);
+ break;
+ }
+ case GST_GL_BUFFER_RBO:
+ {
+ unsigned int fbo;
+
+ glGenFramebuffersEXT (1, &fbo);
+ glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
+
+ glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, buffer->rbo);
+
+ glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
+ glReadPixels (0, 0, buffer->width, buffer->height, GL_RGBA,
+ GL_UNSIGNED_BYTE, data);
+
+ glDeleteFramebuffersEXT (1, &fbo);
+
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ }
+
+ gst_gl_display_unlock (buffer->display);
+}
diff --git a/sys/glsink/gstglbuffer.h b/sys/glsink/gstglbuffer.h
new file mode 100644
index 00000000..969f2161
--- /dev/null
+++ b/sys/glsink/gstglbuffer.h
@@ -0,0 +1,47 @@
+
+#ifndef _GST_GL_BUFFER_H_
+#define _GST_GL_BUFFER_H_
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <xcb/xcb.h>
+#include <glvideo.h>
+
+typedef struct _GstGLBuffer GstGLBuffer;
+
+#define GST_TYPE_GL_BUFFER (gst_gl_buffer_get_type())
+
+#define GST_IS_GL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GL_BUFFER))
+#define GST_GL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GL_BUFFER, GstGLBuffer))
+
+typedef enum {
+ GST_GL_BUFFER_UNKNOWN,
+ GST_GL_BUFFER_XIMAGE,
+ GST_GL_BUFFER_RBO
+} GstGLBufferType;
+
+struct _GstGLBuffer {
+ GstBuffer buffer;
+
+ GstGLDisplay *display;
+
+ GstGLBufferType type;
+
+ XID pixmap;
+ GC gc;
+
+ GLuint rbo;
+
+ int width;
+ int height;
+};
+
+GType gst_gl_buffer_get_type (void);
+
+GstGLBuffer * gst_gl_buffer_new (GstGLDisplay *display, GstVideoFormat format,
+ int width, int height);
+void gst_gl_buffer_upload (GstGLBuffer *buffer, void *data);
+void gst_gl_buffer_download (GstGLBuffer *buffer, void *data);
+
+#endif
+
diff --git a/sys/glsink/gstgldownload.c b/sys/glsink/gstgldownload.c
new file mode 100644
index 00000000..55f9e759
--- /dev/null
+++ b/sys/glsink/gstgldownload.c
@@ -0,0 +1,294 @@
+/*
+ * GStreamer
+ * Copyright (C) 2007 David Schleef <ds@schleef.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gstglbuffer.h>
+
+#define GST_CAT_DEFAULT gst_gl_download_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+#define GST_TYPE_GL_DOWNLOAD (gst_gl_download_get_type())
+#define GST_GL_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DOWNLOAD,GstGLDownload))
+#define GST_IS_GL_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DOWNLOAD))
+#define GST_GL_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_DOWNLOAD,GstGLDownloadClass))
+#define GST_IS_GL_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_DOWNLOAD))
+#define GST_GL_DOWNLOAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_DOWNLOAD,GstGLDownloadClass))
+typedef struct _GstGLDownload GstGLDownload;
+typedef struct _GstGLDownloadClass GstGLDownloadClass;
+
+typedef void (*GstGLDownloadProcessFunc) (GstGLDownload *, guint8 *, guint);
+
+struct _GstGLDownload
+{
+ GstElement element;
+
+ GstPad *srcpad;
+ GstPad *sinkpad;
+
+ /* < private > */
+
+ GstGLDisplay *display;
+ GstVideoFormat format;
+ int width;
+ int height;
+};
+
+struct _GstGLDownloadClass
+{
+ GstElementClass element_class;
+};
+
+static const GstElementDetails element_details = GST_ELEMENT_DETAILS ("FIXME",
+ "Filter/Effect",
+ "FIXME example filter",
+ "FIXME <fixme@fixme.com>");
+
+#define GST_GL_VIDEO_CAPS "video/x-raw-gl"
+
+static GstStaticPadTemplate gst_gl_download_src_pad_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx)
+ );
+
+static GstStaticPadTemplate gst_gl_download_sink_pad_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
+ );
+
+enum
+{
+ PROP_0
+};
+
+#define DEBUG_INIT(bla) \
+ GST_DEBUG_CATEGORY_INIT (gst_gl_download_debug, "gldownload", 0, "gldownload element");
+
+GST_BOILERPLATE_FULL (GstGLDownload, gst_gl_download, GstElement,
+ GST_TYPE_ELEMENT, DEBUG_INIT);
+
+static void gst_gl_download_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_gl_download_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static GstFlowReturn gst_gl_download_chain (GstPad * pad, GstBuffer * buf);
+static void gst_gl_download_reset (GstGLDownload * download);
+static GstStateChangeReturn
+gst_gl_download_change_state (GstElement * element, GstStateChange transition);
+static gboolean gst_gl_download_sink_setcaps (GstPad * pad, GstCaps * caps);
+
+
+static void
+gst_gl_download_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ gst_element_class_set_details (element_class, &element_details);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_gl_download_src_pad_template));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_gl_download_sink_pad_template));
+}
+
+static void
+gst_gl_download_class_init (GstGLDownloadClass * klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gobject_class->set_property = gst_gl_download_set_property;
+ gobject_class->get_property = gst_gl_download_get_property;
+
+ GST_ELEMENT_CLASS (klass)->change_state = gst_gl_download_change_state;
+}
+
+static void
+gst_gl_download_init (GstGLDownload * download, GstGLDownloadClass * klass)
+{
+ gst_element_create_all_pads (GST_ELEMENT (download));
+
+ download->sinkpad =
+ gst_element_get_static_pad (GST_ELEMENT (download), "sink");
+ download->srcpad = gst_element_get_static_pad (GST_ELEMENT (download), "src");
+
+ gst_pad_set_setcaps_function (download->sinkpad,
+ gst_gl_download_sink_setcaps);
+ gst_pad_set_chain_function (download->sinkpad, gst_gl_download_chain);
+
+ gst_gl_download_reset (download);
+}
+
+static void
+gst_gl_download_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ //GstGLDownload *download = GST_GL_DOWNLOAD (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_gl_download_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ //GstGLDownload *download = GST_GL_DOWNLOAD (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_gl_download_reset (GstGLDownload * download)
+{
+ if (download->display) {
+ g_object_unref (download->display);
+ download->display = NULL;
+ }
+ download->format = GST_VIDEO_FORMAT_BGRx;
+}
+
+static gboolean
+gst_gl_download_start (GstGLDownload * download)
+{
+ gboolean ret;
+
+ download->format = GST_VIDEO_FORMAT_BGRx;
+ download->display = gst_gl_display_new ();
+ ret = gst_gl_display_connect (download->display, NULL);
+
+ return ret;
+}
+
+static gboolean
+gst_gl_download_stop (GstGLDownload * download)
+{
+ gst_gl_download_reset (download);
+
+ return TRUE;
+}
+
+static gboolean
+gst_gl_download_sink_setcaps (GstPad * pad, GstCaps * caps)
+{
+ GstGLDownload *download;
+ gboolean ret;
+ GstStructure *structure;
+ GstCaps *srccaps;
+
+ download = GST_GL_DOWNLOAD (gst_pad_get_parent (pad));
+
+ structure = gst_caps_get_structure (caps, 0);
+
+ ret = gst_structure_get_int (structure, "width", &download->width);
+ ret &= gst_structure_get_int (structure, "height", &download->height);
+ if (!ret)
+ return FALSE;
+
+ srccaps = gst_video_format_new_caps (download->format,
+ download->width, download->height, 30, 1, 1, 1);
+ ret = gst_pad_set_caps (download->srcpad, srccaps);
+ gst_caps_unref (srccaps);
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_gl_download_chain (GstPad * pad, GstBuffer * buf)
+{
+ GstGLDownload *download;
+ GstGLBuffer *inbuf = GST_GL_BUFFER (buf);
+ GstBuffer *outbuf;
+
+ GST_ERROR ("got here");
+ download = GST_GL_DOWNLOAD (gst_pad_get_parent (pad));
+
+ outbuf = gst_buffer_new_and_alloc (inbuf->width * inbuf->height * 4);
+
+ gst_buffer_copy_metadata (GST_BUFFER (outbuf), buf,
+ GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS);
+ gst_buffer_set_caps (GST_BUFFER (outbuf), GST_PAD_CAPS (download->srcpad));
+
+ GST_ERROR ("downloading %p size %d",
+ GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf));
+ gst_gl_buffer_download (inbuf, GST_BUFFER_DATA (outbuf));
+
+ gst_pad_push (download->srcpad, GST_BUFFER (outbuf));
+
+ gst_object_unref (download);
+ return GST_FLOW_OK;
+}
+
+static GstStateChangeReturn
+gst_gl_download_change_state (GstElement * element, GstStateChange transition)
+{
+ GstGLDownload *download;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ GST_DEBUG ("change state");
+
+ download = GST_GL_DOWNLOAD (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ gst_gl_download_start (download);
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ gst_gl_download_stop (download);
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
diff --git a/sys/glsink/gstglfilter.c b/sys/glsink/gstglfilter.c
new file mode 100644
index 00000000..c2b91f45
--- /dev/null
+++ b/sys/glsink/gstglfilter.c
@@ -0,0 +1,416 @@
+/*
+ * GStreamer
+ * Copyright (C) 2007 David Schleef <ds@schleef.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gstglbuffer.h>
+
+#define GST_CAT_DEFAULT gst_gl_filter_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+#define GST_TYPE_GL_FILTER (gst_gl_filter_get_type())
+#define GST_GL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTER,GstGLFilter))
+#define GST_IS_GL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTER))
+#define GST_GL_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTER,GstGLFilterClass))
+#define GST_IS_GL_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTER))
+#define GST_GL_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTER,GstGLFilterClass))
+typedef struct _GstGLFilter GstGLFilter;
+typedef struct _GstGLFilterClass GstGLFilterClass;
+
+typedef void (*GstGLFilterProcessFunc) (GstGLFilter *, guint8 *, guint);
+
+struct _GstGLFilter
+{
+ GstElement element;
+
+ GstPad *srcpad;
+ GstPad *sinkpad;
+
+ /* < private > */
+
+ GstGLDisplay *display;
+ GstVideoFormat format;
+ int width;
+ int height;
+};
+
+struct _GstGLFilterClass
+{
+ GstElementClass element_class;
+};
+
+static const GstElementDetails element_details = GST_ELEMENT_DETAILS ("FIXME",
+ "Filter/Effect",
+ "FIXME example filter",
+ "FIXME <fixme@fixme.com>");
+
+#define GST_GL_VIDEO_CAPS "video/x-raw-gl"
+
+static GstStaticPadTemplate gst_gl_filter_src_pad_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
+ );
+
+static GstStaticPadTemplate gst_gl_filter_sink_pad_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
+ );
+
+enum
+{
+ PROP_0
+};
+
+#define DEBUG_INIT(bla) \
+ GST_DEBUG_CATEGORY_INIT (gst_gl_filter_debug, "glfilter", 0, "glfilter element");
+
+GST_BOILERPLATE_FULL (GstGLFilter, gst_gl_filter, GstElement,
+ GST_TYPE_ELEMENT, DEBUG_INIT);
+
+static void gst_gl_filter_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_gl_filter_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static GstFlowReturn gst_gl_filter_chain (GstPad * pad, GstBuffer * buf);
+static void gst_gl_filter_reset (GstGLFilter * filter);
+static GstStateChangeReturn
+gst_gl_filter_change_state (GstElement * element, GstStateChange transition);
+static gboolean gst_gl_filter_sink_setcaps (GstPad * pad, GstCaps * caps);
+static gboolean gst_gl_filter_transform (GstGLBuffer * outbuf,
+ GstGLBuffer * inbuf);
+
+
+static void
+gst_gl_filter_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ gst_element_class_set_details (element_class, &element_details);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_gl_filter_src_pad_template));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_gl_filter_sink_pad_template));
+}
+
+static void
+gst_gl_filter_class_init (GstGLFilterClass * klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gobject_class->set_property = gst_gl_filter_set_property;
+ gobject_class->get_property = gst_gl_filter_get_property;
+
+ GST_ELEMENT_CLASS (klass)->change_state = gst_gl_filter_change_state;
+}
+
+static void
+gst_gl_filter_init (GstGLFilter * filter, GstGLFilterClass * klass)
+{
+ gst_element_create_all_pads (GST_ELEMENT (filter));
+
+ filter->sinkpad = gst_element_get_static_pad (GST_ELEMENT (filter), "sink");
+ filter->srcpad = gst_element_get_static_pad (GST_ELEMENT (filter), "src");
+
+ gst_pad_set_setcaps_function (filter->sinkpad, gst_gl_filter_sink_setcaps);
+ gst_pad_set_chain_function (filter->sinkpad, gst_gl_filter_chain);
+
+ gst_gl_filter_reset (filter);
+}
+
+static void
+gst_gl_filter_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ //GstGLFilter *filter = GST_GL_FILTER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_gl_filter_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ //GstGLFilter *filter = GST_GL_FILTER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_gl_filter_reset (GstGLFilter * filter)
+{
+ if (filter->display) {
+ g_object_unref (filter->display);
+ filter->display = NULL;
+ }
+ filter->format = GST_VIDEO_FORMAT_BGRx;
+}
+
+static gboolean
+gst_gl_filter_start (GstGLFilter * filter)
+{
+ gboolean ret;
+
+ filter->format = GST_VIDEO_FORMAT_BGRx;
+ filter->display = gst_gl_display_new ();
+ ret = gst_gl_display_connect (filter->display, NULL);
+
+ return ret;
+}
+
+static gboolean
+gst_gl_filter_stop (GstGLFilter * filter)
+{
+ gst_gl_filter_reset (filter);
+
+ return TRUE;
+}
+
+static gboolean
+gst_gl_filter_sink_setcaps (GstPad * pad, GstCaps * caps)
+{
+ GstGLFilter *filter;
+ gboolean ret;
+ GstStructure *structure;
+
+ filter = GST_GL_FILTER (gst_pad_get_parent (pad));
+
+ structure = gst_caps_get_structure (caps, 0);
+
+ ret = gst_structure_get_int (structure, "width", &filter->width);
+ ret &= gst_structure_get_int (structure, "height", &filter->height);
+ if (!ret)
+ return FALSE;
+
+ GST_ERROR ("setcaps %d %d", filter->width, filter->height);
+
+ ret = gst_pad_set_caps (filter->srcpad, caps);
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_gl_filter_chain (GstPad * pad, GstBuffer * buf)
+{
+ GstGLFilter *filter;
+ GstGLBuffer *inbuf;
+ GstGLBuffer *outbuf;
+
+ filter = GST_GL_FILTER (gst_pad_get_parent (pad));
+ inbuf = GST_GL_BUFFER (buf);
+
+ outbuf = gst_gl_buffer_new (inbuf->display, filter->format,
+ filter->width, filter->height);
+
+ gst_buffer_copy_metadata (GST_BUFFER (outbuf), buf,
+ GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS);
+ gst_buffer_set_caps (GST_BUFFER (outbuf), GST_PAD_CAPS (filter->srcpad));
+
+ gst_gl_filter_transform (outbuf, inbuf);
+
+ gst_pad_push (filter->srcpad, GST_BUFFER (outbuf));
+
+ gst_object_unref (filter);
+ return GST_FLOW_OK;
+}
+
+static GstStateChangeReturn
+gst_gl_filter_change_state (GstElement * element, GstStateChange transition)
+{
+ GstGLFilter *filter;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ GST_DEBUG ("change state");
+
+ filter = GST_GL_FILTER (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ gst_gl_filter_start (filter);
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ gst_gl_filter_stop (filter);
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+void
+dump_fbconfigs (Display * display)
+{
+ GLXFBConfig *fbconfigs;
+ int n;
+ int i;
+ int j;
+ int ret;
+ int value;
+ struct
+ {
+ int attr;
+ char *name;
+ } list[] = {
+ {
+ GLX_DRAWABLE_TYPE, "drawable type"}, {
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT, "bind to texture targets"}, {
+ GLX_BIND_TO_TEXTURE_RGBA_EXT, "bind to texture rgba"}, {
+ GLX_MAX_PBUFFER_WIDTH, "max pbuffer width"}, {
+ GLX_MAX_PBUFFER_HEIGHT, "max pbuffer height"}, {
+ GLX_MAX_PBUFFER_PIXELS, "max pbuffer pixels"}, {
+ GLX_RENDER_TYPE, "render type"}, {
+ 0, 0}
+ };
+
+ g_print ("screen count: %d\n", ScreenCount (display));
+
+ fbconfigs = glXGetFBConfigs (display, 0, &n);
+ for (i = 0; i < n; i++) {
+ g_print ("%d:\n", i);
+ for (j = 0; list[j].attr; j++) {
+ ret = glXGetFBConfigAttrib (display, fbconfigs[i], list[j].attr, &value);
+ if (ret != Success) {
+ g_print ("%s: failed\n", list[j].name);
+ } else {
+ g_print ("%s: %d\n", list[j].name, value);
+ }
+ }
+ }
+
+}
+
+static gboolean
+gst_gl_filter_transform (GstGLBuffer * outbuf, GstGLBuffer * inbuf)
+{
+ GstGLDisplay *display;
+
+#if 0
+ int pixmapAttribs[] = {
+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_RECTANGLE_EXT,
+ GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
+ None
+ };
+#endif
+ GLXFBConfig *fbconfigs;
+ int n;
+ int i;
+ GLXDrawable glxpixmap;
+ GLXContext context = 0;
+ int fb_index = 0;
+ int attrib[] = { GLX_RGBA, GLX_RED_SIZE, 8,
+ GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None
+ };
+ XVisualInfo *visinfo;
+
+ display = outbuf->display;
+ gst_gl_display_lock (display);
+
+ //context = glXCreateContext (display->display, visinfo, NULL, True);
+
+ dump_fbconfigs (display->display);
+
+ fbconfigs = glXGetFBConfigs (display->display, display->screen_num, &n);
+ for (i = 0; i < n; i++) {
+ XVisualInfo *visinfo;
+ int value;
+
+ GST_DEBUG ("fbconfig %d", i);
+
+ visinfo = glXGetVisualFromFBConfig (display->display, fbconfigs[i]);
+ GST_DEBUG ("visinfo %p", visinfo);
+
+ glXGetFBConfigAttrib (display->display, fbconfigs[i],
+ GLX_DRAWABLE_TYPE, &value);
+ if (!(value & GLX_WINDOW_BIT)) {
+ GST_DEBUG ("GLX_DRAWABLE_TYPE doesn't have GLX_WINDOW_BIT set");
+ continue;
+ }
+
+ glXGetFBConfigAttrib (display->display, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT, &value);
+ if (!(value & GLX_TEXTURE_2D_BIT_EXT)) {
+ GST_DEBUG
+ ("GLX_BIND_TO_TEXTURE_TARGETS_EXT doesn't have GLX_TEXTURE_2D_BIT_EXT set");
+ continue;
+ }
+
+ glXGetFBConfigAttrib (display->display, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_RGBA_EXT, &value);
+ GST_DEBUG ("GLX_BIND_TO_TEXTURE_RGBA_EXT %d", value);
+
+ }
+
+ fb_index = 0;
+
+#if 0
+ {
+ pb = glXCreatePbuffer (display->display, fbconfigs[fb_index], attribs);
+ }
+#endif
+
+ XSync (display->display, False);
+ visinfo = glXChooseVisual (display->display, 0, attrib);
+ glxpixmap = glXCreateGLXPixmap (display->display, visinfo, outbuf->pixmap);
+
+ XSync (display->display, False);
+
+ glXMakeCurrent (display->display, glxpixmap, context);
+
+ glXMakeCurrent (display->display, None, NULL);
+ gst_gl_display_unlock (display);
+
+ return TRUE;
+}
diff --git a/sys/glsink/gstglupload.c b/sys/glsink/gstglupload.c
index 116d9d44..81d73175 100644
--- a/sys/glsink/gstglupload.c
+++ b/sys/glsink/gstglupload.c
@@ -78,7 +78,7 @@ static GstStaticPadTemplate gst_gl_upload_sink_pad_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx)
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx)
);
enum
@@ -99,6 +99,9 @@ static void gst_gl_upload_get_property (GObject * object, guint prop_id,
static GstFlowReturn gst_gl_upload_chain (GstPad * pad, GstBuffer * buf);
static void gst_gl_upload_reset (GstGLUpload * upload);
+static GstStateChangeReturn
+gst_gl_upload_change_state (GstElement * element, GstStateChange transition);
+static gboolean gst_gl_upload_sink_setcaps (GstPad * pad, GstCaps * caps);
static void
@@ -123,11 +126,18 @@ gst_gl_upload_class_init (GstGLUploadClass * klass)
gobject_class->set_property = gst_gl_upload_set_property;
gobject_class->get_property = gst_gl_upload_get_property;
+ GST_ELEMENT_CLASS (klass)->change_state = gst_gl_upload_change_state;
}
static void
gst_gl_upload_init (GstGLUpload * upload, GstGLUploadClass * klass)
{
+ gst_element_create_all_pads (GST_ELEMENT (upload));
+
+ upload->sinkpad = gst_element_get_static_pad (GST_ELEMENT (upload), "sink");
+ upload->srcpad = gst_element_get_static_pad (GST_ELEMENT (upload), "src");
+
+ gst_pad_set_setcaps_function (upload->sinkpad, gst_gl_upload_sink_setcaps);
gst_pad_set_chain_function (upload->sinkpad, gst_gl_upload_chain);
gst_gl_upload_reset (upload);
@@ -162,6 +172,61 @@ gst_gl_upload_get_property (GObject * object, guint prop_id,
static void
gst_gl_upload_reset (GstGLUpload * upload)
{
+ if (upload->display) {
+ g_object_unref (upload->display);
+ upload->display = NULL;
+ }
+ upload->format = GST_VIDEO_FORMAT_BGRx;
+}
+
+static gboolean
+gst_gl_upload_start (GstGLUpload * upload)
+{
+ gboolean ret;
+
+ upload->format = GST_VIDEO_FORMAT_BGRx;
+ upload->display = gst_gl_display_new ();
+ ret = gst_gl_display_connect (upload->display, NULL);
+
+ return ret;
+}
+
+static gboolean
+gst_gl_upload_stop (GstGLUpload * upload)
+{
+ gst_gl_upload_reset (upload);
+
+ return TRUE;
+}
+
+static gboolean
+gst_gl_upload_sink_setcaps (GstPad * pad, GstCaps * caps)
+{
+ GstGLUpload *upload;
+ GstVideoFormat format;
+ int height;
+ int width;
+ gboolean ret;
+ GstCaps *srccaps;
+
+ upload = GST_GL_UPLOAD (gst_pad_get_parent (pad));
+
+ ret = gst_video_format_parse_caps (caps, &format, &width, &height);
+ if (!ret)
+ return FALSE;
+
+ upload->format = format;
+ upload->width = width;
+ upload->height = height;
+
+ GST_ERROR ("setcaps %d %d %d", format, width, height);
+
+ srccaps = gst_caps_new_simple ("video/x-raw-gl",
+ "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
+ ret = gst_pad_set_caps (upload->srcpad, srccaps);
+ gst_caps_unref (srccaps);
+
+ return ret;
}
static GstFlowReturn
@@ -177,6 +242,10 @@ gst_gl_upload_chain (GstPad * pad, GstBuffer * buf)
gst_buffer_copy_metadata (GST_BUFFER (outbuf), buf,
GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS);
+ gst_buffer_set_caps (GST_BUFFER (outbuf), GST_PAD_CAPS (upload->srcpad));
+
+ GST_DEBUG ("uploading %p size %d", GST_BUFFER_DATA (buf),
+ GST_BUFFER_SIZE (buf));
gst_gl_buffer_upload (outbuf, GST_BUFFER_DATA (buf));
gst_pad_push (upload->srcpad, GST_BUFFER (outbuf));
@@ -184,3 +253,44 @@ gst_gl_upload_chain (GstPad * pad, GstBuffer * buf)
gst_object_unref (upload);
return GST_FLOW_OK;
}
+
+static GstStateChangeReturn
+gst_gl_upload_change_state (GstElement * element, GstStateChange transition)
+{
+ GstGLUpload *upload;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ GST_DEBUG ("change state");
+
+ upload = GST_GL_UPLOAD (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ gst_gl_upload_start (upload);
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ gst_gl_upload_stop (upload);
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
diff --git a/sys/glsink/gstopengl.c b/sys/glsink/gstopengl.c
index 7116174a..4889e0a6 100644
--- a/sys/glsink/gstopengl.c
+++ b/sys/glsink/gstopengl.c
@@ -33,6 +33,8 @@
#include <glimagesink.h>
GType gst_gl_upload_get_type (void);
+GType gst_gl_download_get_type (void);
+GType gst_gl_filter_get_type (void);
static gboolean
@@ -46,15 +48,17 @@ plugin_init (GstPlugin * plugin)
return FALSE;
}
if (!gst_element_register (plugin, "glupload",
- GST_RANK_MARGINAL, gst_gl_upload_get_type ())) {
+ GST_RANK_NONE, gst_gl_upload_get_type ())) {
return FALSE;
}
-#if 0
if (!gst_element_register (plugin, "gldownload",
- GST_RANK_MARGINAL, GST_TYPE_GL_DOWNLOAD)) {
+ GST_RANK_NONE, gst_gl_download_get_type ())) {
+ return FALSE;
+ }
+ if (!gst_element_register (plugin, "glfilter",
+ GST_RANK_NONE, gst_gl_filter_get_type ())) {
return FALSE;
}
-#endif
return TRUE;
}