graphics: Remove imageImpl.image member

This commit is contained in:
Hajime Hoshi 2016-09-03 23:08:51 +09:00
parent 438afdac5b
commit fb3724a40e
3 changed files with 96 additions and 45 deletions

View File

@ -95,7 +95,7 @@ func (i *images) restore(context *opengl.Context) error {
if img.isDisposed() { if img.isDisposed() {
continue continue
} }
if err := img.image.Dispose(); err != nil { if err := img.restorable.Image().Dispose(); err != nil {
return err return err
} }
} }

View File

@ -23,13 +23,11 @@ import (
"runtime" "runtime"
"sync" "sync"
"github.com/hajimehoshi/ebiten/internal/graphics"
"github.com/hajimehoshi/ebiten/internal/graphics/opengl" "github.com/hajimehoshi/ebiten/internal/graphics/opengl"
"github.com/hajimehoshi/ebiten/internal/restorable" "github.com/hajimehoshi/ebiten/internal/restorable"
) )
type imageImpl struct { type imageImpl struct {
image *graphics.Image
disposed bool disposed bool
width int width int
height int height int
@ -41,16 +39,15 @@ type imageImpl struct {
} }
func newImageImpl(width, height int, filter Filter, volatile bool) (*imageImpl, error) { func newImageImpl(width, height int, filter Filter, volatile bool) (*imageImpl, error) {
img, err := graphics.NewImage(width, height, glFilter(filter)) img, err := restorable.NewImage(width, height, glFilter(filter))
if err != nil { if err != nil {
return nil, err return nil, err
} }
i := &imageImpl{ i := &imageImpl{
image: img,
width: width, width: width,
height: height, height: height,
filter: filter, filter: filter,
restorable: restorable.NewImage(), restorable: img,
volatile: volatile, volatile: volatile,
} }
runtime.SetFinalizer(i, (*imageImpl).Dispose) runtime.SetFinalizer(i, (*imageImpl).Dispose)
@ -74,17 +71,15 @@ func newImageImplFromImage(source image.Image, filter Filter) (*imageImpl, error
for j := 0; j < h; j++ { for j := 0; j < h; j++ {
copy(p[j*w*4:(j+1)*w*4], rgbaImg.Pix[j*rgbaImg.Stride:]) copy(p[j*w*4:(j+1)*w*4], rgbaImg.Pix[j*rgbaImg.Stride:])
} }
img, err := graphics.NewImageFromImage(rgbaImg, glFilter(filter)) img, err := restorable.NewImageFromImage(rgbaImg, glFilter(filter))
if err != nil { if err != nil {
// TODO: texture should be removed here?
return nil, err return nil, err
} }
i := &imageImpl{ i := &imageImpl{
image: img,
width: w, width: w,
height: h, height: h,
filter: filter, filter: filter,
restorable: restorable.NewImage(), restorable: img,
} }
i.restorable.ReplacePixels(p) i.restorable.ReplacePixels(p)
runtime.SetFinalizer(i, (*imageImpl).Dispose) runtime.SetFinalizer(i, (*imageImpl).Dispose)
@ -92,15 +87,14 @@ func newImageImplFromImage(source image.Image, filter Filter) (*imageImpl, error
} }
func newScreenImageImpl(width, height int) (*imageImpl, error) { func newScreenImageImpl(width, height int) (*imageImpl, error) {
img, err := graphics.NewScreenFramebufferImage(width, height) img, err := restorable.NewScreenFramebufferImage(width, height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
i := &imageImpl{ i := &imageImpl{
image: img,
width: width, width: width,
height: height, height: height,
restorable: restorable.NewImage(), restorable: img,
volatile: true, volatile: true,
screen: true, screen: true,
} }
@ -116,7 +110,7 @@ func (i *imageImpl) Fill(clr color.Color) error {
} }
rgba := color.RGBAModel.Convert(clr).(color.RGBA) rgba := color.RGBAModel.Convert(clr).(color.RGBA)
i.restorable.Fill(rgba) i.restorable.Fill(rgba)
return i.image.Fill(rgba) return i.restorable.Image().Fill(rgba)
} }
func (i *imageImpl) clearIfVolatile() error { func (i *imageImpl) clearIfVolatile() error {
@ -129,7 +123,7 @@ func (i *imageImpl) clearIfVolatile() error {
return nil return nil
} }
i.restorable.Clear() i.restorable.Clear()
return i.image.Fill(color.RGBA{}) return i.restorable.Image().Fill(color.RGBA{})
} }
func (i *imageImpl) DrawImage(image *Image, options *DrawImageOptions) error { func (i *imageImpl) DrawImage(image *Image, options *DrawImageOptions) error {
@ -169,9 +163,9 @@ func (i *imageImpl) DrawImage(image *Image, options *DrawImageOptions) error {
if image.impl.restorable.IsStale() { if image.impl.restorable.IsStale() {
i.restorable.MakeStale() i.restorable.MakeStale()
} else { } else {
i.restorable.AppendDrawImageHistory(image.impl.image, vertices, &geom, &colorm, mode) i.restorable.AppendDrawImageHistory(image.impl.restorable.Image(), vertices, &geom, &colorm, mode)
} }
if err := i.image.DrawImage(image.impl.image, vertices, &geom, &colorm, mode); err != nil { if err := i.restorable.Image().DrawImage(image.impl.restorable.Image(), vertices, &geom, &colorm, mode); err != nil {
return err return err
} }
return nil return nil
@ -187,7 +181,7 @@ func (i *imageImpl) At(x, y int, context *opengl.Context) color.Color {
return color.Transparent return color.Transparent
} }
idx := 4*x + 4*y*i.width idx := 4*x + 4*y*i.width
clr, err := i.restorable.At(idx, i.image, context) clr, err := i.restorable.At(idx, i.restorable.Image(), context)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -203,7 +197,7 @@ func (i *imageImpl) resolveStalePixels(context *opengl.Context) error {
if i.volatile { if i.volatile {
return nil return nil
} }
if err := i.restorable.ReadPixelsFromVRAMIfStale(i.image, context); err != nil { if err := i.restorable.ReadPixelsFromVRAMIfStale(i.restorable.Image(), context); err != nil {
return err return err
} }
return nil return nil
@ -223,7 +217,7 @@ func (i *imageImpl) resetPixelsIfDependingOn(target *imageImpl, context *opengl.
} }
// target is an image that is about to be tried mutating. // target is an image that is about to be tried mutating.
// If pixels object is related to that image, the pixels must be reset. // If pixels object is related to that image, the pixels must be reset.
if !i.restorable.DependsOn(target.image) { if !i.restorable.DependsOn(target.restorable.Image()) {
return nil return nil
} }
i.restorable.MakeStale() i.restorable.MakeStale()
@ -243,26 +237,18 @@ func (i *imageImpl) restore(context *opengl.Context) error {
return nil return nil
} }
if i.screen { if i.screen {
// The screen image should also be recreated because framebuffer might if err := i.restorable.RestoreAsScreen(i.width, i.height); err != nil {
// be changed.
var err error
i.image, err = graphics.NewScreenFramebufferImage(i.width, i.height)
if err != nil {
return err return err
} }
return nil return nil
} }
if i.volatile { if i.volatile {
var err error if err := i.restorable.Recreate(i.width, i.height, glFilter(i.filter)); err != nil {
i.image, err = graphics.NewImage(i.width, i.height, glFilter(i.filter))
if err != nil {
return err return err
} }
return nil return nil
} }
var err error if err := i.restorable.RestoreImage(context, i.width, i.height, glFilter(i.filter)); err != nil {
i.image, err = i.restorable.CreateImage(context, i.width, i.height, glFilter(i.filter))
if err != nil {
return err return err
} }
return nil return nil
@ -275,11 +261,13 @@ func (i *imageImpl) Dispose() error {
return errors.New("ebiten: image is already disposed") return errors.New("ebiten: image is already disposed")
} }
if !i.screen { if !i.screen {
if err := i.image.Dispose(); err != nil { if err := i.restorable.Image().Dispose(); err != nil {
return err return err
} }
} }
i.image = nil if err := i.restorable.Dispose(); err != nil {
return err
}
i.disposed = true i.disposed = true
i.restorable.Clear() i.restorable.Clear()
runtime.SetFinalizer(i, nil) runtime.SetFinalizer(i, nil)
@ -296,7 +284,7 @@ func (i *imageImpl) ReplacePixels(p []uint8) error {
if i.disposed { if i.disposed {
return errors.New("ebiten: image is already disposed") return errors.New("ebiten: image is already disposed")
} }
return i.image.ReplacePixels(p) return i.restorable.Image().ReplacePixels(p)
} }
func (i *imageImpl) isDisposed() bool { func (i *imageImpl) isDisposed() bool {
@ -308,5 +296,5 @@ func (i *imageImpl) isDisposed() bool {
func (i *imageImpl) isInvalidated(context *opengl.Context) bool { func (i *imageImpl) isInvalidated(context *opengl.Context) bool {
i.m.Lock() i.m.Lock()
defer i.m.Unlock() defer i.m.Unlock()
return i.image.IsInvalidated(context) return i.restorable.Image().IsInvalidated(context)
} }

View File

@ -33,6 +33,8 @@ type drawImageHistoryItem struct {
// Image represents an image of an image for restoring when GL context is lost. // Image represents an image of an image for restoring when GL context is lost.
type Image struct { type Image struct {
image *graphics.Image
// baseImage and baseColor are exclusive. // baseImage and baseColor are exclusive.
basePixels []uint8 basePixels []uint8
baseColor color.RGBA baseColor color.RGBA
@ -40,8 +42,35 @@ type Image struct {
stale bool stale bool
} }
func NewImage() *Image { func NewImage(width, height int, filter opengl.Filter) (*Image, error) {
return &Image{} img, err := graphics.NewImage(width, height, filter)
if err != nil {
return nil, err
}
return &Image{
image: img,
}, nil
}
func NewImageFromImage(source *image.RGBA, filter opengl.Filter) (*Image, error) {
img, err := graphics.NewImageFromImage(source, filter)
if err != nil {
// TODO: texture should be removed here?
return nil, err
}
return &Image{
image: img,
}, nil
}
func NewScreenFramebufferImage(width, height int) (*Image, error) {
img, err := graphics.NewScreenFramebufferImage(width, height)
if err != nil {
return nil, err
}
return &Image{
image: img,
}, nil
} }
func (p *Image) IsStale() bool { func (p *Image) IsStale() bool {
@ -79,6 +108,11 @@ func (p *Image) ReplacePixels(pixels []uint8) {
p.stale = false p.stale = false
} }
func (p *Image) Image() *graphics.Image {
// TODO: This function is temporary. Remove this.
return p.image
}
func (p *Image) AppendDrawImageHistory(image *graphics.Image, vertices []int16, geom graphics.Matrix, colorm graphics.Matrix, mode opengl.CompositeMode) { func (p *Image) AppendDrawImageHistory(image *graphics.Image, vertices []int16, geom graphics.Matrix, colorm graphics.Matrix, mode opengl.CompositeMode) {
if p.stale { if p.stale {
return return
@ -148,10 +182,10 @@ func (p *Image) HasDependency() bool {
return p.drawImageHistory != nil return p.drawImageHistory != nil
} }
// CreateImage restores *graphics.Image from the pixels using its state. // RestoreImage restores *graphics.Image from the pixels using its state.
func (p *Image) CreateImage(context *opengl.Context, width, height int, filter opengl.Filter) (*graphics.Image, error) { func (p *Image) RestoreImage(context *opengl.Context, width, height int, filter opengl.Filter) error {
if p.stale { if p.stale {
return nil, errors.New("pixels: pixels must not be stale when restoring") return errors.New("restorable: pixels must not be stale when restoring")
} }
img := image.NewRGBA(image.Rect(0, 0, width, height)) img := image.NewRGBA(image.Rect(0, 0, width, height))
if p.basePixels != nil { if p.basePixels != nil {
@ -161,14 +195,14 @@ func (p *Image) CreateImage(context *opengl.Context, width, height int, filter o
} }
gimg, err := graphics.NewImageFromImage(img, filter) gimg, err := graphics.NewImageFromImage(img, filter)
if err != nil { if err != nil {
return nil, err return err
} }
if p.baseColor != (color.RGBA{}) { if p.baseColor != (color.RGBA{}) {
if p.basePixels != nil { if p.basePixels != nil {
panic("not reach") panic("not reach")
} }
if err := gimg.Fill(p.baseColor); err != nil { if err := gimg.Fill(p.baseColor); err != nil {
return nil, err return err
} }
} }
for _, c := range p.drawImageHistory { for _, c := range p.drawImageHistory {
@ -177,15 +211,44 @@ func (p *Image) CreateImage(context *opengl.Context, width, height int, filter o
panic("not reach") panic("not reach")
}*/ }*/
if err := gimg.DrawImage(c.image, c.vertices, c.geom, c.colorm, c.mode); err != nil { if err := gimg.DrawImage(c.image, c.vertices, c.geom, c.colorm, c.mode); err != nil {
return nil, err return err
} }
} }
p.image = gimg
p.basePixels, err = gimg.Pixels(context) p.basePixels, err = gimg.Pixels(context)
if err != nil { if err != nil {
return nil, err return err
} }
p.baseColor = color.RGBA{} p.baseColor = color.RGBA{}
p.drawImageHistory = nil p.drawImageHistory = nil
p.stale = false p.stale = false
return gimg, nil return nil
}
func (p *Image) RestoreAsScreen(width, height int) error {
// The screen image should also be recreated because framebuffer might
// be changed.
var err error
p.image, err = graphics.NewScreenFramebufferImage(width, height)
if err != nil {
return err
}
// TODO: Reset other values?
return nil
}
func (p *Image) Recreate(width, height int, filter opengl.Filter) error {
var err error
p.image, err = graphics.NewImage(width, height, filter)
if err != nil {
return err
}
// TODO: Reset other values?
return nil
}
func (p *Image) Dispose() error {
p.image = nil
return nil
} }