From 07780031bc2207ed87f895634f56b85f5841eb0d Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 22 Dec 2007 05:01:57 +0000 Subject: [PATCH] [041/906] * sys/glsink/glextensions.c: * sys/glsink/glextensions.h: * sys/glsink/glvideo.c: * sys/glsink/glvideo.h: * sys/glsink/gstglbuffer.c: * sys/glsink/gstgldownload.c: * sys/glsink/gstglupload.c: A careful read of the documentation reveals that I can't use renderbuffers as textures. Duh. Checkpoint because I'm about to rewrite a bunch of code. --- gst-libs/gst/gl/glextensions.c | 2 + gst-libs/gst/gl/glextensions.h | 2 + gst-libs/gst/gl/gstglbuffer.c | 64 +++++++++++++++++-- gst/gl/glvideo.c | 113 +++++++++++++++++++++++++++++++++ gst/gl/glvideo.h | 4 +- gst/gl/gstgldownload.c | 26 ++++---- gst/gl/gstglupload.c | 15 ++++- 7 files changed, 206 insertions(+), 20 deletions(-) diff --git a/gst-libs/gst/gl/glextensions.c b/gst-libs/gst/gl/glextensions.c index 6c48e8b28c..6926a970e0 100644 --- a/gst-libs/gst/gl/glextensions.c +++ b/gst-libs/gst/gl/glextensions.c @@ -179,3 +179,5 @@ DEFINE_FUNC (glFramebufferRenderbufferEXT, (GLenum target, GLenum attachment, DEFINE_FUNC (glGetFramebufferAttachmentParameterivEXT, (GLenum target, GLenum pname, GLint * params), (target, pname, params)); DEFINE_FUNC (glGenerateMipmapEXT, (GLenum target), (target)); + +DEFINE_FUNC (glWindowPos2iARB, (GLint x, GLint y), (x, y)); diff --git a/gst-libs/gst/gl/glextensions.h b/gst-libs/gst/gl/glextensions.h index 48161c4939..7ef01869d5 100644 --- a/gst-libs/gst/gl/glextensions.h +++ b/gst-libs/gst/gl/glextensions.h @@ -54,5 +54,7 @@ void glGetFramebufferAttachmentParameterivEXT (GLenum target, GLenum pname, GLint *params); void glGenerateMipmapEXT (GLenum target); +void glWindowPos2iARB (GLint x, GLint y); + #endif diff --git a/gst-libs/gst/gl/gstglbuffer.c b/gst-libs/gst/gl/gstglbuffer.c index 04421ce79c..da4093d423 100644 --- a/gst-libs/gst/gl/gstglbuffer.c +++ b/gst-libs/gst/gl/gstglbuffer.c @@ -5,6 +5,8 @@ #include #include +#include +#include #include "glextensions.h" #include @@ -86,7 +88,7 @@ gst_gl_buffer_new (GstGLDisplay * display, GstVideoFormat format, GstGLBuffer *buffer; XGCValues values = { 0 }; - g_return_val_if_fail (format == GST_VIDEO_FORMAT_BGRx, NULL); + 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); @@ -112,17 +114,35 @@ gst_gl_buffer_new (GstGLDisplay * display, GstVideoFormat format, } 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; @@ -170,6 +190,8 @@ gst_gl_buffer_upload (GstGLBuffer * buffer, void *data) { unsigned int fbo; + g_assert (glIsRenderbufferEXT (buffer->rbo)); + glGenFramebuffersEXT (1, &fbo); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo); @@ -177,11 +199,40 @@ gst_gl_buffer_upload (GstGLBuffer * buffer, void *data) GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, buffer->rbo); glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT); - //glWindowPos2iARB(0, 0); - glDrawPixels (buffer->width, buffer->height, GL_RGBA, + 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; } @@ -223,8 +274,13 @@ gst_gl_buffer_download (GstGLBuffer * buffer, void *data) glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, buffer->rbo); + glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT); glReadBuffer (GL_COLOR_ATTACHMENT1_EXT); - glReadPixels (0, 0, buffer->width, buffer->height, GL_RGBA, + + 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); diff --git a/gst/gl/glvideo.c b/gst/gl/glvideo.c index f73281537a..8bc8f9f004 100644 --- a/gst/gl/glvideo.c +++ b/gst/gl/glvideo.c @@ -247,11 +247,13 @@ gst_gl_display_lock (GstGLDisplay * display) { g_mutex_lock (display->lock); glXMakeCurrent (display->display, display->window, display->context); + gst_gl_display_check_error (display, __LINE__); } void gst_gl_display_unlock (GstGLDisplay * display) { + gst_gl_display_check_error (display, __LINE__); glXMakeCurrent (display->display, None, NULL); g_mutex_unlock (display->lock); } @@ -346,6 +348,17 @@ gst_gl_display_clear (GstGLDisplay * display) gst_gl_display_unlock (display); } +void +gst_gl_display_check_error (GstGLDisplay * display, int line) +{ + GLenum err = glGetError (); + + if (err) { + GST_ERROR ("GL Error 0x%x at line %d", (int) err, line); + g_assert (0); + } +} + static void @@ -629,3 +642,103 @@ gst_gl_display_draw_image (GstGLDisplay * display, GstGLImageType type, gst_gl_display_unlock (display); } + +void +gst_gl_display_draw_rbo (GstGLDisplay * display, GLuint rbo, + int width, int height) +{ + GLuint texture; + GLuint fbo; + + g_return_if_fail (width > 0); + g_return_if_fail (height > 0); + g_return_if_fail (rbo != None); + + gst_gl_display_lock (display); + + g_assert (display->window != None); + g_assert (display->context != NULL); + + gst_gl_display_update_attributes (display); + + glViewport (0, 0, display->win_width, display->win_height); + + glClearColor (0.3, 0.3, 0.3, 1.0); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + glDisable (GL_CULL_FACE); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); + + glColor4f (1, 1, 1, 1); + + glGenFramebuffersEXT (1, &fbo); + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo); + + glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, rbo); + + glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer (GL_COLOR_ATTACHMENT0_EXT); + + g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) == + GL_FRAMEBUFFER_COMPLETE_EXT); + +#if 1 + { + void *buffer; + + buffer = malloc (320 * 240 * 4); + memset (buffer, random (), 320 * 240 * 4); + free (buffer); + } +#endif + + glEnable (GL_TEXTURE_RECTANGLE_ARB); + glGenTextures (1, &texture); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); + glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, width, height, 0, + GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_RECTANGLE_ARB, texture, 0); + + glDrawBuffer (0); + glReadBuffer (0); + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); + glColor4f (1, 0, 1, 1); + gst_gl_display_check_error (display, __LINE__); +//glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0); + glBegin (GL_QUADS); + + glNormal3f (0, 0, -1); + + glTexCoord2f (width, 0); + glVertex3f (0.9, 0.9, 0); + glTexCoord2f (0, 0); + glVertex3f (-0.9, 0.9, 0); + glTexCoord2f (0, height); + glVertex3f (-0.9, -0.9, 0); + glTexCoord2f (width, height); + glVertex3f (0.9, -0.9, 0); + glEnd (); + gst_gl_display_check_error (display, __LINE__); + glDeleteTextures (1, &texture); + + glDeleteFramebuffersEXT (1, &fbo); + gst_gl_display_check_error (display, __LINE__); + + glXSwapBuffers (display->display, display->window); + + gst_gl_display_unlock (display); +} diff --git a/gst/gl/glvideo.h b/gst/gl/glvideo.h index aef064e3aa..4fb3761e62 100644 --- a/gst/gl/glvideo.h +++ b/gst/gl/glvideo.h @@ -81,7 +81,9 @@ 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); - +void gst_gl_display_draw_rbo (GstGLDisplay * display, GLuint rbo, + int width, int height); +void gst_gl_display_check_error (GstGLDisplay *display, int line); #endif diff --git a/gst/gl/gstgldownload.c b/gst/gl/gstgldownload.c index 55f9e759a5..5c7bbedba8 100644 --- a/gst/gl/gstgldownload.c +++ b/gst/gl/gstgldownload.c @@ -71,7 +71,7 @@ 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) + GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB) ); static GstStaticPadTemplate gst_gl_download_sink_pad_template = @@ -178,19 +178,15 @@ gst_gl_download_reset (GstGLDownload * download) g_object_unref (download->display); download->display = NULL; } - download->format = GST_VIDEO_FORMAT_BGRx; + download->format = GST_VIDEO_FORMAT_RGB; } static gboolean gst_gl_download_start (GstGLDownload * download) { - gboolean ret; + download->format = GST_VIDEO_FORMAT_RGB; - download->format = GST_VIDEO_FORMAT_BGRx; - download->display = gst_gl_display_new (); - ret = gst_gl_display_connect (download->display, NULL); - - return ret; + return TRUE; } static gboolean @@ -211,15 +207,20 @@ gst_gl_download_sink_setcaps (GstPad * pad, GstCaps * caps) download = GST_GL_DOWNLOAD (gst_pad_get_parent (pad)); + GST_ERROR ("called with %" GST_PTR_FORMAT, caps); + 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) + if (!ret) { + GST_ERROR ("bad caps"); return FALSE; + } srccaps = gst_video_format_new_caps (download->format, download->width, download->height, 30, 1, 1, 1); + GST_ERROR ("srccaps %" GST_PTR_FORMAT, srccaps); ret = gst_pad_set_caps (download->srcpad, srccaps); gst_caps_unref (srccaps); @@ -233,16 +234,17 @@ gst_gl_download_chain (GstPad * pad, GstBuffer * buf) 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); + outbuf = + gst_buffer_new_and_alloc (gst_video_format_get_size (download->format, + inbuf->width, inbuf->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 (download->srcpad)); - GST_ERROR ("downloading %p size %d", + GST_DEBUG ("downloading %p size %d", GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf)); gst_gl_buffer_download (inbuf, GST_BUFFER_DATA (outbuf)); diff --git a/gst/gl/gstglupload.c b/gst/gl/gstglupload.c index 81d73175a8..1b0d78f113 100644 --- a/gst/gl/gstglupload.c +++ b/gst/gl/gstglupload.c @@ -53,6 +53,8 @@ struct _GstGLUpload GstVideoFormat format; int width; int height; + + gboolean peek; }; struct _GstGLUploadClass @@ -78,7 +80,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_BGRx) + GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB) ); enum @@ -176,7 +178,8 @@ gst_gl_upload_reset (GstGLUpload * upload) g_object_unref (upload->display); upload->display = NULL; } - upload->format = GST_VIDEO_FORMAT_BGRx; + upload->format = GST_VIDEO_FORMAT_RGB; + upload->peek = TRUE; } static gboolean @@ -184,7 +187,7 @@ gst_gl_upload_start (GstGLUpload * upload) { gboolean ret; - upload->format = GST_VIDEO_FORMAT_BGRx; + upload->format = GST_VIDEO_FORMAT_RGB; upload->display = gst_gl_display_new (); ret = gst_gl_display_connect (upload->display, NULL); @@ -247,6 +250,12 @@ gst_gl_upload_chain (GstPad * pad, GstBuffer * buf) GST_DEBUG ("uploading %p size %d", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); gst_gl_buffer_upload (outbuf, GST_BUFFER_DATA (buf)); + gst_buffer_unref (buf); + + if (upload->peek) { + gst_gl_display_draw_rbo (outbuf->display, outbuf->rbo, + outbuf->width, outbuf->height); + } gst_pad_push (upload->srcpad, GST_BUFFER (outbuf));