SDL2: Cache Bitmaps in Memory, Not on Disk

* Update the SDL2 engine's texture caching to use an sdl.RWops file
  buffer in memory instead of outputting bitmap images to the
  filesystem.
This commit is contained in:
Noah 2019-06-27 12:46:35 -07:00
parent ba6892aa95
commit 3d199ca263
3 changed files with 51 additions and 56 deletions

View File

@ -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
@ -37,6 +38,7 @@ func New(title string, width, height int) *Renderer {
title: title,
width: int32(width),
height: int32(height),
textures: map[string]*Texture{},
}
}

View File

@ -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)
}

View File

@ -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
}