mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
graphics: Bug fix: GL context is not available until graphics context is initialized
This commit is contained in:
parent
e118a755f5
commit
9bbd5e89c3
@ -16,9 +16,11 @@ package ebiten
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
||||
"github.com/hajimehoshi/ebiten/internal/ui"
|
||||
)
|
||||
|
||||
func newGraphicsContext(f func(*Image) error) *graphicsContext {
|
||||
@ -33,7 +35,14 @@ type graphicsContext struct {
|
||||
offscreen2 *Image // TODO: better name
|
||||
screen *Image
|
||||
screenScale float64
|
||||
initialized bool
|
||||
initialized int32
|
||||
}
|
||||
|
||||
func (c *graphicsContext) GLContext() *opengl.Context {
|
||||
if atomic.LoadInt32(&c.initialized) == 0 {
|
||||
return nil
|
||||
}
|
||||
return ui.GLContext()
|
||||
}
|
||||
|
||||
func (c *graphicsContext) SetSize(screenWidth, screenHeight int, screenScale float64) error {
|
||||
@ -82,11 +91,11 @@ func (c *graphicsContext) needsRestoring(context *opengl.Context) (bool, error)
|
||||
}
|
||||
|
||||
func (c *graphicsContext) initializeIfNeeded(context *opengl.Context) error {
|
||||
if !c.initialized {
|
||||
if atomic.LoadInt32(&c.initialized) == 0 {
|
||||
if err := graphics.Reset(context); err != nil {
|
||||
return err
|
||||
}
|
||||
c.initialized = true
|
||||
atomic.StoreInt32(&c.initialized, 1)
|
||||
}
|
||||
r, err := c.needsRestoring(context)
|
||||
if err != nil {
|
||||
|
25
image.go
25
image.go
@ -21,9 +21,20 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
||||
"github.com/hajimehoshi/ebiten/internal/ui"
|
||||
)
|
||||
|
||||
func glContext() *opengl.Context {
|
||||
// This is called from finalizers even when the context or the program is not set.
|
||||
g, ok := theGraphicsContext.Load().(*graphicsContext)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if g == nil {
|
||||
return nil
|
||||
}
|
||||
return g.GLContext()
|
||||
}
|
||||
|
||||
type images struct {
|
||||
images map[*imageImpl]struct{}
|
||||
m sync.Mutex
|
||||
@ -141,7 +152,7 @@ func (i *Image) Size() (width, height int) {
|
||||
//
|
||||
// This function is concurrent-safe.
|
||||
func (i *Image) Clear() error {
|
||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, ui.GLContext()); err != nil {
|
||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, glContext()); err != nil {
|
||||
return err
|
||||
}
|
||||
return i.impl.Fill(color.Transparent)
|
||||
@ -151,7 +162,7 @@ func (i *Image) Clear() error {
|
||||
//
|
||||
// This function is concurrent-safe.
|
||||
func (i *Image) Fill(clr color.Color) error {
|
||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, ui.GLContext()); err != nil {
|
||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, glContext()); err != nil {
|
||||
return err
|
||||
}
|
||||
return i.impl.Fill(clr)
|
||||
@ -174,7 +185,7 @@ func (i *Image) Fill(clr color.Color) error {
|
||||
//
|
||||
// This function is concurrent-safe.
|
||||
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) error {
|
||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, ui.GLContext()); err != nil {
|
||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, glContext()); err != nil {
|
||||
return err
|
||||
}
|
||||
return i.impl.DrawImage(image, options)
|
||||
@ -202,7 +213,7 @@ func (i *Image) ColorModel() color.Model {
|
||||
//
|
||||
// This function is concurrent-safe.
|
||||
func (i *Image) At(x, y int) color.Color {
|
||||
return i.impl.At(x, y, ui.GLContext())
|
||||
return i.impl.At(x, y, glContext())
|
||||
}
|
||||
|
||||
// Dispose disposes the image data. After disposing, the image becomes invalid.
|
||||
@ -212,7 +223,7 @@ func (i *Image) At(x, y int) color.Color {
|
||||
//
|
||||
// This function is concurrent-safe.
|
||||
func (i *Image) Dispose() error {
|
||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, ui.GLContext()); err != nil {
|
||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, glContext()); err != nil {
|
||||
return err
|
||||
}
|
||||
if i.impl.isDisposed() {
|
||||
@ -229,7 +240,7 @@ func (i *Image) Dispose() error {
|
||||
//
|
||||
// This function is concurrent-safe.
|
||||
func (i *Image) ReplacePixels(p []uint8) error {
|
||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, ui.GLContext()); err != nil {
|
||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, glContext()); err != nil {
|
||||
return err
|
||||
}
|
||||
return i.impl.ReplacePixels(p)
|
||||
|
4
run.go
4
run.go
@ -57,6 +57,8 @@ func IsRunningSlowly() bool {
|
||||
return atomic.LoadInt32(&isRunningSlowly) != 0
|
||||
}
|
||||
|
||||
var theGraphicsContext atomic.Value
|
||||
|
||||
// Run runs the game.
|
||||
// f is a function which is called at every frame.
|
||||
// The argument (*Image) is the render target that represents the screen.
|
||||
@ -73,6 +75,7 @@ func Run(f func(*Image) error, width, height int, scale float64, title string) e
|
||||
ch := make(chan error)
|
||||
go func() {
|
||||
g := newGraphicsContext(f)
|
||||
theGraphicsContext.Store(g)
|
||||
if err := loop.Run(g, width, height, scale, title, FPS); err != nil {
|
||||
ch <- err
|
||||
}
|
||||
@ -93,6 +96,7 @@ func RunWithoutMainLoop(f func(*Image) error, width, height int, scale float64,
|
||||
ch := make(chan error)
|
||||
go func() {
|
||||
g := newGraphicsContext(f)
|
||||
theGraphicsContext.Store(g)
|
||||
if err := loop.Run(g, width, height, scale, title, FPS); err != nil {
|
||||
ch <- err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user