uidriver/glfw: Reduce (*thread).Call at (*Input).update

This commit is contained in:
Hajime Hoshi 2020-10-17 05:16:02 +09:00
parent 495b2b722a
commit 1864c22ad6
6 changed files with 80 additions and 89 deletions

View File

@ -22,7 +22,9 @@ import (
type UIContext interface { type UIContext interface {
Update() error Update() error
Layout(outsideWidth, outsideHeight float64) Layout(outsideWidth, outsideHeight float64)
AdjustPosition(x, y float64) (float64, float64)
// AdjustPosition can be called from a different goroutine from Update's or Layout's.
AdjustPosition(x, y float64, deviceScaleFactor float64) (float64, float64)
} }
// RegularTermination represents a regular termination. // RegularTermination represents a regular termination.

View File

@ -308,9 +308,8 @@ func (i *Input) setWheel(xoff, yoff float64) {
i.scrollY = yoff i.scrollY = yoff
} }
// update must be called from the main thread.
func (i *Input) update(window *glfw.Window, context driver.UIContext) { func (i *Input) update(window *glfw.Window, context driver.UIContext) {
var cx, cy float64
_ = i.ui.t.Call(func() error {
i.onceCallback.Do(func() { i.onceCallback.Do(func() {
window.SetCharModsCallback(func(w *glfw.Window, char rune, mods glfw.ModifierKey) { window.SetCharModsCallback(func(w *glfw.Window, char rune, mods glfw.ModifierKey) {
i.appendRuneBuffer(char) i.appendRuneBuffer(char)
@ -331,16 +330,11 @@ func (i *Input) update(window *glfw.Window, context driver.UIContext) {
for gb := range glfwMouseButtonToMouseButton { for gb := range glfwMouseButtonToMouseButton {
i.mouseButtonPressed[gb] = window.GetMouseButton(gb) == glfw.Press i.mouseButtonPressed[gb] = window.GetMouseButton(gb) == glfw.Press
} }
cx, cy = window.GetCursorPos() cx, cy := window.GetCursorPos()
// TODO: This is tricky. Rename the function? // TODO: This is tricky. Rename the function?
cx = i.ui.fromGLFWMonitorPixel(cx) cx = i.ui.fromGLFWMonitorPixel(cx)
cy = i.ui.fromGLFWMonitorPixel(cy) cy = i.ui.fromGLFWMonitorPixel(cy)
return nil cx, cy = context.AdjustPosition(cx, cy, i.ui.deviceScaleFactor())
})
cx, cy = context.AdjustPosition(cx, cy)
_ = i.ui.t.Call(func() error {
i.cursorX, i.cursorY = int(cx), int(cy) i.cursorX, i.cursorY = int(cx), int(cy)
for id := glfw.Joystick(0); id < glfw.Joystick(len(i.gamepads)); id++ { for id := glfw.Joystick(0); id < glfw.Joystick(len(i.gamepads)); id++ {
@ -383,6 +377,4 @@ func (i *Input) update(window *glfw.Window, context driver.UIContext) {
i.gamepads[id].guid = id.GetGUID() i.gamepads[id].guid = id.GetGUID()
i.gamepads[id].name = id.GetName() i.gamepads[id].name = id.GetName()
} }
return nil
})
} }

View File

@ -834,12 +834,9 @@ func (u *UserInterface) update() error {
_ = u.t.Call(func() error { _ = u.t.Call(func() error {
glfw.PollEvents() glfw.PollEvents()
return nil
})
u.input.update(u.window, u.context) u.input.update(u.window, u.context)
_ = u.t.Call(func() error {
defer hooks.ResumeAudio()
defer hooks.ResumeAudio()
for !u.isRunnableOnUnfocused() && u.window.GetAttrib(glfw.Focused) == 0 && !u.window.ShouldClose() { for !u.isRunnableOnUnfocused() && u.window.GetAttrib(glfw.Focused) == 0 && !u.window.ShouldClose() {
hooks.SuspendAudio() hooks.SuspendAudio()
// Wait for an arbitrary period to avoid busy loop. // Wait for an arbitrary period to avoid busy loop.

View File

@ -52,7 +52,7 @@ type Input struct {
} }
func (i *Input) CursorPosition() (x, y int) { func (i *Input) CursorPosition() (x, y int) {
xf, yf := i.ui.context.AdjustPosition(float64(i.cursorX), float64(i.cursorY)) xf, yf := i.ui.context.AdjustPosition(float64(i.cursorX), float64(i.cursorY), i.ui.DeviceScaleFactor())
return int(xf), int(yf) return int(xf), int(yf)
} }
@ -131,9 +131,10 @@ func (i *Input) TouchIDs() []driver.TouchID {
} }
func (i *Input) TouchPosition(id driver.TouchID) (x, y int) { func (i *Input) TouchPosition(id driver.TouchID) (x, y int) {
d := i.ui.DeviceScaleFactor()
for tid, pos := range i.touches { for tid, pos := range i.touches {
if id == tid { if id == tid {
x, y := i.ui.context.AdjustPosition(float64(pos.X), float64(pos.Y)) x, y := i.ui.context.AdjustPosition(float64(pos.X), float64(pos.Y), d)
return int(x), int(y) return int(x), int(y)
} }
} }

View File

@ -402,7 +402,7 @@ func (u *UserInterface) setGBuildSize(widthPx, heightPx int) {
} }
func (u *UserInterface) adjustPosition(x, y int) (int, int) { func (u *UserInterface) adjustPosition(x, y int) (int, int) {
xf, yf := u.context.AdjustPosition(float64(x), float64(y)) xf, yf := u.context.AdjustPosition(float64(x), float64(y), deviceScale())
return int(xf), int(yf) return int(xf), int(yf)
} }

View File

@ -112,27 +112,27 @@ func (c *uiContext) setWindowResizable(resizable bool) {
} }
} }
func (c *uiContext) screenScale() float64 { func (c *uiContext) screenScale(deviceScaleFactor float64) float64 {
if c.offscreen == nil { if c.offscreen == nil {
return 0 return 0
} }
sw, sh := c.offscreen.Size() sw, sh := c.offscreen.Size()
d := uiDriver().DeviceScaleFactor() scaleX := c.outsideWidth / float64(sw) * deviceScaleFactor
scaleX := c.outsideWidth / float64(sw) * d scaleY := c.outsideHeight / float64(sh) * deviceScaleFactor
scaleY := c.outsideHeight / float64(sh) * d
return math.Min(scaleX, scaleY) return math.Min(scaleX, scaleY)
} }
func (c *uiContext) offsets() (float64, float64) { func (c *uiContext) offsets(deviceScaleFactor float64) (float64, float64) {
if c.offscreen == nil { if c.offscreen == nil {
return 0, 0 return 0, 0
} }
sw, sh := c.offscreen.Size() sw, sh := c.offscreen.Size()
d := uiDriver().DeviceScaleFactor() s := c.screenScale(deviceScaleFactor)
s := c.screenScale()
width := float64(sw) * s width := float64(sw) * s
height := float64(sh) * s height := float64(sh) * s
return (c.outsideWidth*d - width) / 2, (c.outsideHeight*d - height) / 2 x := (c.outsideWidth*deviceScaleFactor - width) / 2
y := (c.outsideHeight*deviceScaleFactor - height) / 2
return x, y
} }
func (c *uiContext) Update() error { func (c *uiContext) Update() error {
@ -185,7 +185,7 @@ func (c *uiContext) update() error {
op := &DrawImageOptions{} op := &DrawImageOptions{}
s := c.screenScale() s := c.screenScale(uiDriver().DeviceScaleFactor())
switch vd := uiDriver().Graphics().FramebufferYDirection(); vd { switch vd := uiDriver().Graphics().FramebufferYDirection(); vd {
case driver.Upward: case driver.Upward:
op.GeoM.Scale(s, -s) op.GeoM.Scale(s, -s)
@ -197,7 +197,7 @@ func (c *uiContext) update() error {
panic(fmt.Sprintf("ebiten: invalid v-direction: %d", vd)) panic(fmt.Sprintf("ebiten: invalid v-direction: %d", vd))
} }
op.GeoM.Translate(c.offsets()) op.GeoM.Translate(c.offsets(uiDriver().DeviceScaleFactor()))
op.CompositeMode = CompositeModeCopy op.CompositeMode = CompositeModeCopy
// filterScreen works with >=1 scale, but does not well with <1 scale. // filterScreen works with >=1 scale, but does not well with <1 scale.
@ -211,9 +211,8 @@ func (c *uiContext) update() error {
return nil return nil
} }
func (c *uiContext) AdjustPosition(x, y float64) (float64, float64) { func (c *uiContext) AdjustPosition(x, y float64, deviceScaleFactor float64) (float64, float64) {
d := uiDriver().DeviceScaleFactor() ox, oy := c.offsets(deviceScaleFactor)
ox, oy := c.offsets() s := c.screenScale(deviceScaleFactor)
s := c.screenScale() return (x*deviceScaleFactor - ox) / s, (y*deviceScaleFactor - oy) / s
return (x*d - ox) / s, (y*d - oy) / s
} }