Enable to compile Ebiten on js/wasm with Go 1.14

Fixes #1024
This commit is contained in:
Hajime Hoshi 2019-12-19 00:03:35 +09:00
parent 06f600dfa0
commit 9284380ddd
13 changed files with 150 additions and 26 deletions

2
go.mod
View File

@ -8,7 +8,7 @@ require (
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/hajimehoshi/bitmapfont v1.2.0
github.com/hajimehoshi/go-mp3 v0.2.1
github.com/hajimehoshi/oto v0.5.3
github.com/hajimehoshi/oto v0.5.4-0.20191218145825-0644fbe4140c
github.com/jakecoffman/cp v0.1.0
github.com/jfreymuth/oggvorbis v1.0.0
github.com/jfreymuth/vorbis v1.0.0 // indirect

4
go.sum
View File

@ -10,8 +10,8 @@ github.com/hajimehoshi/bitmapfont v1.2.0/go.mod h1:h9QrPk6Ktb2neObTlAbma6Ini1xgM
github.com/hajimehoshi/go-mp3 v0.2.1 h1:DH4ns3cPv39n3cs8MPcAlWqPeAwLCK8iNgqvg0QBWI8=
github.com/hajimehoshi/go-mp3 v0.2.1/go.mod h1:Rr+2P46iH6PwTPVgSsEwBkon0CK5DxCAeX/Rp65DCTE=
github.com/hajimehoshi/oto v0.3.4/go.mod h1:PgjqsBJff0efqL2nlMJidJgVJywLn6M4y8PI4TfeWfA=
github.com/hajimehoshi/oto v0.5.3 h1:IccIFFUkT0oAr/KdH3LH7USyvI1ZE84HXiGtuCjs3y0=
github.com/hajimehoshi/oto v0.5.3/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto v0.5.4-0.20191218145825-0644fbe4140c h1:Hr7DqgpqLqfeStmF2aTHbWuZGO3/J64Xq2crXC069v8=
github.com/hajimehoshi/oto v0.5.4-0.20191218145825-0644fbe4140c/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/jakecoffman/cp v0.1.0 h1:sgSYEGUgfwiT447fRjloa2c5b6UyYP+7muR3gQK+Ep0=
github.com/jakecoffman/cp v0.1.0/go.mod h1:a3xPx9N8RyFAACD644t2dj/nK4SuLg1v+jL61m2yVo4=
github.com/jfreymuth/oggvorbis v1.0.0 h1:aOpiihGrFLXpsh2osOlEvTcg5/aluzGQeC7m3uYWOZ0=

View File

@ -60,7 +60,7 @@ type context struct {
}
func (c *context) bindTexture(t textureNative) {
if c.lastTexture == t {
if c.lastTexture.equal(t) {
return
}
c.bindTextureImpl(t)
@ -68,7 +68,7 @@ func (c *context) bindTexture(t textureNative) {
}
func (c *context) bindFramebuffer(f framebufferNative) {
if c.lastFramebuffer == f {
if c.lastFramebuffer.equal(f) {
return
}
c.bindFramebufferImpl(f)
@ -86,7 +86,7 @@ func (c *context) setViewport(f *framebuffer) {
// glViewport must be called at least at every frame on iOS.
// As the screen framebuffer is the last render target, next SetViewport should be
// the first call at a frame.
if f.native == c.screenFramebuffer {
if f.native.equal(c.screenFramebuffer) {
c.lastViewportWidth = 0
c.lastViewportHeight = 0
} else {

View File

@ -35,6 +35,30 @@ type (
buffer uint32
)
func (t textureNative) equal(rhs textureNative) bool {
return t == rhs
}
func (f framebufferNative) equal(rhs framebufferNative) bool {
return f == rhs
}
func (s shader) equal(rhs shader) bool {
return s == rhs
}
func (b buffer) equal(rhs buffer) bool {
return b == rhs
}
func (u uniformLocation) equal(rhs uniformLocation) bool {
return u == rhs
}
func (p program) equal(rhs program) bool {
return p == rhs
}
var InvalidTexture textureNative
type (

View File

@ -41,6 +41,30 @@ type (
}
)
func (t textureNative) equal(rhs textureNative) bool {
return jsutil.Equal(js.Value(t), js.Value(rhs))
}
func (f framebufferNative) equal(rhs framebufferNative) bool {
return jsutil.Equal(js.Value(f), js.Value(rhs))
}
func (s shader) equal(rhs shader) bool {
return jsutil.Equal(js.Value(s), js.Value(rhs))
}
func (b buffer) equal(rhs buffer) bool {
return jsutil.Equal(js.Value(b), js.Value(rhs))
}
func (u uniformLocation) equal(rhs uniformLocation) bool {
return jsutil.Equal(js.Value(u), js.Value(rhs))
}
func (p program) equal(rhs program) bool {
return jsutil.Equal(p.value, rhs.value) && p.id == rhs.id
}
var InvalidTexture = textureNative(js.Null())
func getProgramID(p program) programID {
@ -101,11 +125,11 @@ type contextImpl struct {
}
func (c *context) ensureGL() {
if c.gl != (js.Value{}) {
if !jsutil.Equal(c.gl, js.Value{}) {
return
}
if js.Global().Get("WebGLRenderingContext") == js.Undefined() {
if jsutil.Equal(js.Global().Get("WebGLRenderingContext"), js.Undefined()) {
panic("opengl: WebGL is not supported")
}
// TODO: Define id?
@ -114,9 +138,9 @@ func (c *context) ensureGL() {
attr.Set("alpha", true)
attr.Set("premultipliedAlpha", true)
gl := canvas.Call("getContext", "webgl", attr)
if gl == js.Null() {
if jsutil.Equal(gl, js.Null()) {
gl = canvas.Call("getContext", "experimental-webgl", attr)
if gl == js.Null() {
if jsutil.Equal(gl, js.Null()) {
panic("opengl: getContext failed")
}
}
@ -161,7 +185,7 @@ func (c *context) newTexture(width, height int) (textureNative, error) {
c.ensureGL()
gl := c.gl
t := gl.Call("createTexture")
if t == js.Null() {
if jsutil.Equal(t, js.Null()) {
return textureNative(js.Null()), errors.New("opengl: glGenTexture failed")
}
gl.Call("pixelStorei", unpackAlignment, 4)
@ -221,7 +245,7 @@ func (c *context) deleteTexture(t textureNative) {
if !gl.Call("isTexture", js.Value(t)).Bool() {
return
}
if c.lastTexture == t {
if c.lastTexture.equal(t) {
c.lastTexture = textureNative(js.Null())
}
gl.Call("deleteTexture", js.Value(t))
@ -274,7 +298,7 @@ func (c *context) deleteFramebuffer(f framebufferNative) {
// If a framebuffer to be deleted is bound, a newly bound framebuffer
// will be a default framebuffer.
// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteFramebuffers.xml
if c.lastFramebuffer == f {
if c.lastFramebuffer.equal(f) {
c.lastFramebuffer = framebufferNative(js.Null())
c.lastViewportWidth = 0
c.lastViewportHeight = 0
@ -286,7 +310,7 @@ func (c *context) newShader(shaderType shaderType, source string) (shader, error
c.ensureGL()
gl := c.gl
s := gl.Call("createShader", int(shaderType))
if s == js.Null() {
if jsutil.Equal(s, js.Null()) {
return shader(js.Null()), fmt.Errorf("opengl: glCreateShader failed: shader type: %d", shaderType)
}
@ -310,7 +334,7 @@ func (c *context) newProgram(shaders []shader, attributes []string) (program, er
c.ensureGL()
gl := c.gl
v := gl.Call("createProgram")
if v == js.Null() {
if jsutil.Equal(v, js.Null()) {
return program{}, errors.New("opengl: glCreateProgram failed")
}

View File

@ -33,6 +33,26 @@ type (
buffer mgl.Buffer
)
func (t textureNative) equal(rhs textureNative) bool {
return t == rhs
}
func (f framebufferNative) equal(rhs framebufferNative) bool {
return f == rhs
}
func (s shader) equal(rhs shader) bool {
return s == rhs
}
func (b buffer) equal(rhs buffer) bool {
return b == rhs
}
func (p program) equal(rhs program) bool {
return p == rhs
}
var InvalidTexture textureNative
type (
@ -40,6 +60,10 @@ type (
attribLocation mgl.Attrib
)
func (u uniformLocation) equal(rhs uniformLocation) bool {
return u == rhs
}
type programID uint32
var (

View File

@ -45,7 +45,7 @@ func newScreenFramebuffer(context *context, width, height int) *framebuffer {
}
func (f *framebuffer) delete(context *context) {
if f.native != context.getScreenFramebuffer() {
if !f.native.equal(context.getScreenFramebuffer()) {
context.deleteFramebuffer(f.native)
}
}

View File

@ -35,7 +35,7 @@ func (i *Image) Dispose() {
if i.framebuffer != nil {
i.framebuffer.delete(&i.driver.context)
}
if i.textureNative != *new(textureNative) {
if !i.textureNative.equal(*new(textureNative)) {
i.driver.context.deleteTexture(i.textureNative)
}
}

View File

@ -183,10 +183,10 @@ func (s *openGLState) reset(context *context) error {
// On browsers (at least Chrome), buffers are already detached from the context
// and must not be deleted by DeleteBuffer.
if !web.IsBrowser() {
if s.arrayBuffer != zeroBuffer {
if !s.arrayBuffer.equal(zeroBuffer) {
context.deleteBuffer(s.arrayBuffer)
}
if s.elementArrayBuffer != zeroBuffer {
if !s.elementArrayBuffer.equal(zeroBuffer) {
context.deleteBuffer(s.elementArrayBuffer)
}
}
@ -278,9 +278,9 @@ func (d *Driver) useProgram(mode driver.CompositeMode, colorM *affine.ColorM, fi
filter: filter,
address: address,
}]
if d.state.lastProgram != program {
if !d.state.lastProgram.equal(program) {
d.context.useProgram(program)
if d.state.lastProgram == zeroProgram {
if d.state.lastProgram.equal(zeroProgram) {
theArrayBufferLayout.enable(&d.context, program)
d.context.bindBuffer(arrayBuffer, d.state.arrayBuffer)
d.context.bindBuffer(elementArrayBuffer, d.state.elementArrayBuffer)

View File

@ -0,0 +1,25 @@
// Copyright 2019 The Ebiten 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.
// +build !go1.14
package jsutil
import (
"syscall/js"
)
func Equal(a, b js.Value) bool {
return a == b
}

View File

@ -0,0 +1,25 @@
// Copyright 2019 The Ebiten 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.
// +build go1.14
package jsutil
import (
"syscall/js"
)
func Equal(a, b js.Value) bool {
return a.Equal(b)
}

View File

@ -21,6 +21,7 @@ import (
"unicode"
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/jsutil"
)
type pos struct {
@ -218,7 +219,7 @@ func (i *Input) setMouseCursor(x, y int) {
func (i *Input) UpdateGamepads() {
nav := js.Global().Get("navigator")
if nav.Get("getGamepads") == js.Undefined() {
if jsutil.Equal(nav.Get("getGamepads"), js.Undefined()) {
return
}
gamepads := nav.Call("getGamepads")
@ -226,7 +227,7 @@ func (i *Input) UpdateGamepads() {
for id := 0; id < l; id++ {
i.gamepads[id].valid = false
gamepad := gamepads.Index(id)
if gamepad == js.Undefined() || gamepad == js.Null() {
if jsutil.Equal(gamepad, js.Undefined()) || jsutil.Equal(gamepad, js.Null()) {
continue
}
i.gamepads[id].valid = true
@ -259,7 +260,7 @@ func (i *Input) Update(e js.Value) {
switch e.Get("type").String() {
case "keydown":
c := e.Get("code")
if c == js.Undefined() {
if jsutil.Equal(c, js.Undefined()) {
code := e.Get("keyCode").Int()
if keyCodeToKeyEdge[code] == driver.KeyUp ||
keyCodeToKeyEdge[code] == driver.KeyDown ||
@ -287,7 +288,7 @@ func (i *Input) Update(e js.Value) {
i.runeBuffer = append(i.runeBuffer, r)
}
case "keyup":
if e.Get("code") == js.Undefined() {
if jsutil.Equal(e.Get("code"), js.Undefined()) {
// Assume that UA is Edge.
code := e.Get("keyCode").Int()
i.keyUpEdge(code)

View File

@ -26,6 +26,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/devicescale"
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/jsutil"
)
type UserInterface struct {
@ -264,7 +265,7 @@ func (u *UserInterface) loop(context driver.UIContext) <-chan error {
}
func init() {
if document.Get("body") == js.Null() {
if jsutil.Equal(document.Get("body"), js.Null()) {
ch := make(chan struct{})
window.Call("addEventListener", "load", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
close(ch)