我希望开发一些使用 SDL2 在 7" RPi 触摸屏上显示图形的代码,但我不想安装完整的桌面操作系统。我已经安装了 Raspbian Buster Lite。一些简单的测试代码出现错误当我尝试运行它时:
user@rpi4:~/01_hello_SDL $ ./hw
Window could not be created! SDL_Error: Could not initialize EGL
user@rpi4:~/01_hello_SDL $ sudo ./hw
error: XDG_RUNTIME_DIR not set in the environment.
Window could not be created! SDL_Error: Could not initialize EGL
我正在尝试使用
创建窗口SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL )
我发现了一篇post,其中引用了如何在没有 X 的情况下构建 SDL2 的说明,但我希望有人可以告诉我更多关于 SDL 如何在各种环境中找到显示器的信息,以及是否有可能做我想做的事情做。
几年前,我使用 SDL 1.2 在运行 Debian 版本的 Beaglebone Black 上进行全屏图形处理,但我似乎已经丢失了该安装,并且不记得它是如何设置的。我依稀记得有关 fbdev 的一些问题,它是非加速图形,但这在当时并不重要(虽然我现在想获得加速图形,但这并不重要)。
示例代码:
/*This source code copyrighted by Lazy Foo' Productions (2004-2019)
and may not be redistributed without written permission.*/
//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>
//Screen dimension constants
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 480;
int main( int argc, char* args[] )
{
//The window we'll be rendering to
SDL_Window* window = NULL;
//The surface contained by the window
SDL_Surface* screenSurface = NULL;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//Create window
window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//Get window surface
screenSurface = SDL_GetWindowSurface( window );
//Fill the surface white
SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF ) );
//Update the surface
SDL_UpdateWindowSurface( window );
//Wait two seconds
SDL_Delay( 2000 );
}
}
//Destroy window
SDL_DestroyWindow( window );
//Quit SDL subsystems
SDL_Quit();
return 0;
}
好吧,让它在我的 Raspberry Pi 3 上使用
2019-07-10-raspbian-buster-lite.img
工作,两者都具有默认的 Broadcom blobs 和 KMS/DRM 后端:
安装 SDL2 构建依赖项:
# install everything Debian uses to build SDL
sudo apt build-dep libsdl2
# needed for the KMSDRM backend:
sudo apt install libdrm-dev libgbm-dev
从 Git 获取最新的稳定版 SDL 源 tarball
或标签 (
release-2.0.10
) 并将其提取到类似 ~/sdl-src
的位置
configure
脚本:
cd ~/sdl-src
./configure --enable-video-kmsdrm
这是我的
configure
总结:
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
注意
rpi
列表中的 kmsdrm(dynamic)
和 Video drivers
条目:
Video drivers : dummy rpi x11(dynamic) kmsdrm(dynamic) opengl opengl_es1 opengl_es2 vulkan wayland(dynamic)
^^^ ^^^^^^^^^^^^^^^
构建并安装 SDL;我的 Rpi3 花了大约 4.5 分钟:
make -j4 && sudo make install
构建测试程序:
g++ main.cpp `pkg-config --cflags --libs sdl2`
(可选)如果您想使用 KMSDRM 后端而不是默认的 OpenGL ES blob,请启用“完整 KMS”驱动程序:
$ sudo raspi-config
select '7 Advanced Options'
select 'A7 GL Driver'
select 'G3 GL (Full KMS)'
reboot
运行测试程序:
$ ./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
您可以使用环境变量来覆盖默认的视频/渲染驱动程序选择:
SDL_VIDEODRIVER=KMSDRM SDL_RENDER_DRIVER=software ./a.out
我必须用 envvars 握住 SDL 的手才能加载 KMSDRM 后端:
# 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
这是我一直在使用的测试程序:
// g++ main.cpp `pkg-config --cflags --libs sdl2`
#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 | SDL_RENDERER_PRESENTVSYNC );
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;
while( running )
{
SDL_Event ev;
while( SDL_PollEvent( &ev ) )
{
if( SDL_QUIT == ev.type || SDL_KEYDOWN == ev.type )
{
running = false;
}
}
static int dir = 1;
static int i = 0;
i += dir;
if( i > 255 ) { i = 255; dir = -1; }
if( i < 0 ) { i = 0; dir = 1; }
SDL_SetRenderDrawColor( renderer, i, i, i, SDL_ALPHA_OPAQUE );
SDL_RenderClear( renderer );
SDL_RenderPresent( renderer );
}
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
SDL_Quit();
return 0;
}