mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +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
|
screen *Image
|
||||||
screenScale float64
|
screenScale float64
|
||||||
initialized int32
|
initialized int32
|
||||||
|
invalidated bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *graphicsContext) GLContext() *opengl.Context {
|
func (c *graphicsContext) GLContext() *opengl.Context {
|
||||||
@ -45,6 +46,14 @@ func (c *graphicsContext) GLContext() *opengl.Context {
|
|||||||
return ui.GLContext()
|
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 {
|
func (c *graphicsContext) SetSize(screenWidth, screenHeight int, screenScale float64) error {
|
||||||
if c.screen != nil {
|
if c.screen != nil {
|
||||||
if err := c.screen.Dispose(); err != 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) {
|
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.
|
// FlushCommands is required because c.offscreen.impl might not have an actual texture.
|
||||||
if err := graphics.FlushCommands(context); err != nil {
|
if err := graphics.FlushCommands(context); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -178,5 +190,6 @@ func (c *graphicsContext) restore(context *opengl.Context) error {
|
|||||||
if err := theImagesForRestoring.restore(context); err != nil {
|
if err := theImagesForRestoring.restore(context); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
c.invalidated = false
|
||||||
return nil
|
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 {
|
func (i *images) restore(context *opengl.Context) error {
|
||||||
i.m.Lock()
|
i.m.Lock()
|
||||||
defer i.m.Unlock()
|
defer i.m.Unlock()
|
||||||
// Dispose all images first because framebuffer/texture numbers can be reused.
|
// Framebuffers/textures cannot be disposed since framebuffers/textures that
|
||||||
// If framebuffers/textures are not disposed here, a newly created framebuffer/texture
|
// don't belong to the current context.
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
imagesWithoutDependency := []*imageImpl{}
|
imagesWithoutDependency := []*imageImpl{}
|
||||||
imagesWithDependency := []*imageImpl{}
|
imagesWithDependency := []*imageImpl{}
|
||||||
for img := range i.images {
|
for img := range i.images {
|
||||||
|
@ -77,6 +77,7 @@ func (c *runContext) updateFPS(fps float64) {
|
|||||||
type GraphicsContext interface {
|
type GraphicsContext interface {
|
||||||
SetSize(width, height int, scale float64) error
|
SetSize(width, height int, scale float64) error
|
||||||
UpdateAndDraw(context *opengl.Context, updateCount int) error
|
UpdateAndDraw(context *opengl.Context, updateCount int) error
|
||||||
|
Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
type loopGraphicsContext struct {
|
type loopGraphicsContext struct {
|
||||||
@ -92,6 +93,10 @@ func (g *loopGraphicsContext) Update() error {
|
|||||||
return g.runContext.render(g.graphicsContext)
|
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) {
|
func Run(g GraphicsContext, width, height int, scale float64, title string, fps int) (err error) {
|
||||||
if currentRunContext != nil {
|
if currentRunContext != nil {
|
||||||
return errors.New("loop: The game is already running")
|
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 {
|
func (c *Context) IsTexture(t Texture) bool {
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
return gl.IsTexture(t.Object)
|
b := gl.IsTexture(t.Object)
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) TexSubImage2D(p []uint8, width, height int) {
|
func (c *Context) TexSubImage2D(p []uint8, width, height int) {
|
||||||
|
@ -304,13 +304,6 @@ func (p *Image) Dispose() error {
|
|||||||
return nil
|
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 {
|
func (p *Image) IsInvalidated(context *opengl.Context) bool {
|
||||||
return p.image.IsInvalidated(context)
|
return p.image.IsInvalidated(context)
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package ui
|
|||||||
type GraphicsContext interface {
|
type GraphicsContext interface {
|
||||||
SetSize(width, height int, scale float64) error
|
SetSize(width, height int, scale float64) error
|
||||||
Update() error
|
Update() error
|
||||||
|
Invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegularTermination struct {
|
type RegularTermination struct {
|
||||||
|
@ -74,6 +74,7 @@ func (u *userInterface) update(g GraphicsContext) error {
|
|||||||
}
|
}
|
||||||
if glContext.IsContextLost() {
|
if glContext.IsContextLost() {
|
||||||
glContext.RestoreContext()
|
glContext.RestoreContext()
|
||||||
|
g.Invalidate()
|
||||||
}
|
}
|
||||||
currentInput.updateGamepads()
|
currentInput.updateGamepads()
|
||||||
if u.sizeChanged {
|
if u.sizeChanged {
|
||||||
|
Loading…
Reference in New Issue
Block a user