[046/906] * sys/glsink/BUGS: * sys/glsink/Makefile.am: * sys/glsink/gstglbuffer.c: * sys/glsink/gstglbuffer.h: * sys/glsink/gstglconvert.c: * sys/glsink/gstgldisplay.c: * sys/glsink/gstglfilter.c: * sys/glsink/gstglfilter.h: * sys/glsink/gstglfilterexample.c: * sys/glsink/gstgltestsrc.c: * sys/glsink/gstglupload.c: * sys/glsink/gstopengl.c: Remove code that handles non-texture buffers. Add a GstGLBufferFormat type that corresponds to how to use the texture, not the original video format. Convert gstflfilter.c into a base class, add glfilterexample and glconvert elements. * sys/glsink/color_matrix.c: Minor ramblings about color conversion matrices.

This commit is contained in:
David Schleef 2007-12-27 00:52:22 +00:00 committed by Tim-Philipp Müller
parent c46924bb35
commit 5e620c9673
3 changed files with 160 additions and 189 deletions

View File

@ -18,22 +18,14 @@ gst_gl_buffer_finalize (GstGLBuffer * buffer)
{ {
gst_gl_display_lock (buffer->display); 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;
case GST_GL_BUFFER_TEXTURE:
glDeleteTextures (1, &buffer->texture); glDeleteTextures (1, &buffer->texture);
break; if (buffer->texture_u) {
default: glDeleteTextures (1, &buffer->texture_u);
g_assert_not_reached ();
break;
} }
if (buffer->texture_v) {
glDeleteTextures (1, &buffer->texture_v);
}
gst_gl_display_unlock (buffer->display); gst_gl_display_unlock (buffer->display);
g_object_unref (buffer->display); g_object_unref (buffer->display);
@ -85,199 +77,176 @@ gst_gl_buffer_get_type (void)
GstGLBuffer * GstGLBuffer *
gst_gl_buffer_new (GstGLDisplay * display, GstVideoFormat format, gst_gl_buffer_new (GstGLDisplay * display, GstGLBufferFormat format,
int width, int height) int width, int height)
{ {
GstGLBuffer *buffer; GstGLBuffer *buffer;
XGCValues values = { 0 };
g_return_val_if_fail (format == GST_VIDEO_FORMAT_RGBx, NULL);
g_return_val_if_fail (width > 0, NULL); g_return_val_if_fail (width > 0, NULL);
g_return_val_if_fail (height > 0, NULL); g_return_val_if_fail (height > 0, NULL);
buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER); buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
buffer->display = g_object_ref (display); buffer->display = g_object_ref (display);
buffer->type = GST_GL_BUFFER_TEXTURE;
buffer->width = width; buffer->width = width;
buffer->height = height; 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); gst_gl_display_lock (buffer->display);
glGenTextures (1, &buffer->texture);
glGenFramebuffersEXT (1, &fbo); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo); switch (format) {
case GST_GL_BUFFER_FORMAT_RGBA:
glGenRenderbuffersEXT (1, &buffer->rbo); glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, buffer->rbo); buffer->width, buffer->height, 0, GL_RGBA, GL_FLOAT, NULL);
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, buffer->rbo);
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_RGB,
buffer->width, buffer->height);
glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT);
glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
GL_FRAMEBUFFER_COMPLETE_EXT);
glDeleteFramebuffersEXT (1, &fbo);
gst_gl_display_unlock (buffer->display);
break; break;
} case GST_GL_BUFFER_FORMAT_RGB:
case GST_GL_BUFFER_TEXTURE: glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
break; break;
default: default:
g_assert_not_reached (); g_warning ("GL buffer format not handled");
} }
gst_gl_display_unlock (buffer->display);
return buffer; return buffer;
} }
void GstGLBuffer *
gst_gl_buffer_upload (GstGLBuffer * buffer, void *data) gst_gl_buffer_new_from_data (GstGLDisplay * display, GstVideoFormat format,
int width, int height, void *data)
{ {
Display *display = buffer->display->display; GstGLBuffer *buffer;
int comp;
GST_DEBUG ("uploading %p %dx%d", data, buffer->width, buffer->height); g_return_val_if_fail (width > 0, NULL);
g_return_val_if_fail (height > 0, NULL);
g_return_val_if_fail (data != NULL, NULL);
GST_DEBUG ("uploading %p %dx%d", data, width, height);
buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
buffer->display = g_object_ref (display);
buffer->width = width;
buffer->height = height;
gst_gl_display_lock (buffer->display); gst_gl_display_lock (buffer->display);
glGenTextures (1, &buffer->texture);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture);
switch (buffer->type) { switch (format) {
case GST_GL_BUFFER_XIMAGE: case GST_VIDEO_FORMAT_RGBx:
{ buffer->format = GST_GL_BUFFER_FORMAT_RGB;
XImage *image; glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
Visual *visual; buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
int depth; glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
int bpp; GL_RGBA, GL_UNSIGNED_BYTE, data);
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; break;
} case GST_VIDEO_FORMAT_BGRx:
case GST_GL_BUFFER_RBO: buffer->format = GST_GL_BUFFER_FORMAT_RGB;
{ glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
unsigned int fbo; buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
g_assert (glIsRenderbufferEXT (buffer->rbo)); GL_BGRA, GL_UNSIGNED_BYTE, data);
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);
gst_gl_display_check_error (buffer->display, __LINE__);
glWindowPos2iARB (0, 0);
glDrawPixels (buffer->width, buffer->height, GL_RGB,
GL_UNSIGNED_BYTE, data);
glDeleteFramebuffersEXT (1, &fbo);
g_assert (glIsRenderbufferEXT (buffer->rbo));
break; break;
} case GST_VIDEO_FORMAT_xRGB:
case GST_GL_BUFFER_TEXTURE: buffer->format = GST_GL_BUFFER_FORMAT_RGB;
buffer->texture = glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
gst_gl_display_upload_texture_rectangle (buffer->display, buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
GST_VIDEO_FORMAT_RGBx, data, buffer->width, buffer->height); glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, data);
break;
case GST_VIDEO_FORMAT_xBGR:
buffer->format = GST_GL_BUFFER_FORMAT_RGB;
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, data);
break;
case GST_VIDEO_FORMAT_YUY2:
buffer->format = GST_GL_BUFFER_FORMAT_YUYV;
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width, height,
0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, NULL);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, data);
break;
case GST_VIDEO_FORMAT_UYVY:
buffer->format = GST_GL_BUFFER_FORMAT_YUYV;
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width, height,
0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, NULL);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, data);
break;
case GST_VIDEO_FORMAT_AYUV:
buffer->format = GST_GL_BUFFER_FORMAT_RGB;
buffer->is_yuv = TRUE;
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, data);
break;
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
buffer->format = GST_GL_BUFFER_FORMAT_PLANAR420;
buffer->is_yuv = TRUE;
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
buffer->width, buffer->height,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
glGenTextures (1, &buffer->texture_u);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture_u);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
GST_ROUND_UP_2 (buffer->width) / 2,
GST_ROUND_UP_2 (buffer->height) / 2,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
comp = (format == GST_VIDEO_FORMAT_I420) ? 1 : 2;
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (buffer->width) / 2,
GST_ROUND_UP_2 (buffer->height) / 2,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
(guint8 *) data +
gst_video_format_get_component_offset (format, comp, width, height));
glGenTextures (1, &buffer->texture_v);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture_v);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
GST_ROUND_UP_2 (buffer->width) / 2,
GST_ROUND_UP_2 (buffer->height) / 2,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
comp = (format == GST_VIDEO_FORMAT_I420) ? 2 : 1;
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (buffer->width) / 2,
GST_ROUND_UP_2 (buffer->height) / 2,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
(guint8 *) data +
gst_video_format_get_component_offset (format, comp, width, height));
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
gst_gl_display_unlock (buffer->display); gst_gl_display_unlock (buffer->display);
return buffer;
} }
void void
gst_gl_buffer_download (GstGLBuffer * buffer, void *data) gst_gl_buffer_download (GstGLBuffer * buffer, void *data)
{ {
gst_gl_display_lock (buffer->display); GLuint fbo;
GST_DEBUG ("downloading"); GST_DEBUG ("downloading");
switch (buffer->type) { gst_gl_display_lock (buffer->display);
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;
}
case GST_GL_BUFFER_TEXTURE:
{
unsigned int fbo;
glGenFramebuffersEXT (1, &fbo); glGenFramebuffersEXT (1, &fbo);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, buffer->texture, 0);
buffer->texture, 0);
glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT); glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT);
glReadBuffer (GL_COLOR_ATTACHMENT1_EXT); glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
@ -285,15 +254,17 @@ gst_gl_buffer_download (GstGLBuffer * buffer, void *data)
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) == g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
GL_FRAMEBUFFER_COMPLETE_EXT); GL_FRAMEBUFFER_COMPLETE_EXT);
/* needs a reset function */
glMatrixMode (GL_COLOR);
glLoadIdentity ();
glPixelTransferf (GL_POST_COLOR_MATRIX_RED_BIAS, 0);
glPixelTransferf (GL_POST_COLOR_MATRIX_GREEN_BIAS, 0);
glPixelTransferf (GL_POST_COLOR_MATRIX_BLUE_BIAS, 0);
glReadPixels (0, 0, buffer->width, buffer->height, GL_RGBA, glReadPixels (0, 0, buffer->width, buffer->height, GL_RGBA,
GL_UNSIGNED_BYTE, data); GL_UNSIGNED_BYTE, data);
glDeleteFramebuffersEXT (1, &fbo); glDeleteFramebuffersEXT (1, &fbo);
}
break;
default:
g_assert_not_reached ();
}
gst_gl_display_unlock (buffer->display); gst_gl_display_unlock (buffer->display);
} }

