From 4c892cb683d403f106c4b2672fccaa133e7808fd Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 21 Dec 2007 00:03:10 +0000 Subject: [PATCH] [040/906] * 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. --- gst-libs/gst/gl/glextensions.c | 57 ++++++++ gst-libs/gst/gl/glextensions.h | 24 ++++ gst-libs/gst/gl/gstglbuffer.c | 239 +++++++++++++++++++++++++++++++++ gst-libs/gst/gl/gstglbuffer.h | 47 +++++++ 4 files changed, 367 insertions(+) create mode 100644 gst-libs/gst/gl/gstglbuffer.c create mode 100644 gst-libs/gst/gl/gstglbuffer.h diff --git a/gst-libs/gst/gl/glextensions.c b/gst-libs/gst/gl/glextensions.c index 31b862e32b..6c48e8b28c 100644 --- a/gst-libs/gst/gl/glextensions.c +++ b/gst-libs/gst/gl/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/gst-libs/gst/gl/glextensions.h b/gst-libs/gst/gl/glextensions.h index fd3f8ea751..48161c4939 100644 --- a/gst-libs/gst/gl/glextensions.h +++ b/gst-libs/gst/gl/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/gst-libs/gst/gl/gstglbuffer.c b/gst-libs/gst/gl/gstglbuffer.c new file mode 100644 index 0000000000..04421ce79c --- /dev/null +++ b/gst-libs/gst/gl/gstglbuffer.c @@ -0,0 +1,239 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "glextensions.h" + +#include + +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/gst-libs/gst/gl/gstglbuffer.h b/gst-libs/gst/gl/gstglbuffer.h new file mode 100644 index 0000000000..969f216191 --- /dev/null +++ b/gst-libs/gst/gl/gstglbuffer.h @@ -0,0 +1,47 @@ + +#ifndef _GST_GL_BUFFER_H_ +#define _GST_GL_BUFFER_H_ + +#include +#include +#include +#include + +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 +