Table of
contents

8.1.2010The year I started blogging (blogware)
9.1.2010Linux initramfs with iSCSI and bonding support for PXE booting
9.1.2010Using manually tweaked PTX assembly in your CUDA 2 program
9.1.2010OpenCL autoconf m4 macro
9.1.2010Mandelbrot with MPI
10.1.2010Using dynamic libraries for modular client threads
11.1.2010Creating an OpenGL 3 context with GLX
11.1.2010Creating a double buffered X window with the DBE X extension
12.1.2010A simple random file read benchmark
14.12.2011Change local passwords via RoundCube safer
5.1.2012Multi-GPU CUDA stress test
6.1.2012CUDA (Driver API) + nvcc autoconf macro
29.5.2012CUDA (or OpenGL) video capture in Linux
31.7.2012GPGPU abstraction framework (CUDA/OpenCL + OpenGL)
7.8.2012OpenGL (4.3) compute shader example
10.12.2012GPGPU face-off: K20 vs 7970 vs GTX680 vs M2050 vs GTX580
4.8.2013DAViCal with Windows Phone 8 GDR2
5.5.2015Sample pattern generator



11.1.2010

Creating a double buffered X window with the DBE X extension

// Include libX11 and libXext during linking

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xdbe.h>

#include <cstdio>

Display *d_dpy;
Window d_win;
Visual *d_vis = NULL;
XdbeBackBuffer d_backBuf;
GC d_gc;
int d_drawColor;
int d_clearColor;

int width = 800;
int height = 600;


/*
 * Create the context like this:
 */
const char *display = ":0"; // Use NULL for default (environment variable)
if (!(d_dpy = XOpenDisplay(display))) {
    fprintf(stderr, "Couldn't open X11 display\n");
    return 100;
}

// Xdbe extension for double buffering
int major, minor;
if (XdbeQueryExtension(d_dpy, &major, &minor)) {
    printf("Xdbe (%d.%d) supported, using double buffering\n", major, minor);
    int numScreens = 1;
    Drawable screens[] = { DefaultRootWindow(d_dpy) };
    XdbeScreenVisualInfo *info = XdbeGetVisualInfo(d_dpy, screens, &numScreens);
    if (!info || numScreens < 1 || info->count < 1) {
        fprintf(stderr, "No visuals support Xdbe\n");
        return 110;
    }

    // Choosing the first one, seems that they have all perflevel of 0,
    // and the depth varies.
    XVisualInfo xvisinfo_templ;
    xvisinfo_templ.visualid = info->visinfo[0].visual; // We know there's at least one
    // As far as I know, screens are densely packed, so we can assume that if at least 1 exists, it's screen 0.
    xvisinfo_templ.screen = 0;
    xvisinfo_templ.depth = info->visinfo[0].depth;

    int matches;
    XVisualInfo *xvisinfo_match =
        XGetVisualInfo(d_dpy, VisualIDMask|VisualScreenMask|VisualDepthMask, &xvisinfo_templ, &matches);

    if (!xvisinfo_match || matches < 1) {
        fprintf(stderr, "Couldn't match a Visual with double buffering\n");
        return 111;
    }

    /*
    printf("%d supported visuals\n", info->count);
    for (int i = 0; i < info->count; ++i) {
        printf("visual %d/%d: id %d, depth %d, perf %d\n",
                i, info->count,
                info->visinfo[i].visual,
                info->visinfo[i].depth,
                info->visinfo[i].perflevel);
    }
    printf("We got xvisinfo: id: %d, screen %d, depth %d\n",
            xvisinfo_match->visualid, xvisinfo_match->screen, xvisinfo_match->depth);
    */

    // We can use Visual from the match
    d_vis = xvisinfo_match->visual;
} else {
    fprintf(stderr, "No Xdbe support\n");
    return 101;
}

d_drawColor = BlackPixel(d_dpy, DefaultScreen(d_dpy));
d_clearColor = WhitePixel(d_dpy, DefaultScreen(d_dpy));

// The actual window, front buffer, using Xdbe enabled Visual (d_vis)
unsigned long xAttrMask = CWBackPixel;
XSetWindowAttributes xAttr;
xAttr.background_pixel = d_clearColor;
d_win = XCreateWindow(d_dpy, DefaultRootWindow(d_dpy),
        0, 0, width, height, 0, CopyFromParent, CopyFromParent, d_vis,
        xAttrMask, &xAttr);
if (!d_win) {
    fprintf(stderr, "Failure in window creation?\n");
    return 101;
}

// Creating the back buffer, setting swap action hint to background (automatic clearing)
d_backBuf = XdbeAllocateBackBufferName(d_dpy, d_win, XdbeBackground);

XSelectInput(d_dpy, d_win, StructureNotifyMask);
XMapWindow(d_dpy, d_win);
d_gc = XCreateGC(d_dpy, d_backBuf, 0, NULL);
XSetForeground(d_dpy, d_gc, d_drawColor);

// Waiting for MapNotify to inform that the window is mapped onto the screen
for (XEvent e; e.type != MapNotify; XNextEvent(d_dpy, &e));

return 0;


/*
 *  And swap the buffers like this:
 */
XdbeSwapInfo swapInfo;
swapInfo.swap_window = d_win;
swapInfo.swap_action = XdbeBackground;

// XdbeSwapBuffers returns true on success, we return 0 on success.
if (!XdbeSwapBuffers(d_dpy, &swapInfo, 1))
   return 1;    

XFlush(d_dpy);

Comments

  8.8.2010

As it was friendly pointed out to me, an alternative (faster but less compatible) way to achieve double buffering is via the MIT-SHM extension.
- wili






Nick     E-mail   (optional)

Is this spam? (answer "no")