4

This simple SDL2 program opens an empty window on my system (ie. it renders nothing) unless I uncomment the SDL_Delay line.

#include <SDL.h>

int main(int argc, char** argv) {

    constexpr unsigned width = 256, height = 256;

    if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
        return 1;
    }

    SDL_Window* window = SDL_CreateWindow("Test",
                                          SDL_WINDOWPOS_UNDEFINED,
                                          SDL_WINDOWPOS_UNDEFINED,
                                          width, height,
                                          0);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);

    SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
    SDL_RenderClear(renderer);
    // SDL_Delay(20);
    SDL_RenderPresent(renderer);

    bool quit{};
    SDL_Event event;
    while (!quit) {
        SDL_WaitEvent(&event);

        switch (event.type) {
        case SDL_QUIT:
            quit = true;
            break;
        }
    }

    SDL_Quit();

    return 0;
}

The delay has to be about 10-20ms or nothing shows up, but it's not consistent - if it's set to 10ms, it works about half of the time.

After reading this answer I added the event loop, but I get the same behavior without it. Users on #sdl on IRC have gotten the expected blue screen from the same code.

Any idea what's going on here/what I've done wrong?

Community
  • 1
  • 1
scry
  • 1,237
  • 12
  • 29
  • 1
    Try putting the clear and present calls in the loop to see if it reproduces the problem. – Lasoloz Mar 14 '16 at 05:27
  • 2
    Cannot reproduce (on linux) but wouldn't be surprised by that behaviour. Pump events after window creation, then pump again after render present. – keltar Mar 14 '16 at 13:10
  • 1
    Played around with pumping events. A call after render present has no effect, but a call before render clear works. Or, an additional call to SetRenderDrawColor before clear makes it work - maybe that includes a call to pump events. The critical thing seems to be calling it _before_ RenderClear. – scry Mar 14 '16 at 21:07
  • Unfortunately, it's still not consistent. It worked the first few times, but now I mostly get a blank window (pumping before clear and after RenderPresent) – scry Mar 14 '16 at 21:16
  • 1
    What OS? Is window manager compositing enabled? What SDL rendering backend used (https://wiki.libsdl.org/SDL_GetRendererInfo)? Is it the same with `SDL_RENDERER_PRESENTVSYNC`? Do you have the same results with software rendering backend? Never done SDL drawing without main loop, but it is likely you have to redraw each time `SDL_WINDOWEVENT_EXPOSED` event occurs. – keltar Mar 15 '16 at 04:09
  • I'm on Arch linux with no compositing. Renderer is Opengl but I get the same result with software rendering. However, `SDL_RENDERER_PRESENTVSYNC` seems to fix it. I'm not entirely sure what `SDL_WINDOWEVENT_EXPOSED` means though - is that sent when the window is focused or whenever it updates? can't seem to find it documented – scry Mar 15 '16 at 05:07
  • It should be fired when part of window become visible after being shadowed by other window or display borders. Basically when some pixels of your window became visible again and have to be redrawn. – keltar Mar 15 '16 at 12:03

1 Answers1

1

You should call SDL_PollEvent() to avoid blocking the drawing thread.

Try the following:

while (!quit) {
    SDL_Delay(1000/25);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);
    if(!SDL_PollEvent(&event)) continue;

    switch (event.type) {
    case SDL_QUIT:
        quit = true;
        break;
    }
}

Alternatively, for a complete example with keyboard and gamepad polling, compile and run the GPL game Rock Dodger SDL2 Compact Edition, then look at its source code (which is only a single small file).

Stevoisiak
  • 23,794
  • 27
  • 122
  • 225
Joseph Paul
  • 346
  • 1
  • 7