Add RWMutex safety around the SDL2 texture cache

This commit is contained in:
Noah 2022-04-10 12:27:20 -07:00
parent df69b8e525
commit c0c2d05619
2 changed files with 25 additions and 16 deletions

View File

@ -5,6 +5,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"image" "image"
"sync"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
"git.kirsle.net/go/render/event" "git.kirsle.net/go/render/event"
@ -21,10 +22,11 @@ type Renderer struct {
height int32 height int32
// Private fields. // Private fields.
events *event.State events *event.State
window *sdl.Window window *sdl.Window
renderer *sdl.Renderer renderer *sdl.Renderer
textures map[string]*Texture // cached textures textures map[string]*Texture // cached textures
textureMu sync.RWMutex
// Optimizations to minimize SDL calls. // Optimizations to minimize SDL calls.
lastColor render.Color lastColor render.Color

View File

@ -69,30 +69,28 @@ func (r *Renderer) StoreTexture(name string, img image.Image) (render.Texturer,
tex: texture, tex: texture,
image: img, image: img,
} }
r.textureMu.Lock()
r.textures[name] = tex r.textures[name] = tex
r.textureMu.Unlock()
return tex, nil return tex, nil
} }
// CountTextures is a custom function for the SDL2 Engine only that returns the // CountTextures is a custom function for the SDL2 Engine only that returns the
// size of the engine texture cache. // size of the engine texture cache.
// func (r *Renderer) CountTextures() int {
// Returns the number of (Go) Texture objects (which hold cached image.Image r.textureMu.RLock()
// and can garbage collect nicely) and the number of those which also have defer r.textureMu.RUnlock()
// SDL2 Texture objects (which need to be freed manually).
func (r *Renderer) CountTextures() (bitmaps int, sdl2textures int) {
var withTex int // ones with active SDL2 Texture objects
for _, tex := range r.textures {
if tex.tex != nil {
withTex++
}
}
return len(r.textures), withTex return len(r.textures)
} }
// ListTextures is a custom function to peek into the SDL2 texture cache names. // ListTextures is a custom function to peek into the SDL2 texture cache names.
func (r *Renderer) ListTextures() []string { func (r *Renderer) ListTextures() []string {
r.textureMu.RLock()
defer r.textureMu.RUnlock()
var keys = []string{} var keys = []string{}
for key := range r.textures { for key := range r.textures {
keys = append(keys, key) keys = append(keys, key)
@ -112,6 +110,9 @@ func (t *Texture) Image() image.Image {
// Free the SDL2 texture object. // Free the SDL2 texture object.
func (t *Texture) Free() error { func (t *Texture) Free() error {
t.render.textureMu.Lock()
defer t.render.textureMu.Unlock()
var err error var err error
if t.tex != nil { if t.tex != nil {
@ -132,6 +133,9 @@ func (t *Texture) Free() error {
// LoadTexture initializes a texture from a bitmap image. // LoadTexture initializes a texture from a bitmap image.
func (r *Renderer) LoadTexture(name string) (render.Texturer, error) { func (r *Renderer) LoadTexture(name string) (render.Texturer, error) {
r.textureMu.RLock()
defer r.textureMu.RUnlock()
if tex, ok := r.textures[name]; ok { if tex, ok := r.textures[name]; ok {
// If the SDL2 texture had been freed, recreate it. // If the SDL2 texture had been freed, recreate it.
if tex.tex == nil { if tex.tex == nil {
@ -144,6 +148,9 @@ func (r *Renderer) LoadTexture(name string) (render.Texturer, error) {
// FreeTextures flushes the internal cache of SDL2 textures and frees their memory. // FreeTextures flushes the internal cache of SDL2 textures and frees their memory.
func (r *Renderer) FreeTextures() int { func (r *Renderer) FreeTextures() int {
r.textureMu.Lock()
defer r.textureMu.Unlock()
var num = len(r.textures) var num = len(r.textures)
for name, tex := range r.textures { for name, tex := range r.textures {
delete(r.textures, name) delete(r.textures, name)