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

SDL2渲染到纹理示例无窗口显示:版本变化还是Mac兼容问题?

问题描述

学习SDL2渲染到纹理模式时,我从Stack Overflow找到一份示例代码,编译执行无报错,程序会按设定运行8秒,但始终没有窗口显示。将窗口位置改为SDL_WINDOWPOS_UNDEFINED也无效果。

想问:是SDL2十年间的更新导致示例失效?还是Mac系统存在特殊兼容问题?

我的环境:搭载苹果硅芯片的Mac OS 14.2.1,SDL2为近期下载版本,原代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <SDL2/SDL.h>

// Compile: gcc test.c -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2


void putPixel(SDL_Renderer *renderer, int x, int y)
{
    SDL_SetRenderDrawColor(renderer, 255,255,255,255);
    SDL_RenderDrawPoint(renderer, x, y);
}

int main(int argc, char* argv[]) {

    int width = 640;
    int height = 480;

    SDL_Window *window = SDL_CreateWindow("Test", 0,0,width,height, 0);
    if (window == NULL)
    {
        return -1;
    }
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
    if (renderer == NULL)
    {
        return -2;
    }

    SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);

    /* Create texture for display */
    SDL_Texture *display = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);

    SDL_SetRenderTarget(renderer, display);

    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);

    for(int x=0;x<8;x++)
    {
        SDL_SetRenderTarget(renderer, display);

        for(int y=0;y<10;y++)
        {
            putPixel(renderer,40+x*10,50+y);
        }

        SDL_SetRenderTarget(renderer, NULL);
        SDL_RenderCopy(renderer, display, NULL, NULL);
        SDL_RenderPresent(renderer);
        sleep(1);
    }


    SDL_Quit();
    return 0;
}
问题原因与解决办法

核心问题

  • 窗口未设置显示标志:原代码创建窗口时未传入SDL_WINDOW_SHOWN,Mac系统下窗口默认处于隐藏状态。
  • 主线程被阻塞未处理事件:使用sleep(1)会完全阻塞主线程,SDL的窗口管理器需要主线程响应事件才能正确绘制窗口。
  • Apple Silicon架构路径适配:通过brew安装的SDL2在苹果硅Mac上的路径是/opt/homebrew,而非原代码注释的/usr/local,原编译命令可能链接到错误架构的库。

修改后的可运行代码

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>

// Apple Silicon编译命令: gcc test.c -I/opt/homebrew/include/SDL2 -L/opt/homebrew/lib -lSDL2

void putPixel(SDL_Renderer *renderer, int x, int y)
{
    SDL_SetRenderDrawColor(renderer, 255,255,255,255);
    SDL_RenderDrawPoint(renderer, x, y);
}

int main(int argc, char* argv[]) {
    // 显式初始化SDL视频子系统,新版本SDL必须调用
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        fprintf(stderr, "SDL初始化失败: %s\n", SDL_GetError());
        return -1;
    }

    int width = 640;
    int height = 480;

    // 添加SDL_WINDOW_SHOWN标志,确保窗口创建后直接显示
    SDL_Window *window = SDL_CreateWindow("Test", 
                                          SDL_WINDOWPOS_UNDEFINED, 
                                          SDL_WINDOWPOS_UNDEFINED,
                                          width, height, 
                                          SDL_WINDOW_SHOWN);
    if (window == NULL)
    {
        fprintf(stderr, "创建窗口失败: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }

    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
    if (renderer == NULL)
    {
        fprintf(stderr, "创建渲染器失败: %s\n", SDL_GetError());
        SDL_DestroyWindow(window);
        SDL_Quit();
        return -2;
    }

    SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);

    /* 创建目标纹理 */
    SDL_Texture *display = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
    if (display == NULL) {
        fprintf(stderr, "创建纹理失败: %s\n", SDL_GetError());
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        SDL_Quit();
        return -3;
    }

    SDL_SetRenderTarget(renderer, display);
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);

    for(int x=0;x<8;x++)
    {
        SDL_SetRenderTarget(renderer, display);

        for(int y=0;y<10;y++)
        {
            putPixel(renderer,40+x*10,50+y);
        }

        SDL_SetRenderTarget(renderer, NULL);
        SDL_RenderCopy(renderer, display, NULL, NULL);
        SDL_RenderPresent(renderer);

        // 用SDL_Delay配合事件循环替代sleep,避免主线程完全阻塞
        SDL_Event event;
        Uint32 start = SDL_GetTicks();
        while (SDL_GetTicks() - start < 1000) {
            while (SDL_PollEvent(&event)) {
                // 处理窗口关闭事件
                if (event.type == SDL_QUIT) {
                    SDL_DestroyTexture(display);
                    SDL_DestroyRenderer(renderer);
                    SDL_DestroyWindow(window);
                    SDL_Quit();
                    return 0;
                }
            }
        }
    }

    // 释放资源
    SDL_DestroyTexture(display);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

关键修改说明

  1. 显式调用SDL_Init(SDL_INIT_VIDEO):新版本SDL不再隐式初始化子系统,必须显式声明初始化模块。
  2. 添加SDL_WINDOW_SHOWN窗口标志:强制窗口创建后立即显示,解决Mac下窗口隐藏的问题。
  3. 替换sleep(1)为事件循环+SDL_Delay:让主线程在等待期间处理窗口事件,保证窗口能正常渲染。
  4. 修正Apple Silicon编译路径:适配brew安装的SDL2在苹果硅Mac上的默认路径。
  5. 添加错误日志输出:方便排查初始化失败的具体原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 16:44:58