SDL2 on Raspberry Pi without X? SDL2 on Raspberry Pi without X? linux linux

SDL2 on Raspberry Pi without X?


Alrighty, got it working on my Raspberry Pi 3 with 2019-07-10-raspbian-buster-lite.img, both with the default Broadcom blobs & the KMS/DRM backend:

  1. Install SDL2 build dependencies:

     # install everything Debian uses to build SDL sudo apt build-dep libsdl2 # needed for the KMSDRM backend: sudo apt install libdrm-dev libgbm-dev
  2. Grab the latest stable SDL source tarball or tag (release-2.0.10) from Mercurial/Git and extract it somewhere like ~/sdl-src

  3. Run SDL's configure script:

     cd ~/sdl-src ./configure --enable-video-kmsdrm

    Here's my configure summary, note the rpi and kmsdrm(dynamic) entries in the Video drivers list:

     SDL2 Configure Summary: Building Shared Libraries Building Static Libraries Enabled modules : atomic audio video render events joystick haptic sensor power filesystem threads timers file loadso cpuinfo assembly Assembly Math   : Audio drivers   : disk dummy oss alsa(dynamic) pulse(dynamic) sndio(dynamic) Video drivers   : dummy rpi x11(dynamic) kmsdrm(dynamic) opengl opengl_es1 opengl_es2 vulkan wayland(dynamic) X11 libraries   : xcursor xdbe xinerama xinput2 xinput2_multitouch xrandr xscrnsaver xshape xvidmode Input drivers   : linuxev linuxkd Using libsamplerate : YES Using libudev       : YES Using dbus          : YES Using ime           : YES Using ibus          : YES Using fcitx         : YES
  4. Build & install SDL; took ~4.5 minutes on my Rpi3:

     make -j4 && sudo make install
  5. Build test program:

     g++ main.cpp `pkg-config --cflags --libs sdl2`
  6. (Optional) Enable the "Full KMS" driver if you want to use the KMSDRM backend instead of the default OpenGL ES blobs:

     $ sudo raspi-config select '7 Advanced Options' select 'A7 GL Driver' select 'G3 GL (Full KMS)' reboot
  7. Run test program:

     $ ./a.out  Testing video drivers... The path /dev/dri/ cannot be opened or is not available The path /dev/dri/ cannot be opened or is not available SDL_VIDEODRIVER available: x11 wayland KMSDRM RPI dummy SDL_VIDEODRIVER usable   : RPI The path /dev/dri/ cannot be opened or is not available The path /dev/dri/ cannot be opened or is not available SDL_VIDEODRIVER selected : RPI SDL_RENDER_DRIVER available: opengl opengles2 opengles software SDL_RENDER_DRIVER selected : opengles2

    You can use environment variables to override the default video/render driver selection:

     SDL_VIDEODRIVER=KMSDRM SDL_RENDER_DRIVER=software ./a.out

    I had to hold SDL's hand a bit with envvars to get the KMSDRM backend to load:

     # no envvars, fails: $ ./a.out  Testing video drivers... SDL_VIDEODRIVER available: x11 wayland KMSDRM RPI dummy SDL_VIDEODRIVER usable   : KMSDRM SDL_VIDEODRIVER selected : KMSDRM SDL_CreateWindow(): Could not initialize OpenGL / GLES library # with envvars, succeeds: $ SDL_VIDEO_EGL_DRIVER=libEGL.so SDL_VIDEO_GL_DRIVER=libGLESv2.so ./a.out Testing video drivers... SDL_VIDEODRIVER available: x11 wayland KMSDRM RPI dummy SDL_VIDEODRIVER usable   : KMSDRM SDL_VIDEODRIVER selected : KMSDRM SDL_RENDER_DRIVER available: opengl opengles2 opengles software SDL_RENDER_DRIVER selected : opengl

Here's the test program I've been using:

#include <SDL.h>#include <iostream>#include <vector>int main( int argc, char** argv ){    SDL_Init( 0 );    std::cout << "Testing video drivers..." << '\n';    std::vector< bool > drivers( SDL_GetNumVideoDrivers() );    for( int i = 0; i < drivers.size(); ++i )    {        drivers[ i ] = ( 0 == SDL_VideoInit( SDL_GetVideoDriver( i ) ) );        SDL_VideoQuit();    }    std::cout << "SDL_VIDEODRIVER available:";    for( int i = 0; i < drivers.size(); ++i )    {        std::cout << " " << SDL_GetVideoDriver( i );    }    std::cout << '\n';    std::cout << "SDL_VIDEODRIVER usable   :";    for( int i = 0; i < drivers.size(); ++i )    {        if( !drivers[ i ] ) continue;        std::cout << " " << SDL_GetVideoDriver( i );    }    std::cout << '\n';    if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )    {        std::cerr << "SDL_Init(): " << SDL_GetError() << '\n';        return EXIT_FAILURE;    }    std::cout << "SDL_VIDEODRIVER selected : " << SDL_GetCurrentVideoDriver() << '\n';    SDL_Window* window = SDL_CreateWindow        (        "SDL2",        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,        640, 480,        SDL_WINDOW_SHOWN        );    if( nullptr == window )    {        std::cerr << "SDL_CreateWindow(): " << SDL_GetError() << '\n';        return EXIT_FAILURE;    }    std::cout << "SDL_RENDER_DRIVER available:";    for( int i = 0; i < SDL_GetNumRenderDrivers(); ++i )    {        SDL_RendererInfo info;        SDL_GetRenderDriverInfo( i, &info );        std::cout << " " << info.name;    }    std::cout << '\n';    SDL_Renderer* renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );    if( nullptr == renderer )    {        std::cerr << "SDL_CreateRenderer(): " << SDL_GetError() << '\n';        return EXIT_FAILURE;    }    SDL_RendererInfo info;    SDL_GetRendererInfo( renderer, &info );    std::cout << "SDL_RENDER_DRIVER selected : " << info.name << '\n';    bool running = true;    unsigned char i = 0;    while( running )    {        SDL_Event ev;        while( SDL_PollEvent( &ev ) )        {            if( ( ev.type == SDL_QUIT ) ||                ( ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_ESCAPE ) )            {                running = false;            }        }        SDL_SetRenderDrawColor( renderer, i, i, i, SDL_ALPHA_OPAQUE );        SDL_RenderClear( renderer );        SDL_RenderPresent( renderer );        i++;    }    SDL_DestroyRenderer( renderer );    SDL_DestroyWindow( window );    SDL_Quit();    return 0;}