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

Linux/Ubuntu下SDL窗口不显示但事件循环正常的问题求助

SDL2 OpenGL窗口无法显示的问题修复(初代Surface Book + Ubuntu)

在初代Surface Book的Ubuntu系统中使用SDL2编写OpenGL程序,程序编译运行正常,事件循环经cout验证可正常工作,但SDL窗口始终无法显示。已将Mesa更新至20.3.0,设备支持OpenGL 4.6,且尝试在SDL_Init()前调用SDL_SetMainReady(),问题仍未解决。

解决方案

针对该问题,可通过以下几点修改修复:

  • 显式添加窗口显示标志:确保窗口创建后立即显示
  • 初始化OpenGL视口并清除缓冲:避免因无绘制内容导致窗口“空白不可见”
  • 设置垂直同步:确保缓冲交换逻辑正常触发
  • 处理双显卡切换(Surface Book特有):强制程序指定使用集成/独立显卡

修改后的完整代码

#include <SDL2/SDL.h>
#include <iostream>

// Globals
int gScreenWidth = 640;
int gScreenHeight = 480;
SDL_Window* gWindow = nullptr;
SDL_GLContext gContext = nullptr;

bool gQuit = false; // if true we quit

void InitializeProgram(){
    if(SDL_Init(SDL_INIT_VIDEO) < 0){
        std::cout << "SDL2 could not initialize video subsystem" << std::endl;
        exit(1);
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    // 添加SDL_WINDOW_SHOWN标志确保窗口显示
    gWindow = SDL_CreateWindow("OpenGL First Program", 
                               SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
                               gScreenWidth, gScreenHeight, 
                               SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
    if(gWindow == nullptr){
        std::cout << "SDL Window could not be created" << std::endl;
        exit(1);
    }

    gContext = SDL_GL_CreateContext(gWindow);
    if(gContext == nullptr){
        std::cout << "OpenGL Context could not be created" << std::endl;
        exit(1);
    }

    // 设置OpenGL视口
    glViewport(0, 0, gScreenWidth, gScreenHeight);
    // 启用垂直同步,确保缓冲交换正常
    SDL_GL_SetSwapInterval(1);
}

void Input(){
    SDL_Event e;
    while(SDL_PollEvent(&e)){
        if(e.type == SDL_QUIT){
            std::cout << "Goodbye!" << std::endl;
            gQuit = true;
        }
    }
}

void PreDraw(){
    // 清除颜色缓冲,设置背景色
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
}

void Draw(){
    // 可在此添加绘制逻辑,比如简单三角形
}

void MainLoop(){
    while(!gQuit){
        Input();
        PreDraw();
        Draw();
        SDL_GL_SwapWindow(gWindow); // Updates the screen
    }
}

void CleanUp(){
    SDL_GL_DeleteContext(gContext); // 别忘了删除GL上下文
    SDL_DestroyWindow(gWindow);
    SDL_Quit();
}

int main(){
    InitializeProgram();

    MainLoop();

    CleanUp();

    return 0;
}

关键修改说明

  1. 窗口显示标志:
    部分桌面环境或双显卡设备下,SDL_CreateWindow默认创建的窗口可能被隐藏,显式添加SDL_WINDOW_SHOWN可强制窗口显示。

  2. 视口与缓冲清除:
    原代码无任何OpenGL绘制操作,也未清除缓冲,导致交换缓冲时无有效内容,窗口会呈现与桌面融合的“透明”状态。添加glClear后会填充固定背景色,窗口立即可见。

  3. 垂直同步设置:
    SDL_GL_SetSwapInterval(1)强制缓冲交换与显示器垂直同步,避免因交换过快导致的渲染异常,同时减少屏幕撕裂。

  4. 双显卡处理:
    初代Surface Book配备Intel集成显卡和NVIDIA独立显卡,Ubuntu下可能存在切换问题。可通过以下命令强制指定显卡:

    • 强制使用集成显卡:
      __GLX_VENDOR_LIBRARY_NAME=mesa ./your_program
      
    • 强制使用NVIDIA显卡:
      __GLX_VENDOR_LIBRARY_NAME=nvidia ./your_program
      

内容的提问来源于stack exchange,提问作者JackAttack31

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 03:20:14