mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
Revert "internal/ui: bug fix: panic at ReadPixels before running"
This reverts commit 2f6df3d4d6
.
Reason: regression by calling (*ebiten.Image).At from a different goroutine
Updates #2820
This commit is contained in:
parent
2f6df3d4d6
commit
457f6bb964
47
internal/processtest/testdata/issue2820.go
vendored
47
internal/processtest/testdata/issue2820.go
vendored
@ -1,47 +0,0 @@
|
|||||||
// Copyright 2023 The Ebitengine Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
//go:build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e == nil {
|
|
||||||
panic("(*ebiten.Image).At before the main loop must panic but not (1)")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
done := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
select {
|
|
||||||
case <-done:
|
|
||||||
panic("(*ebiten.Image).At before the main loop must panic but not (2)")
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
panic("(*ebiten.Image).At times out unexpectedly")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
img := ebiten.NewImage(1, 1)
|
|
||||||
img.At(0, 0)
|
|
||||||
close(done)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
}
|
|
@ -154,10 +154,6 @@ func (i *Image) WritePixels(pix []byte, region image.Rectangle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) ReadPixels(pixels []byte, region image.Rectangle) {
|
func (i *Image) ReadPixels(pixels []byte, region image.Rectangle) {
|
||||||
if !i.ui.isRunning() {
|
|
||||||
panic("ui: ReadPixels cannot be called before the game starts")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the error existence and avoid unnecessary calls.
|
// Check the error existence and avoid unnecessary calls.
|
||||||
if i.ui.error() != nil {
|
if i.ui.error() != nil {
|
||||||
return
|
return
|
||||||
|
@ -200,7 +200,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) KeyName(key Key) string {
|
func (u *UserInterface) KeyName(key Key) string {
|
||||||
if !u.isRunning() {
|
if !u.running {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
||||||
|
u.context = newContext(game)
|
||||||
|
|
||||||
u.mainThread = thread.NewOSThread()
|
u.mainThread = thread.NewOSThread()
|
||||||
u.renderThread = thread.NewOSThread()
|
u.renderThread = thread.NewOSThread()
|
||||||
graphicscommand.SetRenderThread(u.renderThread)
|
graphicscommand.SetRenderThread(u.renderThread)
|
||||||
@ -36,8 +38,6 @@ func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
|||||||
u.setRunning(true)
|
u.setRunning(true)
|
||||||
defer u.setRunning(false)
|
defer u.setRunning(false)
|
||||||
|
|
||||||
u.context = newContext(game)
|
|
||||||
|
|
||||||
if err := u.initOnMainThread(options); err != nil {
|
if err := u.initOnMainThread(options); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
||||||
|
u.context = newContext(game)
|
||||||
|
|
||||||
// Initialize the main thread first so the thread is available at u.run (#809).
|
// Initialize the main thread first so the thread is available at u.run (#809).
|
||||||
u.mainThread = thread.NewNoopThread()
|
u.mainThread = thread.NewNoopThread()
|
||||||
u.renderThread = thread.NewNoopThread()
|
u.renderThread = thread.NewNoopThread()
|
||||||
@ -30,8 +32,6 @@ func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
|||||||
u.setRunning(true)
|
u.setRunning(true)
|
||||||
defer u.setRunning(false)
|
defer u.setRunning(false)
|
||||||
|
|
||||||
u.context = newContext(game)
|
|
||||||
|
|
||||||
if err := u.initOnMainThread(options); err != nil {
|
if err := u.initOnMainThread(options); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -74,8 +74,6 @@ type UserInterface struct {
|
|||||||
|
|
||||||
isScreenClearedEveryFrame int32
|
isScreenClearedEveryFrame int32
|
||||||
graphicsLibrary int32
|
graphicsLibrary int32
|
||||||
running int32
|
|
||||||
terminated int32
|
|
||||||
|
|
||||||
whiteImage *Image
|
whiteImage *Image
|
||||||
|
|
||||||
@ -178,23 +176,3 @@ func (u *UserInterface) setGraphicsLibrary(library GraphicsLibrary) {
|
|||||||
func (u *UserInterface) GraphicsLibrary() GraphicsLibrary {
|
func (u *UserInterface) GraphicsLibrary() GraphicsLibrary {
|
||||||
return GraphicsLibrary(atomic.LoadInt32(&u.graphicsLibrary))
|
return GraphicsLibrary(atomic.LoadInt32(&u.graphicsLibrary))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) isRunning() bool {
|
|
||||||
return atomic.LoadInt32(&u.running) != 0 && !u.isTerminated()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UserInterface) setRunning(running bool) {
|
|
||||||
if running {
|
|
||||||
atomic.StoreInt32(&u.running, 1)
|
|
||||||
} else {
|
|
||||||
atomic.StoreInt32(&u.running, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UserInterface) isTerminated() bool {
|
|
||||||
return atomic.LoadInt32(&u.terminated) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UserInterface) setTerminated() {
|
|
||||||
atomic.StoreInt32(&u.terminated, 1)
|
|
||||||
}
|
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/file"
|
"github.com/hajimehoshi/ebiten/v2/internal/file"
|
||||||
@ -60,6 +61,8 @@ type userInterfaceImpl struct {
|
|||||||
maxWindowWidthInDIP int
|
maxWindowWidthInDIP int
|
||||||
maxWindowHeightInDIP int
|
maxWindowHeightInDIP int
|
||||||
|
|
||||||
|
running uint32
|
||||||
|
terminated uint32
|
||||||
runnableOnUnfocused bool
|
runnableOnUnfocused bool
|
||||||
fpsMode FPSModeType
|
fpsMode FPSModeType
|
||||||
iconImages []image.Image
|
iconImages []image.Image
|
||||||
@ -283,6 +286,26 @@ func (u *UserInterface) Monitor() *Monitor {
|
|||||||
return monitor
|
return monitor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *UserInterface) isRunning() bool {
|
||||||
|
return atomic.LoadUint32(&u.running) != 0 && !u.isTerminated()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserInterface) isTerminated() bool {
|
||||||
|
return atomic.LoadUint32(&u.terminated) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserInterface) setRunning(running bool) {
|
||||||
|
if running {
|
||||||
|
atomic.StoreUint32(&u.running, 1)
|
||||||
|
} else {
|
||||||
|
atomic.StoreUint32(&u.running, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserInterface) setTerminated() {
|
||||||
|
atomic.StoreUint32(&u.terminated, 1)
|
||||||
|
}
|
||||||
|
|
||||||
// setWindowMonitor must be called on the main thread.
|
// setWindowMonitor must be called on the main thread.
|
||||||
func (u *UserInterface) setWindowMonitor(monitor *Monitor) error {
|
func (u *UserInterface) setWindowMonitor(monitor *Monitor) error {
|
||||||
if microsoftgdk.IsXbox() {
|
if microsoftgdk.IsXbox() {
|
||||||
|
@ -91,6 +91,7 @@ type userInterfaceImpl struct {
|
|||||||
runnableOnUnfocused bool
|
runnableOnUnfocused bool
|
||||||
fpsMode FPSModeType
|
fpsMode FPSModeType
|
||||||
renderingScheduled bool
|
renderingScheduled bool
|
||||||
|
running bool
|
||||||
cursorMode CursorMode
|
cursorMode CursorMode
|
||||||
cursorPrevMode CursorMode
|
cursorPrevMode CursorMode
|
||||||
captureCursorLater bool
|
captureCursorLater bool
|
||||||
@ -743,9 +744,6 @@ func (u *UserInterface) forceUpdateOnMinimumFPSMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
||||||
u.setRunning(true)
|
|
||||||
defer u.setRunning(false)
|
|
||||||
|
|
||||||
if !options.InitUnfocused && window.Truthy() {
|
if !options.InitUnfocused && window.Truthy() {
|
||||||
// Do not focus the canvas when the current document is in an iframe.
|
// Do not focus the canvas when the current document is in an iframe.
|
||||||
// Otherwise, the parent page tries to focus the iframe on every loading, which is annoying (#1373).
|
// Otherwise, the parent page tries to focus the iframe on every loading, which is annoying (#1373).
|
||||||
@ -754,7 +752,7 @@ func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
|||||||
canvas.Call("focus")
|
canvas.Call("focus")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
u.running = true
|
||||||
g, lib, err := newGraphicsDriver(&graphicsDriverCreatorImpl{
|
g, lib, err := newGraphicsDriver(&graphicsDriverCreatorImpl{
|
||||||
canvas: canvas,
|
canvas: canvas,
|
||||||
}, options.GraphicsLibrary)
|
}, options.GraphicsLibrary)
|
||||||
|
@ -269,6 +269,8 @@ func (u *UserInterface) run(game Game, mainloop bool, options *RunOptions) (err
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
u.context = newContext(game)
|
||||||
|
|
||||||
var mgl gl.Context
|
var mgl gl.Context
|
||||||
if mainloop {
|
if mainloop {
|
||||||
// When gomobile-build is used, GL functions must be called via
|
// When gomobile-build is used, GL functions must be called via
|
||||||
@ -279,11 +281,6 @@ func (u *UserInterface) run(game Game, mainloop bool, options *RunOptions) (err
|
|||||||
graphicscommand.SetRenderThread(u.renderThread)
|
graphicscommand.SetRenderThread(u.renderThread)
|
||||||
}
|
}
|
||||||
|
|
||||||
u.setRunning(true)
|
|
||||||
defer u.setRunning(false)
|
|
||||||
|
|
||||||
u.context = newContext(game)
|
|
||||||
|
|
||||||
g, lib, err := newGraphicsDriver(&graphicsDriverCreatorImpl{
|
g, lib, err := newGraphicsDriver(&graphicsDriverCreatorImpl{
|
||||||
gomobileContext: mgl,
|
gomobileContext: mgl,
|
||||||
}, options.GraphicsLibrary)
|
}, options.GraphicsLibrary)
|
||||||
|
@ -84,15 +84,7 @@ func (u *UserInterface) init() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
||||||
u.mainThread = thread.NewOSThread()
|
|
||||||
u.renderThread = thread.NewOSThread()
|
|
||||||
graphicscommand.SetRenderThread(u.renderThread)
|
|
||||||
|
|
||||||
u.setRunning(true)
|
|
||||||
defer u.setRunning(false)
|
|
||||||
|
|
||||||
u.context = newContext(game)
|
u.context = newContext(game)
|
||||||
|
|
||||||
g, lib, err := newGraphicsDriver(&graphicsDriverCreatorImpl{}, options.GraphicsLibrary)
|
g, lib, err := newGraphicsDriver(&graphicsDriverCreatorImpl{}, options.GraphicsLibrary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -107,6 +99,10 @@ func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
|||||||
|
|
||||||
initializeProfiler()
|
initializeProfiler()
|
||||||
|
|
||||||
|
u.mainThread = thread.NewOSThread()
|
||||||
|
u.renderThread = thread.NewOSThread()
|
||||||
|
graphicscommand.SetRenderThread(u.renderThread)
|
||||||
|
|
||||||
ctx, cancel := stdcontext.WithCancel(stdcontext.Background())
|
ctx, cancel := stdcontext.WithCancel(stdcontext.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -64,9 +64,6 @@ func (u *UserInterface) init() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
||||||
u.setRunning(true)
|
|
||||||
defer u.setRunning(false)
|
|
||||||
|
|
||||||
// TODO: Implement this.
|
// TODO: Implement this.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user