| OLD | NEW |
| (Empty) |
| 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 | |
| 6 | |
| 7 package app | |
| 8 | |
| 9 /* | |
| 10 #cgo CFLAGS: -x objective-c | |
| 11 #cgo LDFLAGS: -framework Foundation -framework UIKit -framework GLKit -framework
OpenGLES -framework QuartzCore | |
| 12 #include <sys/utsname.h> | |
| 13 #include <stdint.h> | |
| 14 #include <pthread.h> | |
| 15 | |
| 16 extern struct utsname sysInfo; | |
| 17 | |
| 18 void runApp(void); | |
| 19 void setContext(void* context); | |
| 20 uint64_t threadID(); | |
| 21 */ | |
| 22 import "C" | |
| 23 import ( | |
| 24 "log" | |
| 25 "runtime" | |
| 26 "sync" | |
| 27 "unsafe" | |
| 28 | |
| 29 "golang.org/x/mobile/geom" | |
| 30 "golang.org/x/mobile/gl" | |
| 31 ) | |
| 32 | |
| 33 var initThreadID uint64 | |
| 34 | |
| 35 func init() { | |
| 36 // Lock the goroutine responsible for initialization to an OS thread. | |
| 37 // This means the goroutine running main (and calling the run function | |
| 38 // below) is locked to the OS thread that started the program. This is | |
| 39 // necessary for the correct delivery of UIKit events to the process. | |
| 40 // | |
| 41 // A discussion on this topic: | |
| 42 // https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZB
elsYJ | |
| 43 runtime.LockOSThread() | |
| 44 initThreadID = uint64(C.threadID()) | |
| 45 } | |
| 46 | |
| 47 func run(callbacks Callbacks) { | |
| 48 if tid := uint64(C.threadID()); tid != initThreadID { | |
| 49 log.Fatalf("app.Run called on thread %d, but app.init ran on %d"
, tid, initThreadID) | |
| 50 } | |
| 51 cb = callbacks | |
| 52 C.runApp() | |
| 53 } | |
| 54 | |
| 55 // TODO(crawshaw): determine minimum iOS version and remove irrelevant devices. | |
| 56 var machinePPI = map[string]int{ | |
| 57 "i386": 163, // simulator | |
| 58 "x86_64": 163, // simulator | |
| 59 "iPod1,1": 163, // iPod Touch gen1 | |
| 60 "iPod2,1": 163, // iPod Touch gen2 | |
| 61 "iPod3,1": 163, // iPod Touch gen3 | |
| 62 "iPod4,1": 326, // iPod Touch gen4 | |
| 63 "iPod5,1": 326, // iPod Touch gen5 | |
| 64 "iPhone1,1": 163, // iPhone | |
| 65 "iPhone1,2": 163, // iPhone 3G | |
| 66 "iPhone2,1": 163, // iPhone 3GS | |
| 67 "iPad1,1": 132, // iPad gen1 | |
| 68 "iPad2,1": 132, // iPad gen2 | |
| 69 "iPad2,2": 132, // iPad gen2 GSM | |
| 70 "iPad2,3": 132, // iPad gen2 CDMA | |
| 71 "iPad2,4": 132, // iPad gen2 | |
| 72 "iPad2,5": 163, // iPad Mini gen1 | |
| 73 "iPad2,6": 163, // iPad Mini gen1 AT&T | |
| 74 "iPad2,7": 163, // iPad Mini gen1 VZ | |
| 75 "iPad3,1": 264, // iPad gen3 | |
| 76 "iPad3,2": 264, // iPad gen3 VZ | |
| 77 "iPad3,3": 264, // iPad gen3 AT&T | |
| 78 "iPad3,4": 264, // iPad gen4 | |
| 79 "iPad3,5": 264, // iPad gen4 AT&T | |
| 80 "iPad3,6": 264, // iPad gen4 VZ | |
| 81 "iPad4,1": 264, // iPad Air wifi | |
| 82 "iPad4,2": 264, // iPad Air LTE | |
| 83 "iPad4,3": 264, // iPad Air LTE China | |
| 84 "iPad4,4": 326, // iPad Mini gen2 wifi | |
| 85 "iPad4,5": 326, // iPad Mini gen2 LTE | |
| 86 "iPhone3,1": 326, // iPhone 4 | |
| 87 "iPhone4,1": 326, // iPhone 4S | |
| 88 "iPhone5,1": 326, // iPhone 5 | |
| 89 "iPhone5,2": 326, // iPhone 5 | |
| 90 "iPhone5,3": 326, // iPhone 5c | |
| 91 "iPhone5,4": 326, // iPhone 5c | |
| 92 "iPhone6,1": 326, // iPhone 5s | |
| 93 "iPhone6,2": 326, // iPhone 5s | |
| 94 "iPhone7,1": 401, // iPhone 6 Plus | |
| 95 "iPhone7,2": 326, // iPhone 6 | |
| 96 } | |
| 97 | |
| 98 func ppi() int { | |
| 99 // TODO(crawshaw): use lookup table to get the correct PPI. | |
| 100 //C.uname(&C.sysInfo) | |
| 101 //machine := C.GoString(C.sysInfo.machine) | |
| 102 //return machinePPI[machine] | |
| 103 return 326 | |
| 104 } | |
| 105 | |
| 106 //export setGeom | |
| 107 func setGeom(width, height int) { | |
| 108 geom.PixelsPerPt = float32(ppi()) / 72 | |
| 109 geom.Width = geom.Pt(float32(width) / geom.PixelsPerPt) | |
| 110 geom.Height = geom.Pt(float32(height) / geom.PixelsPerPt) | |
| 111 } | |
| 112 | |
| 113 func initGL() { | |
| 114 } | |
| 115 | |
| 116 var cb Callbacks | |
| 117 var initGLOnce sync.Once | |
| 118 | |
| 119 //export drawgl | |
| 120 func drawgl(ctx uintptr) { | |
| 121 // The call to lockContext loads the OpenGL context into | |
| 122 // thread-local storage for use by the underlying GL calls | |
| 123 // done in the user's Draw function. We need to stay on | |
| 124 // the same thread throughout Draw, so we LockOSThread. | |
| 125 runtime.LockOSThread() | |
| 126 C.setContext(unsafe.Pointer(ctx)) | |
| 127 | |
| 128 initGLOnce.Do(initGL) | |
| 129 | |
| 130 // TODO not here? | |
| 131 gl.ClearColor(0, 0, 0, 1) | |
| 132 gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) | |
| 133 if cb.Draw != nil { | |
| 134 cb.Draw() | |
| 135 } | |
| 136 | |
| 137 // TODO | |
| 138 //C.unlockContext(ctx) | |
| 139 | |
| 140 // This may unlock the original main thread, but that's OK, | |
| 141 // because by the time it does the thread has already entered | |
| 142 // C.runApp, which won't give the thread up. | |
| 143 runtime.UnlockOSThread() | |
| 144 } | |
| OLD | NEW |