libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.73k stars 1.8k forks source link

SDL renderer "ERROR: Could not get a framebuffer" when running a SDL-release-2.30.5 program on a Debian system without X. #10276

Closed fxlevy closed 2 months ago

fxlevy commented 3 months ago

Hello, with the latest SDL release "SDL-release-2.30.5", I'm facing an issue when the "SDL_Renderer" command is executed on a Bookworm Debian system last version 12.6 without X, meaning just the OS, an SSH servers and the standard utilities proposed during the installation process. I have a very simple program that I use to check basic SDL commands and events each time I do an update of a component. I didn't have any issue before when comiling the program and executing it. Eg, no issue with the previous release "2.30.4". The issue is also raised with the tests programs delivered with SDL. Eg with the testrendertarget program. If I recompile SDL with version 2.30.4, the issue disappear.

I have the following error:

ERROR: Could not get a framebuffer.

The "configure" options before compiling are:

--disable-video-opengl --disable-video-opengles1 --disable-video-x11 --disable-pulseaudio --disable-esd --disable-video-wayland --disable-video-rpi --disable-video-vulkan --disable-joystick-virtual --enable-video-kmsdrm --enable-video-opengles2 --enable-alsa

The configure command summary is

SDL2 Configure Summary: Building Shared Libraries Building Static Libraries Enabled modules : atomic audio video render events joystick haptic hidapi sensor power filesystem threads timers file misc locale loadso cpuinfo assembly Assembly Math : mmx 3dnow sse sse2 sse3 Audio drivers : disk dummy oss alsa(dynamic) Video drivers : dummy offscreen kmsdrm(dynamic) opengl_es2 Input drivers : linuxev linuxkd Enable virtual joystick APIs : NO Using libsamplerate : NO Using libudev : YES Using dbus : YES Using ime : YES Using ibus : NO Using fcitx : YES

Then, the program I use for testing which generates the error is the following: Please apologies for the program code quality. I am not a developer expert. My objective is to have the simplest Linux system to execute MAME and have the best performance on a simple SBC like the Pi.

#include <iostream>
#include <vector>
#include <SDL.h>

void fnQuit(int myReturnCode)
{
    std::cout << "Exit Code : " << myReturnCode << std::endl;
    SDL_Quit();
    exit(myReturnCode);
}

void PrintKeyInfo(SDL_KeyboardEvent *myKeyboardEvent)
{
    std::cout << "Scancode: " << myKeyboardEvent->keysym.scancode;
    std::cout << ", Name: " << SDL_GetKeyName(myKeyboardEvent->keysym.sym);
    std::cout << std::endl;
}

