internal/ui: move the error handlings to the ui package

This commit is contained in:
Hajime Hoshi 2022-03-20 16:26:26 +09:00
parent bd07f6246f
commit 673556d03f
5 changed files with 43 additions and 49 deletions

View File

@ -17,7 +17,3 @@ package ebiten
var ( var (
ImageToBytes = imageToBytes ImageToBytes = imageToBytes
) )
func PanicOnErrorAtImageAt() {
panicOnErrorAtImageAt = true
}

View File

@ -25,10 +25,6 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/ui" "github.com/hajimehoshi/ebiten/v2/internal/ui"
) )
// panicOnErrorAtImageAt indicates whether (*Image).At panics on an error or not.
// This value is set only on testing.
var panicOnErrorAtImageAt bool
// Image represents a rectangle set of pixels. // Image represents a rectangle set of pixels.
// The pixel format is alpha-premultiplied RGBA. // The pixel format is alpha-premultiplied RGBA.
// Image implements image.Image and draw.Image. // Image implements image.Image and draw.Image.
@ -716,24 +712,14 @@ func (i *Image) RGBA64At(x, y int) color.RGBA64 {
} }
func (i *Image) at(x, y int) (r, g, b, a uint8) { func (i *Image) at(x, y int) (r, g, b, a uint8) {
// Check the error existence and avoid unnecessary calls.
// TODO: The package ui should have an image struct that treats errors correctly.
if ui.HasError() {
return 0, 0, 0, 0
}
if i.isDisposed() { if i.isDisposed() {
return 0, 0, 0, 0 return 0, 0, 0, 0
} }
if !image.Pt(x, y).In(i.Bounds()) { if !image.Pt(x, y).In(i.Bounds()) {
return 0, 0, 0, 0 return 0, 0, 0, 0
} }
pix, err := i.image.Pixels(x, y, 1, 1) pix := i.image.Pixels(x, y, 1, 1)
if err != nil { if len(pix) == 0 {
if panicOnErrorAtImageAt {
panic(err)
}
ui.SetError(err)
return 0, 0, 0, 0 return 0, 0, 0, 0
} }
return pix[0], pix[1], pix[2], pix[3] return pix[0], pix[1], pix[2], pix[3]
@ -747,10 +733,6 @@ func (i *Image) at(x, y int) (r, g, b, a uint8) {
// //
// If the image is disposed, Set does nothing. // If the image is disposed, Set does nothing.
func (i *Image) Set(x, y int, clr color.Color) { func (i *Image) Set(x, y int, clr color.Color) {
if ui.HasError() {
return
}
i.copyCheck() i.copyCheck()
if i.isDisposed() { if i.isDisposed() {
return return
@ -764,9 +746,7 @@ func (i *Image) Set(x, y int, clr color.Color) {
r, g, b, a := clr.RGBA() r, g, b, a := clr.RGBA()
pix := []byte{byte(r >> 8), byte(g >> 8), byte(b >> 8), byte(a >> 8)} pix := []byte{byte(r >> 8), byte(g >> 8), byte(b >> 8), byte(a >> 8)}
if err := i.image.ReplaceSmallRegionPixels(pix, x, y, 1, 1); err != nil { i.image.ReplaceSmallRegionPixels(pix, x, y, 1, 1)
ui.SetError(err)
}
} }
// Dispose disposes the image data. // Dispose disposes the image data.
@ -802,10 +782,6 @@ func (i *Image) Dispose() {
// //
// When the image is disposed, ReplacePixels does nothing. // When the image is disposed, ReplacePixels does nothing.
func (i *Image) ReplacePixels(pixels []byte) { func (i *Image) ReplacePixels(pixels []byte) {
if ui.HasError() {
return
}
i.copyCheck() i.copyCheck()
if i.isDisposed() { if i.isDisposed() {
@ -816,9 +792,7 @@ func (i *Image) ReplacePixels(pixels []byte) {
// Do not need to copy pixels here. // Do not need to copy pixels here.
// * In internal/mipmap, pixels are copied when necessary. // * In internal/mipmap, pixels are copied when necessary.
// * In internal/atlas, pixels are copied to make its paddings. // * In internal/atlas, pixels are copied to make its paddings.
if err := i.image.ReplaceLargeRegionPixels(pixels, r.Min.X, r.Min.Y, r.Dx(), r.Dy()); err != nil { i.image.ReplaceLargeRegionPixels(pixels, r.Min.X, r.Min.Y, r.Dx(), r.Dy())
ui.SetError(err)
}
} }
// NewImage returns an empty image. // NewImage returns an empty image.

View File

@ -31,6 +31,7 @@ import (
"github.com/hajimehoshi/ebiten/v2/examples/resources/images" "github.com/hajimehoshi/ebiten/v2/examples/resources/images"
"github.com/hajimehoshi/ebiten/v2/internal/graphics" "github.com/hajimehoshi/ebiten/v2/internal/graphics"
t "github.com/hajimehoshi/ebiten/v2/internal/testing" t "github.com/hajimehoshi/ebiten/v2/internal/testing"
"github.com/hajimehoshi/ebiten/v2/internal/ui"
) )
// maxImageSize is a maximum image size that should work in almost every environment. // maxImageSize is a maximum image size that should work in almost every environment.
@ -53,7 +54,7 @@ func skipTooSlowTests(t *testing.T) bool {
} }
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
ebiten.PanicOnErrorAtImageAt() ui.SetPanicOnErrorAtImageAtForTesting(true)
t.MainWithRunLoop(m) t.MainWithRunLoop(m)
} }

View File

@ -242,14 +242,6 @@ func (g *globalState) setScreenFilterEnabled(enabled bool) {
atomic.StoreInt32(&g.screenFilterEnabled_, v) atomic.StoreInt32(&g.screenFilterEnabled_, v)
} }
func HasError() bool {
return theGlobalState.error() != nil
}
func SetError(err error) {
theGlobalState.setError(err)
}
func FPSMode() FPSModeType { func FPSMode() FPSModeType {
return theGlobalState.fpsMode() return theGlobalState.fpsMode()
} }

View File

@ -22,6 +22,14 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/mipmap" "github.com/hajimehoshi/ebiten/v2/internal/mipmap"
) )
// panicOnErrorAtImageAt indicates whether (*Image).At panics on an error or not.
// This value is set only on testing.
var panicOnErrorAtImageAt bool
func SetPanicOnErrorAtImageAtForTesting(value bool) {
panicOnErrorAtImageAt = value
}
type Image struct { type Image struct {
mipmap *mipmap.Mipmap mipmap *mipmap.Mipmap
} }
@ -60,16 +68,39 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
i.mipmap.DrawTriangles(srcMipmaps, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, s, uniforms, evenOdd, canSkipMipmap) i.mipmap.DrawTriangles(srcMipmaps, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, s, uniforms, evenOdd, canSkipMipmap)
} }
func (i *Image) ReplaceLargeRegionPixels(pix []byte, x, y, width, height int) error { func (i *Image) ReplaceLargeRegionPixels(pix []byte, x, y, width, height int) {
return i.mipmap.ReplaceLargeRegionPixels(pix, x, y, width, height) if theGlobalState.error() != nil {
return
}
if err := i.mipmap.ReplaceLargeRegionPixels(pix, x, y, width, height); err != nil {
theGlobalState.setError(err)
}
} }
func (i *Image) ReplaceSmallRegionPixels(pix []byte, x, y, width, height int) error { func (i *Image) ReplaceSmallRegionPixels(pix []byte, x, y, width, height int) {
return i.mipmap.ReplaceSmallRegionPixels(graphicsDriver(), pix, x, y, width, height) if theGlobalState.error() != nil {
return
}
if err := i.mipmap.ReplaceSmallRegionPixels(graphicsDriver(), pix, x, y, width, height); err != nil {
theGlobalState.setError(err)
}
} }
func (i *Image) Pixels(x, y, width, height int) ([]byte, error) { func (i *Image) Pixels(x, y, width, height int) []byte {
return i.mipmap.Pixels(graphicsDriver(), x, y, width, height) // Check the error existence and avoid unnecessary calls.
if theGlobalState.error() != nil {
return nil
}
pix, err := i.mipmap.Pixels(graphicsDriver(), x, y, width, height)
if err != nil {
if panicOnErrorAtImageAt {
panic(err)
}
theGlobalState.setError(err)
return nil
}
return pix
} }
func (i *Image) DumpScreenshot(name string, blackbg bool) error { func (i *Image) DumpScreenshot(name string, blackbg bool) error {