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

使用purego-sdl3时SDL_CreateTextureFromSurface返回nil问题求助

问题排查:SDL_CreateTextureFromSurface 返回nil提示surface无效

问题现象

调用sdl.CreateTextureFromSurface()始终返回nil,SDL错误信息显示“Parameter 'SDL_CreateTextureFromSurface(): surface' is invalid”。IDE中观察textSurface存在宽高及像素数据,但纹理创建失败。

运行环境

  • Go 1.24.1
  • MacOS 14.6.1
  • SDL 3.2.8
  • SDL_TTF 3.2.0

完整代码

package main

import (
    "github.com/jupiterrider/purego-sdl3/sdl"
    "github.com/jupiterrider/purego-sdl3/ttf"
)

func main() {

    var (
        window   *sdl.Window
        renderer *sdl.Renderer
        font     *ttf.Font
    )

    if !sdl.SetHint(sdl.HintRenderVSync, "1") {
        panic(sdl.GetError())
    }

    // initialise sdl
    if !sdl.Init(sdl.InitVideo) {
        panic(sdl.GetError())
    }
    defer sdl.Quit()

    // initialise ttf
    ttf.Init()
    if !ttf.Init() {
        panic(sdl.GetError())
    }
    defer ttf.Quit()

    window = sdl.CreateWindow("Viewdata Terminal 0.1", 1280, 720, sdl.WindowResizable)
    if window == nil {
        panic(sdl.GetError())
    }

    renderer = sdl.CreateRenderer(window, "")
    if renderer == nil {
        panic(sdl.GetError())
    }

    // clean up
    defer func() {
        // stack based calls so executed in last-in first out order
        defer sdl.DestroyWindow(window)
        defer sdl.DestroyRenderer(renderer)
        defer ttf.CloseFont(font)
    }()

    // create the font
    font = ttf.OpenFont("./fonts/KosugiMaru-Regular.ttf", 32)
    if font == nil {
        panic(sdl.GetError())
    }

    // create some text
    color := sdl.Color{255, 255, 255, sdl.AlphaOpaque}
    text := "Hello World"
    textSurface := ttf.RenderTextBlended(font, text, uint64(len(text)), color)

    // create the texture
    texture := sdl.CreateTextureFromSurface(renderer, textSurface)
    sdl.DestroySurface(textSurface)

    if texture == nil {
        sdl.Log("Couldn't create text: %s\n", sdl.GetError())
        panic(sdl.GetError())
    }

Outer:
    for {
        var event sdl.Event
        for sdl.PollEvent(&event) {
            switch event.Type() {
            case sdl.EventQuit:
                break Outer
            case sdl.EventKeyDown:
                if event.Key().Scancode == sdl.ScancodeEscape {
                    break Outer
                }
            }
        }

        var w int32 = 0
        var h int32 = 0
        var dst sdl.FRect
        const scale float32 = 4.0

        /* Center the text and scale it up */
        sdl.GetRenderOutputSize(renderer, &w, &h)
        sdl.SetRenderScale(renderer, scale, scale)
        sdl.GetTextureSize(texture, &dst.W, &dst.H)
        dst.X = ((float32(w) / scale) - dst.W) / 2
        dst.Y = ((float32(h) / scale) - dst.H) / 2

        /* Draw the text */
        sdl.SetRenderDrawColor(renderer, 0, 0, 0, 255)
        sdl.RenderClear(renderer)
        sdl.RenderTexture(renderer, texture, nil, &dst)
        sdl.RenderPresent(renderer)

    }
}

问题原因及修复方案

1. TTF重复初始化导致状态异常

代码中连续调用两次ttf.Init():

ttf.Init()
if !ttf.Init() {
    panic(sdl.GetError())
}

SDL_TTF的Init()第一次调用会初始化成功返回true,第二次调用因已初始化完成会返回false,虽未触发panic,但重复初始化会打乱内部状态,间接影响后续surface的有效性。

修复:保留单次初始化判断:

if !ttf.Init() {
    panic(sdl.GetError())
}

2. 提前销毁surface导致参数失效

当前代码在调用CreateTextureFromSurface()后立即销毁textSurface,但SDL部分渲染后端需要在纹理创建完成后才能安全销毁surface,提前销毁会导致创建纹理时引用的surface参数无效。

修复:将DestroySurface()移到纹理创建成功的逻辑后,失败时也需销毁:

// 创建纹理
texture := sdl.CreateTextureFromSurface(renderer, textSurface)

if texture == nil {
    sdl.Log("Couldn't create text: %s\n", sdl.GetError())
    sdl.DestroySurface(textSurface) // 创建失败时销毁surface
    panic(sdl.GetError())
}
sdl.DestroySurface(textSurface) // 创建成功后再销毁

3. 字体路径隐性问题

确认./fonts/KosugiMaru-Regular.ttf路径正确,若字体加载失败,后续生成的surface可能存在像素格式不兼容等隐性问题,可添加日志明确加载状态:

font = ttf.OpenFont("./fonts/KosugiMaru-Regular.ttf", 32)
if font == nil {
    sdl.Log("Failed to load font: %s", sdl.GetError())
    panic(sdl.GetError())
}

4. 渲染器与surface像素格式不兼容

SDL 3部分渲染后端(如Metal)对surface像素格式有严格要求,可打印surface格式并验证是否与渲染器兼容:

sdl.Log("Surface format: %d", textSurface.Format.Format)

若格式不匹配,可尝试使用ttf.RenderTextBlended_Wrapped()生成兼容格式的surface。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:26:05