mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
internal/graphicsdriver/metal: replace Get with NewGraphics
This is a prepartion to return an error when a graphics driver, especially DirectX, fails to initialize. Updates #2142
This commit is contained in:
parent
a6d415ebf2
commit
7484df0c5e
@ -19,7 +19,6 @@ import (
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
@ -347,18 +346,11 @@ const (
|
||||
noStencil
|
||||
)
|
||||
|
||||
var (
|
||||
// isMetalAvailable reports whether Metal is available or not.
|
||||
isMetalAvailable bool
|
||||
isMetalAvailableOnce sync.Once
|
||||
)
|
||||
|
||||
var theGraphics Graphics
|
||||
|
||||
func Get() *Graphics {
|
||||
isMetalAvailableOnce.Do(func() {
|
||||
// NewGraphics creates an implementation of graphicsdriver.Graphcis for Metal.
|
||||
// The returned graphics value is nil iff the error is not nil.
|
||||
func NewGraphics() (graphicsdriver.Graphics, error) {
|
||||
if !supportsMetal() {
|
||||
return
|
||||
return nil, fmt.Errorf("metal: Metal is not supported in this environment")
|
||||
}
|
||||
|
||||
// Initialize isMetalAvailable on the main thread.
|
||||
@ -368,14 +360,10 @@ func Get() *Graphics {
|
||||
// TODO: Is there a better way to check whether Metal is available or not?
|
||||
// It seems OK to call MTLCreateSystemDefaultDevice multiple times, so this should be fine.
|
||||
if _, ok := mtl.CreateSystemDefaultDevice(); !ok {
|
||||
return
|
||||
return nil, fmt.Errorf("metal: mtl.CreateSystemDefaultDevice failed")
|
||||
}
|
||||
isMetalAvailable = true
|
||||
})
|
||||
if !isMetalAvailable {
|
||||
return nil
|
||||
}
|
||||
return &theGraphics
|
||||
|
||||
return &Graphics{}, nil
|
||||
}
|
||||
|
||||
func (g *Graphics) Begin() error {
|
||||
|
@ -21,19 +21,19 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
)
|
||||
|
||||
type graphicsDriverGetter interface {
|
||||
type graphicsDriverCreator interface {
|
||||
newAuto() (graphicsdriver.Graphics, error)
|
||||
newOpenGL() (graphicsdriver.Graphics, error)
|
||||
getDirectX() graphicsdriver.Graphics
|
||||
getMetal() graphicsdriver.Graphics
|
||||
newMetal() (graphicsdriver.Graphics, error)
|
||||
}
|
||||
|
||||
func chooseGraphicsDriver(getter graphicsDriverGetter) (graphicsdriver.Graphics, error) {
|
||||
func chooseGraphicsDriver(creator graphicsDriverCreator) (graphicsdriver.Graphics, error) {
|
||||
const envName = "EBITEN_GRAPHICS_LIBRARY"
|
||||
|
||||
switch env := os.Getenv(envName); env {
|
||||
case "", "auto":
|
||||
g, err := getter.newAuto()
|
||||
g, err := creator.newAuto()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -42,7 +42,7 @@ func chooseGraphicsDriver(getter graphicsDriverGetter) (graphicsdriver.Graphics,
|
||||
}
|
||||
return g, nil
|
||||
case "opengl":
|
||||
g, err := getter.newOpenGL()
|
||||
g, err := creator.newOpenGL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -51,15 +51,19 @@ func chooseGraphicsDriver(getter graphicsDriverGetter) (graphicsdriver.Graphics,
|
||||
}
|
||||
return g, nil
|
||||
case "directx":
|
||||
if g := getter.getDirectX(); g != nil {
|
||||
if g := creator.getDirectX(); g != nil {
|
||||
return g, nil
|
||||
}
|
||||
return nil, fmt.Errorf("ui: %s=%s is specified but DirectX is not available.", envName, env)
|
||||
case "metal":
|
||||
if g := getter.getMetal(); g != nil {
|
||||
return g, nil
|
||||
g, err := creator.newMetal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if g == nil {
|
||||
return nil, fmt.Errorf("ui: %s=%s is specified but Metal is not available", envName, env)
|
||||
}
|
||||
return g, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("ui: an unsupported graphics library is specified: %s", env)
|
||||
}
|
||||
|
@ -19,22 +19,22 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl"
|
||||
)
|
||||
|
||||
type graphicsDriverGetterImpl struct {
|
||||
type graphicsDriverCreatorImpl struct {
|
||||
gomobileBuild bool
|
||||
}
|
||||
|
||||
func (g *graphicsDriverGetterImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
func (g *graphicsDriverCreatorImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
return g.newOpenGL()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
func (*graphicsDriverCreatorImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
return opengl.NewGraphics()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getDirectX() graphicsdriver.Graphics {
|
||||
func (*graphicsDriverCreatorImpl) getDirectX() graphicsdriver.Graphics {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getMetal() graphicsdriver.Graphics {
|
||||
return nil
|
||||
func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -25,22 +25,22 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl"
|
||||
)
|
||||
|
||||
type graphicsDriverGetterImpl struct{}
|
||||
type graphicsDriverCreatorImpl struct{}
|
||||
|
||||
func (g *graphicsDriverGetterImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
func (g *graphicsDriverCreatorImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
return g.newOpenGL()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
func (*graphicsDriverCreatorImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
return opengl.NewGraphics()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getDirectX() graphicsdriver.Graphics {
|
||||
func (*graphicsDriverCreatorImpl) getDirectX() graphicsdriver.Graphics {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getMetal() graphicsdriver.Graphics {
|
||||
return nil
|
||||
func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
const deviceScaleFactor = 1
|
||||
@ -58,7 +58,7 @@ type userInterfaceImpl struct {
|
||||
|
||||
func (u *userInterfaceImpl) Run(game Game) error {
|
||||
u.context = newContext(game)
|
||||
g, err := chooseGraphicsDriver(&graphicsDriverGetterImpl{})
|
||||
g, err := chooseGraphicsDriver(&graphicsDriverCreatorImpl{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -834,7 +834,7 @@ func (u *userInterfaceImpl) init() error {
|
||||
}
|
||||
glfw.WindowHint(glfw.TransparentFramebuffer, glfwTransparent)
|
||||
|
||||
g, err := chooseGraphicsDriver(&graphicsDriverGetterImpl{
|
||||
g, err := chooseGraphicsDriver(&graphicsDriverCreatorImpl{
|
||||
transparent: transparent,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -248,36 +248,40 @@ package ui
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/glfw"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl"
|
||||
)
|
||||
|
||||
type graphicsDriverGetterImpl struct {
|
||||
type graphicsDriverCreatorImpl struct {
|
||||
transparent bool
|
||||
}
|
||||
|
||||
func (g *graphicsDriverGetterImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
if m := g.getMetal(); m != nil {
|
||||
func (g *graphicsDriverCreatorImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
m, err1 := g.newMetal()
|
||||
if err1 == nil {
|
||||
return m, nil
|
||||
}
|
||||
return g.newOpenGL()
|
||||
o, err2 := g.newOpenGL()
|
||||
if err2 == nil {
|
||||
return o, nil
|
||||
}
|
||||
return nil, fmt.Errorf("ui: failed to choose graphics drivers: Metal: %v, OpenGL: %v", err1, err2)
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
func (*graphicsDriverCreatorImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
return opengl.NewGraphics()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getDirectX() graphicsdriver.Graphics {
|
||||
func (*graphicsDriverCreatorImpl) getDirectX() graphicsdriver.Graphics {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getMetal() graphicsdriver.Graphics {
|
||||
if m := metal.Get(); m != nil {
|
||||
return m
|
||||
}
|
||||
return nil
|
||||
func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) {
|
||||
return metal.NewGraphics()
|
||||
}
|
||||
|
||||
// clearVideoModeScaleCache must be called from the main thread.
|
||||
|
@ -31,24 +31,24 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl"
|
||||
)
|
||||
|
||||
type graphicsDriverGetterImpl struct {
|
||||
type graphicsDriverCreatorImpl struct {
|
||||
transparent bool
|
||||
}
|
||||
|
||||
func (g *graphicsDriverGetterImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
func (g *graphicsDriverCreatorImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
return g.newOpenGL()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
func (*graphicsDriverCreatorImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
return opengl.NewGraphics()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getDirectX() graphicsdriver.Graphics {
|
||||
func (*graphicsDriverCreatorImpl) getDirectX() graphicsdriver.Graphics {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getMetal() graphicsdriver.Graphics {
|
||||
return nil
|
||||
func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type videoModeScaleCacheKey struct{ X, Y int }
|
||||
|
@ -31,22 +31,22 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/microsoftgdk"
|
||||
)
|
||||
|
||||
type graphicsDriverGetterImpl struct {
|
||||
type graphicsDriverCreatorImpl struct {
|
||||
transparent bool
|
||||
}
|
||||
|
||||
func (g *graphicsDriverGetterImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
func (g *graphicsDriverCreatorImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
if d := g.getDirectX(); d != nil {
|
||||
return d, nil
|
||||
}
|
||||
return g.newOpenGL()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
func (*graphicsDriverCreatorImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
return opengl.NewGraphics()
|
||||
}
|
||||
|
||||
func (g *graphicsDriverGetterImpl) getDirectX() graphicsdriver.Graphics {
|
||||
func (g *graphicsDriverCreatorImpl) getDirectX() graphicsdriver.Graphics {
|
||||
if g.transparent {
|
||||
return nil
|
||||
}
|
||||
@ -56,8 +56,8 @@ func (g *graphicsDriverGetterImpl) getDirectX() graphicsdriver.Graphics {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getMetal() graphicsdriver.Graphics {
|
||||
return nil
|
||||
func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -18,40 +18,42 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl"
|
||||
)
|
||||
|
||||
type graphicsDriverGetterImpl struct {
|
||||
type graphicsDriverCreatorImpl struct {
|
||||
gomobileBuild bool
|
||||
}
|
||||
|
||||
func (g *graphicsDriverGetterImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
if m := g.getMetal(); m != nil {
|
||||
func (g *graphicsDriverCreatorImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
m, err1 := g.newMetal()
|
||||
if err1 == nil {
|
||||
return m, nil
|
||||
}
|
||||
return g.newOpenGL()
|
||||
o, err2 := g.newOpenGL()
|
||||
if err2 == nil {
|
||||
return o, nil
|
||||
}
|
||||
return nil, fmt.Errorf("ui: failed to choose graphics drivers: Metal: %v, OpenGL: %v", err1, err2)
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
func (*graphicsDriverCreatorImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
return opengl.NewGraphics()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getDirectX() graphicsdriver.Graphics {
|
||||
func (*graphicsDriverCreatorImpl) getDirectX() graphicsdriver.Graphics {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *graphicsDriverGetterImpl) getMetal() graphicsdriver.Graphics {
|
||||
// When gomobile-build is used, GL functions must be called via
|
||||
// gl.Context so that they are called on the appropriate thread.
|
||||
func (g *graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) {
|
||||
if g.gomobileBuild {
|
||||
return nil
|
||||
return nil, fmt.Errorf("ui: Metal is not available with gomobile-build")
|
||||
}
|
||||
if m := metal.Get(); m != nil {
|
||||
return m
|
||||
}
|
||||
return nil
|
||||
return metal.NewGraphics()
|
||||
}
|
||||
|
||||
func SetUIView(uiview uintptr) {
|
||||
|
@ -25,22 +25,22 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/hooks"
|
||||
)
|
||||
|
||||
type graphicsDriverGetterImpl struct{}
|
||||
type graphicsDriverCreatorImpl struct{}
|
||||
|
||||
func (g *graphicsDriverGetterImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
func (g *graphicsDriverCreatorImpl) newAuto() (graphicsdriver.Graphics, error) {
|
||||
return g.newOpenGL()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
func (*graphicsDriverCreatorImpl) newOpenGL() (graphicsdriver.Graphics, error) {
|
||||
return opengl.NewGraphics()
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getDirectX() graphicsdriver.Graphics {
|
||||
func (*graphicsDriverCreatorImpl) getDirectX() graphicsdriver.Graphics {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*graphicsDriverGetterImpl) getMetal() graphicsdriver.Graphics {
|
||||
return nil
|
||||
func (*graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
@ -609,7 +609,7 @@ func (u *userInterfaceImpl) Run(game Game) error {
|
||||
}
|
||||
}
|
||||
u.running = true
|
||||
g, err := chooseGraphicsDriver(&graphicsDriverGetterImpl{})
|
||||
g, err := chooseGraphicsDriver(&graphicsDriverCreatorImpl{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ func (u *userInterfaceImpl) run(game Game, mainloop bool) (err error) {
|
||||
}()
|
||||
|
||||
u.context = newContext(game)
|
||||
g, err := chooseGraphicsDriver(&graphicsDriverGetterImpl{
|
||||
g, err := chooseGraphicsDriver(&graphicsDriverCreatorImpl{
|
||||
gomobileBuild: mainloop,
|
||||
})
|
||||
if err != nil {
|
||||
@ -279,6 +279,8 @@ func (u *userInterfaceImpl) run(game Game, mainloop bool) (err error) {
|
||||
u.graphicsDriver = g
|
||||
|
||||
if mainloop {
|
||||
// When gomobile-build is used, GL functions must be called via
|
||||
// gl.Context so that they are called on the appropriate thread.
|
||||
ctx := <-glContextCh
|
||||
g.(*opengl.Graphics).SetGomobileGLContext(ctx)
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user