2016-11-22 09:59:24 -06:00
|
|
|
package pixelgl
|
|
|
|
|
2016-11-23 11:50:49 -06:00
|
|
|
import (
|
|
|
|
"runtime"
|
|
|
|
|
2016-11-23 15:27:30 -06:00
|
|
|
"github.com/go-gl/gl/v3.3-core/gl"
|
2016-11-23 11:50:49 -06:00
|
|
|
)
|
2016-11-22 09:59:24 -06:00
|
|
|
|
2016-12-30 10:53:47 -06:00
|
|
|
// Due to the limitations of OpenGL and operating systems, all OpenGL related calls must be
|
|
|
|
// done from the main thread.
|
2016-11-22 09:59:24 -06:00
|
|
|
|
2016-11-24 07:10:33 -06:00
|
|
|
var callQueue = make(chan func(), 32)
|
2016-11-22 09:59:24 -06:00
|
|
|
|
|
|
|
func init() {
|
2016-11-25 10:12:13 -06:00
|
|
|
runtime.LockOSThread()
|
|
|
|
}
|
|
|
|
|
2016-12-30 10:53:47 -06:00
|
|
|
// Run is essentialy the "main" function of the pixelgl package. Run this function from the
|
|
|
|
// main function (because that's guaranteed to run in the main thread).
|
2016-11-25 10:12:13 -06:00
|
|
|
//
|
2016-12-30 10:53:47 -06:00
|
|
|
// This function reserves the main thread for the OpenGL stuff and runs a supplied run function
|
|
|
|
// in a separate goroutine.
|
2016-11-25 10:12:13 -06:00
|
|
|
//
|
|
|
|
// Run returns when the provided run function finishes.
|
|
|
|
func Run(run func()) {
|
|
|
|
done := make(chan struct{})
|
|
|
|
|
2016-11-22 09:59:24 -06:00
|
|
|
go func() {
|
2016-11-25 10:12:13 -06:00
|
|
|
run()
|
|
|
|
close(done)
|
|
|
|
}()
|
|
|
|
|
|
|
|
loop:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case f := <-callQueue:
|
2016-11-22 09:59:24 -06:00
|
|
|
f()
|
2016-11-25 10:12:13 -06:00
|
|
|
case <-done:
|
|
|
|
break loop
|
2016-11-22 09:59:24 -06:00
|
|
|
}
|
2016-11-25 10:12:13 -06:00
|
|
|
}
|
2016-11-22 09:59:24 -06:00
|
|
|
}
|
|
|
|
|
2016-11-23 15:27:30 -06:00
|
|
|
// Init initializes OpenGL by loading the function pointers from the active OpenGL context.
|
2016-11-25 10:12:13 -06:00
|
|
|
// This function must be manually run inside the main thread (Do, DoErr, DoVal, etc.).
|
2016-11-23 15:27:30 -06:00
|
|
|
//
|
2016-12-30 10:53:47 -06:00
|
|
|
// It must be called under the presence of an active OpenGL context, e.g., always after calling
|
|
|
|
// window.MakeContextCurrent(). Also, always call this function when switching contexts.
|
2016-11-23 15:27:30 -06:00
|
|
|
func Init() {
|
2016-11-23 16:31:45 -06:00
|
|
|
err := gl.Init()
|
2016-11-23 15:27:30 -06:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2016-12-03 12:23:18 -06:00
|
|
|
gl.Enable(gl.BLEND)
|
|
|
|
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
|
2016-11-23 15:27:30 -06:00
|
|
|
}
|
|
|
|
|
2016-12-30 10:53:47 -06:00
|
|
|
// DoNoBlock executes a function inside the main OpenGL thread. DoNoBlock does not wait until
|
|
|
|
// the function finishes.
|
2016-11-24 07:10:33 -06:00
|
|
|
func DoNoBlock(f func()) {
|
|
|
|
callQueue <- f
|
|
|
|
}
|
|
|
|
|
2016-12-30 10:53:47 -06:00
|
|
|
// Do executes a function inside the main OpenGL thread. Do blocks until the function finishes.
|
2016-11-22 09:59:24 -06:00
|
|
|
//
|
|
|
|
// All OpenGL calls must be done in the dedicated thread.
|
|
|
|
func Do(f func()) {
|
2016-12-14 18:03:18 -06:00
|
|
|
done := make(chan struct{})
|
2016-11-22 09:59:24 -06:00
|
|
|
callQueue <- func() {
|
|
|
|
f()
|
2016-12-14 18:03:18 -06:00
|
|
|
close(done)
|
2016-11-22 09:59:24 -06:00
|
|
|
}
|
|
|
|
<-done
|
|
|
|
}
|
|
|
|
|
2016-11-25 10:12:13 -06:00
|
|
|
// DoErr executes a function inside the main OpenGL thread and returns an error to the called.
|
2016-11-22 09:59:24 -06:00
|
|
|
// DoErr blocks until the function finishes.
|
|
|
|
//
|
|
|
|
// All OpenGL calls must be done in the dedicated thread.
|
|
|
|
func DoErr(f func() error) error {
|
|
|
|
err := make(chan error)
|
|
|
|
callQueue <- func() {
|
|
|
|
err <- f()
|
|
|
|
}
|
|
|
|
return <-err
|
|
|
|
}
|
|
|
|
|
2016-11-25 10:12:13 -06:00
|
|
|
// DoVal executes a function inside the main OpenGL thread and returns a value to the caller.
|
2016-11-22 09:59:24 -06:00
|
|
|
// DoVal blocks until the function finishes.
|
|
|
|
//
|
2016-11-25 10:12:13 -06:00
|
|
|
// All OpenGL calls must be done in the main thread.
|
2016-11-22 09:59:24 -06:00
|
|
|
func DoVal(f func() interface{}) interface{} {
|
|
|
|
val := make(chan interface{})
|
|
|
|
callQueue <- func() {
|
|
|
|
val <- f()
|
|
|
|
}
|
|
|
|
return <-val
|
|
|
|
}
|