Improve panic messages

This commit is contained in:
Hajime Hoshi 2019-02-06 22:19:24 -10:00
parent 9d291f601e
commit a3eddeb50f
22 changed files with 77 additions and 62 deletions

View File

@ -320,7 +320,7 @@ func NewPlayerFromBytes(context *Context, src []byte) (*Player, error) {
p, err := NewPlayer(context, b)
if err != nil {
// Errors should never happen.
panic(err)
panic(fmt.Sprintf("audio: %v at NewPlayerFromBytes", err))
}
return p, nil
}
@ -418,7 +418,7 @@ func (p *playerImpl) readLoop() {
case s := <-p.seekCh:
seeker, ok := p.src.(io.Seeker)
if !ok {
panic("not reached")
panic("audio: the source must be io.Seeker when seeking")
}
pos, err := seeker.Seek(s.offset, s.whence)
p.buf = nil

View File

@ -75,7 +75,7 @@ func (i *InfiniteLoop) Read(b []byte) (int, error) {
n, err := i.src.Read(b)
i.pos += int64(n)
if i.pos > i.length() {
panic("not reached")
panic(fmt.Sprintf("audio: position must be <= length but not at (*InfiniteLoop).Read: pos: %d, length: %d", i.pos, i.length()))
}
if err != nil && err != io.EOF {

View File

@ -69,7 +69,7 @@ func (s *Samples) Read(buf []float32) (int, error) {
start = 0
}
if len(s.samples[idx]) == 0 {
panic("not reached")
panic(fmt.Sprintf("stb: len(samples[%d]) must be > 0", idx))
}
n := copy(buf, s.samples[idx][start:])
s.posInSamples += int64(n) / int64(s.channels)

View File

@ -15,6 +15,7 @@
package ebiten
import (
"fmt"
"math"
"github.com/hajimehoshi/ebiten/internal/clock"
@ -121,7 +122,7 @@ func (c *graphicsContext) Update(afterFrameUpdate func()) error {
op := &DrawImageOptions{}
switch graphicscommand.Driver().VDirection() {
switch vd := graphicscommand.Driver().VDirection(); vd {
case graphicsdriver.VDownward:
// c.screen is special: its Y axis is down to up,
// and the origin point is lower left.
@ -130,7 +131,7 @@ func (c *graphicsContext) Update(afterFrameUpdate func()) error {
case graphicsdriver.VUpward:
op.GeoM.Scale(c.screenScale, c.screenScale)
default:
panic("not reached")
panic(fmt.Sprintf("ebiten: invalid v-direction: %d", vd))
}
op.GeoM.Translate(c.offsetX, c.offsetY)

View File

@ -44,7 +44,7 @@ func (m *mipmap) original() *shareable.Image {
func (m *mipmap) level(r image.Rectangle, level int) *shareable.Image {
if level == 0 {
panic("not reached")
panic("ebiten: level must not be 0 (original image) at level")
}
imgs, ok := m.imgs[r]
@ -182,7 +182,7 @@ func (i *Image) Fill(clr color.Color) error {
// TODO: Implement this.
if i.isSubimage() {
panic("render to a subimage is not implemented")
panic("ebiten: render to a subimage is not implemented (Fill)")
}
i.resolvePixelsToSet(false)
@ -196,7 +196,7 @@ func (i *Image) Fill(clr color.Color) error {
func (i *Image) disposeMipmaps() {
if i.isDisposed() {
panic("not reached")
panic("ebiten: the image is already disposed at disposeMipmap")
}
i.mipmap.disposeMipmaps()
}
@ -254,7 +254,7 @@ func (i *Image) drawImage(img *Image, options *DrawImageOptions) {
// TODO: Implement this.
if i.isSubimage() {
panic("render to a subimage is not implemented")
panic("ebiten: render to a subimage is not implemented (drawImage)")
}
img.resolvePixelsToSet(true)
@ -326,7 +326,7 @@ func (i *Image) drawImage(img *Image, options *DrawImageOptions) {
}
level = graphics.MipmapLevel(det)
if level < 0 {
panic("not reached")
panic(fmt.Sprintf("ebiten: level must be >= 0 but %d", level))
}
}
if level > 6 {
@ -443,7 +443,7 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
}
if i.isSubimage() {
panic("render to a subimage is not implemented")
panic("ebiten: render to a subimage is not implemented (DrawTriangles)")
}
img.resolvePixelsToSet(true)
@ -663,7 +663,7 @@ func (i *Image) ReplacePixels(p []byte) error {
}
// TODO: Implement this.
if i.isSubimage() {
panic("render to a subimage is not implemented")
panic("ebiten: render to a subimage is not implemented (ReplacePixels)")
}
i.resolvePixelsToSet(false)
s := i.Bounds().Size()

View File

@ -14,6 +14,10 @@
package graphics
import (
"fmt"
)
type CompositeMode int
const (
@ -75,6 +79,6 @@ func (c CompositeMode) Operations() (src Operation, dst Operation) {
case CompositeModeLighter:
return One, One
default:
panic("not reached")
panic(fmt.Sprintf("graphics: invalid composite mode: %d", c))
}
}

View File

@ -15,6 +15,7 @@
package graphics
import (
"fmt"
"sync"
)
@ -36,7 +37,7 @@ const (
func (v *verticesBackend) slice(n int) []float32 {
const num = 1024
if n > num {
panic("not reached")
panic(fmt.Sprintf("graphics: n must be <= num but not: n: %d, num: %d", n, num))
}
v.m.Lock()
@ -67,10 +68,10 @@ func isPowerOf2(x int) bool {
func QuadVertices(width, height int, sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32) []float32 {
if !isPowerOf2(width) {
panic("not reached")
panic(fmt.Sprintf("graphics: width must be power of 2 but not at QuadVertices: %d", width))
}
if !isPowerOf2(height) {
panic("not reached")
panic(fmt.Sprintf("graphics: height must be power of 2 but not at QuadVertices: %d", height))
}
if sx0 >= sx1 || sy0 >= sy1 {
@ -166,10 +167,10 @@ func QuadIndices() []uint16 {
func PutVertex(vs []float32, width, height int, dx, dy, su, sv float32, u0, v0, u1, v1 float32, cr, cg, cb, ca float32) {
if !isPowerOf2(width) {
panic("not reached")
panic(fmt.Sprintf("graphics: width must be power of 2 but not at PutVertices: %d", width))
}
if !isPowerOf2(height) {
panic("not reached")
panic(fmt.Sprintf("graphics: height must be power of 2 but not at PutVertices: %d", height))
}
vs[0] = dx

View File

@ -89,7 +89,7 @@ func (q *commandQueue) appendIndices(indices []uint16, offset uint16) {
func (q *commandQueue) doEnqueueDrawImageCommand(dst, src *Image, nvertices, nindices int, color *affine.ColorM, mode graphics.CompositeMode, filter graphics.Filter, address graphics.Address, forceNewCommand bool) {
if nindices > graphics.IndicesNum {
panic("not reached")
panic(fmt.Sprintf("graphicscommand: nindices must be <= graphics.IndicesNum but not at doEnqueueDrawImageCommand: nindices: %d, graphics.IndicesNum: %d", nindices, graphics.IndicesNum))
}
if !forceNewCommand && 0 < len(q.commands) {
if last := q.commands[len(q.commands)-1]; last.CanMerge(dst, src, color, mode, filter, address) {
@ -114,7 +114,7 @@ func (q *commandQueue) doEnqueueDrawImageCommand(dst, src *Image, nvertices, nin
// EnqueueDrawImageCommand enqueues a drawing-image command.
func (q *commandQueue) EnqueueDrawImageCommand(dst, src *Image, vertices []float32, indices []uint16, color *affine.ColorM, mode graphics.CompositeMode, filter graphics.Filter, address graphics.Address) {
if len(indices) > graphics.IndicesNum {
panic("not reached")
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawImageCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum))
}
split := false
@ -156,7 +156,7 @@ func (q *commandQueue) Flush() {
nc := 0
for _, c := range q.commands {
if c.NumIndices() > graphics.IndicesNum {
panic("not reached")
panic(fmt.Sprintf("graphicscommand: c.NumIndices() must be <= graphics.IndicesNum but not at Flush: c.NumIndices(): %d, graphics.IndicesNum: %d", c.NumIndices(), graphics.IndicesNum))
}
if ne+c.NumIndices() > graphics.IndicesNum {
break

View File

@ -460,7 +460,7 @@ func (d *Driver) Reset() error {
case graphics.OneMinusDstAlpha:
return mtl.BlendFactorOneMinusDestinationAlpha
default:
panic("not reached")
panic(fmt.Sprintf("metal: invalid operation: %d", c))
}
}
@ -627,7 +627,7 @@ func (i *Image) IsInvalidated() bool {
func (i *Image) syncTexture() {
mainthread.Run(func() error {
if i.driver.cb != (mtl.CommandBuffer{}) {
panic("not reached")
panic("metal: command buffer must be empty at syncTexture: flush is not called yet?")
}
cb := i.driver.cq.MakeCommandBuffer()

View File

@ -15,6 +15,8 @@
package opengl
import (
"fmt"
"github.com/hajimehoshi/ebiten/internal/graphics"
)
@ -33,7 +35,7 @@ func convertOperation(op graphics.Operation) operation {
case graphics.OneMinusDstAlpha:
return oneMinusDstAlpha
default:
panic("not reached")
panic(fmt.Sprintf("opengl: invalid operation %d at convertOperation", op))
}
}

View File

@ -391,7 +391,7 @@ func (c *context) uniformFloats(p program, location string, v []float32) {
case 16:
gl.UniformMatrix4fv(l, 1, false, (*float32)(gl.Ptr(v)))
default:
panic("not reached")
panic(fmt.Sprintf("opengl: invalid uniform floats num: %d", len(v)))
}
return nil
})

View File

@ -374,7 +374,7 @@ func (c *context) uniformFloats(p program, location string, v []float32) {
gl.Call("uniformMatrix4fv", js.Value(l), false, arr)
arr.Release()
default:
panic("not reached")
panic(fmt.Sprintf("opengl: invalid uniform floats num: %d", len(v)))
}
}

View File

@ -75,7 +75,7 @@ type contextImpl struct {
func (c *context) doWork(chDone <-chan struct{}) error {
if c.worker == nil {
panic("not reached")
panic("opengl: worker must be initialized but not")
}
// TODO: Check this is called on the rendering thread
workAvailable := c.worker.WorkAvailable()
@ -307,7 +307,7 @@ func (c *context) uniformFloats(p program, location string, v []float32) {
case 16:
gl.UniformMatrix4fv(l, v)
default:
panic("not reached")
panic(fmt.Sprintf("opengl: invalid uniform floats num: %d", len(v)))
}
}

View File

@ -87,8 +87,7 @@ func (i *Image) ensureFramebuffer() error {
func (i *Image) ReplacePixels(p []byte, x, y, width, height int) {
if i.screen {
// The screen image doesn't have a texture to replace pixels.
panic("not reached")
panic("opengl: ReplacePixels cannot be called on the screen, that doesn't have a texture")
}
// glFlush is necessary on Android.

View File

@ -80,7 +80,7 @@ func shaderStr(id shaderID) string {
src = strings.Replace(src, k, v, -1)
}
default:
panic("not reached")
panic(fmt.Sprintf("opengl: invalid shader id: %d", id))
}
checkGLSL(src)

View File

@ -14,6 +14,10 @@
package opengl
import (
"fmt"
)
type (
shaderType int
bufferType int
@ -30,6 +34,6 @@ func (d dataType) SizeInBytes() int {
case float:
return 4
default:
panic("not reached")
panic(fmt.Sprintf("opengl: invalid data type: %d", d))
}
}

View File

@ -130,7 +130,7 @@ func (p *Page) alloc(n *Node, width, height int) *Node {
return p.alloc(n.child0, width, height)
}
if n.child0 == nil || n.child1 == nil {
panic("not reached")
panic("packing: both two children must not be nil at alloc")
}
if node := p.alloc(n.child0, width, height); node != nil {
return node
@ -174,7 +174,7 @@ func (p *Page) Free(node *Node) {
return
}
if node.parent.child0 == nil || node.parent.child1 == nil {
panic("not reached: double free?")
panic("packing: both two children must not be nil at Free: double free happened?")
}
if node.parent.child0.canFree() && node.parent.child1.canFree() {
node.parent.child0 = nil

View File

@ -102,7 +102,7 @@ func NewScreenFramebufferImage(width, height int) *Image {
func (i *Image) clear() {
if i.priority {
panic("not reached")
panic("restorable: clear cannot be called on a priority image")
}
// There are not 'drawImageHistoryItem's for this image and dummyImage.
@ -250,7 +250,7 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
// DrawImage draws a given image img to the image.
func (i *Image) DrawImage(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode graphics.CompositeMode, filter graphics.Filter, address graphics.Address) {
if i.priority {
panic("not reached")
panic("restorable: DrawImage cannot be called on a priority image")
}
if len(vertices) == 0 {
return
@ -412,9 +412,8 @@ func (i *Image) restore() error {
gimg.ReplacePixels(pix, 0, 0, w, h)
}
for _, c := range i.drawImageHistory {
// All dependencies must be already resolved.
if c.image.hasDependency() {
panic("not reached")
panic("restorable: all dependencies must be already resolved but not")
}
gimg.DrawImage(c.image.image, c.vertices, c.indices, c.colorm, c.mode, c.filter, c.address)
}

View File

@ -131,7 +131,7 @@ func (i *images) makeStaleIfDependingOn(target *Image) {
func (i *images) makeStaleIfDependingOnImpl(target *Image) {
if target == nil {
panic("not reached")
panic("restorable: target must not be nil at makeStaleIfDependingOnImpl")
}
if i.lastTarget == target {
return
@ -147,7 +147,7 @@ func (i *images) makeStaleIfDependingOnImpl(target *Image) {
// Restoring means to make all *graphicscommand.Image objects have their textures and framebuffers.
func (i *images) restore() error {
if !IsRestoringEnabled() {
panic("not reached")
panic("restorable: restore cannot be called when restoring is disabled")
}
// Dispose image explicitly

View File

@ -15,6 +15,7 @@
package shareable
import (
"fmt"
"image"
"runtime"
"sync"
@ -71,7 +72,7 @@ func (b *backend) TryAlloc(width, height int) (*packing.Node, bool) {
n := b.page.Alloc(width, height)
if n == nil {
panic("not reached")
panic("shareable: Alloc result must not be nil at TryAlloc")
}
return n, true
}
@ -150,7 +151,7 @@ func (i *Image) forceShared() {
}
if !i.shareable() {
panic("not reached")
panic("shareable: forceShared cannot be called on a non-shareable image")
}
newI := NewImage(i.width, i.height)
@ -171,7 +172,7 @@ func (i *Image) forceShared() {
func (i *Image) region() (x, y, width, height int) {
if i.backend == nil {
panic("not reached")
panic("shareable: backend must not be nil: not allocated yet?")
}
if !i.isShared() {
w, h := i.backend.restorable.Size()
@ -304,7 +305,7 @@ func (i *Image) replacePixels(p []byte) {
x, y, w, h := i.region()
if p != nil {
if l := 4 * w * h; len(p) != l {
panic("not reached")
panic(fmt.Sprintf("shareable: len(p) must be %d but %d", l, len(p)))
}
}
i.backend.restorable.ReplacePixels(p, x, y, w, h)
@ -379,7 +380,7 @@ func (i *Image) dispose(markDisposed bool) {
}
}
if index == -1 {
panic("not reached")
panic("shareable: backend not found at an image being disposed")
}
theBackends = append(theBackends[:index], theBackends[index+1:]...)
}
@ -418,7 +419,7 @@ func (i *Image) shareable() bool {
func (i *Image) allocate(shareable bool) {
if i.backend != nil {
panic("not reached")
panic("shareable: the image is already allocated")
}
if !shareable || !i.shareable() {
@ -440,7 +441,7 @@ func (i *Image) allocate(shareable bool) {
size := initSize
for i.width > size || i.height > size {
if size == maxSize {
panic("not reached")
panic(fmt.Sprintf("shareable: the image being shared is too big: width: %d, height: %d", i.width, i.height))
}
size *= 2
}
@ -453,7 +454,7 @@ func (i *Image) allocate(shareable bool) {
n := b.page.Alloc(i.width, i.height)
if n == nil {
panic("not reached")
panic("shareable: Alloc result must not be nil at allocate")
}
i.backend = b
i.node = n

View File

@ -280,7 +280,7 @@ func SetScreenSize(width, height int) {
panic("ui: Run is not called yet")
}
_ = mainthread.Run(func() error {
u.setScreenSize(width, height, u.scale, u.fullscreen(), u.vsync)
u.setScreenSize(width, height, u.scale, u.isFullscreen(), u.vsync)
return nil
})
}
@ -292,7 +292,7 @@ func SetScreenScale(scale float64) bool {
}
r := false
_ = mainthread.Run(func() error {
r = u.setScreenSize(u.width, u.height, scale, u.fullscreen(), u.vsync)
r = u.setScreenSize(u.width, u.height, scale, u.isFullscreen(), u.vsync)
return nil
})
return r
@ -311,10 +311,10 @@ func ScreenScale() float64 {
return s
}
// fullscreen must be called from the main thread.
func (u *userInterface) fullscreen() bool {
// isFullscreen must be called from the main thread.
func (u *userInterface) isFullscreen() bool {
if !u.isRunning() {
panic("not reached")
panic("ui: the game must be running at isFullscreen")
}
return u.window.GetMonitor() != nil
}
@ -326,7 +326,7 @@ func IsFullscreen() bool {
}
b := false
_ = mainthread.Run(func() error {
b = u.fullscreen()
b = u.isFullscreen()
return nil
})
return b
@ -367,7 +367,7 @@ func SetVsyncEnabled(enabled bool) {
}
_ = mainthread.Run(func() error {
u := currentUI
u.setScreenSize(u.width, u.height, u.scale, u.fullscreen(), enabled)
u.setScreenSize(u.width, u.height, u.scale, u.isFullscreen(), enabled)
return nil
})
}
@ -646,7 +646,7 @@ func Run(width, height int, scale float64, title string, g GraphicsContext, main
s := glfwScale()
w := int(float64(width) / u.scale / s)
h := int(float64(height) / u.scale / s)
if u.fullscreen() {
if u.isFullscreen() {
return
}
u.reqWidth = w
@ -673,7 +673,7 @@ func (u *userInterface) glfwSize() (int, int) {
// getScale must be called from the main thread.
func (u *userInterface) getScale() float64 {
if !u.fullscreen() {
if !u.isFullscreen() {
return u.scale
}
if u.fullscreenScale == 0 {
@ -711,7 +711,7 @@ func (u *userInterface) updateGraphicsContext(g GraphicsContext) {
_ = mainthread.Run(func() error {
actualScale = u.actualScreenScale()
if u.lastActualScale != actualScale {
u.forceSetScreenSize(u.width, u.height, u.scale, u.fullscreen(), u.vsync)
u.forceSetScreenSize(u.width, u.height, u.scale, u.isFullscreen(), u.vsync)
}
u.lastActualScale = actualScale
@ -777,7 +777,7 @@ func (u *userInterface) update(g GraphicsContext) error {
_ = mainthread.Run(func() error {
w, h := u.reqWidth, u.reqHeight
if w != 0 || h != 0 {
u.setScreenSize(w, h, u.scale, u.fullscreen(), u.vsync)
u.setScreenSize(w, h, u.scale, u.isFullscreen(), u.vsync)
}
u.reqWidth = 0
u.reqHeight = 0
@ -822,7 +822,7 @@ func (u *userInterface) swapBuffers() {
// setScreenSize must be called from the main thread.
func (u *userInterface) setScreenSize(width, height int, scale float64, fullscreen bool, vsync bool) bool {
if u.width == width && u.height == height && u.scale == scale && u.fullscreen() == fullscreen && u.vsync == vsync {
if u.width == width && u.height == height && u.scale == scale && u.isFullscreen() == fullscreen && u.vsync == vsync {
return false
}
u.forceSetScreenSize(width, height, scale, fullscreen, vsync)

View File

@ -16,6 +16,10 @@
package mobile
import (
"fmt"
)
// #cgo CFLAGS: -x objective-c
// #cgo LDFLAGS: -framework Foundation -framework UIKit
//
@ -55,6 +59,6 @@ func updateTouchesOnIOSImpl(phase int, ptr int64, x, y int) {
delete(touches, id)
updateTouches()
default:
panic("not reached")
panic(fmt.Sprintf("mobile: invalid phase: %d", phase))
}
}