树莓派3B上SDL2 KMSDRM启动无画面且鼠标异常的技术求助
问题描述
编写了一个利用SDL2的KMSDRM支持实现清屏为灰色的简单测试程序,代码如下:
#include <SDL.h> #include <cstring> #include <iostream> #include <thread> #include <SDL_opengles2.h> using namespace std::chrono_literals; using std::clog; using std::endl; int main() { auto init_re = SDL_VideoInit("KMSDRM"); if (init_re != 0) exit(EXIT_FAILURE); SDL_Window *window = SDL_CreateWindow("SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL); if (nullptr == window) { std::cerr << "SDL_CreateWindow(): " << SDL_GetError() << '\n'; exit(EXIT_FAILURE); } SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); auto gl = SDL_GL_CreateContext(window); clog << "create OpenGL context " << gl << endl; auto make_current_re = SDL_GL_MakeCurrent(window, gl); clog << "make current ctx returned " << make_current_re << endl; clog << "OpenGL version: " << (const char *)glGetString(GL_VERSION) << ", GLSL " << (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION) << endl; glClearColor(0.5, 0.5, 0.5, 1.0); size_t frame_count = 0; SDL_Event e; bool should_break = false; while (!should_break) { while (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) should_break = true; else if (e.type == SDL_KEYDOWN) if (e.key.keysym.sym == SDLK_ESCAPE) should_break = true; } frame_count += 1; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); clog << "frame " << frame_count << endl; std::this_thread::sleep_for(2ms); } SDL_GL_DeleteContext(gl); SDL_DestroyWindow(window); SDL_Quit(); }
程序可正常运行并打印帧计数日志,但无法显示640x480的灰色画面;此外,屏幕左上角显示鼠标指针但不随鼠标移动。
系统及配置信息:
- 32位最新更新的Raspbian bullseye
- 已完整卸载X服务器
- 通过apt从Raspbian仓库安装SDL2
- config.txt相关设置:
dtoverlay=vc4-kms-v3d,composite max_framebuffers=2 gpu_mem=256
一、解决灰色画面无法显示的问题
核心问题是OpenGL ES双缓冲机制未被正确使用,同时窗口参数需要适配KMSDRM环境:
- 添加缓冲区交换调用
OpenGL ES采用双缓冲,绘制内容默认在后台缓冲区,必须调用SDL_GL_SwapWindow才能将内容输出到屏幕。在glClear之后、休眠之前添加:
SDL_GL_SwapWindow(window);
- 调整窗口创建参数
KMSDRM模式下,建议添加无框或全屏属性,同时指定窗口居中:
SDL_Window *window = SDL_CreateWindow("SDL2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS);
若需适配屏幕原生分辨率,可替换为SDL_WINDOW_FULLSCREEN_DESKTOP。
- 提前设置OpenGL上下文属性
将SDL_GL_SetAttribute移到窗口创建前,明确指定GLES版本:
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); // 之后再创建窗口 SDL_Window *window = SDL_CreateWindow(...);
二、解决KMSDRM模式下鼠标工作异常的问题
1. 修复鼠标指针不动的问题
- 初始化输入子系统
当前仅初始化了视频子系统,需补充初始化输入子系统以识别鼠标设备:
// 替换原SDL_VideoInit调用 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_INPUT) != 0) { std::cerr << "SDL_Init(): " << SDL_GetError() << '\n'; exit(EXIT_FAILURE); }
- 处理光标显示(可选)
若屏幕上是SDL默认软件光标,可禁用或切换为硬件光标:
// 禁用软件光标 SDL_ShowCursor(SDL_DISABLE);
Raspbian仓库的SDL2已默认支持libinput,硬件光标可通过SDL_CreateCursor自定义实现。
2. 确保输入设备权限
将当前用户加入input组,获取输入设备访问权限:
sudo usermod -aG input $USER
重启后生效。
内容的提问来源于stack exchange,提问作者jiandingzhe
相关产品推荐
相关产品推荐

