3
\$\begingroup\$

I recently bought a R36S retro handheld linux based game console. The system runs ArkOS which is a Ubuntu based OS. On boot, the system launches the program EmulatorStation, but it is possible to exit this program, and then connect to the system through ssh and get a command prompt. Through apt, it is then possible to install a complete development environment running on the system.

I did so and compiled a simple hello-world SDL2 program, which should show a window with graphical output for five seconds and exit.

The problem is that nothing is displayed on the system, and there is no error.

I also double checked myself with the program 351Files which is provided in binary form on ArkOS. I verified that when I execute the system provided version from the command line, it displays its graphical interface. However, I also pulled the latest version by git, and compiled it myself on the system. And when running the version that I compiled, there is no graphical output, and no error.

Below is the hello-world program which I compiled:

#include <SDL2/SDL.h> #include <stdio.h> int main(int argc, char* argv[]) { // Initialize SDL if (SDL_Init(SDL_INIT_VIDEO) != 0) { printf("SDL_Init Error: %s\n", SDL_GetError()); return 1; } // Create a window SDL_Window *win = SDL_CreateWindow("Hello, SDL2!", 100, 100, 640, 480, SDL_WINDOW_SHOWN); if (win == NULL) { printf("SDL_CreateWindow Error: %s\n", SDL_GetError()); SDL_Quit(); return 1; } // Create a renderer SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (ren == NULL) { SDL_DestroyWindow(win); printf("SDL_CreateRenderer Error: %s\n", SDL_GetError()); SDL_Quit(); return 1; } // Set the draw color to blue SDL_SetRenderDrawColor(ren, 0, 0, 255, 255); // Clear the window SDL_RenderClear(ren); // Present the window SDL_RenderPresent(ren); // Wait for 5 seconds SDL_Delay(5000); // Clean up SDL_DestroyRenderer(ren); SDL_DestroyWindow(win); SDL_Quit(); return 0; } 

So my question is what am I missing to make the graphical output show up?

