How to create a game loop with xlib
Asked Answered
I

2

5

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?

Igniter answered 20/9, 2015 at 14:11 Comment(0)
B
2

Communicating directly with Xlib is so early-90s (read: noone has done this, unless he's a framework designer, in the last 20 years!).

You're right, looping through pixels to update them on the screen is incredibly slow. That's why almost all modern GUI Frameworks use their own Xbuffers that they just draw on and instruct X to render.

As a comment on your approach: Game development on raw X doesn't make the least sense, as there are more protable, better performing, easier to use, small, well-tested libraries. Take SDL as an example.

Update March 2021: As Pablo Ariel pointed out below, it might be important by now to point out that investing time in learning X11 isn't the wises investment by now: X is going away; it took a few decades, but the largest Linux distros (after Debian 10 does that, Ubuntu 21.04 does too, and thus all derivates like Mint use Wayland by default; Fedora 34 does the same) are using Wayland by default; using X11 is still possible on these, but it's an extra step to use something old...

Note that this doesn't mean Wayland is what you should learn if you're trying to learn how to produce games. Or raw OpenGL. Or Vulkan. A graphics/game engine is your friend, because you a) don't want to deal with all the low-level stuff yourself of abstracting the subtle differences between different versions of the same thing, and b) you're not getting any faster than a well-written enginge, and the people writing game engines are going to be better than you at that. Concentrate on the relevant part, not on dealing with lowest-level libraries!

Bettiebettina answered 20/9, 2015 at 14:15 Comment(7)
Thanks for your response. I decided not to use libraries like OpenGL etc. because I want to learn a bit about the maths behind these libraries. What I mean is that I intend to program the rotation matrices, projections etc. by hand instead of just calling an OpenGL function. Do you mean that I should not do that for fps reasons, or is there a way to make this work without such libraries?Igniter
You can draw lines and color pixels on your screen with any proper GUI library; you don't have to do 3D graphics! (hint: if you set all z coordinates in a 3D object to a constant, you get a 2D object, right!?), and doing this in raw Xlib is totally over-complicating things; the loss in speed is just a small downside compared to that. What you're saying is "I didn't want to buy a car because I wanted to learn how cars are built, so I decided to build a car from scratch. For that, I'm not using modern tools, but only stones and dirt." You won't get far with that.Chime
@JeroenD: in modern OpenGL you have to program the rotation and projection matrices in shaders.Consignee
@MarcusMüller What doesn't make any sense is you telling people not to learn and spamming about some random framework nobody cares about.Octavus
@PabloAriel excuse me? I mention SDL in the last half-sentence. It's not really a high-level framework. And "nobody cares about": well, it's certainly not what big-name games use, but it's what people use when they learn how to produce media content and small 2D stuff on screen. And, game development really isn't done in X11 itself, because all that X11 could contribute would be a window; the rest of the game uses non-X11 methods (OpenGL, Vulkan, …) to draw things. I'm sure you've got a reason to attack me?Chime
Thanks, your last edit is good as it points to an alternative to X such as Wayland and without using some upper level framework which in general is not necessary (specially if one is going to use OGL or Vulkan). And yes I know big-name games I've worked in some of them but I can't say they're properly coded even if they somehow try to adhere to some rules. Currently I prefer to do everything in software and only require some window from the system to put the results on because nowadays CPUs are powerful enough and code is simpler without dealing with those apis.Octavus
That really wasn't my message.Chime
H
6

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

Hasty answered 20/9, 2015 at 17:55 Comment(0)
B
2

Communicating directly with Xlib is so early-90s (read: noone has done this, unless he's a framework designer, in the last 20 years!).

You're right, looping through pixels to update them on the screen is incredibly slow. That's why almost all modern GUI Frameworks use their own Xbuffers that they just draw on and instruct X to render.

As a comment on your approach: Game development on raw X doesn't make the least sense, as there are more protable, better performing, easier to use, small, well-tested libraries. Take SDL as an example.

Update March 2021: As Pablo Ariel pointed out below, it might be important by now to point out that investing time in learning X11 isn't the wises investment by now: X is going away; it took a few decades, but the largest Linux distros (after Debian 10 does that, Ubuntu 21.04 does too, and thus all derivates like Mint use Wayland by default; Fedora 34 does the same) are using Wayland by default; using X11 is still possible on these, but it's an extra step to use something old...

Note that this doesn't mean Wayland is what you should learn if you're trying to learn how to produce games. Or raw OpenGL. Or Vulkan. A graphics/game engine is your friend, because you a) don't want to deal with all the low-level stuff yourself of abstracting the subtle differences between different versions of the same thing, and b) you're not getting any faster than a well-written enginge, and the people writing game engines are going to be better than you at that. Concentrate on the relevant part, not on dealing with lowest-level libraries!

Bettiebettina answered 20/9, 2015 at 14:15 Comment(7)
Thanks for your response. I decided not to use libraries like OpenGL etc. because I want to learn a bit about the maths behind these libraries. What I mean is that I intend to program the rotation matrices, projections etc. by hand instead of just calling an OpenGL function. Do you mean that I should not do that for fps reasons, or is there a way to make this work without such libraries?Igniter
You can draw lines and color pixels on your screen with any proper GUI library; you don't have to do 3D graphics! (hint: if you set all z coordinates in a 3D object to a constant, you get a 2D object, right!?), and doing this in raw Xlib is totally over-complicating things; the loss in speed is just a small downside compared to that. What you're saying is "I didn't want to buy a car because I wanted to learn how cars are built, so I decided to build a car from scratch. For that, I'm not using modern tools, but only stones and dirt." You won't get far with that.Chime
@JeroenD: in modern OpenGL you have to program the rotation and projection matrices in shaders.Consignee
@MarcusMüller What doesn't make any sense is you telling people not to learn and spamming about some random framework nobody cares about.Octavus
@PabloAriel excuse me? I mention SDL in the last half-sentence. It's not really a high-level framework. And "nobody cares about": well, it's certainly not what big-name games use, but it's what people use when they learn how to produce media content and small 2D stuff on screen. And, game development really isn't done in X11 itself, because all that X11 could contribute would be a window; the rest of the game uses non-X11 methods (OpenGL, Vulkan, …) to draw things. I'm sure you've got a reason to attack me?Chime
Thanks, your last edit is good as it points to an alternative to X such as Wayland and without using some upper level framework which in general is not necessary (specially if one is going to use OGL or Vulkan). And yes I know big-name games I've worked in some of them but I can't say they're properly coded even if they somehow try to adhere to some rules. Currently I prefer to do everything in software and only require some window from the system to put the results on because nowadays CPUs are powerful enough and code is simpler without dealing with those apis.Octavus
That really wasn't my message.Chime

© 2022 - 2024 — McMap. All rights reserved.