void PrintSDL_Event(SDL_Event *mySDL_Event)
{
    std::cout << "SDL Event : " << mySDL_Event->type << std::endl;
}

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

    int myPgmExitStatus = EXIT_FAILURE;

    // SDL first initialisation for testing purpose
    if (SDL_Init(0) < 0)
    {
        std::cerr << SDL_GetError() << std::endl;
        fnQuit(EXIT_FAILURE);
    }

    // SDL testing installed drivers
    std::cout << "Testing SDL video drivers available:" << std::endl;
    std::vector<bool> drivers(SDL_GetNumVideoDrivers());
    for (int i = 0; i < drivers.size(); ++i)
    {
        std::cout << " " << SDL_GetVideoDriver(i) << std::endl;
        drivers[i] = (0 == SDL_VideoInit(SDL_GetVideoDriver(i)));
        SDL_VideoQuit();
    }
    std::cout << std::endl;

    SDL_Quit();

    // SDL Main initialisation
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        std::cerr << SDL_GetError() << std::endl;
        fnQuit(EXIT_FAILURE);
    }

    std::cout << "SDL video driver selected : " << SDL_GetCurrentVideoDriver() << std::endl;

    // Get screen size from SDL
    SDL_DisplayMode mySDL_DisplayMode{};
    SDL_GetCurrentDisplayMode(0, &mySDL_DisplayMode);
    std::cout << std::endl
              << "Display size" << std::endl
              << "-----------------------------" << std::endl
              << "SDL_DisplayMode Width  : " << mySDL_DisplayMode.w << std::endl
              << "SDL_DisplayMode Height : " << mySDL_DisplayMode.h << std::endl
              << std::endl;

    // Screen dimension constants
    const int SCREEN_WIDTH = mySDL_DisplayMode.w;
    const int SCREEN_HEIGHT = mySDL_DisplayMode.h;

    // Create SDL window
    SDL_Window *mySDL_Window = NULL;
    mySDL_Window = SDL_CreateWindow(
        "SDL2",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        SCREEN_WIDTH,
        SCREEN_HEIGHT,
        SDL_WINDOW_SHOWN);

    if (nullptr == mySDL_Window)
    {
        std::cerr << "SDL_CreateWindow(): " << SDL_GetError() << '\n';
        fnQuit(EXIT_FAILURE);
    }

    SDL_Renderer *mySDL_Renderer = NULL;
    mySDL_Renderer = SDL_CreateRenderer(
        mySDL_Window,
        -1,
        SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (nullptr == mySDL_Renderer)
    {
        std::cerr << "SDL_CreateRenderer(): " << SDL_GetError() << '\n';
        fnQuit(EXIT_FAILURE);
    }

    SDL_RendererInfo mySDL_RendererInfo;
    SDL_GetRendererInfo(mySDL_Renderer, &mySDL_RendererInfo);
    std::cout << "SDL video reenderer selected : " << mySDL_RendererInfo.name << std::endl
              << std::endl;

    // Main program loop
    bool myProgramIsRunning = true;
    static int dir = 1;
    static int myIndex = 0;
    while (myProgramIsRunning)
    {
        myIndex += dir;
        if (myIndex > 255)
        {
            myIndex = 255;
            dir = -1;
        }
        if (myIndex < 0)
        {
            myIndex = 0;
            dir = 1;
        }
        SDL_SetRenderDrawColor(mySDL_Renderer, myIndex, myIndex, myIndex, SDL_ALPHA_OPAQUE);
        SDL_RenderClear(mySDL_Renderer);
        SDL_RenderPresent(mySDL_Renderer);
        SDL_Event mySDL_Event;
        while (SDL_PollEvent(&mySDL_Event))
        {
            PrintSDL_Event(&mySDL_Event);
            switch (mySDL_Event.type)
            {
            case SDL_QUIT:
                myProgramIsRunning = false;
                break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
                PrintKeyInfo(&mySDL_Event.key);
                int myKey = mySDL_Event.key.keysym.sym;
                if (myKey == SDLK_ESCAPE)
                {
                    fnQuit(EXIT_SUCCESS);
                }
                break;
            }
        }
    }

    SDL_DestroyRenderer(mySDL_Renderer);
    SDL_DestroyWindow(mySDL_Window);

    fnQuit(EXIT_SUCCESS);
}

The shell program I used to compile and execute is the following

myRootPath=$(readlink -m $(dirname "${BASH_SOURCE[0]}"))
g++ $myRootPath/SDLbasic.cpp -o $myRootPath/SDLbasic $(sdl2-config --cflags --libs)
[ $? != 0 ] && exit
$myRootPath/SDLbasic

For information the sdl2-config command returns the following:

-I/usr/local/include/SDL2 -D_REENTRANT -L/usr/local/lib -Wl,-rpath,/usr/local/lib -Wl,--enable-new-dtags -lSDL2

The result is as the following:

Testing SDL video drivers available: KMSDRM offscreen dummy evdev

SDL video driver selected : KMSDRM

Display size

SDL_DisplayMode Width : 1024 SDL_DisplayMode Height : 768

SDL video reenderer selected : opengles2

ERROR: Could not get a framebuffer SDL Event : 4352 SDL Event : 4352 SDL Event : 4352 SDL Event : 512 SDL Event : 512 SDL Event : 512 ERROR: Could not get a framebuffer ERROR: Could not get a framebuffer ERROR: Could not get a framebuffer ERROR: Could not get a framebuffer ERROR: Could not get a framebuffer ^CERROR: Could not get a framebuffer SDL Event : 256 Exit Code : 0

