github.com/c-darwin/mobile@v0.0.0-20160313183840-ff625c46f7c9/gl/work.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin linux 6 7 package gl 8 9 /* 10 #cgo darwin,amd64 LDFLAGS: -framework OpenGL 11 #cgo darwin,arm LDFLAGS: -framework OpenGLES 12 #cgo darwin,arm64 LDFLAGS: -framework OpenGLES 13 #cgo linux LDFLAGS: -lGLESv2 14 15 #cgo darwin,amd64 CFLAGS: -Dos_osx 16 #cgo darwin,arm CFLAGS: -Dos_ios 17 #cgo darwin,arm64 CFLAGS: -Dos_ios 18 #cgo linux CFLAGS: -Dos_linux 19 20 #include <stdint.h> 21 #include "work.h" 22 23 struct fnargs cargs[10]; 24 uintptr_t ret; 25 26 void process(int count) { 27 int i; 28 for (i = 0; i < count; i++) { 29 processFn(&cargs[i]); 30 } 31 } 32 */ 33 import "C" 34 35 // work is a queue of calls to execute. 36 var work = make(chan call, 10) 37 38 // retvalue is sent a return value when blocking calls complete. 39 // It is safe to use a global unbuffered channel here as calls 40 // cannot currently be made concurrently. 41 // 42 // TODO: the comment above about concurrent calls isn't actually true: package 43 // app calls package gl, but it has to do so in a separate goroutine, which 44 // means that its gl calls (which may be blocking) can race with other gl calls 45 // in the main program. We should make it safe to issue blocking gl calls 46 // concurrently, or get the gl calls out of package app, or both. 47 var retvalue = make(chan C.uintptr_t) 48 49 type call struct { 50 args C.struct_fnargs 51 blocking bool 52 } 53 54 func enqueue(c call) C.uintptr_t { 55 work <- c 56 57 select { 58 case workAvailable <- struct{}{}: 59 default: 60 } 61 62 if c.blocking { 63 return <-retvalue 64 } 65 return 0 66 } 67 68 var ( 69 workAvailable = make(chan struct{}, 1) 70 // WorkAvailable communicates when DoWork should be called. 71 // 72 // This is an internal implementation detail and should only be used by the 73 // github.com/c-darwin/mobile/app package. 74 WorkAvailable <-chan struct{} = workAvailable 75 ) 76 77 // DoWork performs any pending OpenGL calls. 78 // 79 // This is an internal implementation detail and should only be used by the 80 // github.com/c-darwin/mobile/app package. 81 func DoWork() { 82 queue := make([]call, 0, len(work)) 83 for { 84 // Wait until at least one piece of work is ready. 85 // Accumulate work until a piece is marked as blocking. 86 select { 87 case w := <-work: 88 queue = append(queue, w) 89 default: 90 return 91 } 92 blocking := queue[len(queue)-1].blocking 93 enqueue: 94 for len(queue) < cap(queue) && !blocking { 95 select { 96 case w := <-work: 97 queue = append(queue, w) 98 blocking = queue[len(queue)-1].blocking 99 default: 100 break enqueue 101 } 102 } 103 104 // Process the queued GL functions. 105 for i, q := range queue { 106 C.cargs[i] = q.args 107 } 108 C.process(C.int(len(queue))) 109 110 // Cleanup and signal. 111 queue = queue[:0] 112 if blocking { 113 retvalue <- C.ret 114 } 115 } 116 } 117 118 func glBoolean(b bool) C.uintptr_t { 119 if b { 120 return TRUE 121 } 122 return FALSE 123 }