#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #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_RGB, 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: { GLuint fbo; gst_gl_display_lock (buffer->display); glGenFramebuffersEXT (1, &fbo); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo); glGenRenderbuffersEXT (1, &buffer->rbo); gst_gl_display_check_error (buffer->display, __LINE__); glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, buffer->rbo); gst_gl_display_check_error (buffer->display, __LINE__); glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, buffer->rbo); gst_gl_display_check_error (buffer->display, __LINE__); glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_RGB, buffer->width, buffer->height); gst_gl_display_check_error (buffer->display, __LINE__); glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT); glReadBuffer (GL_COLOR_ATTACHMENT1_EXT); { GLint status; status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT); g_assert (status == GL_FRAMEBUFFER_COMPLETE_EXT); } glDeleteFramebuffersEXT (1, &fbo); 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; g_assert (glIsRenderbufferEXT (buffer->rbo)); 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); glReadBuffer (GL_COLOR_ATTACHMENT1_EXT); g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT); #if 0 { void *newdata; /* FIXME: Some timing issue causes this to work. Note that * we're not actually using the copied buffer. */ gst_gl_display_check_error (buffer->display, __LINE__); glWindowPos2iARB (0, 0); glDrawPixels (buffer->width, buffer->height, GL_RGB, GL_UNSIGNED_BYTE, data); newdata = malloc (4 * buffer->width * buffer->height); //memcpy (newdata, data, 1*buffer->width*buffer->height); memset (newdata, 255, 3 * buffer->width * buffer->height); free (newdata); } #else gst_gl_display_check_error (buffer->display, __LINE__); glWindowPos2iARB (0, 0); glDrawPixels (buffer->width, buffer->height, GL_RGB, GL_UNSIGNED_BYTE, data); #endif gst_gl_display_check_error (buffer->display, __LINE__); glDeleteFramebuffersEXT (1, &fbo); gst_gl_display_check_error (buffer->display, __LINE__); g_assert (glIsRenderbufferEXT (buffer->rbo)); 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); glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT); glReadBuffer (GL_COLOR_ATTACHMENT1_EXT); g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT); glReadPixels (0, 0, buffer->width, buffer->height / 2, GL_RGBA, GL_UNSIGNED_BYTE, data); glDeleteFramebuffersEXT (1, &fbo); break; } default: g_assert_not_reached (); } gst_gl_display_unlock (buffer->display); }