slouken commented 3 months ago

Can you check with the latest SDL2 code? This may have been fixed since the last release.

fxlevy commented 3 months ago

Thanks for the feedback @slouken . When you specify 'latest SDL2 code', you mean to clone the main branch and build from there? I tried but I don't know how to configure the make command, there is no configure command and I don't know how to generate it.

icculus commented 3 months ago

If 2.30.4 works and 2.30.5 doesn't, it's almost certainly this commit: 620e875335e35a6cc6c187079951f598bfd3b595

fxlevy commented 3 months ago

OK, I cloned the last SDL2 code from its branch using the command git clone --branch SDL2 https://github.com/libsdl-org/SDL.git and built it. After install and reload of the libs using the sudo ldconfig -v, I executed the command sdl2-config --versionwhich returned 2.31.0. I rebuilt my program and executed it. I still have an error but it's not the same. The error is now ERROR: Could not set videomode on CRTC and then ERROR: Could not queue pageflip: -22 :

Testing SDL video drivers available: KMSDRM offscreen dummy evdev

SDL video driver selected : KMSDRM

Display size

SDL_DisplayMode Width : 1024 SDL_DisplayMode Height : 768

SDL video reenderer selected : opengles2

ERROR: Could not set videomode on CRTC. SDL Event : 4352 SDL Event : 4352 SDL Event : 4352 SDL Event : 512 SDL Event : 512 SDL Event : 512 ERROR: Could not queue pageflip: -22 ERROR: Could not queue pageflip: -22 ERROR: Could not queue pageflip: -22 ERROR: Could not queue pageflip: -22 ERROR: Could not queue pageflip: -22 ERROR: Could not queue pageflip: -22 ERROR: Could not queue pageflip: -22 ERROR: Could not queue pageflip: -22 ERROR: Could not queue pageflip: -22 ERROR: Could not queue pageflip: -22 ^CERROR: Could not queue pageflip: -22 SDL Event : 256 Exit Code : 0

I rebuilt with the version 2.30.4 and it still works.

christianhaitian commented 2 months ago

I'm getting this exact same issue as fxlevy above building 2.30.5 for a aarch64 build on Ubuntu 19.10 without X. 2.30.3 was the last build that worked without issue on my end. I have not attempted to build and test the latest commit yet.

christianhaitian commented 2 months ago

Building the latest commit for SDL2 (7fdf7943774d2a54e48718316ca6d55d51a37696) seems to have resolved the issue on my end.

slouken commented 2 months ago

Great, thanks for the feedback!

christianhaitian commented 2 months ago

The recently released 2.30.6 works well on my end as well. Thanks again!

slouken commented 2 months ago

Great, you're welcome!

fxlevy commented 2 months ago

Hello, I downloaded and built the latest rlease 2.30.6, I have the same issue I had when testing lastst source code 3 weeks ago with my test pogram I already presented in my first post:

Testing SDL video drivers available:
 KMSDRM
 offscreen
 dummy
 evdev

SDL video driver selected : KMSDRM

Display size
-----------------------------
SDL_DisplayMode Width  : 1024
SDL_DisplayMode Height : 768

SDL video reenderer selected : opengles2

ERROR: Could not set videomode on CRTC.
SDL Event : 4352
SDL Event : 4352
SDL Event : 4352
SDL Event : 512
SDL Event : 512
SDL Event : 512
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22

I then rebuilt the 2.30.4 and rerun my test program without any issue.

slouken commented 2 months ago

Are you able to git bisect to see which commit broke things for you?

fxlevy commented 2 months ago

Thanks @slouken for the quick answer. I am not an expert with Git. I can try to build from a commit but for the moment I don't know how to do it. If someone could explain me the procedure it would be great. Anyway I can dig out for this but it will take me some time to achive this.

slouken commented 2 months ago

Try this:

git clone https://github.com/libsdl-org/SDL.git
cd SDL
git checkout release-2.30.x
git bisect start
git bisect bad
git checkout release-2.30.4
git bisect good

and then follow the instructions from there, building and testing and narrowing down to the bad commit. It shouldn't take long, there aren't that many in that branch.

