csdlsdl-2

SDL_CreateRenderer freezes/hangs


I used GDB and found out that SDL_Init and SDL_CreateWindow works, but when the code comes to SDL_CreateRenderer it calls it and hangs, it never returns and GDB just waits. Also, the CPU usage for the program goes from standard 0.something to 4% (I can hear the CPU fan speeding up so it could be something like an infinite loop?) and when I type "exit" it tries to exit (through exit(0);) but to no avail. (I have another thread that takes std input and processes it.)

The SDL initialization part looks as follows:

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480

if (SDL_Init(SDL_INIT_VIDEO) != 0) {
    printf("Could not initiate the window for VGA module! SDL Error: %s\n", SDL_GetError());
    return;
}

window = SDL_CreateWindow("PT16B00 CPU - Emulator - VGA Module",
            SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
            SCREEN_WIDTH, SCREEN_HEIGHT, 0);
if (window == NULL) {
    printf("VGA module: Window could not be created! SDL Error: %s\n", SDL_GetError());
    return;
}

renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer == NULL) {
    printf("VGA module: Renderer could not be created! SDL Error: %s\n", SDL_GetError());
    return;
}

screen_texture = SDL_CreateTexture(renderer,
        SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING,
        SCREEN_WIDTH, SCREEN_HEIGHT);
if (screen_texture == NULL) {
    printf("VGA module: Texture could not be created! SDL Error: %s\n", SDL_GetError());
    return;
}

I also tried using

renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

and

renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);

but none worked.

I have the event polling loop; the SDL_GetNumRendererDrivers() returns 3; SDL_CreateWindow() opens a window and SDL_CreateRenderer() closes it before entering the "infinite loop" (if that's the case).

I've found out that the following line in some unrelated code makes SDL_CreateRenderer() freeze.

return (uint16_t) ( ((uint16_t)(dev_name[0]) << 8) + (uint16_t)(dev_name[0+1]) );

0 in above code is placeholder for the actual variable, but it still produces the issue. dev_name is declared as:

const unsigned char dev_name[] = "FB_OUT_DEV";

Also, just returning

return (uint16_t)(dev_name[0]);

or

return 70;

still breaks the SDL_CreateRenderer(). (70 for ASCII 'F')

Compiler produces no errors/warnings even with -Wall flag... With that line removed (or with return 0; the SDL_CreateRenderer() works).

How can a non-related function make library function not work? The function with this return statement is not called either before nor after SDL_CreateRenderer(). It would be called only when the state machine of the main code comes to instruction to call it (which can actually never happen...).

That function is also not empty, there are other return statements and they make no problem, only this one.

I can not provide the minimal reproducible example, as I myself have no idea how to reproduce this from scratch. The minimal SDL example, which uses the same code as what I use in this project, (even when I use two threads) works perfectly.


Solution

  • I found the issue! It was this function I added:

    uint16_t read(uint32_t address) {
        // return the length of the device name/id
        if (address == vga_module->address) {
            return sizeof(dev_name)-1;
        }
        // return the device name/id
        if (address < vga_module->address + sizeof(dev_name)) {
            uint8_t index = (address - vga_module->address - 1) * 2;
            return ((uint16_t)(dev_name[index]) << 8) + (uint16_t)(dev_name[index+1]);
        }
    
        // return the mode of the VGA device
        if (address < vga_module->address + sizeof(dev_name) + 1) {
            return mode;
        }
        // return the FB address
        if (address < vga_module->address + sizeof(dev_name) + 1 + 2) {
            if (!(address - vga_module->address - sizeof(dev_name) - 1)) {
                return fb_address & 0xFFFF;
            }
            return fb_address & 0xFFFF0000;
        }
    
        return 0;
    }
    

    The only way to make SDL_CreateRenderer() not freeze, was by changing the line

    return ((uint16_t)(dev_name[index]) << 8) + (uint16_t)(dev_name[index+1]);
    

    to return 0; OR by changing the name of the function to vga_read.

    My guess is, that the CreateRenderer function uses some read() method, which I accidentally override/made naming collision.

    Take care how you name your variables and functions! :D