graphics: Add Pixel's 'inconsistent' state

This commit is contained in:
Hajime Hoshi 2016-07-24 01:28:39 +09:00
parent 75916490b7
commit 8d074ecc20
4 changed files with 60 additions and 3 deletions

View File

@ -132,6 +132,9 @@ func (c *graphicsContext) UpdateAndDraw(context *opengl.Context, updateCount int
if err := c.initializeIfNeeded(context); err != nil { if err := c.initializeIfNeeded(context); err != nil {
return err return err
} }
if err := theImagesForRestoring.flushPixelsIfInconsistent(context); err != nil {
return err
}
for i := 0; i < updateCount; i++ { for i := 0; i < updateCount; i++ {
if err := theImagesForRestoring.clearVolatileImages(); err != nil { if err := theImagesForRestoring.clearVolatileImages(); err != nil {
return err return err

View File

@ -52,6 +52,17 @@ func (i *images) remove(img *Image) {
runtime.SetFinalizer(img, nil) runtime.SetFinalizer(img, nil)
} }
func (i *images) flushPixelsIfInconsistent(context *opengl.Context) error {
i.m.Lock()
defer i.m.Unlock()
for img := range i.images {
if err := img.flushPixelsIfInconsistent(context); err != nil {
return err
}
}
return nil
}
func (i *images) flushPixelsIfNeeded(target *Image, context *opengl.Context) error { func (i *images) flushPixelsIfNeeded(target *Image, context *opengl.Context) error {
i.m.Lock() i.m.Lock()
defer i.m.Unlock() defer i.m.Unlock()

View File

@ -199,6 +199,18 @@ func (i *imageImpl) At(x, y int, context *opengl.Context) color.Color {
return clr return clr
} }
func (i *imageImpl) flushPixelsIfInconsistent(context *opengl.Context) error {
i.m.Lock()
defer i.m.Unlock()
if i.disposed {
return nil
}
if err := i.pixels.flushIfInconsistent(i.image, context); err != nil {
return err
}
return nil
}
func (i *imageImpl) flushPixelsIfNeeded(target *Image, context *opengl.Context) error { func (i *imageImpl) flushPixelsIfNeeded(target *Image, context *opengl.Context) error {
i.m.Lock() i.m.Lock()
defer i.m.Unlock() defer i.m.Unlock()

View File

@ -15,7 +15,6 @@
package ebiten package ebiten
import ( import (
"errors"
"image" "image"
"image/color" "image/color"
@ -34,6 +33,7 @@ type drawImageHistoryItem struct {
// basePixels and baseColor are exclusive. // basePixels and baseColor are exclusive.
type pixels struct { type pixels struct {
inconsistent bool
basePixels []uint8 basePixels []uint8
baseColor color.Color baseColor color.Color
drawImageHistory []*drawImageHistoryItem drawImageHistory []*drawImageHistoryItem
@ -44,32 +44,45 @@ func (p *pixels) resetWithPixels(pixels []uint8) {
p.basePixels = make([]uint8, len(pixels)) p.basePixels = make([]uint8, len(pixels))
} }
copy(p.basePixels, pixels) copy(p.basePixels, pixels)
p.inconsistent = false
p.baseColor = nil p.baseColor = nil
p.drawImageHistory = nil p.drawImageHistory = nil
} }
func (p *pixels) clear() { func (p *pixels) clear() {
p.inconsistent = false
p.basePixels = nil p.basePixels = nil
p.baseColor = nil p.baseColor = nil
p.drawImageHistory = nil p.drawImageHistory = nil
} }
func (p *pixels) isCleared() bool { func (p *pixels) isCleared() bool {
if p.inconsistent {
return false
}
return p.basePixels == nil && p.baseColor == nil && p.drawImageHistory == nil return p.basePixels == nil && p.baseColor == nil && p.drawImageHistory == nil
} }
func (p *pixels) fill(clr color.Color) { func (p *pixels) fill(clr color.Color) {
p.inconsistent = false
p.basePixels = nil p.basePixels = nil
p.baseColor = clr p.baseColor = clr
p.drawImageHistory = nil p.drawImageHistory = nil
} }
func (p *pixels) appendDrawImageHistory(item *drawImageHistoryItem) { func (p *pixels) appendDrawImageHistory(item *drawImageHistoryItem) {
if item.image.impl.pixels.inconsistent {
p.inconsistent = true
}
if p.inconsistent {
return
}
p.drawImageHistory = append(p.drawImageHistory, item) p.drawImageHistory = append(p.drawImageHistory, item)
} }
func (p *pixels) at(image *graphics.Image, idx int, context *opengl.Context) (color.Color, error) { func (p *pixels) at(image *graphics.Image, idx int, context *opengl.Context) (color.Color, error) {
if p.basePixels == nil || p.drawImageHistory != nil { if p.inconsistent || p.basePixels == nil || p.drawImageHistory != nil {
p.inconsistent = false
var err error var err error
p.basePixels, err = image.Pixels(context) p.basePixels, err = image.Pixels(context)
if err != nil { if err != nil {
@ -91,6 +104,21 @@ func (p *pixels) hasHistoryWith(target *Image) bool {
return false return false
} }
func (p *pixels) flushIfInconsistent(image *graphics.Image, context *opengl.Context) error {
if !p.inconsistent {
return nil
}
p.inconsistent = false
var err error
p.basePixels, err = image.Pixels(context)
if err != nil {
return err
}
p.baseColor = nil
p.drawImageHistory = nil
return nil
}
func (p *pixels) flushIfNeeded(image *graphics.Image, target *Image, context *opengl.Context) error { func (p *pixels) flushIfNeeded(image *graphics.Image, target *Image, context *opengl.Context) error {
if p.drawImageHistory == nil { if p.drawImageHistory == nil {
return nil return nil
@ -99,8 +127,10 @@ func (p *pixels) flushIfNeeded(image *graphics.Image, target *Image, context *op
return nil return nil
} }
if context == nil { if context == nil {
return errors.New("ebiten: OpenGL context is missing: before running the main loop, it is forbidden to manipulate an image that is used as a drawing source once.") p.inconsistent = true
return nil
} }
p.inconsistent = false
var err error var err error
p.basePixels, err = image.Pixels(context) p.basePixels, err = image.Pixels(context)
if err != nil { if err != nil {
@ -146,6 +176,7 @@ func (p *pixels) restore(context *opengl.Context, width, height int, filter Filt
return nil, err return nil, err
} }
} }
p.inconsistent = false
p.basePixels, err = gimg.Pixels(context) p.basePixels, err = gimg.Pixels(context)
if err != nil { if err != nil {
return nil, err return nil, err