sezero commented 2 months ago

Shooting in the dark but, this commit: https://github.com/libsdl-org/SDL/commit/5ab1151508ef514b9c5f944da8fc1f3dd6ea0558 (https://github.com/libsdl-org/SDL/pull/10313) seems to be missing in release-2.30.x branch. Is it possible that it may be the reason for the initial success report above? (I may very well be off base here...)

slouken commented 2 months ago

Okay, I merged that commit. I don't think that'll fix it, but... ?

sezero commented 2 months ago

Okay, I merged that commit. I don't think that'll fix it, but... ?

As I said, I may be very well off-base here as I don't have anything to test ksmdrm myself :)

slouken commented 2 months ago

Okay, I merged that commit. I don't think that'll fix it, but... ?

As I said, I may be very well off-base here as I don't have anything to test ksmdrm myself :)

I don’t either, but either way that was a good fix to merge.

fxlevy commented 2 months ago

Thanks for the explantion @slouken . Based on those explanations, the instructions and the post from @icculus I made the following:

After cloning the repo, I built using the follwing command:

sudo cmake -S . -B build && sudo cmake --build build && sudo cmake --install build && sudo ldconfig -v && sdl2-config --version git checkout release-2.30.4 -> OK: The error is NOT there. git checkout 620e875 -> KO : The error IS there (The error is ERROR: Could not get a framebuffer) git checkout c18173c -> OK The error is NOT there (It's the prevous commit just before the error appears).

Based on the post from @sezero , I made a last test: git checkout 5ab1151 -> KO : The error IS there (The Build phase mentions that the version is now 2.31.0). But the error is not the same. It's now ERROR: Could not set videomode on CRTC.

i hope this could help.

slouken commented 2 months ago

Can you try out https://github.com/libsdl-org/SDL/commit/fb4642805802253f91b2a69e013ef7238a5a76ff.patch and see if that fixes it for you?

fxlevy commented 2 months ago

Hello @slouken , I applied but the result is the same. Here is what I did:

git clone https://github.com/libsdl-org/SDL.git
cd SDL
git checkout release-2.30.6
wget https://github.com/libsdl-org/SDL/commit/fb4642805802253f91b2a69e013ef7238a5a76ff.patch
patch -r - -Ni fb4642805802253f91b2a69e013ef7238a5a76ff.patch src/video/kmsdrm/SDL_kmsdrmvideo.c
sudo cmake -S . -B build && sudo cmake --build build && sudo cmake --install build && sudo ldconfig -v && sdl2-config --version

The result of the patch command is:

patching file src/video/kmsdrm/SDL_kmsdrmvideo.c
Hunk #1 succeeded at 379 (offset -11 lines).
Hunk #2 succeeded at 389 (offset -11 lines).

When I execute the patch command again, the result is:

patching file src/video/kmsdrm/SDL_kmsdrmvideo.c
Reversed (or previously applied) patch detected!  Skipping patch.
2 out of 2 hunks ignored

When I re build and run my test program, the result is:

Testing SDL video drivers available:
 KMSDRM
 offscreen
 dummy
 evdev

SDL video driver selected : KMSDRM

Display size
-----------------------------
SDL_DisplayMode Width  : 1024
SDL_DisplayMode Height : 768

SDL video reenderer selected : opengles2

ERROR: Could not set videomode on CRTC.
SDL Event : 4352
SDL Event : 4352
SDL Event : 4352
SDL Event : 512
SDL Event : 512
SDL Event : 512
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22
ERROR: Could not queue pageflip: -22

Remark: when I directly apply the patch without checking out to release-2.30.6, the pach works and the result is the same.

fxlevy commented 2 months ago

Hello @slouken , Any news from this issue?. I have made several tests and the result is alsways the same SDL is not working after 2.30.4. But the error is not the same depending of the version:

Anything I coud do to help?

For further information, I'm testing SDL on a MacOS Parallels Desktop virtual machine executing the latest standard Debian version 12.6 without X (system type: X86_64).

slouken commented 2 months ago

Thanks for the information, I was able to put together a repro setup and fix this.

fxlevy commented 2 months ago

Hello @slouken , from my side, the issue is still there. I did the following, each time I iended the process by doing a SDL test using my test program.

First

git clone git clone https://github.com/libsdl-org/SDL.git
cd SDL
sudo cmake -S . -B build && sudo cmake --build build && sudo cmake --install build && sudo ldconfig -v && sdl2-config --version

ERROR: Could not set videomode on CRTC.

Second

git checkout release-2.30.4
sudo cmake -S . -B build && sudo cmake --build build && sudo cmake --install build && sudo ldconfig -v && sdl2-config --version

No error

Third

git checkout release-2.30.6
sudo cmake -S . -B build && sudo cmake --build build && sudo cmake --install build && sudo ldconfig -v && sdl2-config --version

ERROR: Could not set videomode on CRTC.

Fourth

git checkout 8e99ec3
sudo cmake -S . -B build && sudo cmake --build build && sudo cmake --install build && sudo ldconfig -v && sdl2-config --version

ERROR: Could not set videomode on CRTC.

Fith

git checkout release-2.30.5
sudo cmake -S . -B build && sudo cmake --build build && sudo cmake --install build && sudo ldconfig -v && sdl2-config --version

ERROR: Could not get a framebuffer

Sixth

git checkout release-2.30.4
sudo cmake -S . -B build && sudo cmake --build build && sudo cmake --install build && sudo ldconfig -v && sdl2-config --version

No error

Is there anything I made wrong in my test?

sezero commented 2 months ago

You should "git checkout release-2.30.x` : the fix isn't in any release tags, yet.

fxlevy commented 2 months ago

Indeed @sezero , now it works! Many thanks.

Just for information, there is a warnning message during the build phase.

/home/myuser/SDL/src/video/x11/SDL_x11mouse.c: In function ‘WarpMouseInternal’: /home/myuser/SDL/src/video/x11/SDL_x11mouse.c:323:9: warning: unused variable ‘deviceid’ [-Wunused-variable] 323 | int deviceid = 0; | ^~~~

But it's not related to this issue. This warning was already present in release-2.30.4.

sezero commented 2 months ago

Indeed @sezero , now it works! Many thanks.

You're welcome

Just for information, there is a warnning message during the build phase.

/home/myuser/SDL/src/video/x11/SDL_x11mouse.c: In function ‘WarpMouseInternal’:
/home/myuser/SDL/src/video/x11/SDL_x11mouse.c:323:9: warning: unused variable ‘deviceid’ [-Wunused-variable]
323 |     int deviceid = 0;
|         ^~~~~~~~

That should be fixed now. Thanks.

nckstwrt commented 1 month ago

I've still been getting this same issue when building SDL2 from the latest SDL2 branch. This is when trying it on a rk3326 (Cortex-a53) device. The latest commit doesn't fix the issue for me that was caused by the 620e875 commit after 2.30.4.

The reason the problem still exists is not just because of the changes to SDL_kmsdrmvideo.c but also to SDL_kmsdrmsym.h

SDL_KMSDRM_SYM(int,drmModeAddFB2WithModifiers,(int fd, uint32_t width,
                         uint32_t height, uint32_t pixel_format, const uint32_t bo_handles[4],
                         const uint32_t pitches[4], const uint32_t offsets[4],
                         const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags))
...
SDL_KMSDRM_SYM(uint64_t,gbm_bo_get_modifier,(struct gbm_bo *bo))
SDL_KMSDRM_SYM(int,gbm_bo_get_plane_count,(struct gbm_bo *bo))
SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_offset,(struct gbm_bo *bo, int plane))
SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_stride_for_plane,(struct gbm_bo *bo, int plane))

When these fail on a device that does not support them the function KMSDRM_GetSym nulls the module.

sezero commented 1 month ago

Yes, when there is a fallback possible, newer symbols shouldn't be shoved down the users' throats.

slouken commented 1 month ago

I've still been getting this same issue when building SDL2 from the latest SDL2 branch.

I've created a new issue to track this, thanks!

fxlevy commented 1 month ago

For information, when building the latest release '2.30.7', I don't have the issue. The test program is working fine.