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) {
dim := lhs.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++ {
@ -52,7 +52,7 @@ func add(lhs, rhs, result affine) {
func mul(lhs, rhs, result affine) {
dim := lhs.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++ {

View File

@ -86,7 +86,7 @@ type textureQuads struct {
func (t *textureQuads) vertices(vertices []int16) int {
l := t.parts.Len()
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
w, h := t.width, t.height

View File

@ -22,5 +22,9 @@ import (
var glContext *opengl.Context
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
}
func NewContext() *Context {
func NewContext() (*Context, error) {
c := &Context{
Nearest: gl.NEAREST,
Linear: gl.LINEAR,
@ -74,7 +74,7 @@ func NewContext() *Context {
c.locationCache = newLocationCache()
c.funcs = make(chan func())
c.lastCompositeMode = CompositeModeUnknown
return c
return c, nil
}
func (c *Context) Loop() {
@ -96,18 +96,24 @@ func (c *Context) RunOnContextThread(f func()) {
return
}
func (c *Context) Init() {
func (c *Context) Init() error {
var err error
c.RunOnContextThread(func() {
// This initialization must be done after Loop is called.
// This is why Init is separated from NewContext.
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.
gl.Enable(gl.BLEND)
})
if err != nil {
return err
}
c.BlendFunc(CompositeModeSourceOver)
return nil
}
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) {
c.RunOnContextThread(func() {
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 {
attrib := attribLocation(gl.GetAttribLocation(uint32(p), gl.Str(location+"\x00")))
if attrib == -1 {
panic("invalid attrib location: " + location)
panic("opengl: invalid attrib location: " + location)
}
return attrib
}

View File

@ -70,7 +70,7 @@ type context struct {
lastCompositeMode CompositeMode
}
func NewContext() *Context {
func NewContext() (*Context, error) {
var gl *webgl.Context
if js.Global.Get("require") == js.Undefined {
@ -82,7 +82,7 @@ func NewContext() *Context {
PremultipliedAlpha: true,
})
if err != nil {
panic(err)
return nil, err
}
} else {
// TODO: Now Ebiten with headless-gl doesn't work well (#141).
@ -117,7 +117,7 @@ func NewContext() *Context {
c.locationCache = newLocationCache()
c.lastCompositeMode = CompositeModeUnknown
c.init()
return c
return c, nil
}
func (c *Context) init() {
@ -138,13 +138,6 @@ func (c *Context) BlendFunc(mode CompositeMode) {
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) {
gl := c.gl
t := gl.CreateTexture()

View File

@ -107,12 +107,6 @@ func (c *Context) RunOnContextThread(f func()) {
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) {
t := gl.CreateTexture()
if t.Value <= 0 {

View File

@ -18,7 +18,6 @@ package ui
import (
"errors"
"fmt"
"runtime"
"sync"
"time"
@ -48,12 +47,12 @@ func CurrentUI() *UserInterface {
return currentUI
}
func Init() *opengl.Context {
func Init() (*opengl.Context, error) {
runtime.LockOSThread()
err := glfw.Init()
if err != nil {
panic(fmt.Sprintf("glfw.Init() fails: %v", err))
return nil, err
}
glfw.WindowHint(glfw.Visible, 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.
window, err := glfw.CreateWindow(16, 16, "", nil, nil)
if err != nil {
panic(err)
return nil, err
}
u := &UserInterface{
window: window,
}
ch := make(chan struct{})
ch := make(chan error)
go func() {
runtime.LockOSThread()
u.window.MakeContextCurrent()
glfw.SwapInterval(1)
u.context = opengl.NewContext()
var err error
u.context, err = opengl.NewContext()
if err != nil {
ch <- err
}
close(ch)
u.context.Loop()
}()
currentUI = u
<-ch
u.context.Init()
if err := <-ch; err != nil {
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 {

View File

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

24
run.go
View File

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