mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
graphcis: Bug fix: Can't dispose textures/framebuffers after the context is lost (fixing #305)
This commit is contained in:
parent
d3e1f91511
commit
6e897d1479
@ -36,6 +36,7 @@ type graphicsContext struct {
|
||||
screen *Image
|
||||
screenScale float64
|
||||
initialized int32
|
||||
invalidated bool
|
||||
}
|
||||
|
||||
func (c *graphicsContext) GLContext() *opengl.Context {
|
||||
@ -45,6 +46,14 @@ func (c *graphicsContext) GLContext() *opengl.Context {
|
||||
return ui.GLContext()
|
||||
}
|
||||
|
||||
func (c *graphicsContext) Invalidate() {
|
||||
// Note that this is called only on browsers so far.
|
||||
// TODO: On mobiles, this function is not called and instead IsTexture is called
|
||||
// to detect if the context is lost. This is simple but might not work on some platforms.
|
||||
// Should Invalidate be called explicitly?
|
||||
c.invalidated = true
|
||||
}
|
||||
|
||||
func (c *graphicsContext) SetSize(screenWidth, screenHeight int, screenScale float64) error {
|
||||
if c.screen != nil {
|
||||
if err := c.screen.Dispose(); err != nil {
|
||||
@ -91,6 +100,9 @@ func (c *graphicsContext) SetSize(screenWidth, screenHeight int, screenScale flo
|
||||
}
|
||||
|
||||
func (c *graphicsContext) needsRestoring(context *opengl.Context) (bool, error) {
|
||||
if c.invalidated {
|
||||
return true, nil
|
||||
}
|
||||
// FlushCommands is required because c.offscreen.impl might not have an actual texture.
|
||||
if err := graphics.FlushCommands(context); err != nil {
|
||||
return false, err
|
||||
@ -178,5 +190,6 @@ func (c *graphicsContext) restore(context *opengl.Context) error {
|
||||
if err := theImagesForRestoring.restore(context); err != nil {
|
||||
return err
|
||||
}
|
||||
c.invalidated = false
|
||||
return nil
|
||||
}
|
||||
|
13
image.go
13
image.go
@ -94,17 +94,8 @@ func (i *images) resetPixelsIfDependingOn(target *Image, context *opengl.Context
|
||||
func (i *images) restore(context *opengl.Context) error {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
// Dispose all images first because framebuffer/texture numbers can be reused.
|
||||
// If framebuffers/textures are not disposed here, a newly created framebuffer/texture
|
||||
// number can be a same number as existing one.
|
||||
for img := range i.images {
|
||||
if img.isDisposed() {
|
||||
continue
|
||||
}
|
||||
if err := img.restorable.DisposeOnlyImage(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Framebuffers/textures cannot be disposed since framebuffers/textures that
|
||||
// don't belong to the current context.
|
||||
imagesWithoutDependency := []*imageImpl{}
|
||||
imagesWithDependency := []*imageImpl{}
|
||||
for img := range i.images {
|
||||
|
@ -77,6 +77,7 @@ func (c *runContext) updateFPS(fps float64) {
|
||||
type GraphicsContext interface {
|
||||
SetSize(width, height int, scale float64) error
|
||||
UpdateAndDraw(context *opengl.Context, updateCount int) error
|
||||
Invalidate()
|
||||
}
|
||||
|
||||
type loopGraphicsContext struct {
|
||||
@ -92,6 +93,10 @@ func (g *loopGraphicsContext) Update() error {
|
||||
return g.runContext.render(g.graphicsContext)
|
||||
}
|
||||
|
||||
func (g *loopGraphicsContext) Invalidate() {
|
||||
g.graphicsContext.Invalidate()
|
||||
}
|
||||
|
||||
func Run(g GraphicsContext, width, height int, scale float64, title string, fps int) (err error) {
|
||||
if currentRunContext != nil {
|
||||
return errors.New("loop: The game is already running")
|
||||
|
@ -220,7 +220,8 @@ func (c *Context) DeleteTexture(t Texture) {
|
||||
|
||||
func (c *Context) IsTexture(t Texture) bool {
|
||||
gl := c.gl
|
||||
return gl.IsTexture(t.Object)
|
||||
b := gl.IsTexture(t.Object)
|
||||
return b
|
||||
}
|
||||
|
||||
func (c *Context) TexSubImage2D(p []uint8, width, height int) {
|
||||
|
@ -304,13 +304,6 @@ func (p *Image) Dispose() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Image) DisposeOnlyImage() error {
|
||||
if err := p.image.Dispose(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Image) IsInvalidated(context *opengl.Context) bool {
|
||||
return p.image.IsInvalidated(context)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package ui
|
||||
type GraphicsContext interface {
|
||||
SetSize(width, height int, scale float64) error
|
||||
Update() error
|
||||
Invalidate()
|
||||
}
|
||||
|
||||
type RegularTermination struct {
|
||||
|
@ -74,6 +74,7 @@ func (u *userInterface) update(g GraphicsContext) error {
|
||||
}
|
||||
if glContext.IsContextLost() {
|
||||
glContext.RestoreContext()
|
||||
g.Invalidate()
|
||||
}
|
||||
currentInput.updateGamepads()
|
||||
if u.sizeChanged {
|
||||
|
Loading…
Reference in New Issue
Block a user