使用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
相关产品推荐
相关产品推荐

