GLXWorkstation.st
changeset 151 8123ec03c52f
parent 134 1a09a1d7d28d
child 157 891eff44c2e7
--- a/GLXWorkstation.st	Sun Jun 04 18:38:31 1995 +0200
+++ b/GLXWorkstation.st	Tue Jun 06 06:09:07 1995 +0200
@@ -21,7 +21,7 @@
 COPYRIGHT (c) 1993 by Claus Gittinger
 	      All Rights Reserved
 
-$Header: /cvs/stx/stx/libview/GLXWorkstation.st,v 1.20 1995-05-03 00:03:20 claus Exp $
+$Header: /cvs/stx/stx/libview/GLXWorkstation.st,v 1.21 1995-06-06 04:07:06 claus Exp $
 '!
 
 !GLXWorkstation class methodsFor:'documentation'!
@@ -42,7 +42,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libview/GLXWorkstation.st,v 1.20 1995-05-03 00:03:20 claus Exp $
+$Header: /cvs/stx/stx/libview/GLXWorkstation.st,v 1.21 1995-06-06 04:07:06 claus Exp $
 "
 !
 
@@ -140,12 +140,14 @@
     GLXrgbDoubleBuffer
 } GLXWindowType;
 
+/*
 extern Window GLXCreateWindow();
+*/
 
 #ifdef THISCONTEXT_IN_REGISTER
   extern OBJ __thisContext__;
-# define ENTERGLX	__thisContext__ = __thisContext
-# define LEAVEGLX	__thisContext__ = 0;
+# define ENTERGLX       __thisContext__ = __thisContext
+# define LEAVEGLX       __thisContext__ = 0;
 #else
 # define ENTERGLX    /* nothing */
 # define LEAVEGLX     /* nothing */
