Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a game loop with xlib

Tags:

c++

linux

x11

xlib

I am trying to create a game loop for an xlib window, but I cannot manage to paint the window correctly. Right now I am creating a window with XCreateSimpleWindow(...), and using a for loop to paint all pixels one at a time. (The color of these pixels is read from a large integer array, for now I've set all pixels to be blue.) The actual game loop right now is the following:

void loop() {
    while (true) {
        // Clear the window (the background color is set to white)
        XClearWindow(dsp, win);

        // Loop through all pixels of the 800*600 window
        for (int j = 0; j < 600; j++) {
            for (int i = 0; i < 800; i++) {
                // Read the color from the pixels array (always blue for now)
                long int color = pixels[i + 800*j];
                // Set the foreground color for drawing
                XSetForeground(dsp, gc, color);
                // Draw the pixel
                XDrawPoint(dsp, win, gc, i, j);
            }
        }

        // Flush the output buffer
        XFlush();
    }
}

The variables dsp, win, pixels, gc are defined globally.

Now when I compile and execute the binary file, the rows with low y coordinate are mostly blue, but the rows with high y coordinate are mostly white. In between it is easy to see how it simply takes too much time to draw all pixels at once. I expect that this effect is because the top rows (low y) are drawn first, which means a short delay between XClearWindow() and XDrawPoint() for those pixels. (I also tested the fps, it takes around 7 milliseconds to run the while(true) loop once.)

I did some research, and read about how double buffering might solve this issue. I did follow a guide on double buffering with xlib (Xdbe), but it does not seem to solve the issue. Is there a faster way of drawing with xlib than just looping through all pixels? Is double buffering not supposed to solve this, or am I implementing it incorrectly?

like image 695
JeroenD Avatar asked Sep 20 '15 14:09

JeroenD


1 Answers

The reason you are not seeing anything is because you are neglecting the X event loop. All you do is sending data to the X server, but there is no way for the X server to communicate back.

You must set up a loop where XEvents are read from the queue and dispatched c.q. processed. Something like:

XEvent event;
while (XPending (m_display))
{
  XNextEvent (m_display, &event);
  if (XFilterEvent (&event, None))
  {
    continue;
  }
  switch (event.type)
  {
     case KeyPress:
       ..
     case ButtonPress:
       ..
     case Expose:
       ..
     case MapNotify:
       ..
     // etc
  }
}

This can be combined with your endless loop, though.

But yes, painting pixel by pixel is extremely slow. I don't even want to calculate the protocol overhead... :P

like image 92
JvO Avatar answered Sep 21 '22 05:09

JvO