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:
parent
ba6892aa95
commit
3d199ca263
|
@ -25,6 +25,7 @@ type Renderer struct {
|
||||||
renderer *sdl.Renderer
|
renderer *sdl.Renderer
|
||||||
running bool
|
running bool
|
||||||
ticks uint64
|
ticks uint64
|
||||||
|
textures map[string]*Texture // cached textures
|
||||||
|
|
||||||
// Optimizations to minimize SDL calls.
|
// Optimizations to minimize SDL calls.
|
||||||
lastColor render.Color
|
lastColor render.Color
|
||||||
|
@ -33,10 +34,11 @@ type Renderer struct {
|
||||||
// New creates the SDL renderer.
|
// New creates the SDL renderer.
|
||||||
func New(title string, width, height int) *Renderer {
|
func New(title string, width, height int) *Renderer {
|
||||||
return &Renderer{
|
return &Renderer{
|
||||||
events: events.New(),
|
events: events.New(),
|
||||||
title: title,
|
title: title,
|
||||||
width: int32(width),
|
width: int32(width),
|
||||||
height: int32(height),
|
height: int32(height),
|
||||||
|
textures: map[string]*Texture{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package sdl
|
package sdl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"os"
|
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"git.kirsle.net/apps/doodle/lib/render"
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
@ -30,14 +30,44 @@ type Texture struct {
|
||||||
|
|
||||||
// NewTexture caches an SDL texture from a bitmap.
|
// NewTexture caches an SDL texture from a bitmap.
|
||||||
func (r *Renderer) NewTexture(filename string, img image.Image) (render.Texturer, error) {
|
func (r *Renderer) NewTexture(filename string, img image.Image) (render.Texturer, error) {
|
||||||
fh, err := os.Create(filename)
|
var (
|
||||||
if err != nil {
|
fh = bytes.NewBuffer([]byte{})
|
||||||
return nil, err
|
)
|
||||||
}
|
|
||||||
defer fh.Close()
|
|
||||||
|
|
||||||
err = bmp.Encode(fh, img)
|
err := bmp.Encode(fh, img)
|
||||||
return nil, err
|
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.
|
// 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.
|
// NewBitmap initializes a texture from a bitmap image.
|
||||||
func (r *Renderer) NewBitmap(filename string) (render.Texturer, error) {
|
func (r *Renderer) NewBitmap(filename string) (render.Texturer, error) {
|
||||||
surface, err := sdl.LoadBMP(filename)
|
if tex, ok := r.textures[filename]; ok {
|
||||||
if err != nil {
|
return tex, nil
|
||||||
return nil, fmt.Errorf("NewBitmap: LoadBMP: %s", err)
|
|
||||||
}
|
}
|
||||||
defer surface.Free()
|
return nil, fmt.Errorf("NewBitmap(%s): not found in texture cache", filename)
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,11 @@ package wallpaper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"image"
|
"image"
|
||||||
"os"
|
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/lib/render"
|
"git.kirsle.net/apps/doodle/lib/render"
|
||||||
|
"git.kirsle.net/apps/doodle/pkg/shmem"
|
||||||
"git.kirsle.net/apps/doodle/pkg/userdir"
|
"git.kirsle.net/apps/doodle/pkg/userdir"
|
||||||
"golang.org/x/image/bmp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CornerTexture returns the Texture.
|
// CornerTexture returns the Texture.
|
||||||
|
@ -57,28 +55,9 @@ func (wp *Wallpaper) RepeatTexture(e render.Engine) (render.Texturer, error) {
|
||||||
return wp.tex.repeat, nil
|
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) {
|
func texture(e render.Engine, img *image.RGBA, name string) (render.Texturer, error) {
|
||||||
filename := userdir.CacheFilename("wallpaper", name+".bmp")
|
filename := userdir.CacheFilename("wallpaper", name+".bmp")
|
||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
texture, err := shmem.CurrentRenderEngine.NewTexture(filename, img)
|
||||||
fh, err := os.Create(filename)
|
return texture, err
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user