基于Yocto的树莓派Zero W上SDL/OpenGLES应用指定显示输出问题
解决Raspberry Pi Zero W上SDL/OpenGLES应用指定TFT显示屏的问题
你的思路方向是对的——核心问题确实出在应用直接调用了Broadcom VC4的底层图形API,绕开了你配置的X11环境,加上对VC4 display编号和EGL头文件的理解有偏差,导致设置没生效。下面一步步帮你调整:
1. 先搞清楚应用的图形依赖逻辑
你启动了绑定/dev/fb1的XServer(:1),但用SDL_VIDEODRIVER=x11等环境变量没效果,原因是:
你的应用代码里直接调用了
graphics_get_display_size和vc_dispmanx_display_open这些VC4裸机图形接口,完全绕过了SDL的X11驱动层。SDL的环境变量只对用SDL标准API创建窗口/上下文的代码生效,对直接操作VC4的代码无效。
2. 修正VC4 Display编号的问题
RPi上的vc_dispmanx_display_open参数不是framebuffer的索引(fb0/fb1),而是VC4内部的display编号:
- 默认HDMI对应编号
0,TFT(不管是DPI还是SPI连接)通常对应编号1,但需要先确认:
在Yocto系统里执行命令(需要先安装vc4-tools包):
输出会列出所有可用的VC4 display,比如:tvservice -lAvailable displays: Display Number 0, type HDMI Display Number 1, type DPI - 然后修改代码里的硬编码:
// 把原来的0改成你查到的TFT对应的display编号(比如1) graphics_get_display_size(1, &screen_width, &screen_height); vc_dispmanx_display_open(1); - 同时要确保Yocto配置里启用了TFT对应的display:
根据你的TFT连接方式(DPI/SPI),在local.conf里添加对应的配置,比如DPI屏:ENABLE_DPI_DISPLAY = "1" DPI_DISPLAY_TIMING = "320x240@60"
3. 两种可选的解决方案路径
路径A:让应用走X11环境(利用你已经配置的:1)
如果你想复用已启动的XServer,需要修改应用代码,去掉直接调用VC4 API的部分,改用SDL的标准API创建窗口和EGL上下文:
// 先设置环境变量(或者在启动时通过命令行传) putenv("SDL_VIDEODRIVER=x11"); putenv("DISPLAY=:1"); // 初始化SDL和OpenGL ES SDL_Init(SDL_INIT_VIDEO); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); // 创建对应TFT分辨率的窗口 SDL_Window *window = SDL_CreateWindow( "My App", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN ); SDL_GLContext gl_ctx = SDL_GL_CreateContext(window); // 后续渲染逻辑用SDL/OpenGL ES API,不再直接操作vc_dispmanx
启动时直接用:
DISPLAY=:1 ./SDL_App
路径B:继续用VC4裸机API(不依赖X11)
如果不想修改应用的核心渲染逻辑,除了修正display编号,还要确保:
- Yocto镜像包含VC4用户态工具和驱动:
在local.conf里添加:IMAGE_INSTALL:append = " vc4-userland libbcm2835" - 运行应用时,确保没有被XServer抢占fb1的控制权(可以先关闭
:1的XServer测试)。
4. 关于EGL头文件的误区
你提到找不到EGL/eglvivante.h——这是Vivante GPU(比如NXP i.MX系列)的头文件,而RPi Zero用的是Broadcom VC4 GPU,完全不相关!你应该用标准EGL头文件+VC4的bcm_host库:
#include <EGL/egl.h> #include <bcm_host.h>
编译时链接VC4的EGL和GLES库:
gcc your_app.c -o SDL_App -lSDL2 -lbrcmEGL -lbrcmGLESv2 -lbcm_host
最后验证步骤
- 先单独测试TFT的VC4 display是否正常:用
vcgencmd display_power 1 1命令打开编号1的display(如果是DPI屏),看是否有输出。 - 测试修改后的代码,先关闭XServer,用路径B的方式运行,看是否输出到TFT;再测试路径A的X11方式。
内容的提问来源于stack exchange,提问作者mozcelikors
相关产品推荐
相关产品推荐

