From 4ad32c6edf9fb07f4f325691d46cdfd77d731442 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Thu, 27 Jun 2019 12:46:35 -0700 Subject: [PATCH] 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. --- sdl/sdl.go | 10 +++++--- sdl/texture.go | 68 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/sdl/sdl.go b/sdl/sdl.go index a3a176a..c54767f 100644 --- a/sdl/sdl.go +++ b/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/sdl/texture.go b/sdl/texture.go index 0fdad45..677ef72 100644 --- a/sdl/texture.go +++ b/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) }