Add AsyncGraphicsContext; Use goroutines in the main routine

This commit is contained in:
Hajime Hoshi 2013-06-26 00:56:01 +09:00
parent 6e584eb642
commit 6b1e76b669
4 changed files with 101 additions and 22 deletions

View File

@ -30,29 +30,35 @@ type InputState struct {
Y int
}
func OpenGLRun(game Game, ui UI, screenScale int, input chan InputState) {
ch := make(chan bool, 1)
func OpenGLRun(game Game, ui UI, screenScale int, input <-chan InputState) {
deviceUpdate := make(chan bool)
commandSet := make(chan chan func(graphics.GraphicsContext))
graphicsDevice := opengl.NewDevice(
game.ScreenWidth(), game.ScreenHeight(), screenScale,
func(g graphics.GraphicsContext, offscreen graphics.Texture) {
ticket := <-ch
game.Draw(g, offscreen)
ch <- ticket
})
game.ScreenWidth(), game.ScreenHeight(), screenScale, deviceUpdate, commandSet)
game.Init(graphicsDevice.TextureFactory())
go func() {
frameTime := time.Duration(int64(time.Second) / int64(game.Fps()))
tick := time.Tick(frameTime)
updateTick := time.Tick(frameTime)
for {
<-tick
ticket := <-ch
inputState := <-input
game.Update(inputState)
ch <- ticket
select {
case <-updateTick:
inputState := <-input
game.Update(inputState)
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)
}

View 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)
}
}

View File

@ -9,6 +9,7 @@ import (
type Device interface {
Update()
TextureFactory() TextureFactory
OffscreenTexture() Texture
}
type Rect struct {
@ -26,7 +27,7 @@ type TexturePart struct {
type GraphicsContext interface {
Clear()
Fill(color color.Color)
Fill(clr color.Color)
DrawRect(rect Rect, clr color.Color)
DrawTexture(textureID TextureID,
geometryMatrix matrix.Geometry,

View File

@ -16,23 +16,32 @@ type Device struct {
screenScale int
graphicsContext *GraphicsContext
offscreenTexture graphics.Texture
drawFunc func(graphics.GraphicsContext, graphics.Texture)
deviceUpdate chan<- bool
commandSet <-chan chan func(graphics.GraphicsContext)
}
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{
screenWidth: screenWidth,
screenHeight: screenHeight,
screenScale: screenScale,
graphicsContext: newGraphicsContext(screenWidth, screenHeight, screenScale),
drawFunc: drawFunc,
deviceUpdate: deviceUpdate,
commandSet: commandSet,
graphicsContext: graphicsContext,
}
device.offscreenTexture =
device.graphicsContext.NewTexture(screenWidth, screenHeight)
return device
}
func (device *Device) OffscreenTexture() graphics.Texture {
return device.offscreenTexture
}
func (device *Device) Update() {
g := device.graphicsContext
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)
g.SetOffscreen(device.offscreenTexture.ID)
g.Clear()
device.drawFunc(g, device.offscreenTexture)
device.deviceUpdate <- true
commands := <-device.commandSet
for command := range commands {
command(g)
}
g.flush()
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)