mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 11:12:44 +01:00
Add AsyncGraphicsContext; Use goroutines in the main routine
This commit is contained in:
parent
6e584eb642
commit
6b1e76b669
38
ebiten.go
38
ebiten.go
@ -30,29 +30,35 @@ type InputState struct {
|
|||||||
Y int
|
Y int
|
||||||
}
|
}
|
||||||
|
|
||||||
func OpenGLRun(game Game, ui UI, screenScale int, input chan InputState) {
|
func OpenGLRun(game Game, ui UI, screenScale int, input <-chan InputState) {
|
||||||
ch := make(chan bool, 1)
|
deviceUpdate := make(chan bool)
|
||||||
|
commandSet := make(chan chan func(graphics.GraphicsContext))
|
||||||
|
|
||||||
graphicsDevice := opengl.NewDevice(
|
graphicsDevice := opengl.NewDevice(
|
||||||
game.ScreenWidth(), game.ScreenHeight(), screenScale,
|
game.ScreenWidth(), game.ScreenHeight(), screenScale, deviceUpdate, commandSet)
|
||||||
func(g graphics.GraphicsContext, offscreen graphics.Texture) {
|
|
||||||
ticket := <-ch
|
game.Init(graphicsDevice.TextureFactory())
|
||||||
game.Draw(g, offscreen)
|
|
||||||
ch <- ticket
|
|
||||||
})
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
frameTime := time.Duration(int64(time.Second) / int64(game.Fps()))
|
frameTime := time.Duration(int64(time.Second) / int64(game.Fps()))
|
||||||
tick := time.Tick(frameTime)
|
updateTick := time.Tick(frameTime)
|
||||||
for {
|
for {
|
||||||
<-tick
|
select {
|
||||||
ticket := <-ch
|
case <-updateTick:
|
||||||
inputState := <-input
|
inputState := <-input
|
||||||
game.Update(inputState)
|
game.Update(inputState)
|
||||||
ch <- ticket
|
case <-deviceUpdate:
|
||||||
|
commands := make(chan func(graphics.GraphicsContext))
|
||||||
|
commandSet <- commands
|
||||||
|
g := graphics.NewAsyncGraphicsContext(commands)
|
||||||
|
// TODO: graphicsDevice is shared by multiple goroutines.
|
||||||
|
game.Draw(g, graphicsDevice.OffscreenTexture())
|
||||||
|
close(commands)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
game.Init(graphicsDevice.TextureFactory())
|
|
||||||
ch <- true
|
// UI should be executed on the main thread.
|
||||||
ui.Run(graphicsDevice)
|
ui.Run(graphicsDevice)
|
||||||
}
|
}
|
||||||
|
57
graphics/async_graphics_context.go
Normal file
57
graphics/async_graphics_context.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package graphics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hajimehoshi/go.ebiten/graphics/matrix"
|
||||||
|
"image/color"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AsyncGraphicsContext struct {
|
||||||
|
ch chan<- func(GraphicsContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAsyncGraphicsContext(ch chan<- func(GraphicsContext)) *AsyncGraphicsContext {
|
||||||
|
return &AsyncGraphicsContext{
|
||||||
|
ch: ch,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *AsyncGraphicsContext) Clear() {
|
||||||
|
g.ch <- func(g2 GraphicsContext) {
|
||||||
|
g2.Clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *AsyncGraphicsContext) Fill(clr color.Color) {
|
||||||
|
g.ch <- func(g2 GraphicsContext) {
|
||||||
|
g2.Fill(clr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *AsyncGraphicsContext) DrawRect(rect Rect, clr color.Color) {
|
||||||
|
g.ch <- func(g2 GraphicsContext) {
|
||||||
|
g2.DrawRect(rect, clr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *AsyncGraphicsContext) DrawTexture(textureID TextureID,
|
||||||
|
geometryMatrix matrix.Geometry,
|
||||||
|
colorMatrix matrix.Color) {
|
||||||
|
g.ch <- func(g2 GraphicsContext) {
|
||||||
|
g2.DrawTexture(textureID, geometryMatrix, colorMatrix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *AsyncGraphicsContext) DrawTextureParts(textureID TextureID,
|
||||||
|
locations []TexturePart,
|
||||||
|
geometryMatrix matrix.Geometry,
|
||||||
|
colorMatrix matrix.Color) {
|
||||||
|
g.ch <- func(g2 GraphicsContext) {
|
||||||
|
g2.DrawTextureParts(textureID, locations, geometryMatrix, colorMatrix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *AsyncGraphicsContext) SetOffscreen(textureID TextureID) {
|
||||||
|
g.ch <- func(g2 GraphicsContext) {
|
||||||
|
g2.SetOffscreen(textureID)
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ import (
|
|||||||
type Device interface {
|
type Device interface {
|
||||||
Update()
|
Update()
|
||||||
TextureFactory() TextureFactory
|
TextureFactory() TextureFactory
|
||||||
|
OffscreenTexture() Texture
|
||||||
}
|
}
|
||||||
|
|
||||||
type Rect struct {
|
type Rect struct {
|
||||||
@ -26,7 +27,7 @@ type TexturePart struct {
|
|||||||
|
|
||||||
type GraphicsContext interface {
|
type GraphicsContext interface {
|
||||||
Clear()
|
Clear()
|
||||||
Fill(color color.Color)
|
Fill(clr color.Color)
|
||||||
DrawRect(rect Rect, clr color.Color)
|
DrawRect(rect Rect, clr color.Color)
|
||||||
DrawTexture(textureID TextureID,
|
DrawTexture(textureID TextureID,
|
||||||
geometryMatrix matrix.Geometry,
|
geometryMatrix matrix.Geometry,
|
||||||
|
@ -16,23 +16,32 @@ type Device struct {
|
|||||||
screenScale int
|
screenScale int
|
||||||
graphicsContext *GraphicsContext
|
graphicsContext *GraphicsContext
|
||||||
offscreenTexture graphics.Texture
|
offscreenTexture graphics.Texture
|
||||||
drawFunc func(graphics.GraphicsContext, graphics.Texture)
|
deviceUpdate chan<- bool
|
||||||
|
commandSet <-chan chan func(graphics.GraphicsContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDevice(screenWidth, screenHeight, screenScale int,
|
func NewDevice(screenWidth, screenHeight, screenScale int,
|
||||||
drawFunc func(graphics.GraphicsContext, graphics.Texture)) *Device {
|
deviceUpdate chan<- bool,
|
||||||
|
commandSet <-chan chan func(graphics.GraphicsContext)) *Device {
|
||||||
|
graphicsContext := newGraphicsContext(screenWidth, screenHeight, screenScale)
|
||||||
|
|
||||||
device := &Device{
|
device := &Device{
|
||||||
screenWidth: screenWidth,
|
screenWidth: screenWidth,
|
||||||
screenHeight: screenHeight,
|
screenHeight: screenHeight,
|
||||||
screenScale: screenScale,
|
screenScale: screenScale,
|
||||||
graphicsContext: newGraphicsContext(screenWidth, screenHeight, screenScale),
|
deviceUpdate: deviceUpdate,
|
||||||
drawFunc: drawFunc,
|
commandSet: commandSet,
|
||||||
|
graphicsContext: graphicsContext,
|
||||||
}
|
}
|
||||||
device.offscreenTexture =
|
device.offscreenTexture =
|
||||||
device.graphicsContext.NewTexture(screenWidth, screenHeight)
|
device.graphicsContext.NewTexture(screenWidth, screenHeight)
|
||||||
return device
|
return device
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (device *Device) OffscreenTexture() graphics.Texture {
|
||||||
|
return device.offscreenTexture
|
||||||
|
}
|
||||||
|
|
||||||
func (device *Device) Update() {
|
func (device *Device) Update() {
|
||||||
g := device.graphicsContext
|
g := device.graphicsContext
|
||||||
C.glEnable(C.GL_TEXTURE_2D)
|
C.glEnable(C.GL_TEXTURE_2D)
|
||||||
@ -40,7 +49,13 @@ func (device *Device) Update() {
|
|||||||
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_NEAREST)
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_NEAREST)
|
||||||
g.SetOffscreen(device.offscreenTexture.ID)
|
g.SetOffscreen(device.offscreenTexture.ID)
|
||||||
g.Clear()
|
g.Clear()
|
||||||
device.drawFunc(g, device.offscreenTexture)
|
|
||||||
|
device.deviceUpdate <- true
|
||||||
|
commands := <-device.commandSet
|
||||||
|
for command := range commands {
|
||||||
|
command(g)
|
||||||
|
}
|
||||||
|
|
||||||
g.flush()
|
g.flush()
|
||||||
|
|
||||||
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
|
||||||
|
Loading…
Reference in New Issue
Block a user