From 5043d0629500a77155f9608b7a7dbf0d77069c28 Mon Sep 17 00:00:00 2001
From: faiface <faiface@ksp.sk>
Date: Fri, 25 Nov 2016 17:12:13 +0100
Subject: [PATCH] change pixelgl, so that it runs on the main thread

---
 pixelgl/thread.go | 43 +++++++++++++++++++++++++++++++------------
 1 file changed, 31 insertions(+), 12 deletions(-)

diff --git a/pixelgl/thread.go b/pixelgl/thread.go
index 6153c20..9fc2537 100644
--- a/pixelgl/thread.go
+++ b/pixelgl/thread.go
@@ -7,23 +7,42 @@ import (
 	"github.com/go-gl/gl/v3.3-core/gl"
 )
 
-// Due to the existance and usage of thread-local variables by OpenGL, it's recommended to
-// execute all OpenGL calls from a single dedicated thread. This file defines functions to make
-// it possible.
+// Due to the limitations of OpenGL and operating systems, all OpenGL related calls must be done from the main thread.
 
 var callQueue = make(chan func(), 32)
 
 func init() {
+	runtime.LockOSThread()
+}
+
+// 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).
+//
+// This function reserves the main thread for the OpenGL stuff and runs a supplied run function in a
+// separate goroutine.
+//
+// Run returns when the provided run function finishes.
+func Run(run func()) {
+	done := make(chan struct{})
+
 	go func() {
-		runtime.LockOSThread()
-		for f := range callQueue {
+		run()
+		close(done)
+	}()
+
+loop:
+	for {
+		select {
+		case f := <-callQueue:
 			f()
+		case <-done:
+			break loop
 		}
-	}()
+	}
 }
 
 // Init initializes OpenGL by loading the function pointers from the active OpenGL context.
-// This function must be manually run inside the dedicated thread (Do, DoErr, DoVal, etc.).
+// This function must be manually run inside the main thread (Do, DoErr, DoVal, etc.).
 //
 // 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.
@@ -34,13 +53,13 @@ func Init() {
 	}
 }
 
-// DoNoBlock executes a function inside a dedicated OpenGL thread.
+// DoNoBlock executes a function inside the main OpenGL thread.
 // DoNoBlock does not wait until the function finishes.
 func DoNoBlock(f func()) {
 	callQueue <- f
 }
 
-// Do executes a function inside a dedicated OpenGL thread.
+// Do executes a function inside the main OpenGL thread.
 // Do blocks until the function finishes.
 //
 // All OpenGL calls must be done in the dedicated thread.
@@ -53,7 +72,7 @@ func Do(f func()) {
 	<-done
 }
 
-// DoErr executes a function inside a dedicated OpenGL thread and returns an error to the called.
+// DoErr executes a function inside the main OpenGL thread and returns an error to the called.
 // DoErr blocks until the function finishes.
 //
 // All OpenGL calls must be done in the dedicated thread.
@@ -65,10 +84,10 @@ func DoErr(f func() error) error {
 	return <-err
 }
 
-// DoVal executes a function inside a dedicated OpenGL thread and returns a value to the caller.
+// DoVal executes a function inside the main OpenGL thread and returns a value to the caller.
 // DoVal blocks until the function finishes.
 //
-// All OpenGL calls must be done in the dedicated thread.
+// All OpenGL calls must be done in the main thread.
 func DoVal(f func() interface{}) interface{} {
 	val := make(chan interface{})
 	callQueue <- func() {
-- 
GitLab