/* * glxf.c: subroutines to make it easier to use opengl and xforms together * This code is meant to be generic and should not have to be changed (much). * * Adapted from Andrew Willmott's glxforms.cc, * which is currently in /afs/cs/project/anim/ajw/public/glxforms.tar.gz * * Paul Heckbert 16 Oct 1995 */ #include #include #include "glxf.h" /* for paint program, we don't need a z-buffer, so we probably shouldn't be doing "GLX_DEPTH_SIZE, 12" below -ph 9/17/97 */ static int single_attrs[] = {GLX_RGBA, GLX_DEPTH_SIZE, 12, GLX_RED_SIZE, 8, None}; /* Attributes for a normal, 24-bit, z-buffered and double-buffered window */ static int double_attrs[] = {GLX_RGBA, GLX_DEPTH_SIZE, 12, GLX_DOUBLEBUFFER, None}; static int is_map_notify(Display *foo, XEvent *event, char *arg) { return event->type==MapNotify && event->xmap.window==(Window)arg; } void create_gl_subwindow(Glxf_pane *pane, Window parent, int x, int y, int width, int height, int double_buf) { /* Create a sub-window of the parent window, for Opengl use */ unsigned long winmask; XSetWindowAttributes winattr; XEvent event; Colormap colormap; Display *display; XVisualInfo *visinfo1, *visinfo2, *visinfo; display = XOpenDisplay(0); /* decide between a single-buffered or double-buffered "Visual" */ visinfo1 = glXChooseVisual(display, DefaultScreen(display), single_attrs); visinfo2 = glXChooseVisual(display, DefaultScreen(display), double_attrs); if (double_buf) { if (visinfo2) visinfo = visinfo2; else { fprintf(stderr, "Can't get double buffered window\n"); visinfo = visinfo1; } } else visinfo = visinfo1; if (!visinfo) { fprintf(stderr, "unable to open an X Window of the type requested -- asking for too many bits?\n"); exit(1); } if (visinfo->class==TrueColor || visinfo->class==DirectColor) { printf("glxf: creating colormap\n"); colormap = XCreateColormap(display, RootWindow(display, visinfo->screen), visinfo->visual, AllocNone); /* * note: if you try to create a window with a 24 bit visual when the * default visual is 8 bits (or more precisely, when the parent window * has a different visual or depth) and you don't explicitly set the * colormap and border, you will die with a BadMatch error. * You can thank the brain-damaged designers of X Windows for this. */ winattr.colormap = colormap; winattr.border_pixel = 0; winmask = CWBorderPixel | CWColormap | CWEventMask; } else { printf("glxf: not creating colormap\n"); /* when using Mesa's implementation of OpenGL, and requesting a * 24 bit visual but running on an 8 bit display, we don't want to * create an X colormap, since Mesa is doing that for us. */ winmask = CWEventMask; } winattr.event_mask = StructureNotifyMask; /* create the subwindow */ pane->display = display; pane->window = XCreateWindow(display, parent, /*origin*/ x, y, /*width,height*/ width, height, /*borderwidth*/ 0, /*depth*/ visinfo->depth, /*class*/ InputOutput, visinfo->visual, /*window attribute mask*/ winmask, &winattr); /* tell window manager to draw the window */ XMapWindow(display, pane->window); /* Wait for MapNotify event when the window is first drawn */ XIfEvent(display, &event, is_map_notify, (char *)pane->window); /* Create a graphics context if it hasn't been done before */ /* Bind the X window to an OpenGL context */ pane->context = glXCreateContext(display, visinfo, /*context share list*/ 0, /*direct rendering?*/ GL_TRUE); assert(pane->context); assert(glXMakeCurrent(display, pane->window, pane->context)); glMatrixMode(GL_MODELVIEW); glEnable(GL_DEPTH_TEST); /* turn on z-buffering */ pane->width = width; pane->height = height; } static int event_dispatch(XEvent *event, void *data) { /* call event handler for the pane in which the event occurred */ ((Glxf_pane *)data)->handle_event(event); return 1; } void glxf_bind_pane(Glxf_pane *pane, FL_OBJECT *object, int double_buf, void (*handle_event)(XEvent *event)) { const int inset = 4; pane->handle_event = handle_event; create_gl_subwindow(pane, FL_OBJECT_WID(object), object->x + inset, object->y + inset, object->w - 2 * inset, object->h - 2 * inset, double_buf); /* call pane->handle_event routine when window uncovered (Expose event) * mouse button pressed (ButtonPress), or key pressed (KeyPress) * or other things happen */ fl_add_event_callback(pane->window, /*event type (0 means all)*/ 0, event_dispatch, pane); fl_activate_event_callbacks(pane->window); }