Add RWMutex safety around the SDL2 texture cache
This commit is contained in:
parent
df69b8e525
commit
c0c2d05619
10
sdl/sdl.go
10
sdl/sdl.go
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user