View File

@ -14,24 +14,25 @@ typedef struct _GstGLBuffer GstGLBuffer;
#define GST_GL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GL_BUFFER, GstGLBuffer)) #define GST_GL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GL_BUFFER, GstGLBuffer))
typedef enum { typedef enum {
GST_GL_BUFFER_UNKNOWN, GST_GL_BUFFER_FORMAT_RGBA,
GST_GL_BUFFER_XIMAGE, GST_GL_BUFFER_FORMAT_RGB,
GST_GL_BUFFER_RBO, GST_GL_BUFFER_FORMAT_YUYV,
GST_GL_BUFFER_TEXTURE GST_GL_BUFFER_FORMAT_PLANAR444,
} GstGLBufferType; GST_GL_BUFFER_FORMAT_PLANAR422,
GST_GL_BUFFER_FORMAT_PLANAR420
} GstGLBufferFormat;
struct _GstGLBuffer { struct _GstGLBuffer {
GstBuffer buffer; GstBuffer buffer;
GstGLDisplay *display; GstGLDisplay *display;
GstGLBufferType type; GstGLBufferFormat format;
gboolean is_yuv;
XID pixmap;
GC gc;
GLuint rbo;
GLuint texture; GLuint texture;
GLuint texture_u;
GLuint texture_v;
int width; int width;
int height; int height;
@ -39,9 +40,10 @@ struct _GstGLBuffer {
GType gst_gl_buffer_get_type (void); GType gst_gl_buffer_get_type (void);
GstGLBuffer * gst_gl_buffer_new (GstGLDisplay *display, GstVideoFormat format, GstGLBuffer * gst_gl_buffer_new (GstGLDisplay *display,
int width, int height); GstGLBufferFormat format, int width, int height);
void gst_gl_buffer_upload (GstGLBuffer *buffer, void *data); GstGLBuffer * gst_gl_buffer_new_from_data (GstGLDisplay *display,
GstVideoFormat format, int width, int height, void *data);
void gst_gl_buffer_download (GstGLBuffer *buffer, void *data); void gst_gl_buffer_download (GstGLBuffer *buffer, void *data);
#endif #endif

View File

@ -430,8 +430,6 @@ draw_rect_texture (GstGLDisplay * display, GstVideoFormat type,
#ifdef GL_TEXTURE_RECTANGLE_ARB #ifdef GL_TEXTURE_RECTANGLE_ARB
glEnable (GL_TEXTURE_RECTANGLE_ARB); glEnable (GL_TEXTURE_RECTANGLE_ARB);
//glGenTextures (1, &texture);
//glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
texture = gst_gl_display_upload_texture_rectangle (display, type, texture = gst_gl_display_upload_texture_rectangle (display, type,
data, width, height); data, width, height);