@@ -293,6 +295,295 @@
 !GLXWorkstation primitiveFunctions!
 
 %{
+
+/* 
+ * begin moved from GLXsupport.c
+ */
+
+/*
+ * GLXsupport.c:
+ *
+ *   This file provides a helper function "GLXCreateWindow", which does
+ * all the necessary magic to create an X window suitable for GL drawing 
+ * to take place within.   see the definition of GLXCreateWindow for a 
+ * description of how to call it.
+ *
+ * claus: I really had no time to look into all this,
+ * this file has been just copied from a 4Dgifts demo ..
+ * (will need more than a day to show more ...)
+ */
+#if defined(GLX) || defined(VGL)
+
+#include        <X11/Xlib.h>
+#include        <X11/Xutil.h>
+#ifndef VGL
+# include        <gl/glws.h>  
+#endif
+#include        <signal.h>
+#include        <setjmp.h>
+#include        "stcIntern.h"
+
+/*
+ * glxhelper.h:
+ *
+ *   List of drawing modes supported by GLXCreateWindow (in glxhelper.c).
+ * More than this are possible with mixed model, but this is just an 
+ * example.  You can either expand this list (and the corresponding code in 
+ * GLXCreateWindow) or call the mixed model calls yourself, using 
+ * GLXCreateWindow as an example.
+ */
+
+static char *typeToName[] = {
+    "color index single buffer",
+    "color index double buffer",
+    "rgb single buffer",
+    "rgb double buffer",
+};
+
+#ifndef VGL
+/*
+ * Dorky little helper function used to build up a GLXconfig array.
+ */
+
+static void set_entry (GLXconfig* ptr, int b, int m, int a)
+{
+    ptr->buffer = b;
+    ptr->mode = m;
+    ptr->arg = a;
+}
+#endif /* VGL */
+
+static JMP_BUF errorReturn;
+
+static void
+glAbort() {
+    longjmp(errorReturn, 1);
+}
+
+/*
+ * GLXCreateWindow(dpy, parent, x, y, w, h, boderWidth, type)
+ *
+ * Return value is the X window id of the newly created window.
+ *
+ * Arguments are:
+ *      dpy             The X "Display*" returned by XOpenDisplay
+ *      parent          The parent of the newly created window,
+ *                      a typical value for this is
+ *                      RootWindow(dpy, DefaultScreen(dpy))
+ *      x,y             The location of the window to be created,
+ *                      y coordinate is measured from the top down.
+ *      w,h             size of the new window
+ *      borderWidth     the X border size for this window, should probably
+ *                      be zero.
+ *      type            the GLXWindowType (see glxhelper.h) desribing the
+ *                      typer of GL drawing to be done in this window
+ */
+static Window 
+GLXCreateWindow(dpy, parent, x, y, w, h, borderWidth, type)
+    Display* dpy;
+    Window parent;
+    GLXWindowType type;
+{
+#ifdef VGL
+    Visual visual;
+#else
+    GLXconfig params[50];
+    GLXconfig* next;
+    GLXconfig* retconfig;
+    Colormap cmap = DefaultColormap(dpy, DefaultScreen(dpy));
+    XVisualInfo *vis;
+#endif
+    XVisualInfo template;
+    XColor white;
+    XSetWindowAttributes cwa;
+    XWindowAttributes   pwa;
+    int scr, i, nret;
+    Window win;
+    extern __XErrorHandler__();
+#ifdef IRIX5
+    SIG_PF oldSig;
+#else
+    void *oldSig;
+#endif
+
+    if (setjmp(errorReturn)) {
+	printf("hard error in GL - return\n");
+	signal(SIGSEGV, oldSig);
+	return 0;
+    }
+    __CONT__
+
+#ifdef VGL
+    /*
+     * I know what VGL supports; its somewhat unclean to hard code it here
+     */
+    switch (type) {
+      case GLXcolorIndexSingleBuffer:
+      case GLXcolorIndexDoubleBuffer:
+	break;
+
+      case GLXrgbSingleBuffer:
+      case GLXrgbDoubleBuffer:
+	printf("Sorry, VGL can't support %s type of windows\n", typeToName[type]);
+	return 0;
+    }
+
+    scr = DefaultScreen(dpy);
+    visual.visualid = CopyFromParent;
+    cwa.border_pixel = 0;  /* Even if we don't use it, it must be something */
+    if (w <= 0) {
+	printf("VGL: bad width: %d\n", w);
+	w = 1;
+    }
+    if (h <= 0) {
+	printf("VGL: bad height: %d\n", h);
+	h = 1;
+    }
+    win = XCreateWindow(dpy, parent, x, y, w, h,
+			     borderWidth, DisplayPlanes(dpy, scr), 
+			     InputOutput, &visual,
+			     CWBorderPixel, &cwa);
+
+    /*
+     * on iris, seg-violations occur in te GL, if too many
+     * views are created ... just to make certain, we catch those
+     * in GL too.
+     */
+    oldSig = signal(SIGSEGV, glAbort);
+    i = GLXlink(dpy, win);
+    signal(SIGSEGV, oldSig);
+
+    if (i < 0) {
+	printf("GLXlink returned %d\n", i);
+	return 0;
+    }
+#else /* not VGL */
+    /*
+     * This builds an array in "params" that describes for GLXgetconfig(3G)
+     * the type of GL drawing that will be done.
+     */
+    next = params;
+    switch (type) {
+      case GLXcolorIndexSingleBuffer:
+	set_entry(next++, GLX_NORMAL, GLX_RGB, FALSE);
+	set_entry(next++, GLX_NORMAL, GLX_DOUBLE, FALSE);
+	break;
+      case GLXcolorIndexDoubleBuffer:
+	set_entry(next++, GLX_NORMAL, GLX_RGB, FALSE);
+	set_entry(next++, GLX_NORMAL, GLX_DOUBLE, TRUE);
+	break;
+      case GLXrgbSingleBuffer:
+	set_entry(next++, GLX_NORMAL, GLX_RGB, TRUE);
+	set_entry(next++, GLX_NORMAL, GLX_DOUBLE, FALSE);
+	break;
+      case GLXrgbDoubleBuffer:
+	set_entry(next++, GLX_NORMAL, GLX_RGB, TRUE);
+	set_entry(next++, GLX_NORMAL, GLX_DOUBLE, TRUE);
+	break;
+    }
+    set_entry(next, 0, 0, 0); /* The input to GLXgetconfig is null terminated */
+
+    /*
+     * Get configuration data for a window based on above parameters
+     * First we have to find out which screen the parent window is on,
+     * then we can call GXLgetconfig()
+     */
+    XGetWindowAttributes(dpy, parent, &pwa);
+    retconfig = GLXgetconfig(dpy, XScreenNumberOfScreen(pwa.screen), params);
+    if (retconfig == 0) {
+	printf("Sorry, can't support %s type of windows\n", typeToName[type]);
+	return 0;
+    }
+
+    /*
+     * Scan through config info, pulling info needed to create a window
+     * that supports the rendering mode.
+     */
+    for (next = retconfig; next->buffer; next++) {
+	unsigned long buffer = next->buffer;
+	unsigned long mode = next->mode;
+	unsigned long value = next->arg;
+	switch (mode) {
+	  case GLX_COLORMAP:
+	    if (buffer == GLX_NORMAL) {
+		cmap = value;
+	    }
+	    break;
+	  case GLX_VISUAL:
+	    if (buffer == GLX_NORMAL) {
+		template.visualid = value;
+		template.screen = DefaultScreen(dpy);
+		vis = XGetVisualInfo(dpy, VisualScreenMask|VisualIDMask,
+					  &template, &nret);
+	    }
+	    break;
+	}
+    }
+
+    /*
+     * Create the window
+     */
+    cwa.colormap = cmap;
+    cwa.border_pixel = 0;  /* Even if we don't use it, it must be something */
+    win = XCreateWindow(dpy, parent, x, y, w, h,
+			     borderWidth, vis->depth, InputOutput, vis->visual,
+			     CWColormap|CWBorderPixel, &cwa);
+
+    /*
+     * Rescan configuration info and find window slot that getconfig
+     * provided.  Fill it in with the window we just created.
+     */
+    for (next = retconfig; next->buffer; next++) {
+	if ((next->buffer == GLX_NORMAL) && (next->mode == GLX_WINDOW)) {
+	    next->arg = win;
+	    break;
+	}
+    }
+
+    /*
+     * Now "retconfig" contains all the information the GL needs to
+     * configure the window and its own internal state.
+     */
+    /*
+     * on iris, seg-violations occur in te GL, if too many
+     * views are created ...
+     */
+    oldSig = signal(SIGSEGV, glAbort);
+    i = GLXlink(dpy, retconfig);
+    signal(SIGSEGV, oldSig);
+
+    if (i < 0) {
+	printf("GLXlink returned %d\n", i);
+	return 0;
+    }
+
+    /*
+     * The GL sets its own X error handlers, which exits - this is not what we want
+     */
+    XSetErrorHandler(__XErrorHandler__);
+#endif
+    return win;
+}
+
+static
+GLXUnlinkWindow(dpy, win)
+    Display* dpy;
+    Window win;
+{
+    /*
+     * only needed for VGL - GLX does it automatically
+     */
+#ifdef VGL
+    GLXunlink(dpy, win);
+#endif
+}
+
+#endif /* GLX or VGL */
+
+/* 
+ * end moved from GLXsupport.c
+ */
+
 /*
  * helper for rotation - call rot()
  */