diff --git a/graphicscontext.go b/graphicscontext.go index 0c46f16b6..fa05ad9c0 100644 --- a/graphicscontext.go +++ b/graphicscontext.go @@ -132,6 +132,9 @@ func (c *graphicsContext) UpdateAndDraw(context *opengl.Context, updateCount int if err := c.initializeIfNeeded(context); err != nil { return err } + if err := theImagesForRestoring.flushPixelsIfInconsistent(context); err != nil { + return err + } for i := 0; i < updateCount; i++ { if err := theImagesForRestoring.clearVolatileImages(); err != nil { return err diff --git a/image.go b/image.go index f03f42e38..58c52c61c 100644 --- a/image.go +++ b/image.go @@ -52,6 +52,17 @@ func (i *images) remove(img *Image) { 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 { i.m.Lock() defer i.m.Unlock() diff --git a/imageimpl.go b/imageimpl.go index 80e92ee6d..adbaf41ce 100644 --- a/imageimpl.go +++ b/imageimpl.go @@ -199,6 +199,18 @@ func (i *imageImpl) At(x, y int, context *opengl.Context) color.Color { 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 { i.m.Lock() defer i.m.Unlock() diff --git a/pixels.go b/pixels.go index b093f32f3..281826337 100644 --- a/pixels.go +++ b/pixels.go @@ -15,7 +15,6 @@ package ebiten import ( - "errors" "image" "image/color" @@ -34,6 +33,7 @@ type drawImageHistoryItem struct { // basePixels and baseColor are exclusive. type pixels struct { + inconsistent bool basePixels []uint8 baseColor color.Color drawImageHistory []*drawImageHistoryItem @@ -44,32 +44,45 @@ func (p *pixels) resetWithPixels(pixels []uint8) { p.basePixels = make([]uint8, len(pixels)) } copy(p.basePixels, pixels) + p.inconsistent = false p.baseColor = nil p.drawImageHistory = nil } func (p *pixels) clear() { + p.inconsistent = false p.basePixels = nil p.baseColor = nil p.drawImageHistory = nil } func (p *pixels) isCleared() bool { + if p.inconsistent { + return false + } return p.basePixels == nil && p.baseColor == nil && p.drawImageHistory == nil } func (p *pixels) fill(clr color.Color) { + p.inconsistent = false p.basePixels = nil p.baseColor = clr p.drawImageHistory = nil } 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) } 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 p.basePixels, err = image.Pixels(context) if err != nil { @@ -91,6 +104,21 @@ func (p *pixels) hasHistoryWith(target *Image) bool { 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 { if p.drawImageHistory == nil { return nil @@ -99,8 +127,10 @@ func (p *pixels) flushIfNeeded(image *graphics.Image, target *Image, context *op return 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 p.basePixels, err = image.Pixels(context) if err != nil { @@ -146,6 +176,7 @@ func (p *pixels) restore(context *opengl.Context, width, height int, filter Filt return nil, err } } + p.inconsistent = false p.basePixels, err = gimg.Pixels(context) if err != nil { return nil, err