C语言SDL2调用SDL_GetWindowSurface报无硬件加速渲染器错误求助
问题产生原因
该报错是SDL的标准限制导致:同一个SDL窗口不支持同时使用硬件加速的SDL_Renderer和SDL_GetWindowSurface接口,二者属于互斥的绘制路径。
SDL_RENDERER_ACCELERATED标记的渲染器走GPU绘制逻辑,会独占窗口的硬件绘制缓冲SDL_GetWindowSurface走CPU绘制逻辑,会直接操作窗口的系统层面绘制缓冲
两种逻辑抢占窗口资源,属于违规用法。之前在GTX 1650+Ubuntu20.04环境下运行正常属于未定义行为的巧合,不同硬件、驱动、SDL版本对该错误的容忍度不同,RTX 3060+Ubuntu21.10的环境做了更严格的校验才直接抛出错误。
解决方案
根据你的开发需求二选一即可:
方案1:保留硬件加速渲染(游戏场景优先推荐)
直接删除所有SDL_GetWindowSurface相关的代码,全程使用SDL_Renderer系列API完成绘制:
// ... 保留之前的窗口、渲染器创建代码 puts("Renderer created"); // 删掉以下整块Surface相关代码 /* SDL_Surface* screen_surface = SDL_GetWindowSurface(window); if (!screen_surface) { printf("surface initialization error: %s\n", SDL_GetError()); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 1; } puts("Surface created"); */ // 后续绘制使用SDL_RenderClear/SDL_RenderCopy/SDL_RenderPresent等API SDL_Delay(1000); // 清理逻辑保持不变 SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit();
方案2:保留窗口Surface绘制逻辑
删除硬件加速渲染器的创建代码,所有绘制通过Surface完成后调用SDL_UpdateWindowSurface刷新窗口:
// ... 保留之前的窗口创建代码 puts("Window created"); // 删掉以下整块渲染器创建代码 /* Uint32 rflags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, rflags); if (!renderer) { printf("renderer initialization error: %s\n", SDL_GetError()); SDL_DestroyWindow(window); SDL_Quit(); return 1; } puts("Renderer created"); */ SDL_Surface* screen_surface = SDL_GetWindowSurface(window); if (!screen_surface) { printf("surface initialization error: %s\n", SDL_GetError()); SDL_DestroyWindow(window); SDL_Quit(); return 1; } puts("Surface created"); // 完成Surface绘制后调用以下接口刷新窗口 // SDL_UpdateWindowSurface(window); SDL_Delay(1000); // 清理时不需要销毁渲染器 SDL_DestroyWindow(window); SDL_Quit();
如果确实有特殊场景需要同时使用两种绘制能力,可以额外创建SDL_Surface做内存级CPU绘制,再通过SDL_CreateTextureFromSurface转成纹理交给硬件渲染器绘制,不会触发互斥问题。
内容的提问来源于stack exchange,提问作者yuser099881232
相关产品推荐
相关产品推荐

