Example #1
0
func main(f func(screen.Screen)) error {
	if tid := C.threadID(); tid != initThreadID {
		log.Fatalf("gldriver.Main called on thread %d, but gldriver.init ran on %d", tid, initThreadID)
	}

	mainCallback = f
	C.startDriver()
	return nil
}
Example #2
0
func main(f func(screen.Screen)) error {
	if gl.Version() == "GL_ES_2_0" {
		return errors.New("gldriver: ES 3 required on X11")
	}
	C.startDriver()
	glctx, worker = gl.NewContext()

	closec := make(chan struct{})
	go func() {
		f(theScreen)
		close(closec)
	}()

	// heartbeat is a channel that, at regular intervals, directs the select
	// below to also consider X11 events, not just Go events (channel
	// communications).
	//
	// TODO: select instead of poll. Note that knowing whether to call
	// C.processEvents needs to select on a file descriptor, and the other
	// cases below select on Go channels.
	heartbeat := time.NewTicker(time.Second / 60)
	workAvailable := worker.WorkAvailable()

	for {
		select {
		case <-closec:
			return nil
		case ctx := <-glcontextc:
			// TODO: do we need to synchronize with seeing a size event for
			// this window's context before or after calling makeCurrent?
			// Otherwise, are we racing with the gl.Viewport call? I've
			// occasionally seen a stale viewport, if the window manager sets
			// the window width and height to something other than that
			// requested by XCreateWindow, but it's not easily reproducible.
			C.makeCurrent(C.uintptr_t(ctx))
		case w := <-publishc:
			C.swapBuffers(C.uintptr_t(w.ctx.(uintptr)))
			w.publishDone <- screen.PublishResult{}
		case req := <-uic:
			ret := req.f()
			if req.retc != nil {
				req.retc <- ret
			}
		case <-heartbeat.C:
			C.processEvents()
		case <-workAvailable:
			worker.DoWork()
		}
	}
}