mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
opengl: Remove Init (except for mobile)
This commit is contained in:
parent
16ada03928
commit
4090258904
44
internal/mainthread/mainthread.go
Normal file
44
internal/mainthread/mainthread.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
package mainthread
|
||||||
|
|
||||||
|
var funcs = make(chan func())
|
||||||
|
|
||||||
|
// Loop starts the main-thread loop.
|
||||||
|
//
|
||||||
|
// Loop must be called on the main thread.
|
||||||
|
func Loop(ch <-chan error) error {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case f := <-funcs:
|
||||||
|
f()
|
||||||
|
case err := <-ch:
|
||||||
|
// ch returns a value not only when an error occur but also it is closed.
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run calls f on the main thread.
|
||||||
|
func Run(f func() error) error {
|
||||||
|
ch := make(chan struct{})
|
||||||
|
var err error
|
||||||
|
funcs <- func() {
|
||||||
|
err = f()
|
||||||
|
close(ch)
|
||||||
|
}
|
||||||
|
<-ch
|
||||||
|
return err
|
||||||
|
}
|
@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/go-gl/gl/v2.1/gl"
|
"github.com/go-gl/gl/v2.1/gl"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/mainthread"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -75,21 +76,14 @@ func init() {
|
|||||||
|
|
||||||
type context struct {
|
type context struct {
|
||||||
init bool
|
init bool
|
||||||
runOnMainThread func(func() error) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init(runOnMainThread func(func() error) error) {
|
func init() {
|
||||||
c := &Context{}
|
theContext = &Context{}
|
||||||
c.runOnMainThread = runOnMainThread
|
|
||||||
theContext = c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) runOnContextThread(f func() error) error {
|
|
||||||
return c.runOnMainThread(f)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) reset() error {
|
func (c *Context) reset() error {
|
||||||
if err := c.runOnContextThread(func() error {
|
if err := mainthread.Run(func() error {
|
||||||
if c.init {
|
if c.init {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -108,12 +102,12 @@ func (c *Context) reset() error {
|
|||||||
c.lastViewportWidth = 0
|
c.lastViewportWidth = 0
|
||||||
c.lastViewportHeight = 0
|
c.lastViewportHeight = 0
|
||||||
c.lastCompositeMode = graphics.CompositeModeUnknown
|
c.lastCompositeMode = graphics.CompositeModeUnknown
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.Enable(gl.BLEND)
|
gl.Enable(gl.BLEND)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
c.BlendFunc(graphics.CompositeModeSourceOver)
|
c.BlendFunc(graphics.CompositeModeSourceOver)
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
f := int32(0)
|
f := int32(0)
|
||||||
gl.GetIntegerv(gl.FRAMEBUFFER_BINDING, &f)
|
gl.GetIntegerv(gl.FRAMEBUFFER_BINDING, &f)
|
||||||
c.screenFramebuffer = framebufferNative(f)
|
c.screenFramebuffer = framebufferNative(f)
|
||||||
@ -123,7 +117,7 @@ func (c *Context) reset() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) BlendFunc(mode graphics.CompositeMode) {
|
func (c *Context) BlendFunc(mode graphics.CompositeMode) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
if c.lastCompositeMode == mode {
|
if c.lastCompositeMode == mode {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -137,7 +131,7 @@ func (c *Context) BlendFunc(mode graphics.CompositeMode) {
|
|||||||
|
|
||||||
func (c *Context) newTexture(width, height int) (textureNative, error) {
|
func (c *Context) newTexture(width, height int) (textureNative, error) {
|
||||||
var texture textureNative
|
var texture textureNative
|
||||||
if err := c.runOnContextThread(func() error {
|
if err := mainthread.Run(func() error {
|
||||||
var t uint32
|
var t uint32
|
||||||
gl.GenTextures(1, &t)
|
gl.GenTextures(1, &t)
|
||||||
// TODO: Use gl.IsTexture
|
// TODO: Use gl.IsTexture
|
||||||
@ -151,7 +145,7 @@ func (c *Context) newTexture(width, height int) (textureNative, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
c.bindTexture(texture)
|
c.bindTexture(texture)
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
||||||
@ -163,7 +157,7 @@ func (c *Context) newTexture(width, height int) (textureNative, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) bindFramebufferImpl(f framebufferNative) {
|
func (c *Context) bindFramebufferImpl(f framebufferNative) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.BindFramebufferEXT(gl.FRAMEBUFFER, uint32(f))
|
gl.BindFramebufferEXT(gl.FRAMEBUFFER, uint32(f))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -171,12 +165,12 @@ func (c *Context) bindFramebufferImpl(f framebufferNative) {
|
|||||||
|
|
||||||
func (c *Context) framebufferPixels(f *framebuffer, width, height int) ([]byte, error) {
|
func (c *Context) framebufferPixels(f *framebuffer, width, height int) ([]byte, error) {
|
||||||
var pixels []byte
|
var pixels []byte
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.Flush()
|
gl.Flush()
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
c.bindFramebuffer(f.native)
|
c.bindFramebuffer(f.native)
|
||||||
if err := c.runOnContextThread(func() error {
|
if err := mainthread.Run(func() error {
|
||||||
pixels = make([]byte, 4*width*height)
|
pixels = make([]byte, 4*width*height)
|
||||||
gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pixels))
|
gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pixels))
|
||||||
if e := gl.GetError(); e != gl.NO_ERROR {
|
if e := gl.GetError(); e != gl.NO_ERROR {
|
||||||
@ -191,14 +185,14 @@ func (c *Context) framebufferPixels(f *framebuffer, width, height int) ([]byte,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) bindTextureImpl(t textureNative) {
|
func (c *Context) bindTextureImpl(t textureNative) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.BindTexture(gl.TEXTURE_2D, uint32(t))
|
gl.BindTexture(gl.TEXTURE_2D, uint32(t))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) deleteTexture(t textureNative) {
|
func (c *Context) deleteTexture(t textureNative) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
tt := uint32(t)
|
tt := uint32(t)
|
||||||
if !gl.IsTexture(tt) {
|
if !gl.IsTexture(tt) {
|
||||||
return nil
|
return nil
|
||||||
@ -213,7 +207,7 @@ func (c *Context) deleteTexture(t textureNative) {
|
|||||||
|
|
||||||
func (c *Context) isTexture(t textureNative) bool {
|
func (c *Context) isTexture(t textureNative) bool {
|
||||||
r := false
|
r := false
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
r = gl.IsTexture(uint32(t))
|
r = gl.IsTexture(uint32(t))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -222,7 +216,7 @@ func (c *Context) isTexture(t textureNative) bool {
|
|||||||
|
|
||||||
func (c *Context) texSubImage2D(t textureNative, p []byte, x, y, width, height int) {
|
func (c *Context) texSubImage2D(t textureNative, p []byte, x, y, width, height int) {
|
||||||
c.bindTexture(t)
|
c.bindTexture(t)
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.TexSubImage2D(gl.TEXTURE_2D, 0, int32(x), int32(y), int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(p))
|
gl.TexSubImage2D(gl.TEXTURE_2D, 0, int32(x), int32(y), int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(p))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -235,7 +229,7 @@ func (c *Context) BeforeSwapping() {
|
|||||||
func (c *Context) newFramebuffer(texture textureNative) (framebufferNative, error) {
|
func (c *Context) newFramebuffer(texture textureNative) (framebufferNative, error) {
|
||||||
var framebuffer framebufferNative
|
var framebuffer framebufferNative
|
||||||
var f uint32
|
var f uint32
|
||||||
if err := c.runOnContextThread(func() error {
|
if err := mainthread.Run(func() error {
|
||||||
gl.GenFramebuffersEXT(1, &f)
|
gl.GenFramebuffersEXT(1, &f)
|
||||||
// TODO: Use gl.IsFramebuffer
|
// TODO: Use gl.IsFramebuffer
|
||||||
if f <= 0 {
|
if f <= 0 {
|
||||||
@ -246,7 +240,7 @@ func (c *Context) newFramebuffer(texture textureNative) (framebufferNative, erro
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
c.bindFramebuffer(framebufferNative(f))
|
c.bindFramebuffer(framebufferNative(f))
|
||||||
if err := c.runOnContextThread(func() error {
|
if err := mainthread.Run(func() error {
|
||||||
gl.FramebufferTexture2DEXT(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, uint32(texture), 0)
|
gl.FramebufferTexture2DEXT(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, uint32(texture), 0)
|
||||||
s := gl.CheckFramebufferStatusEXT(gl.FRAMEBUFFER)
|
s := gl.CheckFramebufferStatusEXT(gl.FRAMEBUFFER)
|
||||||
if s != gl.FRAMEBUFFER_COMPLETE {
|
if s != gl.FRAMEBUFFER_COMPLETE {
|
||||||
@ -267,14 +261,14 @@ func (c *Context) newFramebuffer(texture textureNative) (framebufferNative, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) setViewportImpl(width, height int) {
|
func (c *Context) setViewportImpl(width, height int) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.Viewport(0, 0, int32(width), int32(height))
|
gl.Viewport(0, 0, int32(width), int32(height))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) deleteFramebuffer(f framebufferNative) {
|
func (c *Context) deleteFramebuffer(f framebufferNative) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
ff := uint32(f)
|
ff := uint32(f)
|
||||||
if !gl.IsFramebufferEXT(ff) {
|
if !gl.IsFramebufferEXT(ff) {
|
||||||
return nil
|
return nil
|
||||||
@ -291,7 +285,7 @@ func (c *Context) deleteFramebuffer(f framebufferNative) {
|
|||||||
|
|
||||||
func (c *Context) newShader(shaderType shaderType, source string) (shader, error) {
|
func (c *Context) newShader(shaderType shaderType, source string) (shader, error) {
|
||||||
var sh shader
|
var sh shader
|
||||||
if err := c.runOnContextThread(func() error {
|
if err := mainthread.Run(func() error {
|
||||||
s := gl.CreateShader(uint32(shaderType))
|
s := gl.CreateShader(uint32(shaderType))
|
||||||
if s == 0 {
|
if s == 0 {
|
||||||
return fmt.Errorf("opengl: glCreateShader failed: shader type: %d", shaderType)
|
return fmt.Errorf("opengl: glCreateShader failed: shader type: %d", shaderType)
|
||||||
@ -321,7 +315,7 @@ func (c *Context) newShader(shaderType shaderType, source string) (shader, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) deleteShader(s shader) {
|
func (c *Context) deleteShader(s shader) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.DeleteShader(uint32(s))
|
gl.DeleteShader(uint32(s))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -329,7 +323,7 @@ func (c *Context) deleteShader(s shader) {
|
|||||||
|
|
||||||
func (c *Context) newProgram(shaders []shader) (program, error) {
|
func (c *Context) newProgram(shaders []shader) (program, error) {
|
||||||
var pr program
|
var pr program
|
||||||
if err := c.runOnContextThread(func() error {
|
if err := mainthread.Run(func() error {
|
||||||
p := gl.CreateProgram()
|
p := gl.CreateProgram()
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
return errors.New("opengl: glCreateProgram failed")
|
return errors.New("opengl: glCreateProgram failed")
|
||||||
@ -353,14 +347,14 @@ func (c *Context) newProgram(shaders []shader) (program, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) useProgram(p program) {
|
func (c *Context) useProgram(p program) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.UseProgram(uint32(p))
|
gl.UseProgram(uint32(p))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) deleteProgram(p program) {
|
func (c *Context) deleteProgram(p program) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
if !gl.IsProgram(uint32(p)) {
|
if !gl.IsProgram(uint32(p)) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -380,7 +374,7 @@ func (c *Context) getUniformLocationImpl(p program, location string) uniformLoca
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) uniformInt(p program, location string, v int) {
|
func (c *Context) uniformInt(p program, location string, v int) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
l := int32(c.locationCache.GetUniformLocation(c, p, location))
|
l := int32(c.locationCache.GetUniformLocation(c, p, location))
|
||||||
gl.Uniform1i(l, int32(v))
|
gl.Uniform1i(l, int32(v))
|
||||||
return nil
|
return nil
|
||||||
@ -388,7 +382,7 @@ func (c *Context) uniformInt(p program, location string, v int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) uniformFloat(p program, location string, v float32) {
|
func (c *Context) uniformFloat(p program, location string, v float32) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
l := int32(c.locationCache.GetUniformLocation(c, p, location))
|
l := int32(c.locationCache.GetUniformLocation(c, p, location))
|
||||||
gl.Uniform1f(l, v)
|
gl.Uniform1f(l, v)
|
||||||
return nil
|
return nil
|
||||||
@ -396,7 +390,7 @@ func (c *Context) uniformFloat(p program, location string, v float32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) uniformFloats(p program, location string, v []float32) {
|
func (c *Context) uniformFloats(p program, location string, v []float32) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
l := int32(c.locationCache.GetUniformLocation(c, p, location))
|
l := int32(c.locationCache.GetUniformLocation(c, p, location))
|
||||||
switch len(v) {
|
switch len(v) {
|
||||||
case 2:
|
case 2:
|
||||||
@ -423,7 +417,7 @@ func (c *Context) getAttribLocationImpl(p program, location string) attribLocati
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) vertexAttribPointer(p program, location string, size int, dataType DataType, stride int, offset int) {
|
func (c *Context) vertexAttribPointer(p program, location string, size int, dataType DataType, stride int, offset int) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
l := c.locationCache.GetAttribLocation(c, p, location)
|
||||||
gl.VertexAttribPointer(uint32(l), int32(size), uint32(dataType), false, int32(stride), gl.PtrOffset(offset))
|
gl.VertexAttribPointer(uint32(l), int32(size), uint32(dataType), false, int32(stride), gl.PtrOffset(offset))
|
||||||
return nil
|
return nil
|
||||||
@ -431,7 +425,7 @@ func (c *Context) vertexAttribPointer(p program, location string, size int, data
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) enableVertexAttribArray(p program, location string) {
|
func (c *Context) enableVertexAttribArray(p program, location string) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
l := c.locationCache.GetAttribLocation(c, p, location)
|
||||||
gl.EnableVertexAttribArray(uint32(l))
|
gl.EnableVertexAttribArray(uint32(l))
|
||||||
return nil
|
return nil
|
||||||
@ -439,7 +433,7 @@ func (c *Context) enableVertexAttribArray(p program, location string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) disableVertexAttribArray(p program, location string) {
|
func (c *Context) disableVertexAttribArray(p program, location string) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
l := c.locationCache.GetAttribLocation(c, p, location)
|
||||||
gl.DisableVertexAttribArray(uint32(l))
|
gl.DisableVertexAttribArray(uint32(l))
|
||||||
return nil
|
return nil
|
||||||
@ -448,7 +442,7 @@ func (c *Context) disableVertexAttribArray(p program, location string) {
|
|||||||
|
|
||||||
func (c *Context) newArrayBuffer(size int) buffer {
|
func (c *Context) newArrayBuffer(size int) buffer {
|
||||||
var bf buffer
|
var bf buffer
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
var b uint32
|
var b uint32
|
||||||
gl.GenBuffers(1, &b)
|
gl.GenBuffers(1, &b)
|
||||||
gl.BindBuffer(uint32(arrayBuffer), b)
|
gl.BindBuffer(uint32(arrayBuffer), b)
|
||||||
@ -461,7 +455,7 @@ func (c *Context) newArrayBuffer(size int) buffer {
|
|||||||
|
|
||||||
func (c *Context) newElementArrayBuffer(size int) buffer {
|
func (c *Context) newElementArrayBuffer(size int) buffer {
|
||||||
var bf buffer
|
var bf buffer
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
var b uint32
|
var b uint32
|
||||||
gl.GenBuffers(1, &b)
|
gl.GenBuffers(1, &b)
|
||||||
gl.BindBuffer(uint32(elementArrayBuffer), b)
|
gl.BindBuffer(uint32(elementArrayBuffer), b)
|
||||||
@ -473,28 +467,28 @@ func (c *Context) newElementArrayBuffer(size int) buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) bindBuffer(bufferType bufferType, b buffer) {
|
func (c *Context) bindBuffer(bufferType bufferType, b buffer) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.BindBuffer(uint32(bufferType), uint32(b))
|
gl.BindBuffer(uint32(bufferType), uint32(b))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) arrayBufferSubData(data []float32) {
|
func (c *Context) arrayBufferSubData(data []float32) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.BufferSubData(uint32(arrayBuffer), 0, len(data)*4, gl.Ptr(data))
|
gl.BufferSubData(uint32(arrayBuffer), 0, len(data)*4, gl.Ptr(data))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) elementArrayBufferSubData(data []uint16) {
|
func (c *Context) elementArrayBufferSubData(data []uint16) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.BufferSubData(uint32(elementArrayBuffer), 0, len(data)*2, gl.Ptr(data))
|
gl.BufferSubData(uint32(elementArrayBuffer), 0, len(data)*2, gl.Ptr(data))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) deleteBuffer(b buffer) {
|
func (c *Context) deleteBuffer(b buffer) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
bb := uint32(b)
|
bb := uint32(b)
|
||||||
gl.DeleteBuffers(1, &bb)
|
gl.DeleteBuffers(1, &bb)
|
||||||
return nil
|
return nil
|
||||||
@ -502,7 +496,7 @@ func (c *Context) deleteBuffer(b buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) DrawElements(len int, offsetInBytes int) {
|
func (c *Context) DrawElements(len int, offsetInBytes int) {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.DrawElements(gl.TRIANGLES, int32(len), gl.UNSIGNED_SHORT, gl.PtrOffset(offsetInBytes))
|
gl.DrawElements(gl.TRIANGLES, int32(len), gl.UNSIGNED_SHORT, gl.PtrOffset(offsetInBytes))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -510,7 +504,7 @@ func (c *Context) DrawElements(len int, offsetInBytes int) {
|
|||||||
|
|
||||||
func (c *Context) maxTextureSizeImpl() int {
|
func (c *Context) maxTextureSizeImpl() int {
|
||||||
size := 0
|
size := 0
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
s := int32(0)
|
s := int32(0)
|
||||||
gl.GetIntegerv(gl.MAX_TEXTURE_SIZE, &s)
|
gl.GetIntegerv(gl.MAX_TEXTURE_SIZE, &s)
|
||||||
size = int(s)
|
size = int(s)
|
||||||
@ -520,7 +514,7 @@ func (c *Context) maxTextureSizeImpl() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) Flush() {
|
func (c *Context) Flush() {
|
||||||
_ = c.runOnContextThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
gl.Flush()
|
gl.Flush()
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
@ -119,11 +119,18 @@ type context struct {
|
|||||||
lastProgramID programID
|
lastProgramID programID
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init() error {
|
func init() {
|
||||||
if js.Global().Get("WebGLRenderingContext") == js.Undefined() {
|
theContext = &Context{}
|
||||||
return fmt.Errorf("opengl: WebGL is not supported")
|
}
|
||||||
|
|
||||||
|
func (c *Context) ensureGL() {
|
||||||
|
if c.gl != (js.Value{}) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if js.Global().Get("WebGLRenderingContext") == js.Undefined() {
|
||||||
|
panic("opengl: WebGL is not supported")
|
||||||
|
}
|
||||||
// TODO: Define id?
|
// TODO: Define id?
|
||||||
canvas := js.Global().Get("document").Call("querySelector", "canvas")
|
canvas := js.Global().Get("document").Call("querySelector", "canvas")
|
||||||
attr := js.Global().Get("Object").New()
|
attr := js.Global().Get("Object").New()
|
||||||
@ -133,18 +140,15 @@ func Init() error {
|
|||||||
if gl == js.Null() {
|
if gl == js.Null() {
|
||||||
gl = canvas.Call("getContext", "experimental-webgl", attr)
|
gl = canvas.Call("getContext", "experimental-webgl", attr)
|
||||||
if gl == js.Null() {
|
if gl == js.Null() {
|
||||||
return fmt.Errorf("opengl: getContext failed")
|
panic("opengl: getContext failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c := &Context{}
|
|
||||||
c.gl = gl
|
c.gl = gl
|
||||||
|
|
||||||
// Getting an extension might fail after the context is lost, so
|
// Getting an extension might fail after the context is lost, so
|
||||||
// it is required to get the extension here.
|
// it is required to get the extension here.
|
||||||
c.loseContext = gl.Call("getExtension", "WEBGL_lose_context")
|
c.loseContext = gl.Call("getExtension", "WEBGL_lose_context")
|
||||||
|
|
||||||
theContext = c
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) reset() error {
|
func (c *Context) reset() error {
|
||||||
@ -154,6 +158,8 @@ func (c *Context) reset() error {
|
|||||||
c.lastViewportWidth = 0
|
c.lastViewportWidth = 0
|
||||||
c.lastViewportHeight = 0
|
c.lastViewportHeight = 0
|
||||||
c.lastCompositeMode = graphics.CompositeModeUnknown
|
c.lastCompositeMode = graphics.CompositeModeUnknown
|
||||||
|
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("enable", blend)
|
gl.Call("enable", blend)
|
||||||
c.BlendFunc(graphics.CompositeModeSourceOver)
|
c.BlendFunc(graphics.CompositeModeSourceOver)
|
||||||
@ -169,11 +175,13 @@ func (c *Context) BlendFunc(mode graphics.CompositeMode) {
|
|||||||
c.lastCompositeMode = mode
|
c.lastCompositeMode = mode
|
||||||
s, d := mode.Operations()
|
s, d := mode.Operations()
|
||||||
s2, d2 := convertOperation(s), convertOperation(d)
|
s2, d2 := convertOperation(s), convertOperation(d)
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("blendFunc", int(s2), int(d2))
|
gl.Call("blendFunc", int(s2), int(d2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) newTexture(width, height int) (textureNative, error) {
|
func (c *Context) newTexture(width, height int) (textureNative, error) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
t := gl.Call("createTexture")
|
t := gl.Call("createTexture")
|
||||||
if t == js.Null() {
|
if t == js.Null() {
|
||||||
@ -200,11 +208,13 @@ func (c *Context) newTexture(width, height int) (textureNative, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) bindFramebufferImpl(f framebufferNative) {
|
func (c *Context) bindFramebufferImpl(f framebufferNative) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("bindFramebuffer", framebuffer_, js.Value(f))
|
gl.Call("bindFramebuffer", framebuffer_, js.Value(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) framebufferPixels(f *framebuffer, width, height int) ([]byte, error) {
|
func (c *Context) framebufferPixels(f *framebuffer, width, height int) ([]byte, error) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
|
|
||||||
c.bindFramebuffer(f.native)
|
c.bindFramebuffer(f.native)
|
||||||
@ -221,11 +231,13 @@ func (c *Context) framebufferPixels(f *framebuffer, width, height int) ([]byte,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) bindTextureImpl(t textureNative) {
|
func (c *Context) bindTextureImpl(t textureNative) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("bindTexture", texture2d, js.Value(t))
|
gl.Call("bindTexture", texture2d, js.Value(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) deleteTexture(t textureNative) {
|
func (c *Context) deleteTexture(t textureNative) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
if !gl.Call("isTexture", js.Value(t)).Bool() {
|
if !gl.Call("isTexture", js.Value(t)).Bool() {
|
||||||
return
|
return
|
||||||
@ -237,12 +249,14 @@ func (c *Context) deleteTexture(t textureNative) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) isTexture(t textureNative) bool {
|
func (c *Context) isTexture(t textureNative) bool {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
return gl.Call("isTexture", js.Value(t)).Bool()
|
return gl.Call("isTexture", js.Value(t)).Bool()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) texSubImage2D(t textureNative, pixels []byte, x, y, width, height int) {
|
func (c *Context) texSubImage2D(t textureNative, pixels []byte, x, y, width, height int) {
|
||||||
c.bindTexture(t)
|
c.bindTexture(t)
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
// void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
// void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
// GLsizei width, GLsizei height,
|
// GLsizei width, GLsizei height,
|
||||||
@ -253,6 +267,7 @@ func (c *Context) texSubImage2D(t textureNative, pixels []byte, x, y, width, hei
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) newFramebuffer(t textureNative) (framebufferNative, error) {
|
func (c *Context) newFramebuffer(t textureNative) (framebufferNative, error) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
f := gl.Call("createFramebuffer")
|
f := gl.Call("createFramebuffer")
|
||||||
c.bindFramebuffer(framebufferNative(f))
|
c.bindFramebuffer(framebufferNative(f))
|
||||||
@ -266,11 +281,13 @@ func (c *Context) newFramebuffer(t textureNative) (framebufferNative, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) setViewportImpl(width, height int) {
|
func (c *Context) setViewportImpl(width, height int) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("viewport", 0, 0, width, height)
|
gl.Call("viewport", 0, 0, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) deleteFramebuffer(f framebufferNative) {
|
func (c *Context) deleteFramebuffer(f framebufferNative) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
if !gl.Call("isFramebuffer", js.Value(f)).Bool() {
|
if !gl.Call("isFramebuffer", js.Value(f)).Bool() {
|
||||||
return
|
return
|
||||||
@ -287,6 +304,7 @@ func (c *Context) deleteFramebuffer(f framebufferNative) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) newShader(shaderType shaderType, source string) (shader, error) {
|
func (c *Context) newShader(shaderType shaderType, source string) (shader, error) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
s := gl.Call("createShader", int(shaderType))
|
s := gl.Call("createShader", int(shaderType))
|
||||||
if s == js.Null() {
|
if s == js.Null() {
|
||||||
@ -304,11 +322,13 @@ func (c *Context) newShader(shaderType shaderType, source string) (shader, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) deleteShader(s shader) {
|
func (c *Context) deleteShader(s shader) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("deleteShader", js.Value(s))
|
gl.Call("deleteShader", js.Value(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) newProgram(shaders []shader) (program, error) {
|
func (c *Context) newProgram(shaders []shader) (program, error) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
v := gl.Call("createProgram")
|
v := gl.Call("createProgram")
|
||||||
if v == js.Null() {
|
if v == js.Null() {
|
||||||
@ -332,11 +352,13 @@ func (c *Context) newProgram(shaders []shader) (program, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) useProgram(p program) {
|
func (c *Context) useProgram(p program) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("useProgram", p.value)
|
gl.Call("useProgram", p.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) deleteProgram(p program) {
|
func (c *Context) deleteProgram(p program) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
if !gl.Call("isProgram", p.value).Bool() {
|
if !gl.Call("isProgram", p.value).Bool() {
|
||||||
return
|
return
|
||||||
@ -345,17 +367,20 @@ func (c *Context) deleteProgram(p program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) getUniformLocationImpl(p program, location string) uniformLocation {
|
func (c *Context) getUniformLocationImpl(p program, location string) uniformLocation {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
return uniformLocation(gl.Call("getUniformLocation", p.value, location))
|
return uniformLocation(gl.Call("getUniformLocation", p.value, location))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) uniformInt(p program, location string, v int) {
|
func (c *Context) uniformInt(p program, location string, v int) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
l := c.locationCache.GetUniformLocation(c, p, location)
|
l := c.locationCache.GetUniformLocation(c, p, location)
|
||||||
gl.Call("uniform1i", js.Value(l), v)
|
gl.Call("uniform1i", js.Value(l), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) uniformFloat(p program, location string, v float32) {
|
func (c *Context) uniformFloat(p program, location string, v float32) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
l := c.locationCache.GetUniformLocation(c, p, location)
|
l := c.locationCache.GetUniformLocation(c, p, location)
|
||||||
gl.Call("uniform1f", js.Value(l), v)
|
gl.Call("uniform1f", js.Value(l), v)
|
||||||
@ -366,6 +391,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (c *Context) uniformFloats(p program, location string, v []float32) {
|
func (c *Context) uniformFloats(p program, location string, v []float32) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
l := c.locationCache.GetUniformLocation(c, p, location)
|
l := c.locationCache.GetUniformLocation(c, p, location)
|
||||||
switch len(v) {
|
switch len(v) {
|
||||||
@ -383,29 +409,34 @@ func (c *Context) uniformFloats(p program, location string, v []float32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) getAttribLocationImpl(p program, location string) attribLocation {
|
func (c *Context) getAttribLocationImpl(p program, location string) attribLocation {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
return attribLocation(gl.Call("getAttribLocation", p.value, location).Int())
|
return attribLocation(gl.Call("getAttribLocation", p.value, location).Int())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) vertexAttribPointer(p program, location string, size int, dataType DataType, stride int, offset int) {
|
func (c *Context) vertexAttribPointer(p program, location string, size int, dataType DataType, stride int, offset int) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
l := c.locationCache.GetAttribLocation(c, p, location)
|
||||||
gl.Call("vertexAttribPointer", int(l), size, int(dataType), false, stride, offset)
|
gl.Call("vertexAttribPointer", int(l), size, int(dataType), false, stride, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) enableVertexAttribArray(p program, location string) {
|
func (c *Context) enableVertexAttribArray(p program, location string) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
l := c.locationCache.GetAttribLocation(c, p, location)
|
||||||
gl.Call("enableVertexAttribArray", int(l))
|
gl.Call("enableVertexAttribArray", int(l))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) disableVertexAttribArray(p program, location string) {
|
func (c *Context) disableVertexAttribArray(p program, location string) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
l := c.locationCache.GetAttribLocation(c, p, location)
|
l := c.locationCache.GetAttribLocation(c, p, location)
|
||||||
gl.Call("disableVertexAttribArray", int(l))
|
gl.Call("disableVertexAttribArray", int(l))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) newArrayBuffer(size int) buffer {
|
func (c *Context) newArrayBuffer(size int) buffer {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
b := gl.Call("createBuffer")
|
b := gl.Call("createBuffer")
|
||||||
gl.Call("bindBuffer", int(arrayBuffer), js.Value(b))
|
gl.Call("bindBuffer", int(arrayBuffer), js.Value(b))
|
||||||
@ -414,6 +445,7 @@ func (c *Context) newArrayBuffer(size int) buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) newElementArrayBuffer(size int) buffer {
|
func (c *Context) newElementArrayBuffer(size int) buffer {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
b := gl.Call("createBuffer")
|
b := gl.Call("createBuffer")
|
||||||
gl.Call("bindBuffer", int(elementArrayBuffer), js.Value(b))
|
gl.Call("bindBuffer", int(elementArrayBuffer), js.Value(b))
|
||||||
@ -422,11 +454,13 @@ func (c *Context) newElementArrayBuffer(size int) buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) bindBuffer(bufferType bufferType, b buffer) {
|
func (c *Context) bindBuffer(bufferType bufferType, b buffer) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("bindBuffer", int(bufferType), js.Value(b))
|
gl.Call("bindBuffer", int(bufferType), js.Value(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) arrayBufferSubData(data []float32) {
|
func (c *Context) arrayBufferSubData(data []float32) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
arr := js.TypedArrayOf(data)
|
arr := js.TypedArrayOf(data)
|
||||||
gl.Call("bufferSubData", int(arrayBuffer), 0, arr)
|
gl.Call("bufferSubData", int(arrayBuffer), 0, arr)
|
||||||
@ -434,6 +468,7 @@ func (c *Context) arrayBufferSubData(data []float32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) elementArrayBufferSubData(data []uint16) {
|
func (c *Context) elementArrayBufferSubData(data []uint16) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
arr := js.TypedArrayOf(data)
|
arr := js.TypedArrayOf(data)
|
||||||
gl.Call("bufferSubData", int(elementArrayBuffer), 0, arr)
|
gl.Call("bufferSubData", int(elementArrayBuffer), 0, arr)
|
||||||
@ -441,26 +476,31 @@ func (c *Context) elementArrayBufferSubData(data []uint16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) deleteBuffer(b buffer) {
|
func (c *Context) deleteBuffer(b buffer) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("deleteBuffer", js.Value(b))
|
gl.Call("deleteBuffer", js.Value(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) DrawElements(len int, offsetInBytes int) {
|
func (c *Context) DrawElements(len int, offsetInBytes int) {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("drawElements", triangles, len, unsignedShort, offsetInBytes)
|
gl.Call("drawElements", triangles, len, unsignedShort, offsetInBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) maxTextureSizeImpl() int {
|
func (c *Context) maxTextureSizeImpl() int {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
return gl.Call("getParameter", maxTextureSize).Int()
|
return gl.Call("getParameter", maxTextureSize).Int()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) Flush() {
|
func (c *Context) Flush() {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.Call("flush")
|
gl.Call("flush")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) IsContextLost() bool {
|
func (c *Context) IsContextLost() bool {
|
||||||
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
return gl.Call("isContextLost").Bool()
|
return gl.Call("isContextLost").Bool()
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/internal/devicescale"
|
"github.com/hajimehoshi/ebiten/internal/devicescale"
|
||||||
"github.com/hajimehoshi/ebiten/internal/hooks"
|
"github.com/hajimehoshi/ebiten/internal/hooks"
|
||||||
"github.com/hajimehoshi/ebiten/internal/input"
|
"github.com/hajimehoshi/ebiten/internal/input"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/mainthread"
|
||||||
"github.com/hajimehoshi/ebiten/internal/opengl"
|
"github.com/hajimehoshi/ebiten/internal/opengl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -58,8 +59,6 @@ type userInterface struct {
|
|||||||
initWindowDecorated bool
|
initWindowDecorated bool
|
||||||
initIconImages []image.Image
|
initIconImages []image.Image
|
||||||
|
|
||||||
funcs chan func()
|
|
||||||
|
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +101,6 @@ func initialize() error {
|
|||||||
}
|
}
|
||||||
hideConsoleWindowOnWindows()
|
hideConsoleWindowOnWindows()
|
||||||
currentUI.window = window
|
currentUI.window = window
|
||||||
currentUI.funcs = make(chan func())
|
|
||||||
|
|
||||||
currentUI.window.MakeContextCurrent()
|
currentUI.window.MakeContextCurrent()
|
||||||
|
|
||||||
@ -120,23 +118,13 @@ func initialize() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunMainThreadLoop(ch <-chan error) error {
|
func Loop(ch <-chan error) error {
|
||||||
// This must be called on the main thread.
|
|
||||||
|
|
||||||
// TODO: Check this is done on the main thread.
|
|
||||||
currentUI.setRunning(true)
|
currentUI.setRunning(true)
|
||||||
defer func() {
|
if err := mainthread.Loop(ch); err != nil {
|
||||||
currentUI.setRunning(false)
|
|
||||||
}()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case f := <-currentUI.funcs:
|
|
||||||
f()
|
|
||||||
case err := <-ch:
|
|
||||||
// ch returns a value not only when an error occur but also it is closed.
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
currentUI.setRunning(false)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterface) isRunning() bool {
|
func (u *userInterface) isRunning() bool {
|
||||||
@ -217,27 +205,12 @@ func (u *userInterface) setInitIconImages(iconImages []image.Image) {
|
|||||||
u.m.Unlock()
|
u.m.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterface) runOnMainThread(f func() error) error {
|
|
||||||
if u.funcs == nil {
|
|
||||||
// already closed
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ch := make(chan struct{})
|
|
||||||
var err error
|
|
||||||
u.funcs <- func() {
|
|
||||||
err = f()
|
|
||||||
close(ch)
|
|
||||||
}
|
|
||||||
<-ch
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func ScreenSizeInFullscreen() (int, int) {
|
func ScreenSizeInFullscreen() (int, int) {
|
||||||
u := currentUI
|
u := currentUI
|
||||||
var v *glfw.VidMode
|
var v *glfw.VidMode
|
||||||
s := 0.0
|
s := 0.0
|
||||||
if u.isRunning() {
|
if u.isRunning() {
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
v = u.currentMonitor().GetVideoMode()
|
v = u.currentMonitor().GetVideoMode()
|
||||||
s = glfwScale()
|
s = glfwScale()
|
||||||
return nil
|
return nil
|
||||||
@ -255,7 +228,7 @@ func SetScreenSize(width, height int) bool {
|
|||||||
panic("ui: Run is not called yet")
|
panic("ui: Run is not called yet")
|
||||||
}
|
}
|
||||||
r := false
|
r := false
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
r = u.setScreenSize(width, height, u.scale, u.fullscreen(), u.vsync)
|
r = u.setScreenSize(width, height, u.scale, u.fullscreen(), u.vsync)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -268,7 +241,7 @@ func SetScreenScale(scale float64) bool {
|
|||||||
panic("ui: Run is not called yet")
|
panic("ui: Run is not called yet")
|
||||||
}
|
}
|
||||||
r := false
|
r := false
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
r = u.setScreenSize(u.width, u.height, scale, u.fullscreen(), u.vsync)
|
r = u.setScreenSize(u.width, u.height, scale, u.fullscreen(), u.vsync)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -281,7 +254,7 @@ func ScreenScale() float64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
s := 0.0
|
s := 0.0
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
s = u.scale
|
s = u.scale
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -302,7 +275,7 @@ func IsFullscreen() bool {
|
|||||||
return u.isInitFullscreen()
|
return u.isInitFullscreen()
|
||||||
}
|
}
|
||||||
b := false
|
b := false
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
b = u.fullscreen()
|
b = u.fullscreen()
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -315,7 +288,7 @@ func SetFullscreen(fullscreen bool) {
|
|||||||
u.setInitFullscreen(fullscreen)
|
u.setInitFullscreen(fullscreen)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
u := currentUI
|
u := currentUI
|
||||||
u.setScreenSize(u.width, u.height, u.scale, fullscreen, u.vsync)
|
u.setScreenSize(u.width, u.height, u.scale, fullscreen, u.vsync)
|
||||||
return nil
|
return nil
|
||||||
@ -342,7 +315,7 @@ func SetVsyncEnabled(enabled bool) {
|
|||||||
u.m.Unlock()
|
u.m.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
u := currentUI
|
u := currentUI
|
||||||
u.setScreenSize(u.width, u.height, u.scale, u.fullscreen(), enabled)
|
u.setScreenSize(u.width, u.height, u.scale, u.fullscreen(), enabled)
|
||||||
return nil
|
return nil
|
||||||
@ -361,7 +334,7 @@ func SetWindowTitle(title string) {
|
|||||||
if !currentUI.isRunning() {
|
if !currentUI.isRunning() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = currentUI.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
currentUI.window.SetTitle(title)
|
currentUI.window.SetTitle(title)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -372,7 +345,7 @@ func SetWindowIcon(iconImages []image.Image) {
|
|||||||
currentUI.setInitIconImages(iconImages)
|
currentUI.setInitIconImages(iconImages)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = currentUI.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
currentUI.window.SetIcon(iconImages)
|
currentUI.window.SetIcon(iconImages)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -399,7 +372,7 @@ func ScreenPadding() (x0, y0, x1, y1 float64) {
|
|||||||
sx := 0.0
|
sx := 0.0
|
||||||
sy := 0.0
|
sy := 0.0
|
||||||
gs := 0.0
|
gs := 0.0
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
sx = float64(u.width) * u.actualScreenScale()
|
sx = float64(u.width) * u.actualScreenScale()
|
||||||
sy = float64(u.height) * u.actualScreenScale()
|
sy = float64(u.height) * u.actualScreenScale()
|
||||||
gs = glfwScale()
|
gs = glfwScale()
|
||||||
@ -424,7 +397,7 @@ func adjustCursorPosition(x, y int) (int, int) {
|
|||||||
}
|
}
|
||||||
ox, oy, _, _ := ScreenPadding()
|
ox, oy, _, _ := ScreenPadding()
|
||||||
s := 0.0
|
s := 0.0
|
||||||
_ = currentUI.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
s = currentUI.actualScreenScale()
|
s = currentUI.actualScreenScale()
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -442,7 +415,7 @@ func IsCursorVisible() bool {
|
|||||||
return u.isInitCursorVisible()
|
return u.isInitCursorVisible()
|
||||||
}
|
}
|
||||||
v := false
|
v := false
|
||||||
_ = currentUI.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
v = currentUI.window.GetInputMode(glfw.CursorMode) == glfw.CursorNormal
|
v = currentUI.window.GetInputMode(glfw.CursorMode) == glfw.CursorNormal
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -455,7 +428,7 @@ func SetCursorVisible(visible bool) {
|
|||||||
u.setInitCursorVisible(visible)
|
u.setInitCursorVisible(visible)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = currentUI.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
c := glfw.CursorNormal
|
c := glfw.CursorNormal
|
||||||
if !visible {
|
if !visible {
|
||||||
c = glfw.CursorHidden
|
c = glfw.CursorHidden
|
||||||
@ -471,7 +444,7 @@ func IsWindowDecorated() bool {
|
|||||||
return u.isInitWindowDecorated()
|
return u.isInitWindowDecorated()
|
||||||
}
|
}
|
||||||
v := false
|
v := false
|
||||||
_ = currentUI.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
v = currentUI.window.GetAttrib(glfw.Decorated) == glfw.True
|
v = currentUI.window.GetAttrib(glfw.Decorated) == glfw.True
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -490,7 +463,7 @@ func SetWindowDecorated(decorated bool) {
|
|||||||
// TODO: Now SetAttrib doesn't exist on GLFW 3.2. Revisit later (#556).
|
// TODO: Now SetAttrib doesn't exist on GLFW 3.2. Revisit later (#556).
|
||||||
// If SetAttrib exists, the implementation would be:
|
// If SetAttrib exists, the implementation would be:
|
||||||
//
|
//
|
||||||
// _ = currentUI.runOnMainThread(func() error {
|
// _ = mainthread.Run(func() error {
|
||||||
// v := glfw.False
|
// v := glfw.False
|
||||||
// if decorated {
|
// if decorated {
|
||||||
// v = glfw.True
|
// v = glfw.True
|
||||||
@ -506,7 +479,7 @@ func DeviceScaleFactor() float64 {
|
|||||||
return devicescale.GetAt(u.currentMonitor().GetPos())
|
return devicescale.GetAt(u.currentMonitor().GetPos())
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
m := u.currentMonitor()
|
m := u.currentMonitor()
|
||||||
f = devicescale.GetAt(m.GetPos())
|
f = devicescale.GetAt(m.GetPos())
|
||||||
return nil
|
return nil
|
||||||
@ -516,10 +489,7 @@ func DeviceScaleFactor() float64 {
|
|||||||
|
|
||||||
func Run(width, height int, scale float64, title string, g GraphicsContext, mainloop bool) error {
|
func Run(width, height int, scale float64, title string, g GraphicsContext, mainloop bool) error {
|
||||||
u := currentUI
|
u := currentUI
|
||||||
// GLContext must be created before setting the screen size, which requires
|
_ = mainthread.Run(func() error {
|
||||||
// swapping buffers.
|
|
||||||
opengl.Init(currentUI.runOnMainThread)
|
|
||||||
_ = u.runOnMainThread(func() error {
|
|
||||||
// Get the monitor before showing the window.
|
// Get the monitor before showing the window.
|
||||||
//
|
//
|
||||||
// On Windows, there are two types of windows:
|
// On Windows, there are two types of windows:
|
||||||
@ -596,7 +566,7 @@ func (u *userInterface) updateGraphicsContext(g GraphicsContext) {
|
|||||||
actualScale := 0.0
|
actualScale := 0.0
|
||||||
sizeChanged := false
|
sizeChanged := false
|
||||||
// TODO: Is it possible to reduce 'runOnMainThread' calls?
|
// TODO: Is it possible to reduce 'runOnMainThread' calls?
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
actualScale = u.actualScreenScale()
|
actualScale = u.actualScreenScale()
|
||||||
if u.lastActualScale != actualScale {
|
if u.lastActualScale != actualScale {
|
||||||
u.forceSetScreenSize(u.width, u.height, u.scale, u.fullscreen(), u.vsync)
|
u.forceSetScreenSize(u.width, u.height, u.scale, u.fullscreen(), u.vsync)
|
||||||
@ -618,7 +588,7 @@ func (u *userInterface) updateGraphicsContext(g GraphicsContext) {
|
|||||||
|
|
||||||
func (u *userInterface) update(g GraphicsContext) error {
|
func (u *userInterface) update(g GraphicsContext) error {
|
||||||
shouldClose := false
|
shouldClose := false
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
shouldClose = u.window.ShouldClose()
|
shouldClose = u.window.ShouldClose()
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -626,7 +596,7 @@ func (u *userInterface) update(g GraphicsContext) error {
|
|||||||
return RegularTermination
|
return RegularTermination
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
if u.isInitFullscreen() {
|
if u.isInitFullscreen() {
|
||||||
u := currentUI
|
u := currentUI
|
||||||
u.setScreenSize(u.width, u.height, u.scale, true, u.vsync)
|
u.setScreenSize(u.width, u.height, u.scale, true, u.vsync)
|
||||||
@ -638,7 +608,7 @@ func (u *userInterface) update(g GraphicsContext) error {
|
|||||||
// This call is needed for initialization.
|
// This call is needed for initialization.
|
||||||
u.updateGraphicsContext(g)
|
u.updateGraphicsContext(g)
|
||||||
|
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
u.pollEvents()
|
u.pollEvents()
|
||||||
defer hooks.ResumeAudio()
|
defer hooks.ResumeAudio()
|
||||||
for !u.isRunnableInBackground() && u.window.GetAttrib(glfw.Focused) == 0 {
|
for !u.isRunnableInBackground() && u.window.GetAttrib(glfw.Focused) == 0 {
|
||||||
@ -665,7 +635,7 @@ func (u *userInterface) update(g GraphicsContext) error {
|
|||||||
|
|
||||||
func (u *userInterface) loop(g GraphicsContext) error {
|
func (u *userInterface) loop(g GraphicsContext) error {
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
glfw.Terminate()
|
glfw.Terminate()
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -683,7 +653,7 @@ func (u *userInterface) loop(g GraphicsContext) error {
|
|||||||
// before swapping buffers.
|
// before swapping buffers.
|
||||||
opengl.GetContext().BeforeSwapping()
|
opengl.GetContext().BeforeSwapping()
|
||||||
|
|
||||||
_ = u.runOnMainThread(func() error {
|
_ = mainthread.Run(func() error {
|
||||||
if !vsync {
|
if !vsync {
|
||||||
u.swapBuffers()
|
u.swapBuffers()
|
||||||
return nil
|
return nil
|
||||||
|
@ -357,7 +357,7 @@ func init() {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunMainThreadLoop(ch <-chan error) error {
|
func Loop(ch <-chan error) error {
|
||||||
return <-ch
|
return <-ch
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,9 +366,6 @@ func Run(width, height int, scale float64, title string, g GraphicsContext, main
|
|||||||
document.Set("title", title)
|
document.Set("title", title)
|
||||||
u.setScreenSize(width, height, scale, u.fullscreen)
|
u.setScreenSize(width, height, scale, u.fullscreen)
|
||||||
canvas.Call("focus")
|
canvas.Call("focus")
|
||||||
if err := opengl.Init(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return u.loop(g)
|
return u.loop(g)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,11 +166,10 @@ func Run(width, height int, scale float64, title string, g GraphicsContext, main
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunMainThreadLoop runs the main routine for gomobile-build.
|
// Loop runs the main routine for gomobile-build.
|
||||||
func RunMainThreadLoop(ch <-chan error) error {
|
func Loop(ch <-chan error) error {
|
||||||
go func() {
|
go func() {
|
||||||
// As mobile apps never ends, RunMainThreadLoop can't return.
|
// As mobile apps never ends, Loop can't return. Just panic here.
|
||||||
// Just panic here.
|
|
||||||
err := <-ch
|
err := <-ch
|
||||||
panic(err)
|
panic(err)
|
||||||
}()
|
}()
|
||||||
|
2
run.go
2
run.go
@ -318,7 +318,7 @@ func Run(f func(*Image) error, width, height int, scale float64, title string) e
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
// TODO: Use context in Go 1.7?
|
// TODO: Use context in Go 1.7?
|
||||||
if err := ui.RunMainThreadLoop(ch); err != nil {
|
if err := ui.Loop(ch); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user