]> git.cworth.org Git - apitrace/blobdiff - glws_glx.cpp
Use double buffer visuals by default.
[apitrace] / glws_glx.cpp
index 7d286a526f8cb7dd96625c9319fbded9e0b07391..30de2f45b8ba8fa0b1b3cbdcd009346a85504c4b 100644 (file)
  *
  **************************************************************************/
 
+#include <stdlib.h>
+#include <iostream>
+
 #include "glimports.hpp"
 #include "glws.hpp"
 
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
 
 namespace glws {
 
 
+static Display *display = NULL;
+static int screen = 0;
+
+
 class GlxVisual : public Visual
 {
 public:
@@ -45,26 +55,131 @@ public:
 };
 
 
+static void describeEvent(const XEvent &event) {
+    if (0) {
+        switch (event.type) {
+        case ConfigureNotify:
+            std::cerr << "ConfigureNotify";
+            break;
+        case Expose:
+            std::cerr << "Expose";
+            break;
+        case KeyPress:
+            std::cerr << "KeyPress";
+            break;
+        case MapNotify:
+            std::cerr << "MapNotify";
+            break;
+        case ReparentNotify:
+            std::cerr << "ReparentNotify";
+            break;
+        default:
+            std::cerr << "Event " << event.type;
+        }
+        std::cerr << " " << event.xany.window << "\n";
+    }
+}
+
+static void waitForEvent(Window window, int type) {
+    XFlush(display);
+    XEvent event;
+    do {
+        XNextEvent(display, &event);
+        describeEvent(event);
+    } while (event.type != type ||
+             event.xany.window != window);
+}
+
+
 class GlxDrawable : public Drawable
 {
 public:
-    Display *display;
     Window window;
 
-    GlxDrawable(const Visual *vis, Display *dpy, Window win) :
-        Drawable(vis),
-        display(dpy), 
-        window(win)
-    {}
+    GlxDrawable(const Visual *vis, int w, int h) :
+        Drawable(vis, w, h)
+    {
+        XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
+
+        Window root = RootWindow(display, screen);
+
+        /* window attributes */
+        XSetWindowAttributes attr;
+        attr.background_pixel = 0;
+        attr.border_pixel = 0;
+        attr.colormap = XCreateColormap(display, root, visinfo->visual, AllocNone);
+        attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+
+        unsigned long mask;
+        mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+        int x = 0, y = 0;
+
+        window = XCreateWindow(
+            display, root,
+            x, y, width, height,
+            0,
+            visinfo->depth,
+            InputOutput,
+            visinfo->visual,
+            mask,
+            &attr);
+
+        XSizeHints sizehints;
+        sizehints.x = x;
+        sizehints.y = y;
+        sizehints.width  = width;
+        sizehints.height = height;
+        sizehints.flags = USSize | USPosition;
+        XSetNormalHints(display, window, &sizehints);
+
+        const char *name = "glretrace";
+        XSetStandardProperties(
+            display, window, name, name,
+            None, (char **)NULL, 0, &sizehints);
+
+        glXWaitX();
+    }
 
     ~GlxDrawable() {
         XDestroyWindow(display, window);
     }
-    
+
     void
-    resize(unsigned w, unsigned h) {
+    resize(int w, int h) {
+        glXWaitGL();
+
+        // We need to ensure that pending events are processed here, and XSync
+        // with discard = True guarantees that, but it appears the limited
+        // event processing we do so far is sufficient
+        //XSync(display, True);
+
         Drawable::resize(w, h);
+
         XResizeWindow(display, window, w, h);
+
+        // Tell the window manager to respect the requested size
+        XSizeHints *size_hints;
+        size_hints = XAllocSizeHints();
+        size_hints->max_width  = size_hints->min_width  = w;
+        size_hints->max_height = size_hints->min_height = h;
+        size_hints->flags = PMinSize | PMaxSize;
+        XSetWMNormalHints(display, window, size_hints);
+        XFree(size_hints);
+
+        waitForEvent(window, ConfigureNotify);
+
+        glXWaitX();
+    }
+
+    void show(void) {
+        if (!visible) {
+            XMapWindow(display, window);
+
+            waitForEvent(window, Expose);
+
+            Drawable::show();
+        }
     }
 
     void swapBuffers(void) {
@@ -76,12 +191,10 @@ public:
 class GlxContext : public Context
 {
 public:
-    Display *display;
     GLXContext context;
-    
-    GlxContext(const Visual *vis, Display *dpy, GLXContext ctx) :
+
+    GlxContext(const Visual *vis, GLXContext ctx) :
         Context(vis),
-        display(dpy), 
         context(ctx)
     {}
 
@@ -93,14 +206,16 @@ public:
 
 class GlxWindowSystem : public WindowSystem
 {
-private:
-    Display *display;
-    int screen;
-
 public:
     GlxWindowSystem() {
-        display = XOpenDisplay(NULL);
-        screen = DefaultScreen(display);
+        if (!display) {
+            display = XOpenDisplay(NULL);
+            if (!display) {
+                std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n";
+                exit(1);
+            }
+            screen = DefaultScreen(display);
+        }
     }
 
     ~GlxWindowSystem() {
@@ -114,6 +229,7 @@ public:
             GLX_RED_SIZE, 1,
             GLX_GREEN_SIZE, 1,
             GLX_BLUE_SIZE, 1,
+            GLX_ALPHA_SIZE, 1,
             GLX_DEPTH_SIZE, 1,
             GLX_STENCIL_SIZE, 1,
             None
@@ -124,6 +240,7 @@ public:
             GLX_RED_SIZE, 1,
             GLX_GREEN_SIZE, 1,
             GLX_BLUE_SIZE, 1,
+            GLX_ALPHA_SIZE, 1,
             GLX_DOUBLEBUFFER,
             GLX_DEPTH_SIZE, 1,
             GLX_STENCIL_SIZE, 1,
@@ -131,72 +248,39 @@ public:
         };
 
         XVisualInfo *visinfo;
-        
+
         visinfo = glXChooseVisual(display, screen, doubleBuffer ? double_attribs : single_attribs);
 
         return new GlxVisual(visinfo);
     }
-    
+
     Drawable *
-    createDrawable(const Visual *visual)
+    createDrawable(const Visual *visual, int width, int height)
     {
-        XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
-
-        Window root = RootWindow(display, screen);
-
-        /* window attributes */
-        XSetWindowAttributes attr;
-        attr.background_pixel = 0;
-        attr.border_pixel = 0;
-        attr.colormap = XCreateColormap(display, root, visinfo->visual, AllocNone);
-        attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
-        
-        unsigned long mask;
-        mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
-
-        int x = 0, y = 0, width = 256, height = 256;
-
-        Window window = XCreateWindow(
-            display, root, 
-            x, y, width, height,
-            0, 
-            visinfo->depth, 
-            InputOutput,
-            visinfo->visual, 
-            mask, 
-            &attr);
-
-        XSizeHints sizehints;
-        sizehints.x = x;
-        sizehints.y = y;
-        sizehints.width  = width;
-        sizehints.height = height;
-        sizehints.flags = USSize | USPosition;
-        XSetNormalHints(display, window, &sizehints);
-        
-        const char *name = "glretrace";
-        XSetStandardProperties(
-            display, window, name, name,
-            None, (char **)NULL, 0, &sizehints);
-
-        XMapWindow(display, window);
-        
-        return new GlxDrawable(visual, display, window);
+        return new GlxDrawable(visual, width, height);
     }
 
     Context *
-    createContext(const Visual *visual)
+    createContext(const Visual *visual, Context *shareContext)
     {
         XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
-        GLXContext context = glXCreateContext(display, visinfo, NULL, True);
-        return new GlxContext(visual, display, context);
+        GLXContext share_context = NULL;
+        GLXContext context;
+
+        if (shareContext) {
+            share_context = dynamic_cast<GlxContext*>(shareContext)->context;
+        }
+
+        context = glXCreateContext(display, visinfo,
+                                   share_context, True);
+        return new GlxContext(visual, context);
     }
 
     bool
     makeCurrent(Drawable *drawable, Context *context)
     {
         if (!drawable || !context) {
-            return glXMakeCurrent(display, NULL, NULL);
+            return glXMakeCurrent(display, None, NULL);
         } else {
             GlxDrawable *glxDrawable = dynamic_cast<GlxDrawable *>(drawable);
             GlxContext *glxContext = dynamic_cast<GlxContext *>(context);
@@ -207,10 +291,11 @@ public:
 
     bool
     processEvents(void) {
+        XFlush(display);
         while (XPending(display) > 0) {
             XEvent event;
             XNextEvent(display, &event);
-            // TODO
+            describeEvent(event);
         }
         return true;
     }