\$\endgroup\$
5
  • \$\begingroup\$ What exit code does your program return? Is your program definitely able to write to STDOUT? It could be a driver issue - maybe SDL thinks it is working fine (so there is no error) but outputting to video fails for some reason. You could also try using SDL in software-only rendering mode, or hardware-only rendering mode, to see if that makes any difference? \$\endgroup\$ Commented Aug 25, 2024 at 18:23
  • \$\begingroup\$ I added a printf("ok\n") right before exit(0) which it reaches and prints to stdout. I also tried the software rendering mode, but it made no difference. It's like it forgot to switch to the "graphics page". Whatever that means in modern hardware... \$\endgroup\$ Commented Aug 26, 2024 at 3:16
  • 1
    \$\begingroup\$ I compiled your code on macOS 10.15 and do not see any window either? I still use SDL 1 style code in my projects so I do not have a working example using the renderer methodology, but I will try and find an example later on today. \$\endgroup\$ Commented Aug 26, 2024 at 7:41
  • 1
    \$\begingroup\$ I just verified that it works and opens a window on X11 under Linux. (I'm getting paranoid 😅). I'm wondering though what exactly is the size supposed to be when working without a windowing system? Do I have to match the frame buffer size? Could that be the problem? \$\endgroup\$ Commented Aug 26, 2024 at 8:07
  • \$\begingroup\$ On my system, the problem is fixed by adding an event loop in the code. I will post my code in a new answer. \$\endgroup\$ Commented Aug 26, 2024 at 14:04

2 Answers 2

2
\$\begingroup\$

I got it working! The answer was a modification of @Noel Whitemore's loop and putting the SDL_RenderPresent() call inside the loop. The following code now works for drawing and animation.

#include <SDL2/SDL.h> #include <stdio.h> #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 int main(int argc, char* argv[]) { // Initialize SDL if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { printf("SDLInit Error: %s\n", SDL_GetError()); return 1; } // Create a window SDL_Window *win = SDL_CreateWindow("Hello, World!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_FOREIGN); if (win == NULL) { printf("SDL_CreateWindow Error: %s\n", SDL_GetError()); SDL_Quit(); return 1; } // Create a renderer //SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_SOFTWARE); // Setup t0 time using SDL Uint32 t0 = SDL_GetTicks(); if (ren == NULL) { SDL_DestroyWindow(win); printf("SDL_CreateRenderer Error: %s\n", SDL_GetError()); SDL_Quit(); return 1; } // Event loop SDL_bool quit = SDL_FALSE; SDL_Event e = { 0 }; while (!quit) { // Poll for events with timeout of 100ms e = SDL_Event { 0 }; SDL_WaitEventTimeout(&e, 10); switch (e.type) { case SDL_QUIT: quit = SDL_TRUE; break; default: break; } // Set draw the interface SDL_SetRenderDrawColor(ren, 0, 0, 255, 255); SDL_RenderClear(ren); int elapsed = SDL_GetTicks() - t0; if ((elapsed / 1000) % 2) SDL_SetRenderDrawColor(ren, 0x00, 0xFF, 0x00, 0xFF); // Green else SDL_SetRenderDrawColor(ren, 0xFF, 0x00, 0x00, 0xFF); // Red // Draw and animate SDL_Rect fillRect = { SCREEN_WIDTH / 4 + elapsed / 100, SCREEN_HEIGHT / 4, SCREEN_WIDTH/2, SCREEN_HEIGHT / 2 }; SDL_RenderFillRect(ren, &fillRect); SDL_RenderPresent(ren); // Exit after 5 seconds if (elapsed > 10000) break; } // Clean up SDL_DestroyRenderer(ren); SDL_DestroyWindow(win); SDL_Quit(); printf("ok!\n"); return 0; } ``` 
\$\endgroup\$
1
  • \$\begingroup\$ Good job! So, it seems that for some operating systems one of the event polling functions must be called to trigger a window to open, then after that rendering can begin. Any rendering functions called before that point are essentially being ignored because no window exists. That does not seem intuitive because you might not want to always update the window in every iteration of an event loop (for performance reasons). \$\endgroup\$ Commented Aug 26, 2024 at 21:44
1
\$\begingroup\$

To fix this issue, it appears that SDL_PollEvent() may need to be called in order to make the window appear and this behaviour can be dependent on the operating system used to run the program. Adding a simple while() loop to keep the program running does not appear to be sufficient to keep a window open. This issue is discussed here: Why does my window only get shown after I use SDL_PollEvent()?

The revised code is as follows:

#include <SDL2/SDL.h> #include <stdio.h> int main(int argc, char* argv[]) { // Variables used by the event loop SDL_bool quit = SDL_FALSE; SDL_Event e = { 0 }; // Initialize SDL if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { printf("SDL_Init Error: %s\n", SDL_GetError()); return 1; } // Create a window SDL_Window *win = SDL_CreateWindow("Hello, SDL2!", 100, 100, 640, 480, SDL_WINDOW_SHOWN); if (win == NULL) { printf("SDL_CreateWindow Error: %s\n", SDL_GetError()); SDL_Quit(); return 1; } // Create a renderer SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (ren == NULL) { SDL_DestroyWindow(win); printf("SDL_CreateRenderer Error: %s\n", SDL_GetError()); SDL_Quit(); return 1; } // Set the draw color to blue SDL_SetRenderDrawColor(ren, 0, 0, 255, 255); // Clear the window SDL_RenderClear(ren); // Present the window SDL_RenderPresent(ren); // Event loop while (!quit) { while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_QUIT: quit = SDL_TRUE; break; default:break; } } } // Clean up SDL_DestroyRenderer(ren); SDL_DestroyWindow(win); SDL_Quit(); return 0; } 
\$\endgroup\$
1
  • \$\begingroup\$ Thanks. I tested adding the event loop, but it makes no difference. I still do not get any graphics window. :-( \$\endgroup\$ Commented Aug 26, 2024 at 20:20

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.