From 2afed7c92a10bf094172a84fd1a371b430c1b070 Mon Sep 17 00:00:00 2001 From: Gernot Ziegler Date: Fri, 31 Oct 2003 16:40:20 +0000 Subject: glsink with correct threading support Original commit message from CVS: glsink with correct threading support --- sys/glsink/ARB_multitexture.h | 2 + sys/glsink/gstgl_nvimage.c | 39 ++++++++++------ sys/glsink/gstgl_rgbimage.c | 26 +++++------ sys/glsink/gstglsink.c | 105 ++++++++++++++++++++++++++++++++++-------- sys/glsink/gstglxwindow.c | 36 ++++++++++++++- sys/glsink/regcomb_yuvrgb.c | 6 +-- 6 files changed, 162 insertions(+), 52 deletions(-) diff --git a/sys/glsink/ARB_multitexture.h b/sys/glsink/ARB_multitexture.h index af6de323..36dcf011 100644 --- a/sys/glsink/ARB_multitexture.h +++ b/sys/glsink/ARB_multitexture.h @@ -201,7 +201,9 @@ int CheckForARBMultitextureSupport(void) { int i, pos=0; int maxpos=strlen(search)-1; char extensions[10000]; + printf("Getting GLstring, context is %p\n", glXGetCurrentContext()); strcpy(extensions,(const char *)glGetString(GL_EXTENSIONS)); + printf("Examinig GLstring\n"); int len=strlen(extensions); for ( i=0; i1) && extensions[i-1]==' ')) { diff --git a/sys/glsink/gstgl_nvimage.c b/sys/glsink/gstgl_nvimage.c index e7ee1b62..79caf2be 100644 --- a/sys/glsink/gstgl_nvimage.c +++ b/sys/glsink/gstgl_nvimage.c @@ -103,7 +103,7 @@ gboolean gst_gl_nvimage_check_xvideo () { //int ver, rel, req, ev, err; - + printf("Checking NVidia OpenGL extensions.\n"); if (!GL_ARB_multitexture_Init()) return FALSE; if (!GL_EXT_paletted_texture_Init()) return FALSE; if (!GL_NV_register_combiners_Init()) return FALSE; @@ -127,9 +127,13 @@ gst_gl_nvimage_get_caps (GstImageInfo *info) GstCaps *caps = NULL; GstGLImageInfo *xinfo = gst_gl_nvimage_info (info); - g_warning("nvimage get caps called !\n"); + g_warning("nvimage get caps called, context %p !\n", glXGetCurrentContext()); /* we don't handle these image information */ - if (xinfo == NULL) return NULL; + if (xinfo == NULL) + { + printf("Invalid XInfo struct !\n"); + return NULL; + } if (gst_gl_nvimage_check_xvideo () == FALSE) { @@ -138,7 +142,7 @@ gst_gl_nvimage_get_caps (GstImageInfo *info) } caps = gst_caps_append (caps, GST_CAPS_NEW ( - "xvimage_caps", + "nvimage_caps", "video/x-raw-yuv", "format", GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y', 'V', '1', '2')), "width", GST_PROPS_INT_RANGE (0, 1024), @@ -201,7 +205,7 @@ gst_gl_nvimage_get_image (GstImageInfo *info, GstImageConnection *conn) if (nvconn == NULL) return NULL; // I should also check the current GLX context ! - // Ah, Don't have to, I am guarantueed to always be in the same thread + // Ah, Don't have to, I am guarantueed to be in the same thread as put_image image = g_new0(GstNvImage, 1); @@ -242,16 +246,19 @@ gst_gl_nvimage_put_image (GstImageInfo *info, GstImageData *image) g_assert (xinfo != NULL); // both upload the video, and redraw the screen + //glClearColor(0,0.5, 0.3,1.0); // a test color glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glTranslatef(0.0, 0.0, -25.0); - glEnable(GL_TEXTURE_2D); + glTranslatef(0.0, 0.0, -5.0); + glDisable(GL_TEXTURE_2D); if (xinfo->info.demo) { + //g_print("Putting image, context is %p\n", glXGetCurrentContext()); + glTranslatef(0.0, 0.0, -5.0); // make it avoid the clipping plane, zoom 2.0 instead glRotatef(180.0*sin(xinfo->rotX),1,0,0); glRotatef(180.0*cos(xinfo->rotY),0,1,0); @@ -261,10 +268,10 @@ gst_gl_nvimage_put_image (GstImageInfo *info, GstImageData *image) glScalef(zoom,zoom,zoom); //glScalef(0.1,0.1,0.1); - if (xinfo->zoom > 1.0) + if (xinfo->zoom > 2.0) xinfo->zoomdir = -0.01; - if (xinfo->zoom < 0.5) + if (xinfo->zoom < 1.0) xinfo->zoomdir = 0.01; xinfo->zoom += xinfo->zoomdir; @@ -289,28 +296,29 @@ gst_gl_nvimage_put_image (GstImageInfo *info, GstImageData *image) glBegin(GL_QUADS); float aspect = img_width/(float)img_height; - float hor = 4 * aspect; + float hor = aspect; + //g_print("Drawing vertices, context is %p\n", glXGetCurrentContext()); glNormal3f(0, -1, 0); glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0,0); glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,0); glMultiTexCoord2fARB(GL_TEXTURE2_ARB,0,0); - glVertex3f(-hor,4,0); + glVertex3f(-hor,1,0); glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0,ymax); glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,ymax); glMultiTexCoord2fARB(GL_TEXTURE2_ARB,0,ymax); - glVertex3f(-hor,-4,0); + glVertex3f(-hor,-1,0); glMultiTexCoord2fARB(GL_TEXTURE0_ARB,xmax,ymax); glMultiTexCoord2fARB(GL_TEXTURE1_ARB,xmax,ymax); glMultiTexCoord2fARB(GL_TEXTURE2_ARB,xmax,ymax); - glVertex3f(hor,-4,0); + glVertex3f(hor,-1,0); glMultiTexCoord2fARB(GL_TEXTURE0_ARB,xmax,0); glMultiTexCoord2fARB(GL_TEXTURE1_ARB,xmax,0); glMultiTexCoord2fARB(GL_TEXTURE2_ARB,xmax,0); - glVertex3f(hor,4,0); + glVertex3f(hor,1,0); glEnd(); @@ -339,7 +347,7 @@ gst_gl_nvimage_put_image (GstImageInfo *info, GstImageData *image) if (outfile != NULL) { fprintf(outfile, "P6\n"); - fprintf(outfile,"# created by raw_zb\n"); + fprintf(outfile,"# created by glsink from GStreamer\n"); fprintf(outfile,"%d %d\n",img_width,img_height); fprintf(outfile,"255\n"); fwrite(cap_image_data2, sizeof(char), img_width*img_height*3, outfile); @@ -380,6 +388,7 @@ gst_gl_nvimage_open_conn (GstImageConnection *conn, GstImageInfo *info) Ywidth = TEX_XSIZE; Yheight = TEX_YSIZE; UVwidth = TEX_XSIZE/2; UVheight = TEX_YSIZE/2; Initialize_Backend(Ywidth,Yheight,UVwidth,UVheight,GL_LINEAR); } + g_print("Done\n"); } static void diff --git a/sys/glsink/gstgl_rgbimage.c b/sys/glsink/gstgl_rgbimage.c index 68a1329a..a09e7a25 100644 --- a/sys/glsink/gstgl_rgbimage.c +++ b/sys/glsink/gstgl_rgbimage.c @@ -98,6 +98,7 @@ gst_gl_rgbimage_get_caps (GstImageInfo *info) XImage *ximage; GstGLImageInfo *xinfo = gst_gl_rgbimage_info (info); + g_warning("rgbimage get caps called, context %p, endianness %d !\n", glXGetCurrentContext(), G_BIG_ENDIAN); /* we don't handle this image information */ if (xinfo == NULL) return NULL; @@ -122,9 +123,9 @@ gst_gl_rgbimage_get_caps (GstImageInfo *info) "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")), "depth", GST_PROPS_INT(24), "bpp", GST_PROPS_INT(24), - "red_mask", GST_PROPS_INT(0xff0000), + "red_mask", GST_PROPS_INT(0xff), "green_mask", GST_PROPS_INT(0xff00), - "blue_mask", GST_PROPS_INT(0xff), + "blue_mask", GST_PROPS_INT(0xff0000), "endianness", GST_PROPS_INT(G_BIG_ENDIAN), /*= 1234/4321 (INT) <- endianness */ "width", GST_PROPS_INT_RANGE (0, TEX_XSIZE), /* can't have videos larger than TEX_SIZE */ @@ -133,7 +134,7 @@ gst_gl_rgbimage_get_caps (GstImageInfo *info) XDestroyImage (ximage); } - GST_DEBUG ("GL_RGBImage: returning caps at %p", caps); + printf ("GL_RGBImage: returning caps at %p", caps); return caps; } @@ -245,13 +246,13 @@ gst_gl_rgbimage_put_image (GstImageInfo *info, GstImageData *image) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glTranslatef(0.0, 0.0, -25.0); + glTranslatef(0.0, 0.0, -5.0); glEnable(GL_TEXTURE_2D); if (xinfo->info.demo) { - + glTranslatef(0.0, 0.0, -5.0); // make it avoid the clipping plane, zoom 2.0 instead glRotatef(180.0*sin(xinfo->rotX),1,0,0); glRotatef(180.0*cos(xinfo->rotY),0,1,0); @@ -259,12 +260,11 @@ gst_gl_rgbimage_put_image (GstImageInfo *info, GstImageData *image) xinfo->rotY -= 0.015; float zoom = xinfo->zoom; glScalef(zoom,zoom,zoom); - //glScalef(0.1,0.1,0.1); - if (xinfo->zoom > 1.0) + if (xinfo->zoom > 2.0) xinfo->zoomdir = -0.01; - if (xinfo->zoom < 0.5) + if (xinfo->zoom < 1.0) xinfo->zoomdir = 0.01; xinfo->zoom += xinfo->zoomdir; @@ -278,7 +278,7 @@ gst_gl_rgbimage_put_image (GstImageInfo *info, GstImageData *image) ymax = (float)im->conn->h/TEX_YSIZE; float aspect = img_width/(float)img_height; - float hor = 4 * aspect; + float hor = aspect; glColor4f(1,1,1,1); glBegin(GL_QUADS); @@ -286,16 +286,16 @@ gst_gl_rgbimage_put_image (GstImageInfo *info, GstImageData *image) glNormal3f(0, -1, 0); glTexCoord2f(xmax, 0); - glVertex3f(hor,4,0); + glVertex3f(hor,1,0); glTexCoord2f(0, 0); - glVertex3f(-hor,4,0); + glVertex3f(-hor,1,0); glTexCoord2f(0, ymax); - glVertex3f(-hor,-4,0); + glVertex3f(-hor,-1,0); glTexCoord2f(xmax, ymax); - glVertex3f(hor,-4,0); + glVertex3f(hor,-1,0); glEnd(); if (xinfo->info.dumpvideo) diff --git a/sys/glsink/gstglsink.c b/sys/glsink/gstglsink.c index 8a4449fa..30268d31 100644 --- a/sys/glsink/gstglsink.c +++ b/sys/glsink/gstglsink.c @@ -17,6 +17,14 @@ * Boston, MA 02111-1307, USA. */ +/* + your element belongs to a scheduler, which calls some functions from the same thread + all the other functions could be called from any random thread + ds-work: which are the "some" function in that case ? + It is quite costly to do glXGetCurrentContext for every function call. + _chain, -get, _loop +*/ + #include #include @@ -140,6 +148,8 @@ extern GstImagePlugin* get_gl_rgbimage_plugin (void); extern GstImagePlugin* get_gl_nvimage_plugin (void); /* default output */ extern void gst_glxwindow_new (GstGLSink *sink); +extern void gst_glxwindow_hook_context (GstImageInfo *info); +extern void gst_glxwindow_unhook_context (GstImageInfo *info); static GstPadTemplate *sink_template; @@ -257,9 +267,12 @@ gst_glsink_init (GstGLSink *sink) sink->conn = NULL; /* do initialization of default hook here */ - gst_glxwindow_new (sink); + gst_glxwindow_new (sink); + //printf("GLSink_init: Current context %p\n", glXGetCurrentContext()); + gst_glxwindow_unhook_context(sink->hook); } +/** frees the temporary connection that tests the window system capabilities */ static void gst_glsink_release_conn (GstGLSink *sink) { @@ -357,16 +370,21 @@ gst_glsink_get_bufferpool (GstPad *pad) static gboolean gst_glsink_set_caps (GstGLSink *sink, GstCaps *caps) { - //g_warning("in set caps!\n"); + g_warning("in glsink set caps!\n"); + printf("Getting GLstring, context is %p\n", glXGetCurrentContext()); + GList *list = ((GstGLSinkClass *) G_OBJECT_GET_CLASS (sink))->plugins; GstImageConnection *conn = NULL; while (list) { + printf("AGetting GLstring, context is %p\n", glXGetCurrentContext()); GstImagePlugin *plugin = (GstImagePlugin *) list->data; if ((conn = plugin->set_caps (sink->hook, caps)) != NULL) { - gst_glsink_release_conn (sink); + //gst_glsink_release_conn (sink); + printf("BGetting GLstring, context is %p\n", glXGetCurrentContext()); sink->conn = conn; + printf("CGetting GLstring, context is %p\n", glXGetCurrentContext()); sink->plugin = plugin; sink->conn->open_conn (sink->conn, sink->hook); return TRUE; @@ -382,9 +400,9 @@ Link the input video sink internally. static GstPadLinkReturn gst_glsink_sinkconnect (GstPad *pad, GstCaps *caps) { - fprintf(stderr, "in sinkconnect!\n"); + g_warning("in glsink sinkconnect!\n"); GstGLSink *sink; - guint32 fourcc, print_format; + guint32 fourcc, print_format, result; sink = GST_GLSINK (gst_pad_get_parent (pad)); @@ -392,11 +410,15 @@ gst_glsink_sinkconnect (GstPad *pad, GstCaps *caps) if (!GST_CAPS_IS_FIXED (caps)) return GST_PAD_LINK_DELAYED; + gst_glxwindow_hook_context(sink->hook); /* try to set the caps on the output */ - if (gst_glsink_set_caps (sink, caps) == FALSE) - { - return GST_PAD_LINK_REFUSED; - } + result = gst_glsink_set_caps (sink, caps); + gst_glxwindow_unhook_context(sink->hook); + + if (result == FALSE) + { + return GST_PAD_LINK_REFUSED; + } /* remember width & height */ gst_caps_get_int (caps, "width", &sink->width); @@ -418,18 +440,20 @@ gst_glsink_sinkconnect (GstPad *pad, GstCaps *caps) static GstCaps * gst_glsink_getcaps (GstPad *pad, GstCaps *caps) { - //g_warning("in get caps!\n"); + g_warning("in glsink get caps!\n"); /* what is the "caps" parameter good for? */ GstGLSink *sink = GST_GLSINK (gst_pad_get_parent (pad)); GstCaps *ret = NULL; GList *list = ((GstGLSinkClass *) G_OBJECT_GET_CLASS (sink))->plugins; + gst_glxwindow_hook_context(sink->hook); while (list) { ret = gst_caps_append (ret, ((GstImagePlugin *) list->data)->get_caps (sink->hook)); list = g_list_next (list); } + gst_glxwindow_unhook_context(sink->hook); return ret; } @@ -446,9 +470,8 @@ gst_glsink_chain (GstPad *pad, GstData *_data) //g_warning("in glsink_chain!\n"); GstBuffer *buf = GST_BUFFER (_data); GstGLSink *sink; - //GstClockTime time = GST_BUFFER_TIMESTAMP (buf); + GstBuffer *buffer; - //static int frame_drops = 0; g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_PAD (pad)); @@ -468,7 +491,10 @@ gst_glsink_chain (GstPad *pad, GstData *_data) GST_DEBUG ("glsink: clock wait: %llu %u", GST_BUFFER_TIMESTAMP (buf), GST_BUFFER_SIZE (buf)); -#if 0 +#if 0 + GstClockTime time = GST_BUFFER_TIMESTAMP (buf); + static int frame_drops = 0; + if (sink->clock && time != -1) { if (time < gst_clock_get_time(sink->clock)) { @@ -500,10 +526,55 @@ gst_glsink_chain (GstPad *pad, GstData *_data) if (!sink->muted) { + if (glXGetCurrentContext() == NULL) + { + printf("Rehooking window !\n"); + gst_glxwindow_hook_context(sink->hook); + +#if 1 + GST_DEBUG("Initializing OpenGL parameters\n"); + /* initialize OpenGL drawing */ + glEnable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glClearDepth(1.0f); + glClearColor(0, 0, 0, 0); + + glEnable(GL_AUTO_NORMAL); // let OpenGL generate the Normals + + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); + glPolygonMode(GL_FRONT, GL_FILL); + glPolygonMode(GL_BACK, GL_FILL); + + glShadeModel(GL_SMOOTH); + glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); + + GstGLImageInfo *window = (GstGLImageInfo *)sink->hook; + int w=window->width, h = window->height; + + glViewport(0, 0, (GLint) w, (GLint) h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + GLfloat aspect = (GLfloat) w / (GLfloat) h; + glFrustum(-aspect, aspect, -1.0, 1.0, 5.0, 500.0); + +#endif + gst_glxwindow_unhook_context(sink->hook); + gst_glxwindow_hook_context(sink->hook); + glMatrixMode(GL_MODELVIEW); +#if 0 + sink->hook->free_info(sink->hook); + printf("Reallocating window brutally !\n"); + gst_glxwindow_new(sink); +#endif + } + /* free last_image, if any */ if (sink->last_image != NULL) gst_buffer_unref (sink->last_image); if (sink->bufferpool && GST_BUFFER_BUFFERPOOL (buf) == sink->bufferpool) { + // awful hack ! But I currently have no other solution without changing the API sink->hook->demo = sink->demo; sink->hook->dumpvideo = sink->dumpvideo; @@ -522,6 +593,8 @@ gst_glsink_chain (GstPad *pad, GstData *_data) sink->last_image = buffer; gst_buffer_unref (buf); } + + //gst_glxwindow_unhook_context(sink->hook); } } @@ -687,12 +760,6 @@ plugin_init (GModule *module, GstPlugin *plugin) factory = gst_element_factory_new("glsink",GST_TYPE_GLSINK, &gst_glsink_details); - if (factory == NULL) - { - g_warning("DANGER; WILL !\n"); - } - - g_warning("INIT GST_LITTLE_ENDIAN %d!\n", G_LITTLE_ENDIAN); g_return_val_if_fail(factory != NULL, FALSE); /* this is needed later on in the _real_ init (during a gst-launch) */ diff --git a/sys/glsink/gstglxwindow.c b/sys/glsink/gstglxwindow.c index 79b743a0..3f9d3df9 100644 --- a/sys/glsink/gstglxwindow.c +++ b/sys/glsink/gstglxwindow.c @@ -44,6 +44,38 @@ GLfloat LightDiffuse[] = { 0.6, 0.6, 0.6, 1.0 }; /* bluish diffuse light. */ GLfloat LightPosition[] = { 1.5, 1.5, 1.5, 0.0 }; /* position */ +void +gst_glxwindow_unhook_context(GstImageInfo *info) +{ + GstGLImageInfo *window = (GstGLImageInfo *) info; + + if (window->ctx) + { + if (!glXMakeCurrent(window->dpy, None, NULL)) + { + printf("Could not release drawing context.\n"); + } + else + printf("Released drawing context.\n"); + } +} + +void +gst_glxwindow_hook_context(GstImageInfo *info) +{ + GstGLImageInfo *window = (GstGLImageInfo *) info; + + if (window->ctx && window->win && window->ctx) + { + if (!glXMakeCurrent(window->dpy, window->win, window->ctx)) + { + printf("Could not acquire GLX drawing context.\n"); + } + else + printf("Acquired drawing context.\n"); + } +} + static void gst_glxwindow_free (GstImageInfo *info) { @@ -92,7 +124,7 @@ gst_glxwindow_callback(GObject *object, GParamSpec *pspec, GstGLImageInfo *data) XMapRaised (data->dpy, data->win); // resize OpenGL - //g_warning("resizing in OpenGL"); + g_warning("resizing in OpenGL"); glViewport(0, 0, (GLint) w, (GLint) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -205,7 +237,7 @@ gst_glxwindow_new (GstElement *sink) else GST_DEBUG ("Sorry, no Direct Rendering possible!\n"); - GST_DEBUG("Initializing OpenGL parameters\n"); + g_warning("Initializing OpenGL parameters\n"); /* initialize OpenGL drawing */ glEnable(GL_DEPTH_TEST); //glShadeModel(GL_SMOOTH); diff --git a/sys/glsink/regcomb_yuvrgb.c b/sys/glsink/regcomb_yuvrgb.c index 0c953c6f..39c86a0f 100644 --- a/sys/glsink/regcomb_yuvrgb.c +++ b/sys/glsink/regcomb_yuvrgb.c @@ -325,9 +325,9 @@ void LoadYUVPlanes(GLuint Yhandle, GLuint Uhandle, GLuint Vhandle, void Initialize_Backend(unsigned int Ywidth, unsigned int Yheight, unsigned int UVwidth, unsigned int UVheight, GLenum filter) { printf("Reinitializing register combiner backend with res %d x %d!\n", Ywidth, Yheight); - if (!GL_ARB_multitexture_Init()) exit(0); - if (!GL_EXT_paletted_texture_Init()) exit(0); - if (!GL_NV_register_combiners_Init()) exit(0); + //if (!GL_ARB_multitexture_Init()) exit(0); + //if (!GL_EXT_paletted_texture_Init()) exit(0); + //if (!GL_NV_register_combiners_Init()) exit(0); unsigned char Ypal[768]; unsigned char Upal[768]; unsigned char Vpal[768]; -- cgit v1.2.1