diff options
Diffstat (limited to 'sys/glsink/gstglxwindow.c')
-rw-r--r-- | sys/glsink/gstglxwindow.c | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/sys/glsink/gstglxwindow.c b/sys/glsink/gstglxwindow.c new file mode 100644 index 00000000..96ec673a --- /dev/null +++ b/sys/glsink/gstglxwindow.c @@ -0,0 +1,239 @@ +/* gcc -ansi -pedantic on GNU/Linux causes warnings and errors + * unless this is defined: + * warning: #warning "Files using this header must be compiled with _SVID_SOURCE or _XOPEN_SOURCE" + */ +#ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE 1 +#endif + +#include <X11/Xlib.h> +#include <GL/glx.h> +#include <GL/gl.h> +#include <GL/glu.h> +#include "gstglsink.h" +#include <string.h> /* strncmp */ + +/* attributes for a single buffered visual in RGBA format with at least + * 4 bits per color and a 16 bit depth buffer */ +static int attrListSgl[] = +{ + GLX_RGBA, GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 16, + None +}; + +/* attributes for a double buffered visual in RGBA format with at least + * 4 bits per color and a 16 bit depth buffer */ +static int attrListDbl[] = + { + GLX_RGBA, GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 16, + None + }; + + +GLfloat LightAmbient[] = { 0.1, 0.1, 0.1, 1.0 }; /* reddish ambient light */ +GLfloat LightDiffuse[] = { 0.6, 0.6, 0.6, 1.0 }; /* bluish diffuse light. */ +GLfloat LightPosition[] = { 1.5, 1.5, 1.5, 0.0 }; /* position */ + + +static void +gst_glxwindow_free (GstImageInfo *info) +{ + GstGLImageInfo *window = (GstGLImageInfo *) info; + + g_signal_handler_disconnect (window->sink, window->handler_id); + + if (window->ctx) + { + if (!glXMakeCurrent(window->dpy, None, NULL)) + { + printf("Could not release drawing context.\n"); + } + glXDestroyContext(window->dpy, window->ctx); + window->ctx = NULL; + } +#if 0 + /* switch back to original desktop resolution if we were in fs */ + if (GLWin.fs) + { + XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode); + XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); + } +#endif + XCloseDisplay (window->dpy); + g_free (window); +} + +static void +gst_glxwindow_callback(GObject *object, GParamSpec *pspec, GstGLImageInfo *data) +{ + XWindowAttributes attr; + XGetWindowAttributes(data->dpy, data->win, &attr); + + if (strncmp (pspec->name, "width", 5) == 0 || strncmp (pspec->name, "height", 6) == 0) + { + gint w = 0; + gint h = 0; + g_object_get (object, "width", &w, NULL); + g_object_get (object, "height", &h, NULL); + if (w != attr.width || h != attr.height) + { + attr.width = w; + attr.height = h; + XResizeWindow (data->dpy, data->win, attr.width, attr.height); + XMapRaised (data->dpy, data->win); + + // resize OpenGL + g_warning("resizing in OpenGL"); + glViewport(0, 0, (GLint) w, (GLint) h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + GLfloat aspect = (GLfloat) h / (GLfloat) w; + glFrustum(-1.0, 1.0, -aspect, aspect, 5.0, 500.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, -3.0, -50.0); + } + } + if (attr.width != data->width || attr.height != data->height) + { + data->width = attr.width; + data->height = attr.height; + } + +} + +void +gst_glxwindow_new (GstElement *sink) +{ + XGCValues values; + GstGLImageInfo *new; + int glxMajorVersion, glxMinorVersion; + XSetWindowAttributes attrib; + XVisualInfo *vi; + Atom wmDelete; + Window winDummy; + unsigned int borderDummy; + Colormap cmap; + char* title = "GLSink (experimental)"; + + new = g_new0 (GstGLImageInfo, 1); + + if (sink == NULL) + { + sink = gst_element_factory_make ("glsink", "glsink"); + g_assert (sink != NULL); + } + + /* fill in the ImageInfo */ + new->info.id = GST_MAKE_FOURCC ('X', 'l', 'i', 'b'); + new->info.free_info = gst_glxwindow_free; + + new->dpy = XOpenDisplay (NULL); + if (!new->dpy) { + g_warning ("open display failed!\n"); + g_free (new); + return; + } + new->screen = DefaultScreen(new->dpy); + /* get an appropriate visual */ + vi = glXChooseVisual(new->dpy, new->screen, attrListDbl); + if (vi == NULL) + { + vi = glXChooseVisual(new->dpy, new->screen, attrListSgl); + g_warning("Only Singlebuffered Visual!\n"); + } + else + { + g_warning("Got Doublebuffered Visual!\n"); + } + glXQueryVersion(new->dpy, &glxMajorVersion, &glxMinorVersion); + g_warning("glX-Version %d.%d\n", glxMajorVersion, glxMinorVersion); + + /* create a GLX context */ + new->ctx = glXCreateContext(new->dpy, vi, 0, GL_TRUE); + /* create a color map */ + cmap = XCreateColormap(new->dpy, RootWindow(new->dpy, vi->screen), + vi->visual, AllocNone); + new->attr.colormap = cmap; + new->attr.border_pixel = 0; + + /* set sizes */ + new->x = 0; + new->y = 0; + new->width = 10; + new->height = 10; + + new->rotX = 0; + new->rotY = 0; + new->zoom = 2; + + { + /* create a window in window mode*/ + new->attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | + StructureNotifyMask; + new->win = XCreateWindow(new->dpy, RootWindow(new->dpy, vi->screen), + new->x, new->y, new->width, new->height, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask, &new->attr); + if (!new->win) + { + g_warning ("create window failed\n"); + g_free (new); + return; + } + /* only set window title and handle wm_delete_events if in windowed mode */ + wmDelete = XInternAtom(new->dpy, "WM_DELETE_WINDOW", True); + XSetWMProtocols(new->dpy, new->win, &wmDelete, 1); + XSetStandardProperties(new->dpy, new->win, title, + title, None, NULL, 0, NULL); + XMapRaised(new->dpy, new->win); + } + /* connect the glx-context to the window */ + glXMakeCurrent(new->dpy, new->win, new->ctx); + XGetGeometry(new->dpy, new->win, &winDummy, &new->x, &new->y, + &new->width, &new->height, &borderDummy, &new->depth); + printf("Depth %d\n", new->depth); + if (glXIsDirect(new->dpy, new->ctx)) + g_warning("Congrats, you have Direct Rendering!\n"); + else + g_warning("Sorry, no Direct Rendering possible!\n"); + + g_warning("Initializing OpenGL parameters"); + /* initialize OpenGL drawing */ + glEnable(GL_DEPTH_TEST); + //glShadeModel(GL_SMOOTH); + + glEnable(GL_TEXTURE_2D); + glDisable(GL_CULL_FACE); + glClearDepth(1.0f); + glClearColor(0, 0, 0, 0); + + glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient); /* add lighting. (ambient) */ + glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse); /* add lighting. (diffuse). */ + glLightfv(GL_LIGHT0, GL_POSITION,LightPosition); /* set light position. */ + + //glEnable(GL_LIGHT0); // Quick And Dirty Lighting (Assumes Light0 Is Set Up) + //glEnable(GL_LIGHTING); // Enable Lighting + glDisable(GL_COLOR_MATERIAL); // Enable Material Coloring + glEnable(GL_AUTO_NORMAL); // let OpenGL generate the Normals + + glDisable(GL_BLEND); + + glPolygonMode(GL_FRONT, GL_FILL); + glPolygonMode(GL_BACK, GL_FILL); + + XSelectInput (new->dpy, new->win, ExposureMask | StructureNotifyMask); + + g_object_set (sink, "hook", new, NULL); + new->sink = sink; + new->handler_id = g_signal_connect (sink, "notify", G_CALLBACK (gst_glxwindow_callback), new); +} + |