Reduce panics (#196)

This commit is contained in:
Hajime Hoshi 2016-04-11 01:45:13 +09:00
parent e93982ffb5
commit 5a379cb7cb
9 changed files with 54 additions and 52 deletions

View File

@ -38,7 +38,7 @@ func isIdentity(ebiten affine) bool {
func add(lhs, rhs, result affine) { func add(lhs, rhs, result affine) {
dim := lhs.dim() dim := lhs.dim()
if dim != rhs.dim() { if dim != rhs.dim() {
panic("diffrent-sized matrices can't be multiplied") panic("ebiten: diffrent-sized matrices can't be multiplied")
} }
for i := 0; i < dim-1; i++ { for i := 0; i < dim-1; i++ {
@ -52,7 +52,7 @@ func add(lhs, rhs, result affine) {
func mul(lhs, rhs, result affine) { func mul(lhs, rhs, result affine) {
dim := lhs.dim() dim := lhs.dim()
if dim != rhs.dim() { if dim != rhs.dim() {
panic("diffrent-sized matrices can't be multiplied") panic("ebiten: diffrent-sized matrices can't be multiplied")
} }
for i := 0; i < dim-1; i++ { for i := 0; i < dim-1; i++ {

View File

@ -86,7 +86,7 @@ type textureQuads struct {
func (t *textureQuads) vertices(vertices []int16) int { func (t *textureQuads) vertices(vertices []int16) int {
l := t.parts.Len() l := t.parts.Len()
if len(vertices) < l*16 { if len(vertices) < l*16 {
panic(fmt.Sprintf("graphics: vertices size must be greater than %d but %d", l*16, len(vertices))) panic(fmt.Sprintf("ebiten: vertices size must be greater than %d but %d", l*16, len(vertices)))
} }
p := t.parts p := t.parts
w, h := t.width, t.height w, h := t.width, t.height

View File

@ -22,5 +22,9 @@ import (
var glContext *opengl.Context var glContext *opengl.Context
func init() { func init() {
glContext = ui.Init() var err error
glContext, err = ui.Init()
if err != nil {
panic(err)
}
} }

View File

@ -52,7 +52,7 @@ type context struct {
lastCompositeMode CompositeMode lastCompositeMode CompositeMode
} }
func NewContext() *Context { func NewContext() (*Context, error) {
c := &Context{ c := &Context{
Nearest: gl.NEAREST, Nearest: gl.NEAREST,
Linear: gl.LINEAR, Linear: gl.LINEAR,
@ -74,7 +74,7 @@ func NewContext() *Context {
c.locationCache = newLocationCache() c.locationCache = newLocationCache()
c.funcs = make(chan func()) c.funcs = make(chan func())
c.lastCompositeMode = CompositeModeUnknown c.lastCompositeMode = CompositeModeUnknown
return c return c, nil
} }
func (c *Context) Loop() { func (c *Context) Loop() {
@ -96,18 +96,24 @@ func (c *Context) RunOnContextThread(f func()) {
return return
} }
func (c *Context) Init() { func (c *Context) Init() error {
var err error
c.RunOnContextThread(func() { c.RunOnContextThread(func() {
// This initialization must be done after Loop is called. // This initialization must be done after Loop is called.
// This is why Init is separated from NewContext. // This is why Init is separated from NewContext.
if err := gl.Init(); err != nil { if err := gl.Init(); err != nil {
panic(fmt.Sprintf("opengl: initializing error %v", err)) err = fmt.Errorf("opengl: initializing error %v", err)
return
} }
// Textures' pixel formats are alpha premultiplied. // Textures' pixel formats are alpha premultiplied.
gl.Enable(gl.BLEND) gl.Enable(gl.BLEND)
}) })
if err != nil {
return err
}
c.BlendFunc(CompositeModeSourceOver) c.BlendFunc(CompositeModeSourceOver)
return nil
} }
func (c *Context) BlendFunc(mode CompositeMode) { func (c *Context) BlendFunc(mode CompositeMode) {
@ -121,14 +127,6 @@ func (c *Context) BlendFunc(mode CompositeMode) {
}) })
} }
func (c *Context) Check() {
c.RunOnContextThread(func() {
if e := gl.GetError(); e != gl.NO_ERROR {
panic(fmt.Sprintf("check failed: %d", e))
}
})
}
func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (texture Texture, err error) { func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (texture Texture, err error) {
c.RunOnContextThread(func() { c.RunOnContextThread(func() {
var t uint32 var t uint32
@ -364,7 +362,7 @@ func (c *Context) UniformFloats(p Program, location string, v []float32) {
func (c *Context) getAttribLocation(p Program, location string) attribLocation { func (c *Context) getAttribLocation(p Program, location string) attribLocation {
attrib := attribLocation(gl.GetAttribLocation(uint32(p), gl.Str(location+"\x00"))) attrib := attribLocation(gl.GetAttribLocation(uint32(p), gl.Str(location+"\x00")))
if attrib == -1 { if attrib == -1 {
panic("invalid attrib location: " + location) panic("opengl: invalid attrib location: " + location)
} }
return attrib return attrib
} }

View File

@ -70,7 +70,7 @@ type context struct {
lastCompositeMode CompositeMode lastCompositeMode CompositeMode
} }
func NewContext() *Context { func NewContext() (*Context, error) {
var gl *webgl.Context var gl *webgl.Context
if js.Global.Get("require") == js.Undefined { if js.Global.Get("require") == js.Undefined {
@ -82,7 +82,7 @@ func NewContext() *Context {
PremultipliedAlpha: true, PremultipliedAlpha: true,
}) })
if err != nil { if err != nil {
panic(err) return nil, err
} }
} else { } else {
// TODO: Now Ebiten with headless-gl doesn't work well (#141). // TODO: Now Ebiten with headless-gl doesn't work well (#141).
@ -117,7 +117,7 @@ func NewContext() *Context {
c.locationCache = newLocationCache() c.locationCache = newLocationCache()
c.lastCompositeMode = CompositeModeUnknown c.lastCompositeMode = CompositeModeUnknown
c.init() c.init()
return c return c, nil
} }
func (c *Context) init() { func (c *Context) init() {
@ -138,13 +138,6 @@ func (c *Context) BlendFunc(mode CompositeMode) {
gl.BlendFunc(int(s), int(d)) gl.BlendFunc(int(s), int(d))
} }
func (c *Context) Check() {
gl := c.gl
if e := gl.GetError(); e != gl.NO_ERROR {
panic(fmt.Sprintf("opengl: check failed: %d", e))
}
}
func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) { func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) {
gl := c.gl gl := c.gl
t := gl.CreateTexture() t := gl.CreateTexture()

View File

@ -107,12 +107,6 @@ func (c *Context) RunOnContextThread(f func()) {
return return
} }
func (c *Context) Check() {
if e := gl.GetError(); e != mgl.NO_ERROR {
panic(fmt.Sprintf("check failed: %d", e))
}
}
func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) { func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) {
t := gl.CreateTexture() t := gl.CreateTexture()
if t.Value <= 0 { if t.Value <= 0 {

View File

@ -18,7 +18,6 @@ package ui
import ( import (
"errors" "errors"
"fmt"
"runtime" "runtime"
"sync" "sync"
"time" "time"
@ -48,12 +47,12 @@ func CurrentUI() *UserInterface {
return currentUI return currentUI
} }
func Init() *opengl.Context { func Init() (*opengl.Context, error) {
runtime.LockOSThread() runtime.LockOSThread()
err := glfw.Init() err := glfw.Init()
if err != nil { if err != nil {
panic(fmt.Sprintf("glfw.Init() fails: %v", err)) return nil, err
} }
glfw.WindowHint(glfw.Visible, glfw.False) glfw.WindowHint(glfw.Visible, glfw.False)
glfw.WindowHint(glfw.Resizable, glfw.False) glfw.WindowHint(glfw.Resizable, glfw.False)
@ -63,26 +62,34 @@ func Init() *opengl.Context {
// As start, create an window with temporary size to create OpenGL context thread. // As start, create an window with temporary size to create OpenGL context thread.
window, err := glfw.CreateWindow(16, 16, "", nil, nil) window, err := glfw.CreateWindow(16, 16, "", nil, nil)
if err != nil { if err != nil {
panic(err) return nil, err
} }
u := &UserInterface{ u := &UserInterface{
window: window, window: window,
} }
ch := make(chan struct{}) ch := make(chan error)
go func() { go func() {
runtime.LockOSThread() runtime.LockOSThread()
u.window.MakeContextCurrent() u.window.MakeContextCurrent()
glfw.SwapInterval(1) glfw.SwapInterval(1)
u.context = opengl.NewContext() var err error
u.context, err = opengl.NewContext()
if err != nil {
ch <- err
}
close(ch) close(ch)
u.context.Loop() u.context.Loop()
}() }()
currentUI = u currentUI = u
<-ch if err := <-ch; err != nil {
u.context.Init() return nil, err
}
if err := u.context.Init(); err != nil {
return nil, err
}
return u.context return u.context, nil
} }
func (u *UserInterface) SetScreenSize(width, height int) bool { func (u *UserInterface) SetScreenSize(width, height int) bool {

View File

@ -102,7 +102,7 @@ func (u *UserInterface) SwapBuffers() {
} }
} }
func Init() *opengl.Context { func Init() (*opengl.Context, error) {
// Do nothing in node.js. // Do nothing in node.js.
if js.Global.Get("require") != js.Undefined { if js.Global.Get("require") != js.Undefined {
return opengl.NewContext() return opengl.NewContext()

24
run.go
View File

@ -15,6 +15,7 @@
package ebiten package ebiten
import ( import (
"errors"
"sync" "sync"
"time" "time"
@ -104,29 +105,31 @@ func (c *runContext) updateScreenSize(g *graphicsContext) error {
return nil return nil
} }
func (c *runContext) SetScreenSize(width, height int) { func (c *runContext) SetScreenSize(width, height int) error {
c.m.Lock() c.m.Lock()
defer c.m.Unlock() defer c.m.Unlock()
if !c.isRunning { if !c.isRunning {
panic("ebiten: SetScreenSize must be called during Run") return errors.New("ebiten: SetScreenSize must be called during Run")
} }
if width <= 0 || height <= 0 { if width <= 0 || height <= 0 {
panic("ebiten: width and height must be positive") return errors.New("ebiten: width and height must be positive")
} }
c.newScreenWidth = width c.newScreenWidth = width
c.newScreenHeight = height c.newScreenHeight = height
return nil
} }
func (c *runContext) SetScreenScale(scale int) { func (c *runContext) SetScreenScale(scale int) error {
c.m.Lock() c.m.Lock()
defer c.m.Unlock() defer c.m.Unlock()
if !c.isRunning { if !c.isRunning {
panic("ebiten: SetScreenScale must be called during Run") return errors.New("ebiten: SetScreenScale must be called during Run")
} }
if scale <= 0 { if scale <= 0 {
panic("ebiten: scale must be positive") return errors.New("ebiten: scale must be positive")
} }
c.newScreenScale = scale c.newScreenScale = scale
return nil
} }
// FPS represents how many times game updating happens in a second. // FPS represents how many times game updating happens in a second.
@ -172,7 +175,6 @@ func Run(f func(*Image) error, width, height, scale int, title string) error {
} }
defer ui.CurrentUI().Terminate() defer ui.CurrentUI().Terminate()
glContext.Check()
graphicsContext, err := newGraphicsContext(width, height, ui.CurrentUI().ActualScreenScale()) graphicsContext, err := newGraphicsContext(width, height, ui.CurrentUI().ActualScreenScale())
if err != nil { if err != nil {
return err return err
@ -238,14 +240,18 @@ func Run(f func(*Image) error, width, height, scale int, title string) error {
// //
// This function is concurrent-safe. // This function is concurrent-safe.
func SetScreenSize(width, height int) { func SetScreenSize(width, height int) {
currentRunContext.SetScreenSize(width, height) if err := currentRunContext.SetScreenSize(width, height); err != nil {
panic(err)
}
} }
// SetScreenSize changes the scale of the screen. // SetScreenSize changes the scale of the screen.
// //
// This function is concurrent-safe. // This function is concurrent-safe.
func SetScreenScale(scale int) { func SetScreenScale(scale int) {
currentRunContext.SetScreenScale(scale) if err := currentRunContext.SetScreenScale(scale); err != nil {
panic(err)
}
} }
// ScreenScale returns the current screen scale. // ScreenScale returns the current screen scale.