mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +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 (
|
import (
|
||||||
"math"
|
"math"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newGraphicsContext(f func(*Image) error) *graphicsContext {
|
func newGraphicsContext(f func(*Image) error) *graphicsContext {
|
||||||
@ -33,7 +35,14 @@ type graphicsContext struct {
|
|||||||
offscreen2 *Image // TODO: better name
|
offscreen2 *Image // TODO: better name
|
||||||
screen *Image
|
screen *Image
|
||||||
screenScale float64
|
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 {
|
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 {
|
func (c *graphicsContext) initializeIfNeeded(context *opengl.Context) error {
|
||||||
if !c.initialized {
|
if atomic.LoadInt32(&c.initialized) == 0 {
|
||||||
if err := graphics.Reset(context); err != nil {
|
if err := graphics.Reset(context); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.initialized = true
|
atomic.StoreInt32(&c.initialized, 1)
|
||||||
}
|
}
|
||||||
r, err := c.needsRestoring(context)
|
r, err := c.needsRestoring(context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
25
image.go
25
image.go
@ -21,9 +21,20 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
"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 {
|
type images struct {
|
||||||
images map[*imageImpl]struct{}
|
images map[*imageImpl]struct{}
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
@ -141,7 +152,7 @@ func (i *Image) Size() (width, height int) {
|
|||||||
//
|
//
|
||||||
// This function is concurrent-safe.
|
// This function is concurrent-safe.
|
||||||
func (i *Image) Clear() error {
|
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 err
|
||||||
}
|
}
|
||||||
return i.impl.Fill(color.Transparent)
|
return i.impl.Fill(color.Transparent)
|
||||||
@ -151,7 +162,7 @@ func (i *Image) Clear() error {
|
|||||||
//
|
//
|
||||||
// This function is concurrent-safe.
|
// This function is concurrent-safe.
|
||||||
func (i *Image) Fill(clr color.Color) error {
|
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 err
|
||||||
}
|
}
|
||||||
return i.impl.Fill(clr)
|
return i.impl.Fill(clr)
|
||||||
@ -174,7 +185,7 @@ func (i *Image) Fill(clr color.Color) error {
|
|||||||
//
|
//
|
||||||
// This function is concurrent-safe.
|
// This function is concurrent-safe.
|
||||||
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) error {
|
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 err
|
||||||
}
|
}
|
||||||
return i.impl.DrawImage(image, options)
|
return i.impl.DrawImage(image, options)
|
||||||
@ -202,7 +213,7 @@ func (i *Image) ColorModel() color.Model {
|
|||||||
//
|
//
|
||||||
// This function is concurrent-safe.
|
// This function is concurrent-safe.
|
||||||
func (i *Image) At(x, y int) color.Color {
|
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.
|
// 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.
|
// This function is concurrent-safe.
|
||||||
func (i *Image) Dispose() error {
|
func (i *Image) Dispose() error {
|
||||||
if err := theImagesForRestoring.flushPixelsIfNeeded(i, ui.GLContext()); err != nil {
|
if err := theImagesForRestoring.flushPixelsIfNeeded(i, glContext()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if i.impl.isDisposed() {
|
if i.impl.isDisposed() {
|
||||||
@ -229,7 +240,7 @@ func (i *Image) Dispose() error {
|
|||||||
//
|
//
|
||||||
// This function is concurrent-safe.
|
// This function is concurrent-safe.
|
||||||
func (i *Image) ReplacePixels(p []uint8) error {
|
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 err
|
||||||
}
|
}
|
||||||
return i.impl.ReplacePixels(p)
|
return i.impl.ReplacePixels(p)
|
||||||
|
4
run.go
4
run.go
@ -57,6 +57,8 @@ func IsRunningSlowly() bool {
|
|||||||
return atomic.LoadInt32(&isRunningSlowly) != 0
|
return atomic.LoadInt32(&isRunningSlowly) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var theGraphicsContext atomic.Value
|
||||||
|
|
||||||
// Run runs the game.
|
// Run runs the game.
|
||||||
// f is a function which is called at every frame.
|
// f is a function which is called at every frame.
|
||||||
// The argument (*Image) is the render target that represents the screen.
|
// 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)
|
ch := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
g := newGraphicsContext(f)
|
g := newGraphicsContext(f)
|
||||||
|
theGraphicsContext.Store(g)
|
||||||
if err := loop.Run(g, width, height, scale, title, FPS); err != nil {
|
if err := loop.Run(g, width, height, scale, title, FPS); err != nil {
|
||||||
ch <- err
|
ch <- err
|
||||||
}
|
}
|
||||||
@ -93,6 +96,7 @@ func RunWithoutMainLoop(f func(*Image) error, width, height int, scale float64,
|
|||||||
ch := make(chan error)
|
ch := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
g := newGraphicsContext(f)
|
g := newGraphicsContext(f)
|
||||||
|
theGraphicsContext.Store(g)
|
||||||
if err := loop.Run(g, width, height, scale, title, FPS); err != nil {
|
if err := loop.Run(g, width, height, scale, title, FPS); err != nil {
|
||||||
ch <- err
|
ch <- err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user