mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
gomobile bind works
This commit is contained in:
parent
296282435a
commit
6d06b01cae
@ -17,8 +17,6 @@
|
||||
package mobile
|
||||
|
||||
import (
|
||||
_ "image/jpeg"
|
||||
"log"
|
||||
"math"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
@ -49,11 +47,16 @@ func update(screen *ebiten.Image) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func Start() {
|
||||
func Start() error {
|
||||
var err error
|
||||
gophersImage, _, err = common.AssetImage("gophers.jpg", ebiten.FilterNearest)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
mobile.Start(update, screenWidth, screenHeight, 2, "Mobile (Ebiten Demo)")
|
||||
return nil
|
||||
}
|
||||
|
||||
func Render() error {
|
||||
return mobile.Render()
|
||||
}
|
||||
|
@ -14,6 +14,11 @@
|
||||
|
||||
package ebiten
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/internal/ui"
|
||||
)
|
||||
|
||||
func newGraphicsContext(f func(*Image) error) *graphicsContext {
|
||||
return &graphicsContext{
|
||||
f: f,
|
||||
@ -25,6 +30,7 @@ type graphicsContext struct {
|
||||
screen *Image
|
||||
defaultRenderTarget *Image
|
||||
screenScale int
|
||||
imageTasksDone bool
|
||||
}
|
||||
|
||||
func (c *graphicsContext) SetSize(screenWidth, screenHeight, screenScale int) error {
|
||||
@ -49,6 +55,17 @@ func (c *graphicsContext) SetSize(screenWidth, screenHeight, screenScale int) er
|
||||
}
|
||||
|
||||
func (c *graphicsContext) Update() error {
|
||||
if !c.imageTasksDone {
|
||||
if err := graphics.Initialize(ui.GLContext()); err != nil {
|
||||
return err
|
||||
}
|
||||
// This execution is called here because we can say actual GL function calls
|
||||
// should be done here (especailly on mobiles).
|
||||
if err := theDelayedImageTasks.exec(); err != nil {
|
||||
return err
|
||||
}
|
||||
c.imageTasksDone = true
|
||||
}
|
||||
if err := c.screen.Clear(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
4
image.go
4
image.go
@ -561,10 +561,6 @@ func newImageWithZeroFramebuffer(width, height int) (*Image, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// When this is called, OpenGL context should exist.
|
||||
if err := theDelayedImageTasks.exec(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return img, nil
|
||||
}
|
||||
|
||||
|
@ -41,10 +41,12 @@ func (p Program) id() programID {
|
||||
}
|
||||
|
||||
type context struct {
|
||||
gl mgl.Context
|
||||
gl mgl.Context
|
||||
worker mgl.Worker
|
||||
initialized chan struct{}
|
||||
}
|
||||
|
||||
func NewContext() *Context {
|
||||
func NewContext() (*Context, error) {
|
||||
c := &Context{
|
||||
Nearest: mgl.NEAREST,
|
||||
Linear: mgl.LINEAR,
|
||||
@ -65,21 +67,28 @@ func NewContext() *Context {
|
||||
locationCache: newLocationCache(),
|
||||
lastCompositeMode: CompositeModeUnknown,
|
||||
}
|
||||
return c
|
||||
c.gl, c.worker = mgl.NewContext()
|
||||
c.initialized = make(chan struct{})
|
||||
go func() {
|
||||
// GL calls will just enqueue an task to the worker.
|
||||
// Since the worker is not avaialbe, this enqueuing should be done
|
||||
// in a goroutine.
|
||||
|
||||
// Textures' pixel formats are alpha premultiplied.
|
||||
c.gl.Enable(mgl.BLEND)
|
||||
c.BlendFunc(CompositeModeSourceOver)
|
||||
close(c.initialized)
|
||||
}()
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *Context) SetContext(gl mgl.Context) {
|
||||
c.gl = gl
|
||||
if gl == nil {
|
||||
return
|
||||
}
|
||||
// Textures' pixel formats are alpha premultiplied.
|
||||
gl.Enable(mgl.BLEND)
|
||||
c.BlendFunc(CompositeModeSourceOver)
|
||||
func (c *Context) WaitUntilInitializingDone() {
|
||||
// TODO: Call this function at an approriate place
|
||||
<-c.initialized
|
||||
}
|
||||
|
||||
func (c *Context) IsGLContextNil() bool {
|
||||
return c.gl == nil
|
||||
func (c *Context) Worker() mgl.Worker {
|
||||
return c.worker
|
||||
}
|
||||
|
||||
func (c *Context) BlendFunc(mode CompositeMode) {
|
||||
|
@ -150,6 +150,9 @@ func Run(g GraphicsContext, width, height, scale int, title string, fps int) err
|
||||
beforeForUpdate += int64(tt) * int64(time.Second) / int64(fps)
|
||||
frames++
|
||||
}
|
||||
if err := ui.CurrentUI().FinishRendering(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Calc the current FPS.
|
||||
if time.Second <= time.Duration(n2-beforeForFPS) {
|
||||
|
@ -18,6 +18,7 @@ type UserInterface interface {
|
||||
Start(width, height, scale int, title string) error
|
||||
Update() (interface{}, error)
|
||||
SwapBuffers() error
|
||||
FinishRendering() error
|
||||
Terminate() error
|
||||
ScreenScale() int
|
||||
SetScreenSize(width, height int) bool
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-gl/glfw/v3.1/glfw"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
||||
)
|
||||
|
||||
@ -87,9 +86,6 @@ func initialize() (*opengl.Context, error) {
|
||||
if err := u.context.Init(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := graphics.Initialize(u.context); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u.context, nil
|
||||
}
|
||||
@ -262,6 +258,10 @@ func (u *userInterface) swapBuffers() {
|
||||
})
|
||||
}
|
||||
|
||||
func (u *userInterface) FinishRendering() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *userInterface) setScreenSize(width, height, scale int) bool {
|
||||
if u.width == width && u.height == height && u.scale == scale {
|
||||
return false
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/gopherjs/gopherjs/js"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
||||
)
|
||||
|
||||
@ -109,6 +108,10 @@ func (u *userInterface) SwapBuffers() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *userInterface) FinishRendering() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func initialize() (*opengl.Context, error) {
|
||||
// Do nothing in node.js.
|
||||
if js.Global.Get("require") != js.Undefined {
|
||||
@ -116,9 +119,6 @@ func initialize() (*opengl.Context, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := graphics.Initialize(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
@ -226,9 +226,6 @@ func initialize() (*opengl.Context, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := graphics.Initialize(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
@ -17,26 +17,68 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
|
||||
)
|
||||
|
||||
func initialize() (*opengl.Context, error) {
|
||||
// TODO: Implement
|
||||
return nil, nil
|
||||
return opengl.NewContext()
|
||||
}
|
||||
|
||||
func Main() error {
|
||||
return errors.New("ui: don't call this: use RunWithoutMainLoop instead of Run")
|
||||
}
|
||||
|
||||
func Render(chError <-chan error) error {
|
||||
if chError == nil {
|
||||
return errors.New("ui: chError must not be nil")
|
||||
}
|
||||
// TODO: Check this is called on the rendering thread
|
||||
chRender <- struct{}{}
|
||||
worker := glContext.Worker()
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case err := <-chError:
|
||||
return err
|
||||
case <-worker.WorkAvailable():
|
||||
worker.DoWork()
|
||||
case <-chRenderEnd:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type userInterface struct {
|
||||
width int
|
||||
height int
|
||||
scale int
|
||||
sizeChanged bool
|
||||
render chan struct{}
|
||||
renderEnd chan struct{}
|
||||
}
|
||||
|
||||
var (
|
||||
chRender = make(chan struct{})
|
||||
chRenderEnd = make(chan struct{})
|
||||
currentUI = &userInterface{
|
||||
sizeChanged: true,
|
||||
render: chRender,
|
||||
renderEnd: chRenderEnd,
|
||||
}
|
||||
)
|
||||
|
||||
func CurrentUI() UserInterface {
|
||||
return nil
|
||||
return currentUI
|
||||
}
|
||||
|
||||
func (u *userInterface) Start(width, height, scale int, title string) error {
|
||||
u.width = width
|
||||
u.height = height
|
||||
u.scale = scale
|
||||
// title is ignored?
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -45,21 +87,46 @@ func (u *userInterface) Terminate() error {
|
||||
}
|
||||
|
||||
func (u *userInterface) Update() (interface{}, error) {
|
||||
return nil, nil
|
||||
// TODO: Need lock?
|
||||
if u.sizeChanged {
|
||||
u.sizeChanged = false
|
||||
e := ScreenSizeEvent{
|
||||
Width: u.width,
|
||||
Height: u.height,
|
||||
Scale: u.scale,
|
||||
ActualScale: u.actualScreenScale(),
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
select {
|
||||
case <-u.render:
|
||||
return RenderEvent{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (u *userInterface) SwapBuffers() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *userInterface) FinishRendering() error {
|
||||
u.renderEnd <- struct{}{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *userInterface) SetScreenSize(width, height int) bool {
|
||||
// TODO: Implement
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *userInterface) SetScreenScale(scale int) bool {
|
||||
// TODO: Implement
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *userInterface) ScreenScale() int {
|
||||
return 1
|
||||
return u.scale
|
||||
}
|
||||
|
||||
func (u *userInterface) actualScreenScale() int {
|
||||
return u.scale
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
package mobile
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"runtime"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
@ -28,16 +29,6 @@ var chError <-chan error
|
||||
// Different from ebiten.Run, this invokes only the game loop and not the main (UI) loop.
|
||||
func Start(f func(*ebiten.Image) error, width, height, scale int, title string) {
|
||||
chError = ebiten.RunWithoutMainLoop(f, width, height, scale, title)
|
||||
return
|
||||
}
|
||||
|
||||
func LastErrorString() string {
|
||||
select {
|
||||
case err := <-chError:
|
||||
return err.Error()
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func SetScreenSize(width, height int) {
|
||||
@ -48,13 +39,12 @@ func SetScreenScale(scale int) {
|
||||
ui.CurrentUI().SetScreenScale(scale)
|
||||
}
|
||||
|
||||
func Render() {
|
||||
func Render() error {
|
||||
runtime.LockOSThread()
|
||||
// TODO: Implement this
|
||||
/*select {
|
||||
case <-workAvailable:
|
||||
DoWork()
|
||||
case <-done:
|
||||
return
|
||||
}*/
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
if chError == nil {
|
||||
return errors.New("mobile: chError must not be nil: Start is not called yet?")
|
||||
}
|
||||
return ui.Render(chError)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user