SDL 学习笔记

3 阅读3分钟

SDL 学习笔记:从入门到理解核心原理

一、SDL 是什么?

SDL(Simple DirectMedia Layer) 是一个跨平台的硬件抽象层,提供统一的 API 来操作:

子系统作用
Video窗口创建、渲染(OpenGL/Vulkan/DirectX)
Audio音频播放、录制
Input键盘、鼠标、游戏手柄事件
Thread多线程、互斥锁、条件变量
Timer高精度定时器

核心价值:一套代码,Windows/Linux/macOS/Android/iOS 全平台运行。


二、SDL 核心原理

2.1 架构图

你的应用程序
      │
      ▼
  SDL API(统一接口)
      │
      ├─ Windows ─→ DirectX / Win32 API
      ├─ Linux   ─→ X11 / Wayland / DRM / OpenGL
      ├─ macOS   ─→ Metal / Cocoa
      └─ Android ─→ SurfaceFlinger / OpenGL ES

2.2 核心概念:渲染管线

初始化 SDL
    │
    ▼
创建窗口(Window)── 操作系统的"画框"
    │
    ▼
创建渲染器(Renderer)── 决定用哪种 GPU API 画图
    │
    ▼
创建纹理(Texture)── GPU 内存中的图像数据
    │
    ▼
渲染循环:
  ├─ 处理事件(键盘、鼠标、关闭)
  ├─ 更新纹理数据(把解码后的 YUV/RGB 拷进去)
  ├─ 清空画布 → 绘制纹理 → 显示到屏幕
  └─ 循环直到退出
    │
    ▼
清理资源

2.3 为什么要区分 Renderer 和 Texture?

概念作用类比
Window操作系统窗口画框
RendererGPU 渲染管线画家
TextureGPU 内存中的图像颜料

数据流:CPU 内存 → SDL_UpdateTexture → GPU 显存(Texture)→ SDL_RenderTexture → 屏幕。


三、常用 API 速查

3.1 初始化与清理

API作用参数说明
SDL_Init(flags)初始化 SDL 子系统SDL_INIT_VIDEO 视频,SDL_INIT_AUDIO 音频,SDL_INIT_EVENTS 事件
SDL_Quit()清理所有 SDL 资源

3.2 窗口

API作用参数说明
SDL_CreateWindow(title, w, h, flags)创建窗口flagsSDL_WINDOW_RESIZABLE(可调整大小)、SDL_WINDOW_OPENGL(支持 OpenGL)
SDL_DestroyWindow(window)销毁窗口窗口指针

3.3 渲染器

API作用参数说明
SDL_CreateRenderer(window, driver, flags)创建渲染器driverNULL 自动选择;flagsSDL_RENDERER_ACCELERATED(硬件加速)
SDL_DestroyRenderer(renderer)销毁渲染器渲染器指针

3.4 纹理

API作用参数说明
SDL_CreateTexture(renderer, format, access, w, h)创建纹理format:像素格式;accessSDL_TEXTUREACCESS_STREAMING(频繁更新)
SDL_UpdateYUVTexture(texture, rect, Y, Ypitch, U, Upitch, V, Vpitch)更新 YUV 纹理Y/U/V:数据指针;pitch:每行字节数
SDL_UpdateTexture(texture, rect, pixels, pitch)更新 RGB 纹理pixels:数据指针
SDL_DestroyTexture(texture)销毁纹理纹理指针

3.5 渲染

API作用参数说明
SDL_RenderClear(renderer)清空画布渲染器指针
SDL_RenderTexture(renderer, texture, srcRect, dstRect)绘制纹理srcRect:源区域(NULL=全部);dstRect:目标区域(NULL=全屏)
SDL_RenderPresent(renderer)显示到屏幕渲染器指针(交换缓冲区)

3.6 事件

API作用参数说明
SDL_PollEvent(&event)非阻塞获取事件有事件返回 1,无事件返回 0
SDL_WaitEvent(&event)阻塞等待事件直到有事件才返回

事件类型

事件含义
SDL_EVENT_QUIT窗口关闭
SDL_EVENT_KEY_DOWN键盘按下
SDL_EVENT_MOUSE_BUTTON_DOWN鼠标按下

四、常用像素格式

格式常量含义典型用途
SDL_PIXELFORMAT_IYUVYUV420P 平面格式FFmpeg 解码输出
SDL_PIXELFORMAT_NV12YUV420 半平面MPP 硬解码输出
SDL_PIXELFORMAT_RGB248 位 RGB 打包通用显示
SDL_PIXELFORMAT_ARGB8888带 Alpha 的 RGBUI 叠加

五、标准代码模板

#include <SDL3/SDL.h>

int main() {
    // 1. 初始化
    SDL_Init(SDL_INIT_VIDEO);
    
    // 2. 创建窗口
    SDL_Window *win = SDL_CreateWindow("SDL Demo", 
                                       1920, 1080, 
                                       SDL_WINDOW_RESIZABLE);
    
    // 3. 创建渲染器
    SDL_Renderer *renderer = SDL_CreateRenderer(win, NULL, 
                                                SDL_RENDERER_ACCELERATED);
    
    // 4. 创建纹理
    SDL_Texture *tex = SDL_CreateTexture(renderer,
                                         SDL_PIXELFORMAT_IYUV,
                                         SDL_TEXTUREACCESS_STREAMING,
                                         1920, 1080);
    
    // 5. 渲染循环
    int running = 1;
    while (running) {
        SDL_Event e;
        while (SDL_PollEvent(&e)) {
            if (e.type == SDL_EVENT_QUIT) running = 0;
        }
        
        // TODO: 更新纹理数据
        // SDL_UpdateYUVTexture(tex, NULL, Y, Ypitch, U, Upitch, V, Vpitch);
        
        SDL_RenderClear(renderer);
        SDL_RenderTexture(renderer, tex, NULL, NULL);
        SDL_RenderPresent(renderer);
    }
    
    // 6. 清理
    SDL_DestroyTexture(tex);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(win);
    SDL_Quit();
    return 0;
}

六、与 FFmpeg 对接

AVFrame *frame = /* FFmpeg 解码后的帧 */;

SDL_UpdateYUVTexture(texture, NULL,
                     frame->data[0], frame->linesize[0],  // Y
                     frame->data[1], frame->linesize[1],  // U
                     frame->data[2], frame->linesize[2]); // V