OpenGL+SDL启用双缓冲时窗口缩放卡顿闪烁原因咨询
SDL+OpenGL双缓冲模式下窗口缩放闪烁延迟问题
问题现象
我在使用OpenGL搭配SDL开发图形程序时,需要将固定尺寸为320x240的软件渲染framebuffer等比缩放至当前客户端窗口大小,宽高比不匹配时在画面两侧添加黑边,保证原始宽高比不变。
测试过程中发现两种缓冲模式下表现差异明显:
- 单缓冲模式:窗口拖拽resize过程中渲染效果流畅,无异常
- 开启双缓冲(double buffering)后:出现严重画面闪烁,画面缩放效果跟随窗口尺寸变化存在明显延迟
实际开发中我更倾向使用双缓冲:窗口尺寸调整属于低频操作,其余绝大多数场景下双缓冲可以提供更流畅的动画效果,因此希望定位双缓冲模式下窗口缩放出现卡顿、闪烁的根本原因。
验证过程
最初我认为该问题是SDL的缺陷,至少其Linux后端实现存在该问题。将SDL替换为freeglut后,相同程序在窗口缩放时双缓冲模式运行流畅,后续经过验证确认SDL本身不存在相关问题,具体说明可见评论区。
核心复现代码
#include <stdio.h> #include <stdint.h> #include <assert.h> #include <math.h> #include <SDL2/SDL.h> #include <GL/gl.h> #define WindowW 800 #define WindowH 600 #define FbW 320 #define FbH 240 #define FbTexW 0x200 #define FbTexH 0x100 static const float VertexCoord[] = {0, 0, FbTexW, 0, 0, FbTexH, FbTexW, FbTexH}; static void initGl() { glEnable(GL_TEXTURE_2D); glEnableClientState(GL_VERTEX_ARRAY); glClearColor(0, 0, 0, 0); glShadeModel(GL_FLAT); glOrtho(0, FbW, FbH, 0, 1, -1); glVertexPointer(2, GL_FLOAT, 0, VertexCoord); } static void resize(int w, int h) { int p = w * FbH; int q = h * FbW; if (p > q) { float w_ = (float)q / FbH; glViewport((int)roundf((w - w_) * 0.5f), 0, (int)roundf(w_), h); } else { float h_ = (float)p / FbW; glViewport(0, (int)roundf((h - h_) * 0.5f), w, (int)roundf(h_)); } } static void draw() { glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } int main(int argc, char **argv) { (void)argc, (void)argv; assert(!SDL_Init(SDL_INIT_VIDEO)); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // 1为双缓冲,0为单缓冲 SDL_Window *win = SDL_CreateWindow("test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WindowW, WindowH, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL); assert(win); SDL_GLContext gl = SDL_GL_CreateContext(win); assert(gl); initGl(); for (;;) { SDL_Event event; assert(SDL_WaitEvent(&event)); switch (event.type) { case SDL_QUIT: SDL_GL_DeleteContext(gl); SDL_DestroyWindow(win); SDL_Quit(); return 0; case SDL_WINDOWEVENT: if (event.window.event != SDL_WINDOWEVENT_SIZE_CHANGED) { int w, h; SDL_GL_GetDrawableSize(win, &w, &h); resize(w, h); } } draw(); SDL_GL_SwapWindow(win); } }
内容的提问来源于stack exchange,提问作者xiver77
相关产品推荐
相关产品推荐

