/* This stores the common OpenGL initialization stuff for all instances */ /* 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 #include #include #include #include "gstglsink.h" #include /* 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); } } 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); glShadeModel(GL_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); 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); }