diff --git a/lib/render/sdl/sdl.go b/lib/render/sdl/sdl.go index a3a176a..c54767f 100644 --- a/lib/render/sdl/sdl.go +++ b/lib/render/sdl/sdl.go @@ -25,6 +25,7 @@ type Renderer struct { renderer *sdl.Renderer running bool ticks uint64 + textures map[string]*Texture // cached textures // Optimizations to minimize SDL calls. lastColor render.Color @@ -33,10 +34,11 @@ type Renderer struct { // New creates the SDL renderer. func New(title string, width, height int) *Renderer { return &Renderer{ - events: events.New(), - title: title, - width: int32(width), - height: int32(height), + events: events.New(), + title: title, + width: int32(width), + height: int32(height), + textures: map[string]*Texture{}, } } diff --git a/lib/render/sdl/texture.go b/lib/render/sdl/texture.go index 0fdad45..677ef72 100644 --- a/lib/render/sdl/texture.go +++ b/lib/render/sdl/texture.go @@ -1,9 +1,9 @@ package sdl import ( + "bytes" "fmt" "image" - "os" "git.kirsle.net/apps/doodle/lib/render" "github.com/veandco/go-sdl2/sdl" @@ -30,14 +30,44 @@ type Texture struct { // NewTexture caches an SDL texture from a bitmap. func (r *Renderer) NewTexture(filename string, img image.Image) (render.Texturer, error) { - fh, err := os.Create(filename) - if err != nil { - return nil, err - } - defer fh.Close() + var ( + fh = bytes.NewBuffer([]byte{}) + ) - err = bmp.Encode(fh, img) - return nil, err + err := bmp.Encode(fh, img) + if err != nil { + return nil, fmt.Errorf("NewTexture: bmp.Encode: %s", err) + } + + // Create an SDL RWOps from the bitmap data in memory. + sdlRW, err := sdl.RWFromMem(fh.Bytes()) + if err != nil { + return nil, fmt.Errorf("NewTexture: sdl.RWFromMem: %s", err) + } + + surface, err := sdl.LoadBMPRW(sdlRW, true) + if err != nil { + return nil, fmt.Errorf("NewTexture: sdl.LoadBMPRW: %s", err) + } + defer surface.Free() + + // TODO: chroma key color hardcoded to white here + key := sdl.MapRGB(surface.Format, 255, 255, 255) + surface.SetColorKey(true, key) + + texture, err := r.renderer.CreateTextureFromSurface(surface) + if err != nil { + return nil, fmt.Errorf("NewBitmap: create texture: %s", err) + } + + tex := &Texture{ + width: surface.W, + height: surface.H, + tex: texture, + } + r.textures[filename] = tex + + return tex, nil } // Size returns the dimensions of the texture. @@ -47,24 +77,8 @@ func (t *Texture) Size() render.Rect { // NewBitmap initializes a texture from a bitmap image. func (r *Renderer) NewBitmap(filename string) (render.Texturer, error) { - surface, err := sdl.LoadBMP(filename) - if err != nil { - return nil, fmt.Errorf("NewBitmap: LoadBMP: %s", err) + if tex, ok := r.textures[filename]; ok { + return tex, nil } - defer surface.Free() - - // TODO: chroma key color hardcoded to white here - key := sdl.MapRGB(surface.Format, 255, 255, 255) - surface.SetColorKey(true, key) - - tex, err := r.renderer.CreateTextureFromSurface(surface) - if err != nil { - return nil, fmt.Errorf("NewBitmap: create texture: %s", err) - } - - return &Texture{ - width: surface.W, - height: surface.H, - tex: tex, - }, nil + return nil, fmt.Errorf("NewBitmap(%s): not found in texture cache", filename) } diff --git a/pkg/wallpaper/texture.go b/pkg/wallpaper/texture.go index ebdc87f..30e1eda 100644 --- a/pkg/wallpaper/texture.go +++ b/pkg/wallpaper/texture.go @@ -4,13 +4,11 @@ package wallpaper import ( "errors" - "fmt" "image" - "os" "git.kirsle.net/apps/doodle/lib/render" + "git.kirsle.net/apps/doodle/pkg/shmem" "git.kirsle.net/apps/doodle/pkg/userdir" - "golang.org/x/image/bmp" ) // CornerTexture returns the Texture. @@ -57,28 +55,9 @@ func (wp *Wallpaper) RepeatTexture(e render.Engine) (render.Texturer, error) { return wp.tex.repeat, nil } +// texture creates or returns a cached texture for a wallpaper. func texture(e render.Engine, img *image.RGBA, name string) (render.Texturer, error) { filename := userdir.CacheFilename("wallpaper", name+".bmp") - if _, err := os.Stat(filename); os.IsNotExist(err) { - fh, err := os.Create(filename) - if err != nil { - return nil, fmt.Errorf("texture(%s): %s", name, err.Error()) - } - - err = bmp.Encode(fh, img) - if err != nil { - return nil, fmt.Errorf("texture(%s): bmp.Encode: %s", name, err.Error()) - } - - err = fh.Close() - if err != nil { - return nil, fmt.Errorf("texture(%s): fh.Close: %s", name, err.Error()) - } - } - - texture, err := e.NewBitmap(filename) - if err != nil { - return nil, fmt.Errorf("CornerTexture: NewBitmap(%s): %s", filename, err.Error()) - } - return texture, nil + texture, err := shmem.CurrentRenderEngine.NewTexture(filename, img) + return texture, err }