You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 11:09:23