├── .gitignore ├── LICENSE.txt ├── Makefile ├── README.md ├── android.yml ├── android ├── android.go ├── cgo_helpers.c ├── cgo_helpers.go ├── cgo_helpers.h ├── const.go ├── doc.go ├── helpers.go ├── jni.go ├── jni_call.c ├── jni_call.h ├── jni_classes.go ├── jni_util.go ├── jvalue.go ├── sensors.go ├── types.go └── window.go ├── app ├── app.c ├── app.go ├── assets.go ├── events.go ├── internal │ └── callfn │ │ ├── callfn.go │ │ ├── callfn_386.s │ │ ├── callfn_amd64.s │ │ ├── callfn_arm.s │ │ └── callfn_arm64.s ├── logging.go └── queue.go ├── cmd └── android-project │ ├── LICENSE.txt │ ├── Makefile │ ├── README.md │ ├── bindata.go │ ├── main.go │ ├── templates.go │ └── templates │ ├── build.xml.tpl │ ├── local.properties.tpl │ ├── proguard-project.txt.tpl │ └── project.properties.tpl ├── egl.yml ├── egl ├── cgo_helpers.go ├── cgo_helpers.h ├── const.go ├── defaults.go ├── display_handle.go ├── doc.go ├── egl.go ├── errors.go └── types.go ├── example-egl ├── .gitignore ├── README.md ├── android │ ├── build.gradle │ └── src │ │ └── main │ │ └── AndroidManifest.xml ├── bash_script │ ├── build_go.sh │ └── build_toolchain.sh ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── main.go ├── sensor.go └── settings.gradle ├── example-x86 ├── .gitignore ├── Makefile ├── README.md ├── android │ ├── AndroidManifest.xml │ ├── Makefile │ └── jni │ │ ├── Android.mk │ │ └── Application.mk └── main.go ├── examples ├── build-android.sh ├── minimal │ ├── README.md │ ├── android │ │ ├── .gitignore │ │ ├── app │ │ │ ├── build.gradle │ │ │ └── src │ │ │ │ └── main │ │ │ │ └── AndroidManifest.xml │ │ ├── build.gradle │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ └── settings.gradle │ └── main.go └── tests │ ├── README.md │ ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ └── main │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ └── settings.gradle │ ├── assets.go │ ├── assets │ └── testAsset │ ├── createTestAsset.go │ ├── main.go │ └── tests.go ├── gles.yml ├── gles ├── cgo_helpers.go ├── cgo_helpers.h ├── const.go ├── doc.go ├── gles.go └── types.go ├── gles2.yml ├── gles2 ├── cgo_helpers.go ├── cgo_helpers.h ├── const.go ├── doc.go ├── gles2.go └── types.go ├── gles3.yml ├── gles3 ├── cgo_helpers.go ├── cgo_helpers.h ├── const.go ├── doc.go ├── gles3.go └── types.go ├── gles31.yml ├── gles31 ├── cgo_helpers.go ├── cgo_helpers.h ├── const.go ├── doc.go ├── gles31.go └── types.go └── go.mod /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | *.iml 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright © 2016-2017 Maxim Kupriianov 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the “Software”), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CPP = $(shell ndk-which cpp) 2 | 3 | all: gen-android gen-egl gen-gles gen-gles2 gen-gles3 gen-gles31 4 | 5 | gen-android: 6 | CPP="$(CPP)" c-for-go -ccdefs=true android.yml 7 | 8 | gen-egl: 9 | c-for-go egl.yml 10 | 11 | gen-gles: 12 | c-for-go gles.yml 13 | 14 | gen-gles2: 15 | c-for-go gles2.yml 16 | 17 | gen-gles3: 18 | c-for-go gles3.yml 19 | 20 | gen-gles31: 21 | c-for-go gles31.yml 22 | 23 | clean: clean-egl clean-gles clean-gles2 clean-gles3 clean-gles31 24 | rm -f android/cgo_helpers.go android/cgo_helpers.h android/cgo_helpers.c 25 | rm -f android/doc.go android/types.go android/const.go 26 | rm -f android/android.go 27 | 28 | clean-egl: 29 | rm -f egl/cgo_helpers.go egl/cgo_helpers.h egl/cgo_helpers.c 30 | rm -f egl/doc.go egl/types.go egl/const.go 31 | rm -f egl/egl.go 32 | 33 | clean-gles: 34 | rm -f gles/cgo_helpers.go gles/cgo_helpers.h gles/cgo_helpers.c 35 | rm -f gles/doc.go gles/types.go gles/const.go 36 | rm -f gles/gles.go 37 | 38 | clean-gles2: 39 | rm -f gles2/cgo_helpers.go gles2/cgo_helpers.h gles2/cgo_helpers.c 40 | rm -f gles2/doc.go gles2/types.go gles2/const.go 41 | rm -f gles2/gles2.go 42 | 43 | clean-gles3: 44 | rm -f gles3/cgo_helpers.go gles3/cgo_helpers.h gles3/cgo_helpers.c 45 | rm -f gles3/doc.go gles3/types.go gles3/const.go 46 | rm -f gles3/gles3.go 47 | 48 | clean-gles31: 49 | rm -f gles31/cgo_helpers.go gles31/cgo_helpers.h gles31/cgo_helpers.c 50 | rm -f gles31/doc.go gles31/types.go gles31/const.go 51 | rm -f gles31/gles31.go 52 | 53 | test: 54 | cd android && go build 55 | 56 | test-egl: 57 | cd egl && go build 58 | 59 | test-gles: 60 | cd gles && go build 61 | 62 | test-gles2: 63 | cd gles2 && go build 64 | 65 | test-gles3: 66 | cd gles3 && go build 67 | 68 | test-gles31: 69 | cd gles31 && go build 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | android-go [![Go Report Card](https://goreportcard.com/badge/github.com/xlab/android-go)](https://goreportcard.com/report/github.com/xlab/android-go) ![Lines of Code](https://img.shields.io/badge/lines-7K-blue.svg) 2 | ========== 3 | 4 | The **android-go** project aims to provide a platform (namely an SDK) for 5 | writing native Android apps in Go programming language. All things here were 6 | designed to be less coupled as possible, thus maintaining a great level of 7 | flexibility while keeping things simple and easy to use. The approach and tools 8 | are different from [gomobile](https://github.com/golang/mobile), please 9 | distinguish them apart. 10 | 11 | The project was one of [the best Go Newsletter items of 2016](http://golangweekly.com/issues/140). In this final issue of the year, they look back at the most popular Go news and links of 2016. 🌟 12 | 13 | ❗️Important! Please see [cmd/android-project](/cmd/android-project) utility that replaces the original `android` from SDK that has been stripped in latest SDK releases. All example Makefiles were updated, I advise you to do the same rather than stick to old SDK versions. 14 | 15 | ## Project structure 16 | 17 | ### android [![GoDoc](https://godoc.org/github.com/xlab/android-go/android?status.svg)](https://godoc.org/github.com/xlab/android-go/android) 18 | 19 | Package **android** provides Go bindings for the Android NDK API. They've been 20 | automatically generated by [c-for-go](https://git.io/c-for-go) using the 21 | official NDK headers from `android-23` platform. Keep in mind that different NDK 22 | platforms may implement different sets of API available, thus some of features 23 | used by this binding may not be available in older versions of platform. But I 24 | tested with the `android-21` toolchain and got no issues. Some files, like 25 | [android/sensors.go] for example, have been written by hand to expose some 26 | features that CGO does not handle well. 27 | 28 | This package allows to write code that works directly with NDK API, bypassing 29 | all the CGO bookkeeping and boilerplate bloat in your code. But safety is 30 | strictly advised. There is also a JNI calling mechanism that allows easy interactions with 31 | Java VM and exposes the full potential of Android SDK! See [android/jni_util.go] for example 32 | of toggling Android keyboard and other JNI-based utils. 33 | 34 | **Example usages:** [app/queue.go], [example], [example-egl], [nk-android]. 35 | 36 | [app/queue.go]: https://github.com/xlab/android-go/blob/master/app/queue.go 37 | [android/jni_util.go]: https://github.com/xlab/android-go/blob/master/android/jni_util.go 38 | [android/sensors.go]: https://github.com/xlab/android-go/blob/master/android/sensors.go 39 | 40 | ### cmd/android-project 41 | 42 | Tool **android-project** is a simple replacement for infamous `android` util from Android SDK, prior to Android SDK Tools [Revision 25.3.0 (March 2017) release](https://developer.android.com/studio/releases/sdk-tools.html) when they dropped that util abruptly and got back a stripped version later. Needs to be installed first: 43 | 44 | ``` 45 | go get github.com/xlab/android-go/cmd/android-project 46 | ``` 47 | 48 | ### app [![GoDoc](https://godoc.org/github.com/xlab/android-go/app?status.svg)](https://godoc.org/github.com/xlab/android-go/app) 49 | 50 | Package **app** implements a NativeActivity glue layer required to properly 51 | handle the startup process and the native activity events. Import this package 52 | into your Go application to make it Android-compatible. Some pieces required 53 | for a proper `main.main` trampoline have been borrowed from gomobile, the 54 | absolute minimum to get this stuff invokable as a native activity. Most of the 55 | code in this package provides wrappers around NativeActivity event callbacks. 56 | 57 | **Example usages:** [example], [example-egl], [nk-android]. 58 | 59 | [example]: https://github.com/xlab/android-go/tree/master/example 60 | [example-egl]: https://github.com/xlab/android-go/tree/master/example-egl 61 | 62 | ### egl [![GoDoc](https://godoc.org/github.com/xlab/android-go/egl?status.svg)](https://godoc.org/github.com/xlab/android-go/egl) 63 | 64 | Package **egl** provides Go bindings for EGL API. They've been automatically 65 | generated by [c-for-go](https://c-for-go.com) using the official NDK headers 66 | from `android-23` platform. All functions have their reference to the offical 67 | Khronos documentation. Some files, like [egl/errors.go] for example, have been 68 | written by hand to expose some features that would make it more idiomatic in the 69 | Go world. 70 | 71 | Examples of usage in conjuction with the **android** package: [example-egl], [nk-android]. 72 | 73 | [egl/errors.go]: https://github.com/xlab/android-go/blob/master/egl/errors.go 74 | 75 | ### gles [![GoDoc](https://godoc.org/github.com/xlab/android-go/gles?status.svg)](https://godoc.org/github.com/xlab/android-go/gles) 76 | 77 | Package **gles** provides Go bindings for the OpenGL ES v1 API. They've been 78 | automatically generated by [c-for-go](https://c-for-go.com) using the 79 | official NDK headers from `android-23` platform. All functions have their 80 | reference to the offical documentation. 81 | 82 | Example of usage in conjuction with the **android** package: [example-egl]. 83 | 84 | ### gles2 [![GoDoc](https://godoc.org/github.com/xlab/android-go/gles2?status.svg)](https://godoc.org/github.com/xlab/android-go/gles2) 85 | 86 | Package **gles2** provides Go bindings for the OpenGL ES v2 API. They've been 87 | automatically generated by [c-for-go](https://c-for-go.com) using the 88 | official NDK headers from `android-23` platform. All functions have their 89 | reference to the offical documentation. 90 | 91 | Example of usage in conjuction with the **android** package: [nk-android]. 92 | 93 | ### gles3 [![GoDoc](https://godoc.org/github.com/xlab/android-go/gles3?status.svg)](https://godoc.org/github.com/xlab/android-go/gles3) 94 | 95 | Package **gles3** provides Go bindings for the OpenGL ES v3 API. They've been 96 | automatically generated by [c-for-go](https://c-for-go.com) using the 97 | official NDK headers from `android-23` platform. All functions have their 98 | reference to the offical documentation. 99 | 100 | Example of usage in conjuction with the **android** package: [nk-android]. 101 | 102 | ### gles31 [![GoDoc](https://godoc.org/github.com/xlab/android-go/gles31?status.svg)](https://godoc.org/github.com/xlab/android-go/gles31) 103 | 104 | Package **gles31** provides Go bindings for the OpenGL ES v3.1 API. They've been 105 | automatically generated by [c-for-go](https://c-for-go.com) using the 106 | official NDK headers from `android-23` platform. All functions have their 107 | reference to the offical documentation. The OpenGL ES computing API is supported. 108 | 109 | ## Examples 110 | 111 | Refer the example links to get more info about them. 112 | 113 | There are three examples. The first [example] is a template app showing how 114 | to create and build an Android application using the absolute minimum of code and 115 | boilerplate. It also shows the primitives of an activity and how to handle 116 | activity events, there is no visual part, so be ready to read the lines from the 117 | ADB logcat. If this one works correctly on your device, my congratulations. If 118 | not, please open an issue. 119 | 120 | The [example-egl] leverages all three packages together: **android**, **egl** 121 | and of course **gles** (OpenGL ES 1.0) to create an visual app that animates its color based 122 | on the accelerometer values. It also reads input events such as key events and 123 | multitouch motion events (with pressure, if supported by the device), you can 124 | check these events in the ADB logcat. Please see the video of the expected 125 | behaviour: 126 | 127 | [![Golang + EGL/GLES App on Android](https://img.youtube.com/vi/H2cafzATUEw/0.jpg)](https://www.youtube.com/watch?v=H2cafzATUEw) 128 | 129 | And recently I took [nuklear] package and implemented a few backends in Go, 130 | including two for Android that initialize OpenGL ES 2 or ES 3 context using 131 | **android**, **egl**, **gles2** and **gles3** packages. They also responsible 132 | for handling touch and other input events. So now it is possible to create GUI 133 | apps for Android, see [nk-android] for an example Nuklear GUI app. 134 | 135 | [nuklear]: http://github.com/golang-ui/nuklear 136 | [nk-android]: https://github.com/golang-ui/nuklear/tree/master/cmd/nk-android 137 | 138 | [![Nuklear GUI App written in Golang runs on Android](https://img.youtube.com/vi/3-MiceegZlM/0.jpg)](https://www.youtube.com/watch?v=3-MiceegZlM) 139 | 140 | Android keyboard toggling [video](https://goo.gl/photos/TFkYFKC48Re6RnbUA). 141 | 142 | ## On existing tools or why not just use Gomobile 143 | 144 | **TL;DR** it's a "three wheel bicycle" in terms of hacking flexibility. Conversely, this 145 | project tries to fill the niche by providing a platform that is minimal as 146 | possible and respects the bleeding-edge features such as OpenGL ES 3.1, ES 3.2 147 | and of course Vulkan API. 148 | 149 | GoMobile has different aims and motivation with a lot of implications. First of 150 | all, it has been grown as a bootstrap-script. That's it: a tool with a lot of 151 | hardcoded logic that helped to popularize Go on mobile platforms. Still provides a 152 | simple way to start building Android and iOS apps in no time, without diving 153 | deeply into any of the platform-specific complications. It provides a lot of wrappers and 154 | helpers that abstract all the platform-related boilerplate and logic away, 155 | making your apps look the same on any platform: Android, iOS, PC (Linux/OS 156 | X/Windows). 157 | 158 | Also, considering that binding feature of GoMobile, it's a good option to use 159 | when you already have lots of Java/Obj-C code and want to integrate some of Go 160 | libs into the project. The tool is mostly for experienced mobile developers who 161 | just want to try Go sometimes. They provide a framework that hides platform 162 | details, but they also may be to restrictive and limited due to this and can't 163 | be used for crazy experimenting stuff. 164 | 165 | An example: for Android developent, gomobile defaults to `r10` SDK with `android-15` 166 | stripped-down NDK, there is a lot of code written to automate this process and 167 | there is no way to override this environment, even by rewriting a lot of 168 | gomobile bootstrapping code. It's a great mess. I wasted too much time trying to 169 | switch to the `r12-beta1` SDK and the `android-23` NDK platform. Instead of providing 170 | a good document how to build the Go-based apps and incorporate them into any of 171 | the existing development process, GoMobile project introduces tons of 172 | hardcoded scripts. 173 | 174 | ## Contributing 175 | 176 | Feel free to share bugs, I expect a lot of weird cases. Please also share this 177 | project in social networks so more people would know how to write Go apps for 178 | Android that are not limited. 179 | 180 | ## License 181 | 182 | All the code except when stated otherwise is licensed under the [MIT license](/LICENSE.txt). 183 | -------------------------------------------------------------------------------- /android.yml: -------------------------------------------------------------------------------- 1 | --- 2 | GENERATOR: 3 | PackageName: android 4 | PackageDescription: "Package android provides Go bindings for the Android NDK API." 5 | PackageLicense: "THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS." 6 | FlagGroups: 7 | - {name: LDFLAGS, flags: [-landroid -llog]} 8 | Includes: 9 | - jni_call.h 10 | SysIncludes: 11 | - android/api-level.h 12 | - android/asset_manager.h 13 | - android/asset_manager_jni.h 14 | - android/configuration.h 15 | - android/input.h 16 | - android/keycodes.h 17 | - android/log.h 18 | - android/looper.h 19 | - android/native_activity.h 20 | - android/native_window.h 21 | - android/native_window_jni.h 22 | - android/obb.h 23 | - android/rect.h 24 | - android/sensor.h 25 | - android/storage_manager.h 26 | - android/tts.h 27 | - android/window.h 28 | - jni.h 29 | 30 | PARSER: 31 | Arch: arm 32 | Defines: 33 | __STDC_HOSTED__: null 34 | 35 | IncludePaths: 36 | - android 37 | # NOTE: Replace these paths if you want to re-generate. 38 | # NOTE: Can be processed only with -ccdefs cgogen option enabled. 39 | - /Users/xlab/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/include 40 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include 41 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include/linux 42 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include/android 43 | 44 | SourcesPaths: 45 | - api-level.h 46 | - asset_manager.h 47 | - asset_manager_jni.h 48 | - configuration.h 49 | - input.h 50 | - keycodes.h 51 | - log.h 52 | - looper.h 53 | - native_activity.h 54 | - native_window.h 55 | - native_window_jni.h 56 | - obb.h 57 | - rect.h 58 | - sensor.h 59 | - storage_manager.h 60 | - tts.h 61 | - window.h 62 | - jni.h 63 | - android/jni_call.h 64 | 65 | TRANSLATOR: 66 | ConstRules: 67 | defines: expand 68 | enum: expand 69 | MemTips: 70 | - {target: JavaVMAttachArgs$, self: bind} 71 | - {target: ^J, self: raw} 72 | - {target: AAssetManager$, self: raw} 73 | - {target: ANativeActivityCallbacks$, self: raw} 74 | TypeTips: 75 | type: 76 | - {target: ^jboolean$, self: plain} 77 | - {target: ^jbyte$, self: plain} 78 | - {target: ^jchar$, self: plain} 79 | - {target: ^jshort$, self: plain} 80 | - {target: ^jint$, self: plain} 81 | - {target: ^jlong$, self: plain} 82 | - {target: ^jfloat$, self: plain} 83 | - {target: ^jdouble$, self: plain} 84 | - {target: ^jsize$, self: plain} 85 | PtrTips: 86 | function: 87 | - {target: ^__android} 88 | - {target: _DefineClass$, tips: [ref,arr,0,arr,size]} 89 | - {target: ^JNIEnv_CallNonvirtual, tips: [ref,0,0,0,arr]} 90 | - {target: ^JNIEnv_Call, tips: [ref,0,0,arr]} 91 | - {target: ^JNIEnv_NewObject, tips: [ref,ref,0,arr]} 92 | - {target: ".", tips: [sref,sref,sref,sref,sref]} # ref by default for all 93 | 94 | Rules: 95 | global: 96 | - {action: accept, from: ^A} 97 | - {action: ignore, from: ^ABS} 98 | - {action: accept, from: ^android_Log} 99 | - {action: replace, from: ^android_Log, to: Log} 100 | - {action: replace, from: "(?i)^Android"} 101 | - {action: replace, from: ^A} 102 | function: 103 | - {action: accept, from: ^__android_log_write} 104 | - {action: replace, from: ^__android} 105 | - {action: accept, from: ^JNI} 106 | - {action: ignore, from: JNI_OnLoad} 107 | - {action: ignore, from: JNI_OnUnload} 108 | - {action: ignore, from: ANativeActivity_onCreate} 109 | - {action: ignore, from: ASensorManager_getSensorList} 110 | type: 111 | - {action: accept, from: ^J} 112 | - {action: accept, from: ^j} 113 | - {action: replace, from: "_t$"} 114 | const: 115 | - {action: accept, from: ^JNI} 116 | - {action: ignore, from: TTS_H$} 117 | - {transform: lower} 118 | - {transform: upper, from: "(?i)^JNI"} 119 | private: 120 | - {transform: unexport} 121 | post-global: 122 | - {transform: export} 123 | - {load: snakecase} 124 | -------------------------------------------------------------------------------- /android/cgo_helpers.c: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:44 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | #include "_cgo_export.h" 7 | #include "cgo_helpers.h" 8 | 9 | int ALooper_callbackFunc_7e6b484c(int fd, int events, void* data) { 10 | return looperCallbackFunc7E6B484C(fd, events, data); 11 | } 12 | 13 | void ANativeActivity_createFunc_76dce4(ANativeActivity* activity, void* savedState, unsigned int savedStateSize) { 14 | nativeActivityCreateFunc76DCE4(activity, savedState, savedStateSize); 15 | } 16 | 17 | void AStorageManager_obbCallbackFunc_e8b15c3e(char* filename, int state, void* data) { 18 | storageManagerObbCallbackFuncE8B15C3E(filename, state, data); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /android/cgo_helpers.h: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:44 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "jni_call.h" 24 | #include 25 | #pragma once 26 | 27 | #define __CGOGEN 1 28 | 29 | // ALooper_callbackFunc_7e6b484c is a proxy for callback ALooper_callbackFunc. 30 | int ALooper_callbackFunc_7e6b484c(int fd, int events, void* data); 31 | 32 | // ANativeActivity_createFunc_76dce4 is a proxy for callback ANativeActivity_createFunc. 33 | void ANativeActivity_createFunc_76dce4(ANativeActivity* activity, void* savedState, unsigned int savedStateSize); 34 | 35 | // AStorageManager_obbCallbackFunc_e8b15c3e is a proxy for callback AStorageManager_obbCallbackFunc. 36 | void AStorageManager_obbCallbackFunc_e8b15c3e(char* filename, int state, void* data); 37 | 38 | -------------------------------------------------------------------------------- /android/doc.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:44 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | /* 7 | Package android provides Go bindings for the Android NDK API. 8 | */ 9 | package android 10 | -------------------------------------------------------------------------------- /android/helpers.go: -------------------------------------------------------------------------------- 1 | package android 2 | 3 | type Unwind []func() 4 | 5 | func (u Unwind) Add(cleanup func()) { 6 | u = append(u, cleanup) 7 | } 8 | 9 | func (u Unwind) Unwind() { 10 | for i := len(u) - 1; i >= 0; i-- { 11 | u[i]() 12 | } 13 | } 14 | 15 | func (u Unwind) Discard() { 16 | if len(u) > 0 { 17 | u = u[:0] 18 | } 19 | } 20 | 21 | func orPanic(err error, finalizers ...func()) { 22 | if err != nil { 23 | for _, fn := range finalizers { 24 | fn() 25 | } 26 | panic(err) 27 | } 28 | } 29 | 30 | func s(str string) string { 31 | if str[len(str)-1] == '\x00' { 32 | return str 33 | } 34 | return str + "\x00" 35 | } 36 | -------------------------------------------------------------------------------- /android/jni.go: -------------------------------------------------------------------------------- 1 | package android 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | // JNICall attaches a JavaVM thread and does JNI stuff, provide a handler 9 | // that will work with JNIEnv and activity/context classes to invoke methods, 10 | // read fields of Android SDK. 11 | // 12 | // Caution: the call is not thread safe, also it must run from a thread-locked 13 | // goroutine, i.e. that's locked using runtime.LockOSThread(). The main android-go 14 | // goroutine is a such goroutine. 15 | func (a *NativeActivity) JNICall(fn func(env *JNIEnv, 16 | activity Jobject, activityClass, contextClass *Jclass) error) (err error) { 17 | a.Deref() 18 | if ret := JNIAttachCurrentThread(a.Vm, &a.Env, &JavaVMAttachArgs{ 19 | Version: JNIVersion16, 20 | Name: s("NativeThread"), 21 | }); ret == JNIErr { 22 | return errors.New("JNICall: JNIAttachCurrentThread failed") 23 | } 24 | defer JNIDetachCurrentThread(a.Vm) 25 | activityClass := JNIEnvGetObjectClass(a.Env, a.Clazz) 26 | contextClass := JNIEnvFindClass(a.Env, JClassContext.Name()) 27 | 28 | defer func(err *error) { 29 | if v := recover(); v != nil { 30 | *err = fmt.Errorf("JNICall handler failed: %v", v) 31 | } 32 | }(&err) 33 | err = fn(a.Env, a.Clazz, activityClass, contextClass) 34 | return err 35 | } 36 | 37 | // JNITypeSpec defines a Java VM Type Signature specification 38 | // that can be used to specify signatures of method args or class fields. 39 | type JNITypeSpec struct { 40 | // Signature specifies custom signature that will be used if provided. Expected non NULL-terminated. 41 | Signature string 42 | // Class specifies a class name of type, e.g. JNIClassString that will be used 43 | // to generate a proper Java VM type signature string. Not used if Signature is provided. 44 | Class className 45 | // IsArray specifies whether there should be an array. Not used if Signature is provided. 46 | IsArray bool 47 | } 48 | 49 | // Returns a NULL-terminated Java VM Type Signature for this spec. 50 | func (j JNITypeSpec) Sig() string { 51 | if len(j.Signature) > 0 { 52 | return j.Signature + "\x00" 53 | } 54 | return JNITypeSig(string(j.Class), j.IsArray) + "\x00" 55 | } 56 | 57 | // JNIMethodSig generates a NULL-terminated Java VM Type Signature of method. 58 | // See http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html 59 | func JNIMethodSig(ret JNITypeSpec, args ...JNITypeSpec) string { 60 | var argsStr string 61 | for _, arg := range args { 62 | if len(arg.Signature) > 0 { 63 | argsStr += arg.Signature 64 | continue 65 | } 66 | if len(arg.Class) > 0 { 67 | argsStr += JNITypeSig(string(arg.Class), arg.IsArray) 68 | } 69 | } 70 | var retStr string 71 | if len(ret.Signature) > 0 { 72 | retStr = ret.Signature 73 | } else if len(ret.Class) > 0 { 74 | retStr = JNITypeSig(string(ret.Class), ret.IsArray) 75 | } else { 76 | retStr = JNITypeSig(string(JVoid)) 77 | } 78 | sig := fmt.Sprintf("(%s)%s\x00", argsStr, retStr) 79 | return sig 80 | } 81 | 82 | // JNITypeSig generates a non-NULL terminated Java VM Type Signature string. 83 | // See http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html 84 | func JNITypeSig(name string, arr ...bool) string { 85 | var prefix string 86 | if len(arr) > 0 && arr[0] { 87 | prefix = "[" 88 | } 89 | switch className(name) { 90 | case JVoid: 91 | return prefix + "V" 92 | case JBoolean: 93 | return prefix + "Z" 94 | case JByte: 95 | return prefix + "B" 96 | case JChar: 97 | return prefix + "C" 98 | case JShort: 99 | return prefix + "S" 100 | case JInt: 101 | return prefix + "I" 102 | case JLong: 103 | return prefix + "J" 104 | case JFloat: 105 | return prefix + "F" 106 | case JDouble: 107 | return prefix + "D" 108 | default: 109 | return fmt.Sprintf("%sL%s;", prefix, name) 110 | } 111 | } 112 | 113 | type className string 114 | 115 | // Name returns a NULL-terminated class name. 116 | func (c className) Name() string { 117 | return string(c) + "\x00" 118 | } 119 | 120 | // Spec returns a ready JNITypeSpec for use in JNIMethodSig. 121 | func (c className) Spec(arr ...bool) JNITypeSpec { 122 | return JNITypeSpec{ 123 | Class: c, 124 | IsArray: len(arr) > 0 && arr[0], 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /android/jni_call.h: -------------------------------------------------------------------------------- 1 | #ifndef JNI_CALL_H 2 | #define JNI_CALL_H 3 | 4 | #include 5 | 6 | jint JNI_DestroyJavaVM(JavaVM* vm); 7 | jint JNI_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, JavaVMAttachArgs* thr_args); 8 | jint JNI_DetachCurrentThread(JavaVM* vm); 9 | jint JNI_GetEnv(JavaVM* vm, JNIEnv** p_env, jint version); 10 | jint JNI_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args); 11 | 12 | jint JNIEnv_GetVersion(JNIEnv* env); 13 | 14 | jclass JNIEnv_DefineClass(JNIEnv* env, const char* name, jobject obj, jbyte* buf, jsize bufLen); 15 | jclass JNIEnv_FindClass(JNIEnv* env, const char* name); 16 | 17 | jmethodID JNIEnv_FromReflectedMethod(JNIEnv* env, jobject obj); 18 | jfieldID JNIEnv_FromReflectedField(JNIEnv* env, jobject obj); 19 | jobject JNIEnv_ToReflectedMethod(JNIEnv* env, jclass clazz, jmethodID id, jboolean isStatic); 20 | 21 | jclass JNIEnv_GetSuperclass(JNIEnv* env, jclass clazz); 22 | jboolean JNIEnv_IsAssignableFrom(JNIEnv* env, jclass clazz1, jclass clazz2); 23 | 24 | jobject JNIEnv_ToReflectedField(JNIEnv* env, jclass clazz, jfieldID id, jboolean isStatic); 25 | 26 | jint JNIEnv_Throw(JNIEnv* env, jthrowable ex); 27 | jint JNIEnv_ThrowNew(JNIEnv* env, jclass clazz, const char* msg); 28 | jthrowable JNIEnv_ExceptionOccurred(JNIEnv* env); 29 | void JNIEnv_ExceptionDescribe(JNIEnv* env); 30 | void JNIEnv_ExceptionClear(JNIEnv* env); 31 | void JNIEnv_FatalError(JNIEnv* env, const char* msg); 32 | 33 | jint JNIEnv_PushLocalFrame(JNIEnv* env, jint capacity); 34 | jobject JNIEnv_PopLocalFrame(JNIEnv* env, jobject obj); 35 | 36 | jobject JNIEnv_NewGlobalRef(JNIEnv* env, jobject ref); 37 | void JNIEnv_DeleteGlobalRef(JNIEnv* env, jobject ref); 38 | void JNIEnv_DeleteLocalRef(JNIEnv* env, jobject ref); 39 | jboolean JNIEnv_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2); 40 | 41 | jobject JNIEnv_NewLocalRef(JNIEnv* env, jobject obj); 42 | jint JNIEnv_EnsureLocalCapacity(JNIEnv* env, jint capacity); 43 | 44 | jobject JNIEnv_AllocObject(JNIEnv* env, jclass clazz); 45 | jobject JNIEnv_NewObject(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 46 | 47 | jclass JNIEnv_GetObjectClass(JNIEnv* env, jobject obj); 48 | jboolean JNIEnv_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz); 49 | jmethodID JNIEnv_GetMethodID(JNIEnv* env, jclass clazz, const char* name, const char* sig); 50 | 51 | jobject JNIEnv_CallObjectMethod(JNIEnv* env, jobject obj, jmethodID id, jvalue* args); 52 | jboolean JNIEnv_CallBooleanMethod(JNIEnv* env, jobject obj, jmethodID id, jvalue* args); 53 | jbyte JNIEnv_CallByteMethod(JNIEnv* env, jobject obj, jmethodID id, jvalue* args); 54 | jchar JNIEnv_CallCharMethod(JNIEnv* env, jobject obj, jmethodID id, jvalue* args); 55 | jshort JNIEnv_CallShortMethod(JNIEnv* env, jobject obj, jmethodID id, jvalue* args); 56 | jint JNIEnv_CallIntMethod(JNIEnv* env, jobject obj, jmethodID id, jvalue* args); 57 | jlong JNIEnv_CallLongMethod(JNIEnv* env, jobject obj, jmethodID id, jvalue* args); 58 | jfloat JNIEnv_CallFloatMethod(JNIEnv* env, jobject obj, jmethodID id, jvalue* args); 59 | jdouble JNIEnv_CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID id, jvalue* args); 60 | void JNIEnv_CallVoidMethod(JNIEnv* env, jobject obj, jmethodID id, jvalue* args); 61 | 62 | jobject JNIEnv_CallNonvirtualObjectMethod(JNIEnv* env, jobject obj, jclass clazz, jmethodID id, jvalue* args); 63 | jboolean JNIEnv_CallNonvirtualBooleanMethod(JNIEnv* env, jobject obj, jclass clazz, jmethodID id, jvalue* args); 64 | jbyte JNIEnv_CallNonvirtualByteMethod(JNIEnv* env, jobject obj, jclass clazz, jmethodID id, jvalue* args); 65 | jchar JNIEnv_CallNonvirtualCharMethod(JNIEnv* env, jobject obj, jclass clazz, jmethodID id, jvalue* args); 66 | jshort JNIEnv_CallNonvirtualShortMethod(JNIEnv* env, jobject obj, jclass clazz, jmethodID id, jvalue* args); 67 | jint JNIEnv_CallNonvirtualIntMethod(JNIEnv* env, jobject obj, jclass clazz, jmethodID id, jvalue* args); 68 | jlong JNIEnv_CallNonvirtualLongMethod(JNIEnv* env, jobject obj, jclass clazz, jmethodID id, jvalue* args); 69 | jfloat JNIEnv_CallNonvirtualFloatMethod(JNIEnv* env, jobject obj, jclass clazz, jmethodID id, jvalue* args); 70 | jdouble JNIEnv_CallNonvirtualDoubleMethod(JNIEnv* env, jobject obj, jclass clazz, jmethodID id, jvalue* args); 71 | void JNIEnv_CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass clazz, jmethodID id, jvalue* args); 72 | 73 | jfieldID JNIEnv_GetFieldID(JNIEnv* env, jclass clazz, const char* name, const char* sig); 74 | 75 | jobject JNIEnv_GetObjectField(JNIEnv* env, jobject obj, jfieldID id); 76 | jboolean JNIEnv_GetBooleanField(JNIEnv* env, jobject obj, jfieldID id); 77 | jbyte JNIEnv_GetByteField(JNIEnv* env, jobject obj, jfieldID id); 78 | jchar JNIEnv_GetCharField(JNIEnv* env, jobject obj, jfieldID id); 79 | jshort JNIEnv_GetShortField(JNIEnv* env, jobject obj, jfieldID id); 80 | jint JNIEnv_GetIntField(JNIEnv* env, jobject obj, jfieldID id); 81 | jlong JNIEnv_GetLongField(JNIEnv* env, jobject obj, jfieldID id); 82 | jfloat JNIEnv_GetFloatField(JNIEnv* env, jobject obj, jfieldID id); 83 | jdouble JNIEnv_GetDoubleField(JNIEnv* env, jobject obj, jfieldID id); 84 | 85 | void JNIEnv_SetObjectField(JNIEnv* env, jobject obj, jfieldID id, jobject val); 86 | void JNIEnv_SetBooleanField(JNIEnv* env, jobject obj, jfieldID id, jboolean val); 87 | void JNIEnv_SetByteField(JNIEnv* env, jobject obj, jfieldID id, jbyte val); 88 | void JNIEnv_SetCharField(JNIEnv* env, jobject obj, jfieldID id, jchar val); 89 | void JNIEnv_SetShortField(JNIEnv* env, jobject obj, jfieldID id, jshort val); 90 | void JNIEnv_SetIntField(JNIEnv* env, jobject obj, jfieldID id, jint val); 91 | void JNIEnv_SetLongField(JNIEnv* env, jobject obj, jfieldID id, jlong val); 92 | void JNIEnv_SetFloatField(JNIEnv* env, jobject obj, jfieldID id, jfloat val); 93 | void JNIEnv_SetDoubleField(JNIEnv* env, jobject obj, jfieldID id, jdouble val); 94 | 95 | jmethodID JNIEnv_GetStaticMethodID(JNIEnv* env, jclass clazz, const char* name, const char* sig); 96 | 97 | jobject JNIEnv_CallStaticObjectMethod(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 98 | jboolean JNIEnv_CallStaticBooleanMethod(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 99 | jbyte JNIEnv_CallStaticByteMethod(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 100 | jchar JNIEnv_CallStaticCharMethod(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 101 | jshort JNIEnv_CallStaticShortMethod(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 102 | jint JNIEnv_CallStaticIntMethod(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 103 | jlong JNIEnv_CallStaticLongMethod(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 104 | jfloat JNIEnv_CallStaticFloatMethod(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 105 | jdouble JNIEnv_CallStaticDoubleMethod(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 106 | void JNIEnv_CallStaticVoidMethod(JNIEnv* env, jclass clazz, jmethodID id, jvalue* args); 107 | 108 | jfieldID JNIEnv_GetStaticFieldID(JNIEnv* env, jclass clazz, const char* name, const char* sig); 109 | 110 | jobject JNIEnv_GetStaticObjectField(JNIEnv* env, jclass clazz, jfieldID id); 111 | jboolean JNIEnv_GetStaticBooleanField(JNIEnv* env, jclass clazz, jfieldID id); 112 | jbyte JNIEnv_GetStaticByteField(JNIEnv* env, jclass clazz, jfieldID id); 113 | jchar JNIEnv_GetStaticCharField(JNIEnv* env, jclass clazz, jfieldID id); 114 | jshort JNIEnv_GetStaticShortField(JNIEnv* env, jclass clazz, jfieldID id); 115 | jint JNIEnv_GetStaticIntField(JNIEnv* env, jclass clazz, jfieldID id); 116 | jlong JNIEnv_GetStaticLongField(JNIEnv* env, jclass clazz, jfieldID id); 117 | jfloat JNIEnv_GetStaticFloatField(JNIEnv* env, jclass clazz, jfieldID id); 118 | jdouble JNIEnv_GetStaticDoubleField(JNIEnv* env, jclass clazz, jfieldID id); 119 | 120 | void JNIEnv_SetStaticObjectField(JNIEnv* env, jclass clazz, jfieldID id, jobject val); 121 | void JNIEnv_SetStaticBooleanField(JNIEnv* env, jclass clazz, jfieldID id, jboolean val); 122 | void JNIEnv_SetStaticByteField(JNIEnv* env, jclass clazz, jfieldID id, jbyte val); 123 | void JNIEnv_SetStaticCharField(JNIEnv* env, jclass clazz, jfieldID id, jchar val); 124 | void JNIEnv_SetStaticShortField(JNIEnv* env, jclass clazz, jfieldID id, jshort val); 125 | void JNIEnv_SetStaticIntField(JNIEnv* env, jclass clazz, jfieldID id, jint val); 126 | void JNIEnv_SetStaticLongField(JNIEnv* env, jclass clazz, jfieldID id, jlong val); 127 | void JNIEnv_SetStaticFloatField(JNIEnv* env, jclass clazz, jfieldID id, jfloat val); 128 | void JNIEnv_SetStaticDoubleField(JNIEnv* env, jclass clazz, jfieldID id, jdouble val); 129 | 130 | jstring JNIEnv_NewString(JNIEnv* env, jchar* buf, jsize bufLen); 131 | jsize JNIEnv_GetStringLength(JNIEnv* env, jstring str); 132 | const jchar* JNIEnv_GetStringChars(JNIEnv* env, jstring str, jboolean* isCopy); 133 | void JNIEnv_ReleaseStringChars(JNIEnv* env, jstring str, jchar* chars); 134 | jstring JNIEnv_NewStringUTF(JNIEnv* env, const char* str); 135 | jsize JNIEnv_GetStringUTFLength(JNIEnv* env, jstring str); 136 | const char* JNIEnv_GetStringUTFChars(JNIEnv* env, jstring str, jboolean* isCopy); 137 | void JNIEnv_ReleaseStringUTFChars(JNIEnv* env, jstring str, const char* utf); 138 | jsize JNIEnv_GetArrayLength(JNIEnv* env, jarray arr); 139 | jobjectArray JNIEnv_NewObjectArray(JNIEnv* env, jsize length, jclass clazz, jobject obj); 140 | jobject JNIEnv_GetObjectArrayElement(JNIEnv* env, jobjectArray arr, jsize index); 141 | void JNIEnv_SetObjectArrayElement(JNIEnv* env, jobjectArray arr, jsize index, jobject obj); 142 | 143 | jbooleanArray JNIEnv_NewBooleanArray(JNIEnv* env, jsize length); 144 | jbyteArray JNIEnv_NewByteArray(JNIEnv* env, jsize length); 145 | jcharArray JNIEnv_NewCharArray(JNIEnv* env, jsize length); 146 | jshortArray JNIEnv_NewShortArray(JNIEnv* env, jsize length); 147 | jintArray JNIEnv_NewIntArray(JNIEnv* env, jsize length); 148 | jlongArray JNIEnv_NewLongArray(JNIEnv* env, jsize length); 149 | jfloatArray JNIEnv_NewFloatArray(JNIEnv* env, jsize length); 150 | jdoubleArray JNIEnv_NewDoubleArray(JNIEnv* env, jsize length); 151 | 152 | jboolean* JNIEnv_GetBooleanArrayElements(JNIEnv* env, jbooleanArray arr, jboolean* isCopy); 153 | jbyte* JNIEnv_GetByteArrayElements(JNIEnv* env, jbyteArray arr, jboolean* isCopy); 154 | jchar* JNIEnv_GetCharArrayElements(JNIEnv* env, jcharArray arr, jboolean* isCopy); 155 | jshort* JNIEnv_GetShortArrayElements(JNIEnv* env, jshortArray arr, jboolean* isCopy); 156 | jint* JNIEnv_GetIntArrayElements(JNIEnv* env, jintArray arr, jboolean* isCopy); 157 | jlong* JNIEnv_GetLongArrayElements(JNIEnv* env, jlongArray arr, jboolean* isCopy); 158 | jfloat* JNIEnv_GetFloatArrayElements(JNIEnv* env, jfloatArray arr, jboolean* isCopy); 159 | jdouble* JNIEnv_GetDoubleArrayElements(JNIEnv* env, jdoubleArray arr, jboolean* isCopy); 160 | 161 | void JNIEnv_ReleaseBooleanArrayElements(JNIEnv* env, jbooleanArray arr, jboolean* elems, jint mode); 162 | void JNIEnv_ReleaseByteArrayElements(JNIEnv* env, jbyteArray arr, jbyte* elems, jint mode); 163 | void JNIEnv_ReleaseCharArrayElements(JNIEnv* env, jcharArray arr, jchar* elems, jint mode); 164 | void JNIEnv_ReleaseShortArrayElements(JNIEnv* env, jshortArray arr, jshort* elems, jint mode); 165 | void JNIEnv_ReleaseIntArrayElements(JNIEnv* env, jintArray arr, jint* elems, jint mode); 166 | void JNIEnv_ReleaseLongArrayElements(JNIEnv* env, jlongArray arr, jlong* elems, jint mode); 167 | void JNIEnv_ReleaseFloatArrayElements(JNIEnv* env, jfloatArray arr, jfloat* elems, jint mode); 168 | void JNIEnv_ReleaseDoubleArrayElements(JNIEnv* env, jdoubleArray arr, jdouble* elems, jint mode); 169 | 170 | void JNIEnv_GetBooleanArrayRegion(JNIEnv* env, jbooleanArray arr, jsize start, jsize length, jboolean* buf); 171 | void JNIEnv_GetByteArrayRegion(JNIEnv* env, jbyteArray arr, jsize start, jsize length, jbyte* buf); 172 | void JNIEnv_GetCharArrayRegion(JNIEnv* env, jcharArray arr, jsize start, jsize length, jchar* buf); 173 | void JNIEnv_GetShortArrayRegion(JNIEnv* env, jshortArray arr, jsize start, jsize length, jshort* buf); 174 | void JNIEnv_GetIntArrayRegion(JNIEnv* env, jintArray arr, jsize start, jsize length, jint* buf); 175 | void JNIEnv_GetLongArrayRegion(JNIEnv* env, jlongArray arr, jsize start, jsize length, jlong* buf); 176 | void JNIEnv_GetFloatArrayRegion(JNIEnv* env, jfloatArray arr, jsize start, jsize length, jfloat* buf); 177 | void JNIEnv_GetDoubleArrayRegion(JNIEnv* env, jdoubleArray arr, jsize start, jsize length, jdouble* buf); 178 | 179 | void JNIEnv_SetBooleanArrayRegion(JNIEnv* env, jbooleanArray arr, jsize start, jsize length, jboolean* buf); 180 | void JNIEnv_SetByteArrayRegion(JNIEnv* env, jbyteArray arr, jsize start, jsize length, jbyte* buf); 181 | void JNIEnv_SetCharArrayRegion(JNIEnv* env, jcharArray arr, jsize start, jsize length, jchar* buf); 182 | void JNIEnv_SetShortArrayRegion(JNIEnv* env, jshortArray arr, jsize start, jsize length, jshort* buf); 183 | void JNIEnv_SetIntArrayRegion(JNIEnv* env, jintArray arr, jsize start, jsize length, jint* buf); 184 | void JNIEnv_SetLongArrayRegion(JNIEnv* env, jlongArray arr, jsize start, jsize length, jlong* buf); 185 | void JNIEnv_SetFloatArrayRegion(JNIEnv* env, jfloatArray arr, jsize start, jsize length, jfloat* buf); 186 | void JNIEnv_SetDoubleArrayRegion(JNIEnv* env, jdoubleArray arr, jsize start, jsize length, jdouble* buf); 187 | 188 | jint JNIEnv_RegisterNatives(JNIEnv* env, jclass clazz, JNINativeMethod* methods, jint nMethods); 189 | jint JNIEnv_UnregisterNatives(JNIEnv* env, jclass clazz); 190 | jint JNIEnv_MonitorEnter(JNIEnv* env, jobject obj); 191 | jint JNIEnv_MonitorExit(JNIEnv* env, jobject obj); 192 | jint JNIEnv_GetJavaVM(JNIEnv* env, JavaVM** p_vm); 193 | 194 | void JNIEnv_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize length, jchar* buf); 195 | void JNIEnv_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize length, char* buf); 196 | 197 | void* JNIEnv_GetPrimitiveArrayCritical(JNIEnv* env, jarray arr, jboolean* isCopy); 198 | void JNIEnv_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray arr, void* carray, jint mode); 199 | 200 | const jchar* JNIEnv_GetStringCritical(JNIEnv* env, jstring str, jboolean* isCopy); 201 | void JNIEnv_ReleaseStringCritical(JNIEnv* env, jstring str, jchar* carray); 202 | 203 | jweak JNIEnv_NewWeakGlobalRef(JNIEnv* env, jobject obj); 204 | void JNIEnv_DeleteWeakGlobalRef(JNIEnv* env, jweak obj); 205 | 206 | jboolean JNIEnv_ExceptionCheck(JNIEnv* env); 207 | 208 | jobject JNIEnv_NewDirectByteBuffer(JNIEnv* env, void* buf, jlong capacity); 209 | void* JNIEnv_GetDirectBufferAddress(JNIEnv* env, jobject buf); 210 | jlong JNIEnv_GetDirectBufferCapacity(JNIEnv* env, jobject buf); 211 | 212 | jobjectRefType JNIEnv_GetObjectRefType(JNIEnv* env, jobject obj); 213 | 214 | #endif // JNI_CALL_H 215 | -------------------------------------------------------------------------------- /android/jni_util.go: -------------------------------------------------------------------------------- 1 | package android 2 | 3 | import "errors" 4 | 5 | type SoftKeyboardState int32 6 | 7 | const ( 8 | SoftKeyboardHidden SoftKeyboardState = iota 9 | SoftKeyboardVisible 10 | ) 11 | 12 | // SetSoftKeyboardState allows to toggle Android virtual keyboard using JNI calls into JavaVM. 13 | func (a *NativeActivity) SetSoftKeyboardState(state SoftKeyboardState) error { 14 | return a.JNICall(func(env *JNIEnv, activity Jobject, activityClass, contextClass *Jclass) error { 15 | // Context.INPUT_METHOD_SERVICE 16 | inputMethodService := JNIEnvGetStaticObjectField(env, contextClass, 17 | JNIEnvGetStaticFieldID(env, contextClass, 18 | s("INPUT_METHOD_SERVICE"), JClassString.Spec().Sig()), 19 | ) 20 | if inputMethodService == nil { 21 | return errors.New("failed to get INPUT_METHOD_SERVICE") 22 | } 23 | 24 | // getSystemService(Context.INPUT_METHOD_SERVICE) 25 | getSystemService := JNIEnvGetMethodID(env, activityClass, 26 | s("getSystemService"), JNIMethodSig(JClassObject.Spec(), JClassString.Spec())) 27 | inputMethodManager := JNIEnvCallObjectMethod(env, activity, getSystemService, []Jvalue{ 28 | JobjectV(inputMethodService), 29 | }) 30 | if inputMethodManager == nil { 31 | return errors.New("failed to run getSystemService()") 32 | } 33 | defer JNIEnvDeleteLocalRef(env, inputMethodManager) 34 | 35 | // getWindow().getDecorView() 36 | getWindowMethod := JNIEnvGetMethodID(env, activityClass, 37 | s("getWindow"), JNIMethodSig(JClassWindow.Spec())) 38 | getDecorViewMethod := JNIEnvGetMethodID(env, JNIEnvFindClass(env, JClassWindow.Name()), 39 | s("getDecorView"), JNIMethodSig(JClassView.Spec())) 40 | window := JNIEnvCallObjectMethod(env, activity, getWindowMethod, nil) 41 | if window == nil { 42 | return errors.New("failed to run getWindow()") 43 | } 44 | defer JNIEnvDeleteLocalRef(env, window) 45 | decorView := JNIEnvCallObjectMethod(env, window, getDecorViewMethod, nil) 46 | if decorView == nil { 47 | return errors.New("failed to run getDecorView()") 48 | } 49 | defer JNIEnvDeleteLocalRef(env, decorView) 50 | 51 | switch state { 52 | case SoftKeyboardHidden: 53 | const flags = 0 54 | 55 | // decorView.getWindowToken() 56 | getWindowTokenMethod := JNIEnvGetMethodID(env, 57 | JNIEnvFindClass(env, JClassView.Name()), 58 | s("getWindowToken"), JNIMethodSig(JClassIBinder.Spec())) 59 | binder := JNIEnvCallObjectMethod(env, decorView, getWindowTokenMethod, nil) 60 | if binder == nil { 61 | return errors.New("failed to run getWindowToken()") 62 | } 63 | defer JNIEnvDeleteLocalRef(env, binder) 64 | 65 | // inputMethodManager.hideSoftInputFromWindow(...) 66 | hideSoftInputFromWindowMethod := JNIEnvGetMethodID(env, 67 | JNIEnvFindClass(env, JClassInputMethodManager.Name()), 68 | s("hideSoftInputFromWindow"), JNIMethodSig(JBoolean.Spec(), JClassIBinder.Spec(), JInt.Spec())) 69 | result := JNIEnvCallBooleanMethod(env, inputMethodManager, 70 | hideSoftInputFromWindowMethod, []Jvalue{ 71 | JobjectV(binder), JintV(flags), 72 | }) 73 | if result == JNIFalse { 74 | return errors.New("failed to run hideSoftInputFromWindow()") 75 | } 76 | 77 | case SoftKeyboardVisible: 78 | const flags = 0 79 | // inputMethodManager.showSoftInput(...) 80 | showSoftInputMethod := JNIEnvGetMethodID(env, 81 | JNIEnvFindClass(env, JClassInputMethodManager.Name()), 82 | s("showSoftInput"), JNIMethodSig(JBoolean.Spec(), JClassView.Spec(), JInt.Spec())) 83 | result := JNIEnvCallBooleanMethod(env, inputMethodManager, 84 | showSoftInputMethod, []Jvalue{ 85 | JobjectV(decorView), JintV(flags), 86 | }) 87 | if result == JNIFalse { 88 | return errors.New("failed to run showSoftInput()") 89 | } 90 | } 91 | return nil 92 | }) 93 | } 94 | 95 | // KeyEventGetUnicodeChar gets the Unicode character generated by the specified key and meta key state combination. 96 | func (a *NativeActivity) KeyEventGetUnicodeChar(action, keyCode, metaState int32) (rune, error) { 97 | var result rune 98 | err := a.JNICall(func(env *JNIEnv, activity Jobject, activityClass, contextClass *Jclass) error { 99 | keyEventClass := JNIEnvFindClass(env, JClassKeyEvent.Name()) 100 | keyEventInit := JNIEnvGetMethodID(env, keyEventClass, 101 | s(""), JNIMethodSig(JVoid.Spec(), JInt.Spec(), JInt.Spec())) 102 | keyEvent := JNIEnvNewObject(env, keyEventClass, keyEventInit, []Jvalue{ 103 | JintV(action), JintV(keyCode), 104 | }) 105 | defer JNIEnvDeleteLocalRef(env, keyEvent) 106 | 107 | if keyEvent == nil { 108 | return errors.New("failed to construct new KeyEvent") 109 | } 110 | if metaState == 0 { 111 | getUnicodeCharMethod := JNIEnvGetMethodID(env, keyEventClass, 112 | s("getUnicodeChar"), JNIMethodSig(JInt.Spec())) 113 | result = rune(JNIEnvCallIntMethod(env, keyEvent, getUnicodeCharMethod, nil)) 114 | } else { 115 | getUnicodeCharMethod := JNIEnvGetMethodID(env, keyEventClass, 116 | s("getUnicodeChar"), JNIMethodSig(JInt.Spec(), JInt.Spec())) 117 | result = rune(JNIEnvCallIntMethod(env, keyEvent, getUnicodeCharMethod, []Jvalue{ 118 | JintV(metaState), 119 | })) 120 | } 121 | return nil 122 | }) 123 | return result, err 124 | } 125 | -------------------------------------------------------------------------------- /android/jvalue.go: -------------------------------------------------------------------------------- 1 | package android 2 | 3 | import "unsafe" 4 | 5 | // typedef union jvalue { 6 | // jboolean z; 7 | // jbyte b; 8 | // jchar c; 9 | // jshort s; 10 | // jint i; 11 | // jlong j; 12 | // jfloat f; 13 | // jdouble d; 14 | // jobject l; 15 | // } jvalue; 16 | 17 | func JbooleanV(z bool) Jvalue { 18 | if z { 19 | var b = JNITrue 20 | return *(*Jvalue)(unsafe.Pointer(&b)) 21 | } 22 | var b = JNIFalse 23 | return *(*Jvalue)(unsafe.Pointer(&b)) 24 | } 25 | 26 | func JbyteV(b byte) Jvalue { 27 | return *(*Jvalue)(unsafe.Pointer(&b)) 28 | } 29 | 30 | func JcharV(c uint16) Jvalue { 31 | return *(*Jvalue)(unsafe.Pointer(&c)) 32 | } 33 | 34 | func JshortV(s int16) Jvalue { 35 | return *(*Jvalue)(unsafe.Pointer(&s)) 36 | } 37 | 38 | func JintV(i int32) Jvalue { 39 | return *(*Jvalue)(unsafe.Pointer(&i)) 40 | } 41 | 42 | func JlongV(j int32) Jvalue { 43 | return *(*Jvalue)(unsafe.Pointer(&j)) 44 | } 45 | 46 | func JfloatV(f float32) Jvalue { 47 | return *(*Jvalue)(unsafe.Pointer(&f)) 48 | } 49 | 50 | func JdoubleV(d float64) Jvalue { 51 | return *(*Jvalue)(unsafe.Pointer(&d)) 52 | } 53 | 54 | func JobjectV(l Jobject) Jvalue { 55 | return *(*Jvalue)(unsafe.Pointer(&l)) 56 | } 57 | -------------------------------------------------------------------------------- /android/sensors.go: -------------------------------------------------------------------------------- 1 | package android 2 | 3 | import "unsafe" 4 | 5 | func (e SensorEvent) Acceleration() (x, y, z float32) { 6 | ref := e.Ref() 7 | if ref == nil { 8 | return 9 | } 10 | tuple := *(*[3]float32)(unsafe.Pointer(&ref.anon0)) 11 | x = tuple[0] 12 | y = tuple[1] 13 | z = tuple[2] 14 | return 15 | } 16 | -------------------------------------------------------------------------------- /android/types.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:44 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package android 7 | 8 | /* 9 | #cgo LDFLAGS: -landroid -llog 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "jni_call.h" 28 | #include 29 | #include "cgo_helpers.h" 30 | */ 31 | import "C" 32 | import "unsafe" 33 | 34 | // AssetManager as declared in android/asset_manager.h:28 35 | type AssetManager C.AAssetManager 36 | 37 | // AssetDir as declared in android/asset_manager.h:31 38 | type AssetDir C.AAssetDir 39 | 40 | // Asset as declared in android/asset_manager.h:34 41 | type Asset C.AAsset 42 | 43 | // Jboolean type as declared in include/jni.h:44 44 | type Jboolean byte 45 | 46 | // Jbyte type as declared in include/jni.h:45 47 | type Jbyte byte 48 | 49 | // Jchar type as declared in include/jni.h:46 50 | type Jchar uint16 51 | 52 | // Jshort type as declared in include/jni.h:47 53 | type Jshort int16 54 | 55 | // Jint type as declared in include/jni.h:48 56 | type Jint int32 57 | 58 | // Jlong type as declared in include/jni.h:49 59 | type Jlong int64 60 | 61 | // Jfloat type as declared in include/jni.h:50 62 | type Jfloat float32 63 | 64 | // Jdouble type as declared in include/jni.h:51 65 | type Jdouble float64 66 | 67 | // Jsize type as declared in include/jni.h:55 68 | type Jsize int32 69 | 70 | // Jobject type as declared in include/jni.h:98 71 | type Jobject unsafe.Pointer 72 | 73 | // Jclass type as declared in include/jni.h:99 74 | type Jclass unsafe.Pointer 75 | 76 | // Jstring type as declared in include/jni.h:100 77 | type Jstring unsafe.Pointer 78 | 79 | // Jarray type as declared in include/jni.h:101 80 | type Jarray unsafe.Pointer 81 | 82 | // JobjectArray type as declared in include/jni.h:102 83 | type JobjectArray unsafe.Pointer 84 | 85 | // JbooleanArray type as declared in include/jni.h:103 86 | type JbooleanArray unsafe.Pointer 87 | 88 | // JbyteArray type as declared in include/jni.h:104 89 | type JbyteArray unsafe.Pointer 90 | 91 | // JcharArray type as declared in include/jni.h:105 92 | type JcharArray unsafe.Pointer 93 | 94 | // JshortArray type as declared in include/jni.h:106 95 | type JshortArray unsafe.Pointer 96 | 97 | // JintArray type as declared in include/jni.h:107 98 | type JintArray unsafe.Pointer 99 | 100 | // JlongArray type as declared in include/jni.h:108 101 | type JlongArray unsafe.Pointer 102 | 103 | // JfloatArray type as declared in include/jni.h:109 104 | type JfloatArray unsafe.Pointer 105 | 106 | // JdoubleArray type as declared in include/jni.h:110 107 | type JdoubleArray unsafe.Pointer 108 | 109 | // Jthrowable type as declared in include/jni.h:111 110 | type Jthrowable unsafe.Pointer 111 | 112 | // Jweak type as declared in include/jni.h:112 113 | type Jweak unsafe.Pointer 114 | 115 | // JfieldID as declared in include/jni.h:117 116 | type JfieldID C.jfieldID 117 | 118 | // JmethodID as declared in include/jni.h:120 119 | type JmethodID C.jmethodID 120 | 121 | // Jvalue as declared in include/jni.h:134 122 | const sizeofJvalue = unsafe.Sizeof(C.jvalue{}) 123 | 124 | type Jvalue [sizeofJvalue]byte 125 | 126 | // JNINativeMethod as declared in include/jni.h:147 127 | type JNINativeMethod C.JNINativeMethod 128 | 129 | // JNIEnv as declared in include/jni.h:157 130 | type JNIEnv C.JNIEnv 131 | 132 | // JavaVM as declared in include/jni.h:158 133 | type JavaVM C.JavaVM 134 | 135 | // JavaVMAttachArgs as declared in include/jni.h:1106 136 | type JavaVMAttachArgs struct { 137 | Version Jint 138 | Name string 139 | Group Jobject 140 | refab42f020 *C.JavaVMAttachArgs 141 | allocsab42f020 interface{} 142 | } 143 | 144 | // JavaVMOption as declared in include/jni.h:1115 145 | type JavaVMOption C.JavaVMOption 146 | 147 | // JavaVMInitArgs as declared in include/jni.h:1123 148 | type JavaVMInitArgs C.JavaVMInitArgs 149 | 150 | // Configuration as declared in android/configuration.h:27 151 | type Configuration C.AConfiguration 152 | 153 | // Looper as declared in android/looper.h:39 154 | type Looper C.ALooper 155 | 156 | // LooperCallbackFunc type as declared in android/looper.h:159 157 | type LooperCallbackFunc func(fd int32, events int32, data unsafe.Pointer) int32 158 | 159 | // NativeActivity as declared in android/native_activity.h:108 160 | type NativeActivity struct { 161 | Callbacks *NativeActivityCallbacks 162 | Vm *JavaVM 163 | Env *JNIEnv 164 | Clazz Jobject 165 | InternalDataPath string 166 | ExternalDataPath string 167 | SdkVersion int32 168 | Instance unsafe.Pointer 169 | AssetManager *AssetManager 170 | ObbPath string 171 | ref2cc295bf *C.ANativeActivity 172 | allocs2cc295bf interface{} 173 | } 174 | 175 | // NativeActivityCallbacks as declared in android/native_activity.h:225 176 | type NativeActivityCallbacks C.ANativeActivityCallbacks 177 | 178 | // NativeActivityCreateFunc type as declared in android/native_activity.h:235 179 | type NativeActivityCreateFunc func(activity *NativeActivity, savedState unsafe.Pointer, savedStateSize uint32) 180 | 181 | // InputEvent as declared in android/input.h:136 182 | type InputEvent C.AInputEvent 183 | 184 | // InputQueue as declared in android/input.h:803 185 | type InputQueue C.AInputQueue 186 | 187 | // NativeWindow as declared in android/native_window.h:36 188 | type NativeWindow C.ANativeWindow 189 | 190 | // NativeWindowBuffer as declared in android/native_window.h:57 191 | type NativeWindowBuffer struct { 192 | Width int32 193 | Height int32 194 | Stride int32 195 | Format int32 196 | Bits unsafe.Pointer 197 | Reserved [6]uint32 198 | ref3db2646c *C.ANativeWindow_Buffer 199 | allocs3db2646c interface{} 200 | } 201 | 202 | // Rect as declared in android/rect.h:35 203 | type Rect struct { 204 | Left int32 205 | Top int32 206 | Right int32 207 | Bottom int32 208 | ref9511c547 *C.ARect 209 | allocs9511c547 interface{} 210 | } 211 | 212 | // ObbInfo as declared in android/obb.h:28 213 | type ObbInfo C.AObbInfo 214 | 215 | // SensorVector as declared in android/sensor.h:119 216 | type SensorVector struct { 217 | Status byte 218 | Reserved [3]byte 219 | refdc35e822 *C.ASensorVector 220 | allocsdc35e822 interface{} 221 | } 222 | 223 | // MetaDataEvent as declared in android/sensor.h:124 224 | type MetaDataEvent struct { 225 | What int32 226 | Sensor int32 227 | ref4f7ec3e5 *C.AMetaDataEvent 228 | allocs4f7ec3e5 interface{} 229 | } 230 | 231 | // UncalibratedEvent as declared in android/sensor.h:143 232 | type UncalibratedEvent struct { 233 | ref193d9a7d *C.AUncalibratedEvent 234 | allocs193d9a7d interface{} 235 | } 236 | 237 | // HeartRateEvent as declared in android/sensor.h:148 238 | type HeartRateEvent struct { 239 | Bpm float32 240 | Status byte 241 | ref1342bcf5 *C.AHeartRateEvent 242 | allocs1342bcf5 interface{} 243 | } 244 | 245 | // SensorEvent as declared in android/sensor.h:181 246 | type SensorEvent struct { 247 | Version int32 248 | Sensor int32 249 | Type int32 250 | Reserved0 int32 251 | Timestamp int64 252 | Flags uint32 253 | Reserved1 [3]int32 254 | refb7a6c7dc *C.ASensorEvent 255 | allocsb7a6c7dc interface{} 256 | } 257 | 258 | // SensorManager as declared in android/sensor.h:184 259 | type SensorManager C.ASensorManager 260 | 261 | // SensorEventQueue as declared in android/sensor.h:187 262 | type SensorEventQueue C.ASensorEventQueue 263 | 264 | // Sensor as declared in android/sensor.h:190 265 | type Sensor C.ASensor 266 | 267 | // SensorRef as declared in android/sensor.h:191 268 | type SensorRef C.ASensor 269 | 270 | // SensorList as declared in android/sensor.h:192 271 | type SensorList C.ASensorRef 272 | 273 | // StorageManager as declared in android/storage_manager.h:28 274 | type StorageManager C.AStorageManager 275 | 276 | // StorageManagerObbCallbackFunc type as declared in android/storage_manager.h:98 277 | type StorageManagerObbCallbackFunc func(filename string, state int32, data unsafe.Pointer) 278 | -------------------------------------------------------------------------------- /android/window.go: -------------------------------------------------------------------------------- 1 | package android 2 | 3 | import "unsafe" 4 | 5 | func (w *NativeWindow) Ptr() uintptr { 6 | return uintptr(unsafe.Pointer(w)) 7 | } 8 | -------------------------------------------------------------------------------- /app/app.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "_cgo_export.h" 7 | 8 | #define LOG_FATAL(...) __android_log_print(ANDROID_LOG_FATAL, "Go", __VA_ARGS__) 9 | 10 | int main_running = 0; 11 | 12 | // ANativeActivity_onCreate implements the application's entry point. 13 | // 14 | // This is the function that must be in the native code to instantiate 15 | // the application's native activity. It is called with the activity 16 | // instance; if the code is being instantiated from a 17 | // previously saved instance, the savedState will be non-NULL and 18 | // point to the saved data. You must make any copy of this data you 19 | // need – it will be released after you return from this function. 20 | // 21 | // See https://developer.android.com/ndk/reference/group___native_activity.html 22 | // 23 | // The Activity may be created and destroyed multiple times throughout 24 | // the life of a single process. Each time, onCreate is called. 25 | void ANativeActivity_onCreate(ANativeActivity *activity, void* savedState, size_t savedStateSize) { 26 | if (!main_running) { 27 | // Call the Go main.main. 28 | uintptr_t mainPC = (uintptr_t)dlsym(RTLD_DEFAULT, "main.main"); 29 | if (!mainPC) { 30 | LOG_FATAL("missing main.main"); 31 | } 32 | callMain(mainPC); 33 | main_running = 1; 34 | } 35 | 36 | // Set the native activity callbacks, see: 37 | // https://developer.android.com/ndk/reference/struct_a_native_activity_callbacks.html 38 | activity->callbacks->onStart = onStart; 39 | activity->callbacks->onResume = onResume; 40 | activity->callbacks->onSaveInstanceState = onSaveInstanceState; 41 | activity->callbacks->onPause = onPause; 42 | activity->callbacks->onStop = onStop; 43 | activity->callbacks->onDestroy = onDestroy; 44 | activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; 45 | activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; 46 | activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded; 47 | activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; 48 | activity->callbacks->onInputQueueCreated = onInputQueueCreated; 49 | activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; 50 | activity->callbacks->onConfigurationChanged = onConfigurationChanged; 51 | activity->callbacks->onLowMemory = onLowMemory; 52 | 53 | onCreate(activity); 54 | } 55 | -------------------------------------------------------------------------------- /app/app.go: -------------------------------------------------------------------------------- 1 | // Package app implements a NativeActivity glue layer required to 2 | // properly handle the startup process and the native activity events. 3 | // 4 | // Import this package into your Go application to make it Android-compatible. 5 | package app 6 | 7 | // #cgo LDFLAGS: -llog 8 | // 9 | // #include 10 | // #include 11 | import "C" 12 | 13 | import ( 14 | "os" 15 | "sync" 16 | "time" 17 | "unsafe" 18 | 19 | "github.com/xlab/android-go/android" 20 | "github.com/xlab/android-go/app/internal/callfn" 21 | ) 22 | 23 | //export callMain 24 | func callMain(mainPC uintptr) { 25 | // This function as well as the CallFn trampoline is borrowed from the 26 | // gomobile project. 27 | 28 | // N.B: the main.main must present in the actual app 29 | // that imports this package. 30 | 31 | for _, name := range []string{"TMPDIR", "PATH", "LD_LIBRARY_PATH"} { 32 | n := C.CString(name) 33 | os.Setenv(name, C.GoString(C.getenv(n))) 34 | C.free(unsafe.Pointer(n)) 35 | } 36 | 37 | // Set timezone. 38 | // 39 | // Note that Android zoneinfo is stored in /system/usr/share/zoneinfo, 40 | // but it is in some kind of packed TZiff file that we do not support 41 | // yet. As a stopgap, we build a fixed zone using the tm_zone name. 42 | var curtime C.time_t 43 | var curtm C.struct_tm 44 | C.time(&curtime) 45 | C.localtime_r(&curtime, &curtm) 46 | tzOffset := int(curtm.tm_gmtoff) 47 | tz := C.GoString(curtm.tm_zone) 48 | time.Local = time.FixedZone(tz, tzOffset) 49 | 50 | go callfn.CallFn(mainPC) 51 | } 52 | 53 | type NativeActivity interface { 54 | InitDone() 55 | NativeWindowRedrawDone() 56 | InputQueueHandled() 57 | NativeActivity() *android.NativeActivity 58 | LifecycleEvents() <-chan LifecycleEvent 59 | HandleSaveInstanceState(fn SaveStateFunc) 60 | HandleWindowFocusEvents(out chan<- WindowFocusEvent) 61 | HandleNativeWindowEvents(out chan<- NativeWindowEvent) 62 | HandleInputQueueEvents(out chan<- InputQueueEvent) 63 | HandleContentRectEvents(out chan<- ContentRectEvent) 64 | HandleActivityEvents(out chan<- ActivityEvent) 65 | GetAsset(name string) ([]byte, error) 66 | OpenAsset(name string) (*AssetReader, error) 67 | } 68 | 69 | var defaultApp = &nativeActivity{ 70 | lifecycleEvents: make(chan LifecycleEvent), 71 | nativeWindowRedrawDone: make(chan Signal, 1), 72 | inputQueueHandled: make(chan Signal, 1), 73 | maxDispatchTime: 1 * time.Second, 74 | 75 | initWG: new(sync.WaitGroup), 76 | mux: new(sync.RWMutex), 77 | } 78 | 79 | func init() { 80 | defaultApp.initWG.Add(1) 81 | } 82 | 83 | func Main(fn func(app NativeActivity)) { 84 | // runtime.LockOSThread() 85 | // defer runtime.UnlockOSThread() 86 | fn(defaultApp) 87 | } 88 | 89 | type nativeActivity struct { 90 | // activity holds the reference to NativeActivity passed to us in the onCreate callback. 91 | activity *android.NativeActivity 92 | 93 | // lifecycleEvents must be handled in real-time. 94 | lifecycleEvents chan LifecycleEvent 95 | 96 | // maxDispatchTime sets the maximum time the send operation 97 | // allowed to wait while channel is blocked. 98 | maxDispatchTime time.Duration 99 | // channels below are optional and will be sent to only 100 | // if handled by an external client. 101 | 102 | windowFocusEvents chan<- WindowFocusEvent 103 | nativeWindowEvents chan<- NativeWindowEvent 104 | inputQueueEvents chan<- InputQueueEvent 105 | contentRectEvents chan<- ContentRectEvent 106 | activityEvents chan<- ActivityEvent 107 | 108 | saveInstanceStateFunc SaveStateFunc 109 | nativeWindowRedrawDone chan Signal 110 | inputQueueHandled chan Signal 111 | 112 | initWG *sync.WaitGroup 113 | mux *sync.RWMutex 114 | } 115 | 116 | func (a *nativeActivity) InitDone() { 117 | a.initWG.Done() 118 | } 119 | 120 | func (a *nativeActivity) NativeActivity() *android.NativeActivity { 121 | a.mux.RLock() 122 | activity := a.activity 123 | a.mux.RUnlock() 124 | return activity 125 | } 126 | 127 | func (a *nativeActivity) LifecycleEvents() <-chan LifecycleEvent { 128 | return a.lifecycleEvents 129 | } 130 | 131 | type Signal struct{} 132 | 133 | // NativeWindowRedrawDone should be invoked as soon as WindowRedrawNeeded event has 134 | // been processed and the redraw has been completed. 135 | // 136 | // Refer to https://developer.android.com/ndk/reference/struct_a_native_activity_callbacks.html 137 | func (a *nativeActivity) NativeWindowRedrawDone() { 138 | select { 139 | case a.nativeWindowRedrawDone <- Signal{}: 140 | default: 141 | } 142 | } 143 | 144 | func (a *nativeActivity) InputQueueHandled() { 145 | select { 146 | case a.inputQueueHandled <- Signal{}: 147 | default: 148 | } 149 | } 150 | 151 | func (a *nativeActivity) HandleWindowFocusEvents(out chan<- WindowFocusEvent) { 152 | a.mux.Lock() 153 | a.windowFocusEvents = out 154 | a.mux.Unlock() 155 | } 156 | 157 | func (a *nativeActivity) getWindowFocusEventsOut() chan<- WindowFocusEvent { 158 | a.mux.RLock() 159 | out := a.windowFocusEvents 160 | a.mux.RUnlock() 161 | return out 162 | } 163 | 164 | func (a *nativeActivity) HandleNativeWindowEvents(out chan<- NativeWindowEvent) { 165 | a.mux.Lock() 166 | a.nativeWindowEvents = out 167 | a.mux.Unlock() 168 | } 169 | 170 | func (a *nativeActivity) getNativeWindowEventsOut() chan<- NativeWindowEvent { 171 | a.mux.RLock() 172 | out := a.nativeWindowEvents 173 | a.mux.RUnlock() 174 | return out 175 | } 176 | 177 | func (a *nativeActivity) HandleInputQueueEvents(out chan<- InputQueueEvent) { 178 | a.mux.Lock() 179 | a.inputQueueEvents = out 180 | a.mux.Unlock() 181 | } 182 | 183 | func (a *nativeActivity) getInputQueueEventsOut() chan<- InputQueueEvent { 184 | a.mux.RLock() 185 | out := a.inputQueueEvents 186 | a.mux.RUnlock() 187 | return out 188 | } 189 | 190 | func (a *nativeActivity) HandleContentRectEvents(out chan<- ContentRectEvent) { 191 | a.mux.Lock() 192 | a.contentRectEvents = out 193 | a.mux.Unlock() 194 | } 195 | 196 | func (a *nativeActivity) getContentRectEventsOut() chan<- ContentRectEvent { 197 | a.mux.RLock() 198 | out := a.contentRectEvents 199 | a.mux.RUnlock() 200 | return out 201 | } 202 | 203 | func (a *nativeActivity) HandleActivityEvents(out chan<- ActivityEvent) { 204 | a.mux.Lock() 205 | a.activityEvents = out 206 | a.mux.Unlock() 207 | } 208 | 209 | func (a *nativeActivity) getActivityEventsOut() chan<- ActivityEvent { 210 | a.mux.RLock() 211 | out := a.activityEvents 212 | a.mux.RUnlock() 213 | return out 214 | } 215 | 216 | func (a *nativeActivity) HandleSaveInstanceState(fn SaveStateFunc) { 217 | a.mux.Lock() 218 | a.saveInstanceStateFunc = fn 219 | a.mux.Unlock() 220 | } 221 | 222 | func (a *nativeActivity) getSaveInstanceStateFunc() SaveStateFunc { 223 | a.mux.RLock() 224 | fn := a.saveInstanceStateFunc 225 | a.mux.RUnlock() 226 | return fn 227 | } 228 | -------------------------------------------------------------------------------- /app/assets.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "os" 9 | "sync" 10 | "unsafe" 11 | 12 | "github.com/xlab/android-go/android" 13 | ) 14 | 15 | // AssetReader represents an asset opened for reading 16 | type AssetReader struct { 17 | mux sync.Mutex 18 | asset *android.Asset 19 | } 20 | 21 | // OpenAsset returns an asset reader, if the asset exists. OpenAsset must not be called before the onCreate event was received. 22 | func (a *nativeActivity) OpenAsset(name string) (reader *AssetReader, err error) { 23 | a.mux.RLock() 24 | if a.activity == nil { 25 | err = errors.New("app: GetAsset must be called on initialized native activity") 26 | } else { 27 | reader = new(AssetReader) 28 | reader.asset = android.AssetManagerOpen(a.activity.AssetManager, name+"\x00", android.AssetModeStreaming) 29 | if reader.asset == nil { 30 | err = os.ErrNotExist 31 | } 32 | } 33 | a.mux.RUnlock() 34 | return 35 | } 36 | 37 | // Read reads up to len(b) bytes from the AssetReader. It returns the number of bytes read and or any error encountered. At end of the asset, Read returns 0, io.EOF. 38 | func (r *AssetReader) Read(b []byte) (n int, err error) { 39 | r.mux.Lock() 40 | if r.asset == nil { 41 | err = os.ErrClosed 42 | } else if len(b) > 0 { 43 | n = int(android.AssetRead(r.asset, unsafe.Pointer(&b[0]), uint32(len(b)))) 44 | if n <= 0 { 45 | if n < 0 { 46 | err = fmt.Errorf("Read error %d", -n) 47 | n = 0 48 | } else { 49 | err = io.EOF 50 | } 51 | r.close() 52 | } 53 | } 54 | r.mux.Unlock() 55 | return 56 | } 57 | 58 | // Close frees the resources associated with the AssetReader, rendering it unusable. It always returns nil. 59 | func (r *AssetReader) Close() error { 60 | r.mux.Lock() 61 | r.close() 62 | r.mux.Unlock() 63 | return nil 64 | } 65 | 66 | func (r *AssetReader) close() { 67 | if r.asset != nil { 68 | android.AssetClose(r.asset) 69 | r.asset = nil 70 | } 71 | } 72 | 73 | // GetAsset returns the asset data of the specified asset or an error. GetAsset must not be called before the onCreate event was received. 74 | func (a *nativeActivity) GetAsset(name string) ([]byte, error) { 75 | var r, err = a.OpenAsset(name) 76 | if err != nil { 77 | return nil, err 78 | } 79 | return ioutil.ReadAll(r) 80 | } 81 | -------------------------------------------------------------------------------- /app/events.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | // #cgo LDFLAGS: -landroid 4 | // 5 | // #include 6 | // #include 7 | // #include 8 | import "C" 9 | 10 | import ( 11 | "time" 12 | "unsafe" 13 | 14 | "github.com/xlab/android-go/android" 15 | ) 16 | 17 | type LifecycleEvent struct { 18 | Activity *android.NativeActivity 19 | Kind LifecycleEventKind 20 | } 21 | 22 | type LifecycleEventKind string 23 | 24 | const ( 25 | OnCreate LifecycleEventKind = "onCreate" 26 | OnDestroy LifecycleEventKind = "onDestroy" 27 | OnStart LifecycleEventKind = "onStart" 28 | OnStop LifecycleEventKind = "onStop" 29 | OnPause LifecycleEventKind = "onPause" 30 | OnResume LifecycleEventKind = "onResume" 31 | ) 32 | 33 | //export onCreate 34 | func onCreate(activity *C.ANativeActivity) { 35 | defaultApp.initWG.Wait() 36 | 37 | defaultApp.mux.Lock() 38 | defaultApp.activity = android.NewNativeActivityRef(unsafe.Pointer(activity)) 39 | defaultApp.activity.Deref() 40 | defaultApp.mux.Unlock() 41 | 42 | event := LifecycleEvent{ 43 | Activity: defaultApp.activity, 44 | Kind: OnCreate, 45 | } 46 | defaultApp.lifecycleEvents <- event 47 | } 48 | 49 | //export onDestroy 50 | func onDestroy(activity *C.ANativeActivity) { 51 | defaultApp.initWG.Wait() 52 | 53 | event := LifecycleEvent{ 54 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 55 | Kind: OnDestroy, 56 | } 57 | defaultApp.lifecycleEvents <- event 58 | } 59 | 60 | //export onStart 61 | func onStart(activity *C.ANativeActivity) { 62 | defaultApp.initWG.Wait() 63 | 64 | event := LifecycleEvent{ 65 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 66 | Kind: OnStart, 67 | } 68 | defaultApp.lifecycleEvents <- event 69 | } 70 | 71 | //export onStop 72 | func onStop(activity *C.ANativeActivity) { 73 | defaultApp.initWG.Wait() 74 | 75 | event := LifecycleEvent{ 76 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 77 | Kind: OnStop, 78 | } 79 | defaultApp.lifecycleEvents <- event 80 | } 81 | 82 | //export onPause 83 | func onPause(activity *C.ANativeActivity) { 84 | defaultApp.initWG.Wait() 85 | 86 | event := LifecycleEvent{ 87 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 88 | Kind: OnPause, 89 | } 90 | defaultApp.lifecycleEvents <- event 91 | } 92 | 93 | //export onResume 94 | func onResume(activity *C.ANativeActivity) { 95 | defaultApp.initWG.Wait() 96 | 97 | event := LifecycleEvent{ 98 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 99 | Kind: OnResume, 100 | } 101 | defaultApp.lifecycleEvents <- event 102 | } 103 | 104 | type SaveStateFunc func(activity *android.NativeActivity, size uintptr) unsafe.Pointer 105 | 106 | //export onSaveInstanceState 107 | func onSaveInstanceState(activity *C.ANativeActivity, outSize *C.size_t) unsafe.Pointer { 108 | defaultApp.initWG.Wait() 109 | 110 | // https://developer.android.com/training/basics/activity-lifecycle/recreating.html 111 | fn := defaultApp.getSaveInstanceStateFunc() 112 | if fn == nil { 113 | return nil 114 | } 115 | activityRef := android.NewNativeActivityRef(unsafe.Pointer(activity)) 116 | result := fn(activityRef, uintptr(unsafe.Pointer(outSize))) 117 | return result 118 | } 119 | 120 | type WindowFocusEvent struct { 121 | Activity *android.NativeActivity 122 | HasFocus bool 123 | } 124 | 125 | //export onWindowFocusChanged 126 | func onWindowFocusChanged(activity *C.ANativeActivity, hasFocus C.int) { 127 | defaultApp.initWG.Wait() 128 | 129 | out := defaultApp.getWindowFocusEventsOut() 130 | if out == nil { 131 | return 132 | } 133 | event := WindowFocusEvent{ 134 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 135 | HasFocus: hasFocus > 0, 136 | } 137 | select { 138 | case out <- event: 139 | // dispatched 140 | case <-time.After(defaultApp.maxDispatchTime): 141 | // timed out 142 | } 143 | } 144 | 145 | type NativeWindowEvent struct { 146 | Activity *android.NativeActivity 147 | Window *android.NativeWindow 148 | Kind NativeWindowEventKind 149 | } 150 | 151 | type NativeWindowEventKind string 152 | 153 | const ( 154 | NativeWindowCreated NativeWindowEventKind = "nativeWindowCreated" 155 | NativeWindowRedrawNeeded NativeWindowEventKind = "nativeWindowRedrawNeeded" 156 | NativeWindowDestroyed NativeWindowEventKind = "nativeWindowDestroyed" 157 | ) 158 | 159 | //export onNativeWindowCreated 160 | func onNativeWindowCreated(activity *C.ANativeActivity, window *C.ANativeWindow) { 161 | defaultApp.initWG.Wait() 162 | 163 | out := defaultApp.getNativeWindowEventsOut() 164 | if out == nil { 165 | return 166 | } 167 | event := NativeWindowEvent{ 168 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 169 | Window: (*android.NativeWindow)(window), 170 | Kind: NativeWindowCreated, 171 | } 172 | select { 173 | case out <- event: 174 | // dispatched 175 | case <-time.After(defaultApp.maxDispatchTime): 176 | // timed out 177 | } 178 | } 179 | 180 | //export onNativeWindowRedrawNeeded 181 | func onNativeWindowRedrawNeeded(activity *C.ANativeActivity, window *C.ANativeWindow) { 182 | defaultApp.initWG.Wait() 183 | 184 | out := defaultApp.getNativeWindowEventsOut() 185 | if out == nil { 186 | return 187 | } 188 | event := NativeWindowEvent{ 189 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 190 | Window: (*android.NativeWindow)(window), 191 | Kind: NativeWindowRedrawNeeded, 192 | } 193 | select { 194 | case <-defaultApp.nativeWindowRedrawDone: 195 | default: 196 | // skip check 197 | } 198 | select { 199 | case out <- event: 200 | // dispatched 201 | case <-time.After(defaultApp.maxDispatchTime): 202 | return // timed out 203 | } 204 | // The drawing window for this native activity needs to be 205 | // redrawn. To avoid transient artifacts during screen changes 206 | // (such resizing after rotation), applications should not return 207 | // from this function until they have finished drawing their 208 | // window in its current state. 209 | // 210 | // Refer to 211 | // https://developer.android.com/ndk/reference/struct_a_native_activity_callbacks.html 212 | <-defaultApp.nativeWindowRedrawDone 213 | } 214 | 215 | //export onNativeWindowDestroyed 216 | func onNativeWindowDestroyed(activity *C.ANativeActivity, window *C.ANativeWindow) { 217 | defaultApp.initWG.Wait() 218 | 219 | out := defaultApp.getNativeWindowEventsOut() 220 | if out == nil { 221 | return 222 | } 223 | event := NativeWindowEvent{ 224 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 225 | Window: (*android.NativeWindow)(window), 226 | Kind: NativeWindowDestroyed, 227 | } 228 | select { 229 | case out <- event: 230 | // dispatched 231 | case <-time.After(defaultApp.maxDispatchTime): 232 | // timed out 233 | } 234 | } 235 | 236 | type InputQueueEvent struct { 237 | Activity *android.NativeActivity 238 | Queue *android.InputQueue 239 | Kind InputQueueEventKind 240 | } 241 | 242 | type InputQueueEventKind string 243 | 244 | const ( 245 | QueueCreated InputQueueEventKind = "queueCreated" 246 | QueueDestroyed InputQueueEventKind = "queueDestroyed" 247 | ) 248 | 249 | //export onInputQueueCreated 250 | func onInputQueueCreated(activity *C.ANativeActivity, queue *C.AInputQueue) { 251 | defaultApp.initWG.Wait() 252 | 253 | out := defaultApp.getInputQueueEventsOut() 254 | if out == nil { 255 | return 256 | } 257 | event := InputQueueEvent{ 258 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 259 | Queue: (*android.InputQueue)(queue), 260 | Kind: QueueCreated, 261 | } 262 | select { 263 | case out <- event: 264 | // dispatched 265 | case <-time.After(defaultApp.maxDispatchTime): 266 | return // timed out 267 | } 268 | 269 | <-defaultApp.inputQueueHandled 270 | } 271 | 272 | //export onInputQueueDestroyed 273 | func onInputQueueDestroyed(activity *C.ANativeActivity, queue *C.AInputQueue) { 274 | defaultApp.initWG.Wait() 275 | 276 | out := defaultApp.getInputQueueEventsOut() 277 | if out == nil { 278 | return 279 | } 280 | event := InputQueueEvent{ 281 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 282 | Queue: (*android.InputQueue)(queue), 283 | Kind: QueueDestroyed, 284 | } 285 | select { 286 | case out <- event: 287 | // dispatched 288 | case <-time.After(defaultApp.maxDispatchTime): 289 | return // timed out 290 | } 291 | 292 | <-defaultApp.inputQueueHandled 293 | } 294 | 295 | type ContentRectEvent struct { 296 | Activity *android.NativeActivity 297 | Rect *android.Rect 298 | } 299 | 300 | //export onContentRectChanged 301 | func onContentRectChanged(activity *C.ANativeActivity, rect *C.ARect) { 302 | defaultApp.initWG.Wait() 303 | 304 | out := defaultApp.getContentRectEventsOut() 305 | if out == nil { 306 | return 307 | } 308 | event := ContentRectEvent{ 309 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 310 | Rect: android.NewRectRef(unsafe.Pointer(rect)), 311 | } 312 | select { 313 | case out <- event: 314 | // dispatched 315 | case <-time.After(defaultApp.maxDispatchTime): 316 | // timed out 317 | } 318 | } 319 | 320 | type ActivityEvent struct { 321 | Activity *android.NativeActivity 322 | Kind ActivityEventKind 323 | } 324 | 325 | type ActivityEventKind string 326 | 327 | const ( 328 | OnConfigurationChanged ActivityEventKind = "onConfigurationChanged" 329 | OnLowMemory ActivityEventKind = "onLowMemory" 330 | ) 331 | 332 | //export onConfigurationChanged 333 | func onConfigurationChanged(activity *C.ANativeActivity) { 334 | defaultApp.initWG.Wait() 335 | 336 | out := defaultApp.getActivityEventsOut() 337 | if out == nil { 338 | return 339 | } 340 | event := ActivityEvent{ 341 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 342 | Kind: OnConfigurationChanged, 343 | } 344 | select { 345 | case out <- event: 346 | // dispatched 347 | case <-time.After(defaultApp.maxDispatchTime): 348 | // timed out 349 | } 350 | } 351 | 352 | //export onLowMemory 353 | func onLowMemory(activity *C.ANativeActivity) { 354 | defaultApp.initWG.Wait() 355 | 356 | out := defaultApp.getActivityEventsOut() 357 | if out == nil { 358 | return 359 | } 360 | event := ActivityEvent{ 361 | Activity: android.NewNativeActivityRef(unsafe.Pointer(activity)), 362 | Kind: OnLowMemory, 363 | } 364 | select { 365 | case out <- event: 366 | // dispatched 367 | case <-time.After(defaultApp.maxDispatchTime): 368 | // timed out 369 | } 370 | } 371 | -------------------------------------------------------------------------------- /app/internal/callfn/callfn.go: -------------------------------------------------------------------------------- 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 android 6 | // +build arm 386 amd64 arm64 7 | 8 | // Package callfn provides an android entry point. 9 | // 10 | // It is a separate package from app because it contains Go assembly, 11 | // which does not compile in a package using cgo. 12 | package callfn 13 | 14 | // CallFn calls a zero-argument function by its program counter. 15 | // It is only intended for calling main.main. Using it for 16 | // anything else will not end well. 17 | func CallFn(fn uintptr) 18 | -------------------------------------------------------------------------------- /app/internal/callfn/callfn_386.s: -------------------------------------------------------------------------------- 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 | #include "textflag.h" 6 | #include "funcdata.h" 7 | 8 | TEXT ·CallFn(SB),$0-4 9 | MOVL fn+0(FP), AX 10 | CALL AX 11 | RET 12 | -------------------------------------------------------------------------------- /app/internal/callfn/callfn_amd64.s: -------------------------------------------------------------------------------- 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 | #include "textflag.h" 6 | #include "funcdata.h" 7 | 8 | TEXT ·CallFn(SB),$0-8 9 | MOVQ fn+0(FP), AX 10 | CALL AX 11 | RET 12 | -------------------------------------------------------------------------------- /app/internal/callfn/callfn_arm.s: -------------------------------------------------------------------------------- 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 | #include "textflag.h" 6 | #include "funcdata.h" 7 | 8 | TEXT ·CallFn(SB),$0-4 9 | MOVW fn+0(FP), R0 10 | BL (R0) 11 | RET 12 | -------------------------------------------------------------------------------- /app/internal/callfn/callfn_arm64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2016 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 | #include "textflag.h" 6 | #include "funcdata.h" 7 | 8 | TEXT ·CallFn(SB),$0-8 9 | MOVD fn+0(FP), R0 10 | BL (R0) 11 | RET 12 | -------------------------------------------------------------------------------- /app/logging.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "bufio" 5 | "log" 6 | "os" 7 | "sync" 8 | 9 | "github.com/xlab/android-go/android" 10 | ) 11 | 12 | var ( 13 | logTag string 14 | logTagFunc func() string 15 | logTagMux sync.Mutex 16 | ) 17 | 18 | func SetLogTag(tag string) { 19 | logTagMux.Lock() 20 | logTag = tag + "\x00" 21 | logTagFunc = func() string { 22 | return logTag 23 | } 24 | logTagMux.Unlock() 25 | } 26 | 27 | type logger struct{} 28 | 29 | func (logger) Write(p []byte) (n int, err error) { 30 | android.LogWrite(int32(android.LogInfo), logTagFunc(), string(p)+"\x00") 31 | return len(p), nil 32 | } 33 | 34 | func init() { 35 | SetLogTag("GoApp") 36 | 37 | log.SetOutput(logger{}) 38 | // android logcat includes all of log.LstdFlags 39 | log.SetFlags(log.Flags() &^ log.LstdFlags) 40 | 41 | r, w, err := os.Pipe() 42 | if err != nil { 43 | panic(err) 44 | } 45 | os.Stderr = w 46 | go lineLog(r, android.LogError) 47 | 48 | r, w, err = os.Pipe() 49 | if err != nil { 50 | panic(err) 51 | } 52 | os.Stdout = w 53 | go lineLog(r, android.LogInfo) 54 | } 55 | 56 | func lineLog(f *os.File, priority android.LogPriority) { 57 | const logSize = 1024 // matches android/log.h. 58 | r := bufio.NewReaderSize(f, logSize) 59 | for { 60 | line, _, err := r.ReadLine() 61 | str := string(line) 62 | if err != nil { 63 | str += " " + err.Error() 64 | } 65 | android.LogWrite(int32(priority), logTagFunc(), str+"\x00") 66 | if err != nil { 67 | break 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/queue.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/xlab/android-go/android" 8 | ) 9 | 10 | var SkipInputEvents = func(ev *android.InputEvent) {} 11 | 12 | var LogInputEvents = func(ev *android.InputEvent) { 13 | switch android.InputEventGetType(ev) { 14 | case android.InputEventTypeKey: 15 | key := android.KeyEventGetKeyCode(ev) 16 | log.Printf("key event [%d]", key) 17 | case android.InputEventTypeMotion: 18 | str := "motion event " 19 | fingers := android.MotionEventGetPointerCount(ev) 20 | for i := uint32(0); i < fingers; i++ { 21 | x := android.MotionEventGetX(ev, i) 22 | y := android.MotionEventGetY(ev, i) 23 | pressure := android.MotionEventGetPressure(ev, i) 24 | str += fmt.Sprintf("[%.0f; %.0f; %.2f]", x, y, pressure) 25 | } 26 | log.Println(str) 27 | } 28 | } 29 | 30 | func HandleInputQueues(queueChan <-chan *android.InputQueue, onProcessed func(), 31 | evHandler func(ev *android.InputEvent)) { 32 | 33 | looper := android.LooperPrepare(android.LooperPrepareAllowNonCallbacks) 34 | pending := make(chan *android.InputQueue, 1) 35 | go func() { 36 | for queue := range queueChan { 37 | pending <- queue 38 | android.LooperWake(looper) 39 | } 40 | }() 41 | 42 | var current *android.InputQueue 43 | for { 44 | if android.LooperPollAll(-1, nil, nil, nil) == android.LooperPollWake { 45 | select { 46 | default: 47 | case p := <-pending: 48 | if current != nil { 49 | handleEvents(current, evHandler) 50 | android.InputQueueDetachLooper(current) 51 | } 52 | current = p 53 | if current != nil { 54 | android.InputQueueAttachLooper(current, looper, 0, nil, nil) 55 | } 56 | onProcessed() 57 | } 58 | } 59 | if current != nil { 60 | handleEvents(current, evHandler) 61 | } 62 | } 63 | } 64 | 65 | func handleEvents(queue *android.InputQueue, evHandler func(ev *android.InputEvent)) { 66 | var ev *android.InputEvent 67 | for android.InputQueueGetEvent(queue, &ev) >= 0 { 68 | if android.InputQueuePreDispatchEvent(queue, ev) != 0 { 69 | continue 70 | } 71 | evHandler(ev) 72 | var response int32 = 0 73 | 74 | switch android.InputEventGetType(ev) { 75 | case android.InputEventTypeKey: 76 | key := android.KeyEventGetKeyCode(ev) 77 | if key == android.KeycodeBack { 78 | response = 1 79 | } 80 | } 81 | android.InputQueueFinishEvent(queue, ev, response) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /cmd/android-project/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright © 2017 Maxim Kupriianov 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the “Software”), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /cmd/android-project/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go-bindata -pkg main templates/ 3 | -------------------------------------------------------------------------------- /cmd/android-project/README.md: -------------------------------------------------------------------------------- 1 | ## android-project 2 | 3 | Android Project tool is a simple replacement for infamous `android` util from Android SDK, prior to Android SDK Tools [Revision 25.3.0 (March 2017) release](https://developer.android.com/studio/releases/sdk-tools.html) when they dropped that util abruptly. Realising their mistake later that March, they got it back, so it actually forwards the commands for `avd`, `target`, and `device` to the underlying layers properly, but still lacks of `android project update` capability. 4 | 5 | I used `android project update` to simply create Ant build scripts for the projects with guarantees, that platform exists and is supported. So this tool does the same thing and it's the only feature implemented now. 6 | 7 | ### Installation 8 | 9 | ``` 10 | go install github.com/xlab/android-go/cmd/android-project@latest 11 | ``` 12 | 13 | Also you must set `$ANDROID_HOME` to your Android SDK location, e.g. 14 | 15 | ``` 16 | export ANDROID_HOME=/Users/xlab/Library/Android/sdk 17 | ``` 18 | 19 | ### Usage 20 | 21 | ``` 22 | Usage: android-project update [--sdk] [--target] [--force] --name --path 23 | 24 | Updates an Android project (must already have an AndroidManifest.xml) 25 | ``` 26 | 27 | [GolangExample](https://github.com/xlab/android-go/blob/master/example/android/Makefile) 28 | 29 | ``` 30 | $ android-project update --target android-23 --name GolangExample --path . 31 | . 32 | ├── Environment 33 | │   ├── [/Users/xlab/Library/Android/sdk] Android SDK location 34 | │   ├── [/Users/xlab/Library/Android/sdk/ndk-bundle] Android NDK location 35 | │   ├── [/Users/xlab/Library/Android/sdk/platforms] Android Platforms location 36 | │   └── [[android-23 android-N]] Android Platforms available 37 | ├── Project 38 | │   ├── [GolangExample] Project name 39 | │   ├── [android-23] Project target 40 | │   └── [.] Project location 41 | └── Files updated 42 | ├── build.xml 43 | ├── local.properties 44 | ├── project.properties 45 | └── proguard-project.txt 46 | ``` 47 | 48 | As you can see, the effect of running this command is very similar to `android project update`. At least is used to be. 49 | 50 | ``` 51 | $ android project update 52 | ************************************************************************* 53 | The "android" command is deprecated. 54 | For manual SDK, AVD, and project management, please use Android Studio. 55 | For command-line tools, use tools/bin/sdkmanager and tools/bin/avdmanager 56 | ************************************************************************* 57 | Invalid or unsupported command "project update" 58 | ``` 59 | 60 | ### License 61 | 62 | MIT 63 | -------------------------------------------------------------------------------- /cmd/android-project/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "path/filepath" 7 | 8 | "github.com/jawher/mow.cli" 9 | "github.com/xlab/closer" 10 | "github.com/xlab/treeprint" 11 | ) 12 | 13 | var app = cli.App("android-project", `Android project bootstrap tool for use instead of version that was removed from Android SDK (since Revision 25.3.0). 14 | See https://developer.android.com/studio/releases/sdk-tools.html`) 15 | 16 | func init() { 17 | log.SetFlags(0) 18 | } 19 | 20 | func main() { 21 | app.Command("update", "Updates an Android project (must already have an AndroidManifest.xml).", cmdUpdateFunc) 22 | app.Command("platforms", "Lists Android platforms supported within SDK.", cmdPlatformsFunc) 23 | 24 | if err := app.Run(os.Args); err != nil { 25 | closer.Fatalln(err) 26 | } 27 | } 28 | 29 | func cmdPlatformsFunc(c *cli.Cmd) { 30 | sdkDir := c.String(cli.StringOpt{ 31 | Name: "sdk", 32 | Desc: "Android SDK location, can also be set using ANDROID_HOME env variable.", 33 | EnvVar: "ANDROID_HOME", 34 | HideValue: true, 35 | }) 36 | c.Spec = "[--sdk]" 37 | c.Action = func() { 38 | defer closer.Close() 39 | 40 | if len(*sdkDir) == 0 { 41 | closer.Fatalln("ANDROID_HOME environment variable not set (or --sdk flag not provided).") 42 | } 43 | _, platformsDir := learnPaths(*sdkDir) 44 | log.Println("Available Android platforms:") 45 | platforms := learnPlatforms(platformsDir) 46 | for _, platform := range platforms { 47 | log.Println("*", platform) 48 | } 49 | } 50 | } 51 | 52 | func cmdUpdateFunc(c *cli.Cmd) { 53 | pathOpt := c.StringOpt("p path", "", "The project's directory.") 54 | nameOpt := c.StringOpt("n name", "", "Project name.") 55 | forceOpt := c.BoolOpt("f force", false, "Force generation, even if the target platform is not supported.") 56 | targetOpt := c.StringOpt("t target", "android-23", "Target ID to set for the project.") 57 | sdkDir := c.String(cli.StringOpt{ 58 | Name: "sdk", 59 | Desc: "Android SDK location, can also be set using ANDROID_HOME env variable.", 60 | EnvVar: "ANDROID_HOME", 61 | HideValue: true, 62 | }) 63 | c.Spec = "[--sdk] [--target] [--force] --name --path" 64 | c.Action = func() { 65 | defer closer.Close() 66 | 67 | if len(*sdkDir) == 0 { 68 | closer.Fatalln("ANDROID_HOME environment variable not set (or --sdk flag not provided).") 69 | } 70 | tree := treeprint.New() 71 | closer.Bind(func() { 72 | log.Println(tree) 73 | }) 74 | ndkDir, platformsDir := learnPaths(*sdkDir) 75 | 76 | env := tree.AddBranch("Environment"). 77 | AddMetaNode(*sdkDir, "Android SDK location"). 78 | AddMetaNode(ndkDir, "Android NDK location"). 79 | AddMetaNode(platformsDir, "Android Platforms location") 80 | platforms := learnPlatforms(platformsDir) 81 | env.AddMetaNode(platforms, "Android Platforms available") 82 | 83 | ctx := &TemplateContext{ 84 | ProjectName: *nameOpt, 85 | ProjectTarget: *targetOpt, 86 | 87 | SDKDir: *sdkDir, 88 | } 89 | tree.AddBranch("Project"). 90 | AddMetaNode(ctx.ProjectName, "Project name"). 91 | AddMetaNode(ctx.ProjectTarget, "Project target"). 92 | AddMetaNode(*pathOpt, "Project location") 93 | 94 | manifestFileName := filepath.Join(*pathOpt, "AndroidManifest.xml") 95 | if _, err := os.Stat(manifestFileName); os.IsNotExist(err) { 96 | closer.Fatalln("AndroidManifest.xml not found in project location") 97 | } 98 | var platformSupported bool 99 | for _, platform := range platforms { 100 | if *targetOpt == platform { 101 | platformSupported = true 102 | } 103 | } 104 | if !platformSupported && !(*forceOpt) { 105 | closer.Fatalln("Platform", *targetOpt, "not supported within this SDK, build may fail. Use -f flag to override.") 106 | } 107 | 108 | files := tree.AddBranch("Files updated") 109 | for _, tpl := range templates { 110 | fileName := filepath.Join(*pathOpt, tpl.TargetName()) 111 | f, err := os.Create(fileName) 112 | if err != nil { 113 | closer.Fatalf("Failed to create file %s: %v", fileName, err) 114 | } 115 | if err := tpl.Render(ctx, f); err != nil { 116 | closer.Fatalf("Failed to render template %s: %v", tpl.Name(), err) 117 | } 118 | f.Close() 119 | files.AddNode(fileName) 120 | } 121 | } 122 | } 123 | 124 | func learnPlatforms(platformsDir string) []string { 125 | var platforms []string 126 | filepath.Walk(platformsDir, func(path string, info os.FileInfo, err error) error { 127 | if err != nil { 128 | return err 129 | } 130 | if path == platformsDir { 131 | return nil 132 | } 133 | platforms = append(platforms, filepath.Base(path)) 134 | return filepath.SkipDir 135 | }) 136 | return platforms 137 | } 138 | 139 | func learnPaths(sdkDir string) (ndkDir, platformsDir string) { 140 | if _, err := os.Stat(sdkDir); err != nil { 141 | closer.Fatalln("Android SDK location is provided but not valid:", sdkDir) 142 | } 143 | ndkDir = filepath.Join(sdkDir, "ndk-bundle") 144 | if _, err := os.Stat(sdkDir); err != nil { 145 | log.Println("WARN: Android SDK location is provided but has no ndk-bundle:", ndkDir) 146 | } 147 | platformsDir = filepath.Join(sdkDir, "platforms") 148 | if _, err := os.Stat(sdkDir); err != nil { 149 | closer.Fatalln("Android SDK location is provided but has no platforms:", platformsDir) 150 | } 151 | return 152 | } 153 | -------------------------------------------------------------------------------- /cmd/android-project/templates.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "text/template" 6 | ) 7 | 8 | type TemplateContext struct { 9 | ProjectName string 10 | ProjectTarget string 11 | SDKDir string 12 | } 13 | 14 | type Template interface { 15 | Name() string 16 | TargetName() string 17 | Render(ctx *TemplateContext, wr io.Writer) error 18 | } 19 | 20 | var templates = []Template{ 21 | &tpl{ 22 | name: "build.xml.tpl", 23 | target: "build.xml", 24 | Template: template.Must(template.New("build.xml.tpl"). 25 | Parse(string(MustAsset("templates/build.xml.tpl")))), 26 | }, 27 | &tpl{ 28 | name: "local.properties.tpl", 29 | target: "local.properties", 30 | Template: template.Must(template.New("local.properties.tpl"). 31 | Parse(string(MustAsset("templates/local.properties.tpl")))), 32 | }, 33 | &tpl{ 34 | name: "project.properties.tpl", 35 | target: "project.properties", 36 | Template: template.Must(template.New("project.properties.tpl"). 37 | Parse(string(MustAsset("templates/project.properties.tpl")))), 38 | }, 39 | &tpl{ 40 | name: "proguard-project.txt.tpl", 41 | target: "proguard-project.txt", 42 | Template: template.Must(template.New("proguard-project.txt.tpl"). 43 | Parse(string(MustAsset("templates/proguard-project.txt.tpl")))), 44 | }, 45 | } 46 | 47 | type tpl struct { 48 | *template.Template 49 | 50 | name string 51 | target string 52 | } 53 | 54 | func (t *tpl) Name() string { 55 | return t.name 56 | } 57 | 58 | func (t *tpl) TargetName() string { 59 | return t.target 60 | } 61 | 62 | func (t *tpl) Render(ctx *TemplateContext, wr io.Writer) error { 63 | return t.Template.Execute(wr, ctx) 64 | } 65 | -------------------------------------------------------------------------------- /cmd/android-project/templates/build.xml.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 49 | 50 | 51 | 52 | 56 | 57 | 69 | 70 | 71 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /cmd/android-project/templates/local.properties.tpl: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | 7 | # location of the SDK. This is only used by Ant 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | sdk.dir={{.SDKDir}} 11 | -------------------------------------------------------------------------------- /cmd/android-project/templates/proguard-project.txt.tpl: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /cmd/android-project/templates/project.properties.tpl: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target={{.ProjectTarget}} 15 | -------------------------------------------------------------------------------- /egl.yml: -------------------------------------------------------------------------------- 1 | --- 2 | GENERATOR: 3 | PackageName: egl 4 | PackageDescription: "Package egl provides Go bindings for EGL API." 5 | PackageLicense: "THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS." 6 | FlagGroups: 7 | - {name: LDFLAGS, flags: [-lEGL]} 8 | SysIncludes: 9 | - EGL/egl.h 10 | 11 | PARSER: 12 | Arch: arm 13 | SourcesPaths: 14 | - EGL/egl.h 15 | IncludePaths: 16 | # NOTE: Replace these paths if you want to re-generate. 17 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include 18 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include/linux 19 | Defines: 20 | __ANDROID__: 1 21 | EGLAPIENTRYP: {} 22 | 23 | TRANSLATOR: 24 | ConstRules: 25 | defines: expand 26 | enum: expand 27 | PtrTips: 28 | function: 29 | - {target: ^eglGetConfigs$, tips: [0,arr,size,ref]} 30 | - {target: ^eglChooseConfig$, tips: [0,arr,arr,size,ref]} 31 | - {target: ^eglCreateWindowSurface$, tips: [0,0,0,arr]} 32 | - {target: ^eglCreatePbufferSurface$, tips: [0,0,arr]} 33 | - {target: ^eglCreatePixmapSurface$, tips: [0,0,0,arr]} 34 | - {target: ^eglCreatePbufferFromClientBuffer$, tips: [0,0,0,0,arr]} 35 | - {target: ^eglCreateContext$, tips: [0,0,0,arr]} 36 | - {target: ^egl, tips: [ref,ref,ref,ref]} # covers the rest 37 | TypeTips: 38 | type: 39 | - {target: EGLint$, self: plain} 40 | function: 41 | - {target: ^eglGetError$, self: plain} 42 | Rules: 43 | global: 44 | - {action: accept, from: "^EGL"} 45 | - {action: replace, from: "^EGL"} 46 | function: 47 | - {action: accept, from: ^egl} 48 | - {action: replace, from: ^egl} 49 | - {action: ignore, from: ^eglGetProcAddress} 50 | type: 51 | - {action: replace, from: "_t$"} 52 | const: 53 | - {action: ignore, from: EGL_NO_DISPLAY} 54 | - {action: ignore, from: EGL_NO_SURFACE} 55 | - {action: ignore, from: EGL_NO_CONTEXT} 56 | - {action: ignore, from: EGL_DEFAULT_DISPLAY} 57 | - {transform: lower} 58 | private: 59 | - {transform: unexport} 60 | post-global: 61 | - {action: doc, from: "^egl", 62 | to: "https://www.khronos.org/registry/egl/sdk/docs/man/html/$name.xhtml"} 63 | - {transform: export} 64 | - {load: snakecase} 65 | 66 | 67 | -------------------------------------------------------------------------------- /egl/cgo_helpers.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package egl 7 | 8 | /* 9 | #cgo LDFLAGS: -lEGL 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | import ( 16 | "sync" 17 | "unsafe" 18 | ) 19 | 20 | // cgoAllocMap stores pointers to C allocated memory for future reference. 21 | type cgoAllocMap struct { 22 | mux sync.RWMutex 23 | m map[unsafe.Pointer]struct{} 24 | } 25 | 26 | var cgoAllocsUnknown = new(cgoAllocMap) 27 | 28 | func (a *cgoAllocMap) Add(ptr unsafe.Pointer) { 29 | a.mux.Lock() 30 | if a.m == nil { 31 | a.m = make(map[unsafe.Pointer]struct{}) 32 | } 33 | a.m[ptr] = struct{}{} 34 | a.mux.Unlock() 35 | } 36 | 37 | func (a *cgoAllocMap) IsEmpty() bool { 38 | a.mux.RLock() 39 | isEmpty := len(a.m) == 0 40 | a.mux.RUnlock() 41 | return isEmpty 42 | } 43 | 44 | func (a *cgoAllocMap) Borrow(b *cgoAllocMap) { 45 | if b == nil || b.IsEmpty() { 46 | return 47 | } 48 | b.mux.Lock() 49 | a.mux.Lock() 50 | for ptr := range b.m { 51 | if a.m == nil { 52 | a.m = make(map[unsafe.Pointer]struct{}) 53 | } 54 | a.m[ptr] = struct{}{} 55 | delete(b.m, ptr) 56 | } 57 | a.mux.Unlock() 58 | b.mux.Unlock() 59 | } 60 | 61 | func (a *cgoAllocMap) Free() { 62 | a.mux.Lock() 63 | for ptr := range a.m { 64 | C.free(ptr) 65 | delete(a.m, ptr) 66 | } 67 | a.mux.Unlock() 68 | } 69 | 70 | // packPCharString creates a Go string backed by *C.char and avoids copying. 71 | func packPCharString(p *C.char) (raw string) { 72 | if p != nil && *p != 0 { 73 | h := (*stringHeader)(unsafe.Pointer(&raw)) 74 | h.Data = uintptr(unsafe.Pointer(p)) 75 | for *p != 0 { 76 | p = (*C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++ 77 | } 78 | h.Len = int(uintptr(unsafe.Pointer(p)) - h.Data) 79 | } 80 | return 81 | } 82 | 83 | type stringHeader struct { 84 | Data uintptr 85 | Len int 86 | } 87 | 88 | // RawString reperesents a string backed by data on the C side. 89 | type RawString string 90 | 91 | // Copy returns a Go-managed copy of raw string. 92 | func (raw RawString) Copy() string { 93 | if len(raw) == 0 { 94 | return "" 95 | } 96 | h := (*stringHeader)(unsafe.Pointer(&raw)) 97 | return C.GoStringN((*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len)) 98 | } 99 | 100 | type sliceHeader struct { 101 | Data uintptr 102 | Len int 103 | Cap int 104 | } 105 | -------------------------------------------------------------------------------- /egl/cgo_helpers.h: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | #include 7 | #include 8 | #pragma once 9 | 10 | #define __CGOGEN 1 11 | 12 | -------------------------------------------------------------------------------- /egl/const.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package egl 7 | 8 | /* 9 | #cgo LDFLAGS: -lEGL 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | 16 | const ( 17 | // Version10 as defined in EGL/egl.h:53 18 | Version10 = 1 19 | // Version11 as defined in EGL/egl.h:54 20 | Version11 = 1 21 | // Version12 as defined in EGL/egl.h:55 22 | Version12 = 1 23 | // Version13 as defined in EGL/egl.h:56 24 | Version13 = 1 25 | // Version14 as defined in EGL/egl.h:57 26 | Version14 = 1 27 | // False as defined in EGL/egl.h:64 28 | False = 0 29 | // True as defined in EGL/egl.h:65 30 | True = 1 31 | // DontCare as defined in EGL/egl.h:74 32 | DontCare = ((Int)(-1)) 33 | // Success as defined in EGL/egl.h:77 34 | Success = 0x3000 35 | // NotInitialized as defined in EGL/egl.h:78 36 | NotInitialized = 0x3001 37 | // BadAccess as defined in EGL/egl.h:79 38 | BadAccess = 0x3002 39 | // BadAlloc as defined in EGL/egl.h:80 40 | BadAlloc = 0x3003 41 | // BadAttribute as defined in EGL/egl.h:81 42 | BadAttribute = 0x3004 43 | // BadConfig as defined in EGL/egl.h:82 44 | BadConfig = 0x3005 45 | // BadContext as defined in EGL/egl.h:83 46 | BadContext = 0x3006 47 | // BadCurrentSurface as defined in EGL/egl.h:84 48 | BadCurrentSurface = 0x3007 49 | // BadDisplay as defined in EGL/egl.h:85 50 | BadDisplay = 0x3008 51 | // BadMatch as defined in EGL/egl.h:86 52 | BadMatch = 0x3009 53 | // BadNativePixmap as defined in EGL/egl.h:87 54 | BadNativePixmap = 0x300A 55 | // BadNativeWindow as defined in EGL/egl.h:88 56 | BadNativeWindow = 0x300B 57 | // BadParameter as defined in EGL/egl.h:89 58 | BadParameter = 0x300C 59 | // BadSurface as defined in EGL/egl.h:90 60 | BadSurface = 0x300D 61 | // ContextLost as defined in EGL/egl.h:91 62 | ContextLost = 0x300E 63 | // BufferSize as defined in EGL/egl.h:96 64 | BufferSize = 0x3020 65 | // AlphaSize as defined in EGL/egl.h:97 66 | AlphaSize = 0x3021 67 | // BlueSize as defined in EGL/egl.h:98 68 | BlueSize = 0x3022 69 | // GreenSize as defined in EGL/egl.h:99 70 | GreenSize = 0x3023 71 | // RedSize as defined in EGL/egl.h:100 72 | RedSize = 0x3024 73 | // DepthSize as defined in EGL/egl.h:101 74 | DepthSize = 0x3025 75 | // StencilSize as defined in EGL/egl.h:102 76 | StencilSize = 0x3026 77 | // ConfigCaveat as defined in EGL/egl.h:103 78 | ConfigCaveat = 0x3027 79 | // ConfigId as defined in EGL/egl.h:104 80 | ConfigId = 0x3028 81 | // Level as defined in EGL/egl.h:105 82 | Level = 0x3029 83 | // MaxPbufferHeight as defined in EGL/egl.h:106 84 | MaxPbufferHeight = 0x302A 85 | // MaxPbufferPixels as defined in EGL/egl.h:107 86 | MaxPbufferPixels = 0x302B 87 | // MaxPbufferWidth as defined in EGL/egl.h:108 88 | MaxPbufferWidth = 0x302C 89 | // NativeRenderable as defined in EGL/egl.h:109 90 | NativeRenderable = 0x302D 91 | // NativeVisualId as defined in EGL/egl.h:110 92 | NativeVisualId = 0x302E 93 | // NativeVisualType as defined in EGL/egl.h:111 94 | NativeVisualType = 0x302F 95 | // Samples as defined in EGL/egl.h:112 96 | Samples = 0x3031 97 | // SampleBuffers as defined in EGL/egl.h:113 98 | SampleBuffers = 0x3032 99 | // SurfaceType as defined in EGL/egl.h:114 100 | SurfaceType = 0x3033 101 | // TransparentType as defined in EGL/egl.h:115 102 | TransparentType = 0x3034 103 | // TransparentBlueValue as defined in EGL/egl.h:116 104 | TransparentBlueValue = 0x3035 105 | // TransparentGreenValue as defined in EGL/egl.h:117 106 | TransparentGreenValue = 0x3036 107 | // TransparentRedValue as defined in EGL/egl.h:118 108 | TransparentRedValue = 0x3037 109 | // None as defined in EGL/egl.h:119 110 | None = 0x3038 111 | // BindToTextureRgb as defined in EGL/egl.h:120 112 | BindToTextureRgb = 0x3039 113 | // BindToTextureRgba as defined in EGL/egl.h:121 114 | BindToTextureRgba = 0x303A 115 | // MinSwapInterval as defined in EGL/egl.h:122 116 | MinSwapInterval = 0x303B 117 | // MaxSwapInterval as defined in EGL/egl.h:123 118 | MaxSwapInterval = 0x303C 119 | // LuminanceSize as defined in EGL/egl.h:124 120 | LuminanceSize = 0x303D 121 | // AlphaMaskSize as defined in EGL/egl.h:125 122 | AlphaMaskSize = 0x303E 123 | // ColorBufferType as defined in EGL/egl.h:126 124 | ColorBufferType = 0x303F 125 | // RenderableType as defined in EGL/egl.h:127 126 | RenderableType = 0x3040 127 | // MatchNativePixmap as defined in EGL/egl.h:128 128 | MatchNativePixmap = 0x3041 129 | // Conformant as defined in EGL/egl.h:129 130 | Conformant = 0x3042 131 | // SlowConfig as defined in EGL/egl.h:134 132 | SlowConfig = 0x3050 133 | // NonConformantConfig as defined in EGL/egl.h:135 134 | NonConformantConfig = 0x3051 135 | // TransparentRgb as defined in EGL/egl.h:136 136 | TransparentRgb = 0x3052 137 | // RgbBuffer as defined in EGL/egl.h:137 138 | RgbBuffer = 0x308E 139 | // LuminanceBuffer as defined in EGL/egl.h:138 140 | LuminanceBuffer = 0x308F 141 | // NoTexture as defined in EGL/egl.h:141 142 | NoTexture = 0x305C 143 | // TextureRgb as defined in EGL/egl.h:142 144 | TextureRgb = 0x305D 145 | // TextureRgba as defined in EGL/egl.h:143 146 | TextureRgba = 0x305E 147 | // Texture2d as defined in EGL/egl.h:144 148 | Texture2d = 0x305F 149 | // PbufferBit as defined in EGL/egl.h:147 150 | PbufferBit = 0x0001 151 | // PixmapBit as defined in EGL/egl.h:148 152 | PixmapBit = 0x0002 153 | // WindowBit as defined in EGL/egl.h:149 154 | WindowBit = 0x0004 155 | // VgColorspaceLinearBit as defined in EGL/egl.h:150 156 | VgColorspaceLinearBit = 0x0020 157 | // VgAlphaFormatPreBit as defined in EGL/egl.h:151 158 | VgAlphaFormatPreBit = 0x0040 159 | // MultisampleResolveBoxBit as defined in EGL/egl.h:152 160 | MultisampleResolveBoxBit = 0x0200 161 | // SwapBehaviorPreservedBit as defined in EGL/egl.h:153 162 | SwapBehaviorPreservedBit = 0x0400 163 | // OpenglEsBit as defined in EGL/egl.h:155 164 | OpenglEsBit = 0x0001 165 | // OpenvgBit as defined in EGL/egl.h:156 166 | OpenvgBit = 0x0002 167 | // OpenglEs2Bit as defined in EGL/egl.h:157 168 | OpenglEs2Bit = 0x0004 169 | // OpenglBit as defined in EGL/egl.h:158 170 | OpenglBit = 0x0008 171 | // Vendor as defined in EGL/egl.h:161 172 | Vendor = 0x3053 173 | // Version as defined in EGL/egl.h:162 174 | Version = 0x3054 175 | // Extensions as defined in EGL/egl.h:163 176 | Extensions = 0x3055 177 | // ClientApis as defined in EGL/egl.h:164 178 | ClientApis = 0x308D 179 | // Height as defined in EGL/egl.h:167 180 | Height = 0x3056 181 | // Width as defined in EGL/egl.h:168 182 | Width = 0x3057 183 | // LargestPbuffer as defined in EGL/egl.h:169 184 | LargestPbuffer = 0x3058 185 | // TextureFormat as defined in EGL/egl.h:170 186 | TextureFormat = 0x3080 187 | // TextureTarget as defined in EGL/egl.h:171 188 | TextureTarget = 0x3081 189 | // MipmapTexture as defined in EGL/egl.h:172 190 | MipmapTexture = 0x3082 191 | // MipmapLevel as defined in EGL/egl.h:173 192 | MipmapLevel = 0x3083 193 | // RenderBuffer as defined in EGL/egl.h:174 194 | RenderBuffer = 0x3086 195 | // VgColorspace as defined in EGL/egl.h:175 196 | VgColorspace = 0x3087 197 | // VgAlphaFormat as defined in EGL/egl.h:176 198 | VgAlphaFormat = 0x3088 199 | // HorizontalResolution as defined in EGL/egl.h:177 200 | HorizontalResolution = 0x3090 201 | // VerticalResolution as defined in EGL/egl.h:178 202 | VerticalResolution = 0x3091 203 | // PixelAspectRatio as defined in EGL/egl.h:179 204 | PixelAspectRatio = 0x3092 205 | // SwapBehavior as defined in EGL/egl.h:180 206 | SwapBehavior = 0x3093 207 | // MultisampleResolve as defined in EGL/egl.h:181 208 | MultisampleResolve = 0x3099 209 | // BackBuffer as defined in EGL/egl.h:184 210 | BackBuffer = 0x3084 211 | // SingleBuffer as defined in EGL/egl.h:185 212 | SingleBuffer = 0x3085 213 | // VgColorspaceSrgb as defined in EGL/egl.h:188 214 | VgColorspaceSrgb = 0x3089 215 | // VgColorspaceLinear as defined in EGL/egl.h:189 216 | VgColorspaceLinear = 0x308A 217 | // VgAlphaFormatNonpre as defined in EGL/egl.h:192 218 | VgAlphaFormatNonpre = 0x308B 219 | // VgAlphaFormatPre as defined in EGL/egl.h:193 220 | VgAlphaFormatPre = 0x308C 221 | // DisplayScaling as defined in EGL/egl.h:198 222 | DisplayScaling = 10000 223 | // Unknown as defined in EGL/egl.h:201 224 | Unknown = ((Int)(-1)) 225 | // BufferPreserved as defined in EGL/egl.h:204 226 | BufferPreserved = 0x3094 227 | // BufferDestroyed as defined in EGL/egl.h:205 228 | BufferDestroyed = 0x3095 229 | // OpenvgImage as defined in EGL/egl.h:208 230 | OpenvgImage = 0x3096 231 | // ContextClientType as defined in EGL/egl.h:211 232 | ContextClientType = 0x3097 233 | // ContextClientVersion as defined in EGL/egl.h:214 234 | ContextClientVersion = 0x3098 235 | // MultisampleResolveDefault as defined in EGL/egl.h:217 236 | MultisampleResolveDefault = 0x309A 237 | // MultisampleResolveBox as defined in EGL/egl.h:218 238 | MultisampleResolveBox = 0x309B 239 | // OpenglEsApi as defined in EGL/egl.h:221 240 | OpenglEsApi = 0x30A0 241 | // OpenvgApi as defined in EGL/egl.h:222 242 | OpenvgApi = 0x30A1 243 | // OpenglApi as defined in EGL/egl.h:223 244 | OpenglApi = 0x30A2 245 | // Draw as defined in EGL/egl.h:226 246 | Draw = 0x3059 247 | // Read as defined in EGL/egl.h:227 248 | Read = 0x305A 249 | // CoreNativeEngine as defined in EGL/egl.h:230 250 | CoreNativeEngine = 0x305B 251 | // Colorspace as defined in EGL/egl.h:233 252 | Colorspace = VgColorspace 253 | // AlphaFormat as defined in EGL/egl.h:234 254 | AlphaFormat = VgAlphaFormat 255 | // ColorspaceSrgb as defined in EGL/egl.h:235 256 | ColorspaceSrgb = VgColorspaceSrgb 257 | // ColorspaceLinear as defined in EGL/egl.h:236 258 | ColorspaceLinear = VgColorspaceLinear 259 | // AlphaFormatNonpre as defined in EGL/egl.h:237 260 | AlphaFormatNonpre = VgAlphaFormatNonpre 261 | // AlphaFormatPre as defined in EGL/egl.h:238 262 | AlphaFormatPre = VgAlphaFormatPre 263 | ) 264 | -------------------------------------------------------------------------------- /egl/defaults.go: -------------------------------------------------------------------------------- 1 | package egl 2 | 3 | var ( 4 | // DefaultDisplay as defined in EGL/egl.h:68 5 | DefaultDisplay = ((NativeDisplayType)(nil)) 6 | // NoContext as defined in EGL/egl.h:69 7 | NoContext = ((Context)(nil)) 8 | // NoDisplay as defined in EGL/egl.h:70 9 | NoDisplay = ((Display)(nil)) 10 | // NoSurface as defined in EGL/egl.h:71 11 | NoSurface = ((Surface)(nil)) 12 | ) 13 | -------------------------------------------------------------------------------- /egl/display_handle.go: -------------------------------------------------------------------------------- 1 | package egl 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "unsafe" 7 | 8 | "github.com/xlab/android-go/android" 9 | ) 10 | 11 | type DisplayHandle struct { 12 | display Display 13 | surface Surface 14 | context Context 15 | 16 | Width int 17 | Height int 18 | } 19 | 20 | func (d *DisplayHandle) EGLDisplay() Display { 21 | return d.display 22 | } 23 | 24 | func (d *DisplayHandle) EGLSurface() Surface { 25 | return d.surface 26 | } 27 | 28 | func (d *DisplayHandle) EGLContext() Context { 29 | return d.context 30 | } 31 | 32 | func (d *DisplayHandle) Destroy() { 33 | if d == nil { 34 | return 35 | } 36 | MakeCurrent(d.display, NoSurface, NoSurface, NoContext) 37 | DestroyContext(d.display, d.context) 38 | DestroySurface(d.display, d.surface) 39 | Terminate(d.display) 40 | if err := Error(); err != nil { 41 | log.Println("EGL error:", err) 42 | } 43 | } 44 | 45 | // NewDisplayHandle initializes EGL display/surface/context and returns a handle object or error. 46 | // Use expectedConfig to specify the desired EGL config constraints like: 47 | // 48 | // map[int32]int32{ 49 | // egl.SurfaceType: egl.WindowBit, 50 | // egl.RedSize: 8, 51 | // egl.GreenSize: 8, 52 | // egl.BlueSize: 8, 53 | // egl.AlphaSize: 8, 54 | // egl.DepthSize: 24, 55 | // } 56 | func NewDisplayHandle(window *android.NativeWindow, expectedConfig map[int32]int32) (*DisplayHandle, error) { 57 | display := GetDisplay(DefaultDisplay) 58 | if Initialize(display, nil, nil) == False { 59 | err := fmt.Errorf("eglInitialize failed: %v", Error()) 60 | return nil, err 61 | } 62 | 63 | var count int32 64 | GetConfigs(display, nil, 0, &count) 65 | configs := make([]Config, count) 66 | GetConfigs(display, configs, count, &count) 67 | var format int32 68 | var foundConfig = -1 69 | var v int32 70 | if expectedConfig == nil { 71 | expectedConfig = map[int32]int32{} 72 | } 73 | for i, cfg := range configs { 74 | GetConfigAttrib(display, cfg, SurfaceType, &v) 75 | if e := expectedConfig[SurfaceType]; e > 0 && v&e != e { 76 | continue 77 | } 78 | GetConfigAttrib(display, cfg, RedSize, &v) 79 | if e := expectedConfig[RedSize]; e > 0 && v != e { 80 | continue 81 | } 82 | GetConfigAttrib(display, cfg, GreenSize, &v) 83 | if e := expectedConfig[GreenSize]; e > 0 && v != e { 84 | continue 85 | } 86 | GetConfigAttrib(display, cfg, BlueSize, &v) 87 | if e := expectedConfig[BlueSize]; e > 0 && v != e { 88 | continue 89 | } 90 | GetConfigAttrib(display, cfg, AlphaSize, &v) 91 | if e := expectedConfig[AlphaSize]; e > 0 && v != e { 92 | continue 93 | } 94 | GetConfigAttrib(display, cfg, DepthSize, &v) 95 | if e := expectedConfig[DepthSize]; e > 0 && v != e { 96 | continue 97 | } 98 | // gotcha! 99 | foundConfig = i 100 | // NativeVisualId is an attribute of the Config that is 101 | // guaranteed to be accepted by android.NativeWindowSetBuffersGeometry(). 102 | // As soon as we picked a Config, we can safely reconfigure the 103 | // NativeWindow buffers to match, using NativeVisualId. 104 | GetConfigAttrib(display, cfg, NativeVisualId, &format) 105 | } 106 | if foundConfig < 0 { 107 | Terminate(display) 108 | err := fmt.Errorf("failed to find EGL config for %#v", expectedConfig) 109 | return nil, err 110 | } 111 | android.NativeWindowSetBuffersGeometry(window, 0, 0, format) 112 | windowPtr := NativeWindowType(unsafe.Pointer(window)) 113 | surface := CreateWindowSurface(display, configs[foundConfig], windowPtr, nil) 114 | var ctxRequest []int32 115 | if ctxVer := expectedConfig[ContextClientVersion]; ctxVer > 0 { 116 | ctxRequest = []int32{ContextClientVersion, ctxVer, None} 117 | } 118 | context := CreateContext(display, configs[foundConfig], NoContext, ctxRequest) 119 | if MakeCurrent(display, surface, surface, context) == False { 120 | DestroyContext(display, context) 121 | DestroySurface(display, surface) 122 | Terminate(display) 123 | err := fmt.Errorf("eglMakeCurrent failed: %v", Error()) 124 | return nil, err 125 | } 126 | handle := &DisplayHandle{ 127 | display: display, 128 | surface: surface, 129 | context: context, 130 | } 131 | handle.UpdateDimensions() 132 | return handle, nil 133 | } 134 | 135 | func (d *DisplayHandle) UpdateDimensions() { 136 | var width, height int32 137 | QuerySurface(d.display, d.surface, Width, &width) 138 | QuerySurface(d.display, d.surface, Height, &height) 139 | d.Width = int(width) 140 | d.Height = int(height) 141 | } 142 | 143 | func (d *DisplayHandle) SwapBuffers() { 144 | SwapBuffers(d.display, d.surface) 145 | } 146 | -------------------------------------------------------------------------------- /egl/doc.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | /* 7 | Package egl provides Go bindings for EGL API. 8 | */ 9 | package egl 10 | -------------------------------------------------------------------------------- /egl/errors.go: -------------------------------------------------------------------------------- 1 | package egl 2 | 3 | import "errors" 4 | 5 | func Error() error { 6 | switch GetError() { 7 | case Success: 8 | return nil 9 | case NotInitialized: 10 | return ErrNotInitialized 11 | case BadAccess: 12 | return ErrBadAccess 13 | case BadAlloc: 14 | return ErrBadAlloc 15 | case BadAttribute: 16 | return ErrBadAttribute 17 | case BadConfig: 18 | return ErrBadConfig 19 | case BadContext: 20 | return ErrBadContext 21 | case BadCurrentSurface: 22 | return ErrBadCurrentSurface 23 | case BadDisplay: 24 | return ErrBadDisplay 25 | case BadMatch: 26 | return ErrBadMatch 27 | case BadNativePixmap: 28 | return ErrBadNativePixmap 29 | case BadNativeWindow: 30 | return ErrBadNativeWindow 31 | case BadParameter: 32 | return ErrBadParameter 33 | case BadSurface: 34 | return ErrBadSurface 35 | case ContextLost: 36 | return ErrContextLost 37 | default: 38 | return ErrUnknown 39 | } 40 | } 41 | 42 | var ( 43 | ErrUnknown = errors.New("unknown error") 44 | ErrNotInitialized = errors.New("not initialized") 45 | ErrBadAccess = errors.New("bad access") 46 | ErrBadAlloc = errors.New("bad alloc") 47 | ErrBadAttribute = errors.New("bad attribute") 48 | ErrBadConfig = errors.New("bad config") 49 | ErrBadContext = errors.New("bad context") 50 | ErrBadCurrentSurface = errors.New("bad current surface") 51 | ErrBadDisplay = errors.New("bad display") 52 | ErrBadMatch = errors.New("bad match") 53 | ErrBadNativePixmap = errors.New("bad native pixmap") 54 | ErrBadNativeWindow = errors.New("bad native window") 55 | ErrBadParameter = errors.New("bad parameter") 56 | ErrBadSurface = errors.New("bad surface") 57 | ErrContextLost = errors.New("context lost") 58 | ) 59 | -------------------------------------------------------------------------------- /egl/types.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package egl 7 | 8 | /* 9 | #cgo LDFLAGS: -lEGL 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | import "unsafe" 16 | 17 | // Boolean type as declared in EGL/egl.h:44 18 | type Boolean uint32 19 | 20 | // Enum type as declared in EGL/egl.h:45 21 | type Enum uint32 22 | 23 | // Config type as declared in EGL/egl.h:46 24 | type Config unsafe.Pointer 25 | 26 | // Context type as declared in EGL/egl.h:47 27 | type Context unsafe.Pointer 28 | 29 | // Display type as declared in EGL/egl.h:48 30 | type Display unsafe.Pointer 31 | 32 | // Surface type as declared in EGL/egl.h:49 33 | type Surface unsafe.Pointer 34 | 35 | // ClientBuffer type as declared in EGL/egl.h:50 36 | type ClientBuffer unsafe.Pointer 37 | 38 | // NativeWindowType as declared in EGL/eglplatform.h:91 39 | type NativeWindowType C.EGLNativeWindowType 40 | 41 | // NativePixmapType as declared in EGL/eglplatform.h:92 42 | type NativePixmapType C.EGLNativePixmapType 43 | 44 | // NativeDisplayType type as declared in EGL/eglplatform.h:93 45 | type NativeDisplayType unsafe.Pointer 46 | 47 | // Int type as declared in EGL/eglplatform.h:122 48 | type Int int32 49 | -------------------------------------------------------------------------------- /example-egl/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .gradle 3 | .idea 4 | *.iml 5 | build/ 6 | android/build 7 | android/build_go 8 | android/bin/ 9 | android/build.xml 10 | android/jni/lib/ 11 | android/src/main/jniLibs 12 | android/libs/ 13 | android/local.properties 14 | android/obj/ 15 | android/proguard-project.txt 16 | android/project.properties 17 | toolchain/ 18 | -------------------------------------------------------------------------------- /example-egl/README.md: -------------------------------------------------------------------------------- 1 | EGLActivity 2 | =========== 3 | 4 | This app leverages all three packages together: **android**, **egl** 5 | and of course **gles** to create quite a rich app that animates its color based 6 | on the accelerometer values. It also reads input events such as key events and 7 | multitouch motion events (with pressure, if supported by the device), you can 8 | check these events in the ADB Shell. Check out the video of the expected 9 | behaviour: 10 | 11 | [![Golang + EGL/GLES App on Android](https://img.youtube.com/vi/H2cafzATUEw/0.jpg)](https://www.youtube.com/watch?v=H2cafzATUEw) 12 | 13 | ### Prerequisites 14 | 15 | * Install the latest Android SDK or extract the Android SDK command line tools into your preferred Android SDK root (available as archive at https://developer.android.com/studio/index.html, see bottom of page). 16 | 17 | * Make sure you have the `$ANDROID_HOME` environment variable set to the Android SDK root (default is `$HOME/android-sdk`). 18 | 19 | [example]: https://github.com/xlab/android-go/tree/master/example 20 | 21 | ### Building 22 | 23 | ``` 24 | $ ./gradlew build 25 | ``` 26 | 27 | ### Deploying 28 | 29 | ``` 30 | $ ./gradlew installDebug 31 | ``` 32 | Use adb to make sure your phone attached correctly: 33 | ``` 34 | $ adb devices 35 | ``` 36 | 37 | ### Cleanup 38 | 39 | To remove standalone toolchains you can execute: 40 | ``` 41 | $ ./gradlew cleanToolchain 42 | ``` 43 | Toolchains will be regenerated on the next build. -------------------------------------------------------------------------------- /example-egl/android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion = rootProject.ext.sdkVersion 5 | 6 | defaultConfig { 7 | ndk { 8 | abiFilters rootProject.ext.archs.split(",") 9 | } 10 | } 11 | buildTypes { 12 | release 13 | debug { 14 | jniDebuggable true 15 | } 16 | } 17 | } 18 | 19 | task buildGo(type: Exec) { 20 | commandLine '../bash_script/build_go.sh', rootProject.ext.archs, rootProject.ext.sdkVersion 21 | } 22 | 23 | task prepareToolchain(type: Exec) { 24 | commandLine '../bash_script/build_toolchain.sh', rootProject.ext.archs, rootProject.ext.sdkVersion 25 | } 26 | 27 | task cleanToolchain(type: Exec) { 28 | commandLine 'rm', '-r', 'build_go/toolchain' 29 | } 30 | 31 | task cleanOutput(type: Exec) { 32 | commandLine 'rm', '-r', 'build_go/output' 33 | } 34 | 35 | 36 | afterEvaluate { 37 | buildGo.dependsOn prepareToolchain 38 | preBuild.dependsOn buildGo 39 | clean.dependsOn cleanOutput 40 | } -------------------------------------------------------------------------------- /example-egl/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example-egl/bash_script/build_go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #Working directory is /android 3 | set -e 4 | 5 | if ! [ -d "$ANDROID_HOME" ]; 6 | then 7 | printf "ANDROID_HOME does not point to any directory. Please set ANDROID_HOME variable\n" 8 | exit 1 9 | fi 10 | 11 | ABIS=($(echo $1 | sed 's/,/ /g')) 12 | ANDROID_API=$2 13 | printf "Build Go sources using ABIs: %s Android API: %s\n" "${ABIS[*]}" "$ANDROID_API" 14 | 15 | TOOLCHAIN_ROOT_DIR=build_go/toolchain 16 | OUTPUT_ROOT_DIR=build_go/output 17 | printf "Cleaning output dir %s\n" "$OUTPUT_ROOT_DIR" 18 | rm -rf "$OUTPUT_ROOT_DIR" 19 | 20 | for ABI in ${ABIS[*]} 21 | do 22 | GOARCH= 23 | GOARM= 24 | CC= 25 | CXX= 26 | CGO_CFLAGS= 27 | 28 | case $ABI in 29 | armeabi-v7a) 30 | GOARCH="arm" 31 | GOARM=7 32 | CC="$TOOLCHAIN_ROOT_DIR/arm/bin/arm-linux-androideabi-gcc" 33 | CXX="$TOOLCHAIN_ROOT_DIR/arm/bin/arm-linux-androideabi-g++" 34 | CGO_CFLAGS="-march=armv7-a" 35 | ;; 36 | x86) 37 | GOARCH="386" 38 | GOARM= 39 | CC="$TOOLCHAIN_ROOT_DIR/x86/bin/i686-linux-android-gcc" 40 | CXX="$TOOLCHAIN_ROOT_DIR/x86/bin/i686-linux-android-g++" 41 | CGO_CFLAGS= 42 | ;; 43 | *) 44 | continue 45 | ;; 46 | esac 47 | 48 | 49 | OUTPUT_DIR="$OUTPUT_ROOT_DIR/$ABI" 50 | mkdir -p "$OUTPUT_DIR" 51 | 52 | cd .. 53 | set -x 54 | CURRENT_DIR=$(pwd) 55 | CC="$CURRENT_DIR/android/$CC" CXX="$CURRENT_DIR/android/$CXX" CGO_ENABLED=1 \ 56 | CGO_CFLAGS="$CGO_CFLAGS" GOOS=android GOARCH="$GOARCH" GOARM="$GOARM" \ 57 | go build -i -pkgdir "$CURRENT_DIR/android/$OUTPUT_DIR" -buildmode=c-shared -o "android/src/main/jniLibs/$ABI/libgomain.so" 58 | cd android 59 | set +x 60 | done -------------------------------------------------------------------------------- /example-egl/bash_script/build_toolchain.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #Working directory is /android 3 | set -e 4 | 5 | if ! [ -d "$ANDROID_HOME" ]; 6 | then 7 | printf "ANDROID_HOME does not point to any directory. Please set ANDROID_HOME variable\n" 8 | exit 1 9 | fi 10 | 11 | ABIS=($(echo $1 | sed 's/,/ /g')) 12 | ANDROID_API=$2 13 | printf "Preparing toolchains for ABIs: %s Android API: %s\n" "${ABIS[*]}" $ANDROID_API 14 | 15 | 16 | TOOLCHAIN_ROOT_DIR=build_go/toolchain 17 | 18 | declare -A ARCHS 19 | for ABI in ${ABIS[*]} 20 | do 21 | case $ABI in 22 | armeabi-v7a) 23 | ARCH="arm" 24 | ;; 25 | x86) 26 | ARCH="x86" 27 | ;; 28 | *) 29 | continue 30 | ;; 31 | esac 32 | 33 | ARCHS[$ARCH]=1 34 | done 35 | 36 | for ARCH in ${!ARCHS[*]} 37 | do 38 | TOOLCHAIN_DIR="$TOOLCHAIN_ROOT_DIR/$ARCH" 39 | 40 | if [ -d "$TOOLCHAIN_DIR" ]; 41 | then 42 | printf "Using existing standalone toolchain for arch: %s\n" $ARCH 43 | continue 44 | fi 45 | 46 | printf "Making standalone toolchain for arch: %s\n" $ARCH 47 | set -x 48 | "$ANDROID_HOME"/ndk-bundle/build/tools/make_standalone_toolchain.py \ 49 | --api=$ANDROID_API --install-dir=$TOOLCHAIN_DIR \ 50 | --arch=$ARCH --stl libc++ 51 | set +x 52 | printf "Standalone toolchain ready\n" 53 | done 54 | -------------------------------------------------------------------------------- /example-egl/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:3.0.0' 8 | } 9 | ext { 10 | archs = "armeabi-v7a,x86" 11 | sdkVersion = 26 12 | } 13 | } -------------------------------------------------------------------------------- /example-egl/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlab/android-go/3cc54d5032fa0527fca83f107744654cf5bc0196/example-egl/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example-egl/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip 6 | distributionSha256Sum=15ebe098ce0392a2d06d252bff24143cc88c4e963346582c8d88814758d93ac7 7 | -------------------------------------------------------------------------------- /example-egl/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /example-egl/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /example-egl/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "runtime" 6 | "time" 7 | 8 | "github.com/xlab/android-go/android" 9 | "github.com/xlab/android-go/app" 10 | "github.com/xlab/android-go/egl" 11 | gl "github.com/xlab/android-go/gles" 12 | ) 13 | 14 | func init() { 15 | app.SetLogTag("EGLActivity") 16 | } 17 | 18 | func main() { 19 | runtime.LockOSThread() 20 | defer runtime.UnlockOSThread() 21 | 22 | nativeWindowEvents := make(chan app.NativeWindowEvent, 1) 23 | windowFocusEvents := make(chan app.WindowFocusEvent, 1) 24 | inputQueueEvents := make(chan app.InputQueueEvent, 1) 25 | inputQueueChan := make(chan *android.InputQueue, 1) 26 | var displayHandle *egl.DisplayHandle 27 | var windowFocused bool 28 | 29 | type vec3 struct { 30 | X, Y, Z float32 31 | } 32 | sensorEvents := make(chan vec3, 100) 33 | sensorMan := NewSensorMan(20*time.Millisecond, func(event *android.SensorEvent) { 34 | x, y, z := event.Acceleration() 35 | select { 36 | case sensorEvents <- vec3{x, y, z}: 37 | default: 38 | } 39 | }) 40 | 41 | stateX := float32(0.5) 42 | stateY := float32(0.5) 43 | stateZ := float32(0.5) 44 | stateRiseY := true 45 | 46 | app.Main(func(a app.NativeActivity) { 47 | a.HandleNativeWindowEvents(nativeWindowEvents) 48 | a.HandleWindowFocusEvents(windowFocusEvents) 49 | a.HandleInputQueueEvents(inputQueueEvents) 50 | go app.HandleInputQueues(inputQueueChan, func() { 51 | a.InputQueueHandled() 52 | }, app.LogInputEvents) 53 | a.InitDone() 54 | for { 55 | select { 56 | case vec := <-sensorEvents: 57 | // log.Printf("accelerometer x=%0.3f y=%0.3f z=%0.3f", vec.X, vec.Y, vec.Z) 58 | stateX = 0.5 + vec.X/10.0 59 | stateZ = 0.5 + vec.Y/10.0 60 | if stateRiseY { 61 | stateY += 0.01 62 | if stateY >= 1 { 63 | stateRiseY = false 64 | } 65 | } else { 66 | stateY -= 0.01 67 | if stateY <= 0 { 68 | stateRiseY = true 69 | } 70 | } 71 | draw(displayHandle, stateX, stateY, stateZ) 72 | case <-a.LifecycleEvents(): 73 | case event := <-windowFocusEvents: 74 | if event.HasFocus && !windowFocused { 75 | windowFocused = true 76 | sensorMan.Start() 77 | } 78 | if !event.HasFocus && windowFocused { 79 | windowFocused = false 80 | sensorMan.Stop() 81 | } 82 | draw(displayHandle, stateX, stateY, stateZ) 83 | case event := <-inputQueueEvents: 84 | switch event.Kind { 85 | case app.QueueCreated: 86 | inputQueueChan <- event.Queue 87 | case app.QueueDestroyed: 88 | inputQueueChan <- nil 89 | } 90 | case event := <-nativeWindowEvents: 91 | switch event.Kind { 92 | case app.NativeWindowRedrawNeeded: 93 | draw(displayHandle, stateX, stateY, stateZ) 94 | a.NativeWindowRedrawDone() 95 | case app.NativeWindowCreated: 96 | expectedSurface := map[int32]int32{ 97 | egl.SurfaceType: egl.WindowBit, 98 | egl.RedSize: 8, 99 | egl.GreenSize: 8, 100 | egl.BlueSize: 8, 101 | } 102 | if handle, err := egl.NewDisplayHandle(event.Window, expectedSurface); err != nil { 103 | log.Fatalln("EGL error:", err) 104 | } else { 105 | displayHandle = handle 106 | log.Printf("EGL display res: %dx%d", handle.Width, handle.Height) 107 | } 108 | initGL() 109 | case app.NativeWindowDestroyed: 110 | displayHandle.Destroy() 111 | } 112 | } 113 | } 114 | }) 115 | } 116 | 117 | func initGL() { 118 | gl.Hint(gl.PERSPECTIVE_CORRECTION_HINT, gl.FASTEST) 119 | gl.Enable(gl.CULL_FACE) 120 | gl.Disable(gl.DEPTH_TEST) 121 | gl.ShadeModel(gl.SMOOTH) 122 | } 123 | 124 | func draw(handle *egl.DisplayHandle, x, y, z float32) { 125 | gl.ClearColor(x, y, z, 1) 126 | gl.Clear(gl.COLOR_BUFFER_BIT) 127 | handle.SwapBuffers() 128 | } 129 | -------------------------------------------------------------------------------- /example-egl/sensor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "runtime" 6 | "time" 7 | 8 | "github.com/xlab/android-go/android" 9 | ) 10 | 11 | type SensorMan struct { 12 | handler func(event *android.SensorEvent) 13 | 14 | sensorManager *android.SensorManager 15 | sensorEventQueue *android.SensorEventQueue 16 | 17 | refreshRate time.Duration 18 | accelerometer *android.Sensor 19 | looper *android.Looper 20 | 21 | startC chan struct{} 22 | stopC chan struct{} 23 | quitC chan struct{} 24 | sleep bool 25 | 26 | quit bool 27 | } 28 | 29 | func NewSensorMan(refresh time.Duration, 30 | handler func(event *android.SensorEvent)) *SensorMan { 31 | s := &SensorMan{ 32 | handler: handler, 33 | refreshRate: refresh, 34 | 35 | startC: make(chan struct{}), 36 | stopC: make(chan struct{}), 37 | quitC: make(chan struct{}), 38 | } 39 | go s.loop() 40 | return s 41 | } 42 | 43 | const queueIdent = 15 44 | 45 | func (s *SensorMan) loop() { 46 | runtime.LockOSThread() 47 | defer runtime.UnlockOSThread() 48 | 49 | s.looper = android.LooperPrepare(android.LooperPrepareAllowNonCallbacks) 50 | s.sensorManager = android.SensorManagerGetInstance() 51 | s.accelerometer = android.SensorManagerGetDefaultSensor(s.sensorManager, android.SensorTypeAccelerometer) 52 | s.sensorEventQueue = android.SensorManagerCreateEventQueue(s.sensorManager, 53 | s.looper, queueIdent, nil, nil) 54 | 55 | for { 56 | select { 57 | case <-s.quitC: 58 | s.quit = true 59 | android.SensorEventQueueDisableSensor(s.sensorEventQueue, s.accelerometer) 60 | android.SensorManagerDestroyEventQueue(s.sensorManager, s.sensorEventQueue) 61 | return 62 | case <-s.startC: 63 | s.sleep = false 64 | android.SensorEventQueueEnableSensor(s.sensorEventQueue, s.accelerometer) 65 | android.SensorEventQueueSetEventRate(s.sensorEventQueue, s.accelerometer, 66 | int32(s.refreshRate/time.Microsecond)) 67 | case <-s.stopC: 68 | s.sleep = true 69 | android.SensorEventQueueDisableSensor(s.sensorEventQueue, s.accelerometer) 70 | default: 71 | var delay int32 = 10 72 | if s.sleep { 73 | delay = 250 74 | } 75 | if ident := android.LooperPollAll(delay, nil, nil, nil); ident != queueIdent { 76 | switch ident { 77 | case android.LooperPollTimeout: 78 | default: 79 | log.Println("illegal poll ident:", ident) 80 | } 81 | continue 82 | } 83 | var ev android.SensorEvent 84 | for android.SensorEventQueueGetEvents(s.sensorEventQueue, &ev, 1) > 0 { 85 | s.handler(&ev) 86 | } 87 | } 88 | } 89 | } 90 | 91 | func (s *SensorMan) Start() { 92 | if s.quit { 93 | return 94 | } 95 | s.startC <- struct{}{} 96 | } 97 | 98 | func (s *SensorMan) Stop() { 99 | if s.quit { 100 | return 101 | } 102 | s.stopC <- struct{}{} 103 | } 104 | 105 | func (s *SensorMan) Destroy() { 106 | if s.quit { 107 | return 108 | } 109 | s.quitC <- struct{}{} 110 | } 111 | -------------------------------------------------------------------------------- /example-egl/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':android' -------------------------------------------------------------------------------- /example-x86/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | android/bin/ 3 | android/build.xml 4 | android/jni/lib/ 5 | android/libs/ 6 | android/local.properties 7 | android/obj/ 8 | android/proguard-project.txt 9 | android/project.properties 10 | toolchain/ 11 | -------------------------------------------------------------------------------- /example-x86/Makefile: -------------------------------------------------------------------------------- 1 | ANDROID_TOOLCHAIN_DIR ?= $(shell pwd)/toolchain 2 | ANDROID_API ?= 23 3 | ANDROID_SYSROOT = $(NDK)/platforms/android-$(ANDROID_API)/arch-x86 4 | 5 | all: toolchain build apk 6 | 7 | toolchain: 8 | $(NDK)/build/tools/make_standalone_toolchain.py \ 9 | --api=$(ANDROID_API) --install-dir=$(ANDROID_TOOLCHAIN_DIR) \ 10 | --arch=x86 --stl libc++ 11 | 12 | build: 13 | mkdir -p android/jni/lib 14 | CC="$(ANDROID_TOOLCHAIN_DIR)/bin/i686-linux-android-gcc" \ 15 | CXX="$(ANDROID_TOOLCHAIN_DIR)/bin/i686-linux-android-g++" \ 16 | CGO_CFLAGS="" \ 17 | GOARCH=386 \ 18 | GOOS=android \ 19 | CGO_ENABLED=1 \ 20 | go build -buildmode=c-shared -o android/jni/lib/libexample.so 21 | 22 | apk: 23 | cd android && make 24 | 25 | clean: 26 | cd android && make clean 27 | 28 | install: 29 | cd android && make install 30 | 31 | listen: 32 | adb logcat -c 33 | adb logcat *:S GolangExample 34 | -------------------------------------------------------------------------------- /example-x86/README.md: -------------------------------------------------------------------------------- 1 | GolangExample x86 2 | ================= 3 | 4 | This is a simple Android Go app template. The same as [/example](https://github.com/xlab/android-go/tree/master/example) but it builds and deploys to android `x86` platform, not `arm`. 5 | -------------------------------------------------------------------------------- /example-x86/android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example-x86/android/Makefile: -------------------------------------------------------------------------------- 1 | all: project build 2 | 3 | build: 4 | ndk-build 5 | ant debug 6 | 7 | install: 8 | ndk-build 9 | ant debug install 10 | 11 | project: 12 | # (required) go get github.com/xlab/android-go/cmd/android-project 13 | android-project update --target android-23 --name GolangExample --path . 14 | 15 | project-n: 16 | android-project update --target android-N --name GolangExample --path . 17 | 18 | clean: 19 | rm -rf libs obj bin gen jni/lib 20 | rm -f proguard-project.txt project.properties 21 | rm -f local.properties build.xml 22 | -------------------------------------------------------------------------------- /example-x86/android/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := example 6 | LOCAL_SRC_FILES := lib/libexample.so 7 | LOCAL_LDLIBS := -llog -landroid 8 | APP_ABI := x86 9 | 10 | include $(PREBUILT_SHARED_LIBRARY) 11 | -------------------------------------------------------------------------------- /example-x86/android/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-23 2 | APP_ABI := x86 3 | -------------------------------------------------------------------------------- /example-x86/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "runtime" 6 | 7 | "github.com/xlab/android-go/app" 8 | ) 9 | 10 | func init() { 11 | app.SetLogTag("GolangExample") 12 | } 13 | 14 | func main() { 15 | log.Println("NativeActivity has started ^_^") 16 | log.Printf("Platform: %s %s", runtime.GOOS, runtime.GOARCH) 17 | nativeWindowEvents := make(chan app.NativeWindowEvent) 18 | 19 | app.Main(func(a app.NativeActivity) { 20 | a.HandleNativeWindowEvents(nativeWindowEvents) 21 | a.InitDone() 22 | for { 23 | select { 24 | case event := <-a.LifecycleEvents(): 25 | switch event.Kind { 26 | case app.OnCreate: 27 | log.Println(event.Kind, "handled") 28 | default: 29 | log.Println(event.Kind, "event ignored") 30 | } 31 | case event := <-nativeWindowEvents: 32 | switch event.Kind { 33 | case app.NativeWindowRedrawNeeded: 34 | a.NativeWindowRedrawDone() 35 | log.Println(event.Kind, "handled") 36 | default: 37 | log.Println(event.Kind, "event ignored") 38 | } 39 | } 40 | } 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /examples/build-android.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | # This script builds an android native-activity from go sourcecode and packages it as an apk. 5 | 6 | # Android Studio does not need to be installed to run this script. The only prerequisite are the android-sdk 7 | # command line tools (available as archive at https://developer.android.com/studio/index.html, see bottom of page). 8 | # This script assumes that the command line tools are located in $HOME/android-sdk. If you wish to use 9 | # another location set the $ANDROID_HOME environment variable accordingly. If the android-skd is already installed, 10 | # you will likely want to call this script like this: "ANDROID_HOME=path/to/sdk path/to/this/script/build-android.sh". 11 | 12 | # This script should be called from the folder containing the go source code, which in turn is expected to contain a folder called 13 | # "android" with gradle files and the manifest. The native toolchain, go shared libray, assets and final apks will be copied into 14 | # or created in this folder and it's subfolders. See the examples at (https://github.com/xlab/android-go/tree/master/examples) for 15 | # example of the expected layout and content of the "android" folder 16 | 17 | # Set default values if they are not provided by the environment. 18 | : ${ANDROID_API:=26} 19 | : ${ANDROID_HOME:=$HOME/android-sdk} 20 | : ${ANDROID_NDK_HOME:=$ANDROID_HOME/ndk-bundle} 21 | export ANDROID_API ANDROID_HOME ANDROID_NDK_HOME 22 | 23 | # Install the ndk 24 | $ANDROID_HOME/tools/bin/sdkmanager --update 25 | $ANDROID_HOME/tools/bin/sdkmanager "ndk-bundle" 26 | 27 | # Create native android toolchain 28 | rm -rf android/toolchain 29 | $ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py --install-dir=android/toolchain --arch=arm --api=$ANDROID_API --stl=libc++ 30 | 31 | # Build .so 32 | mkdir -p android/app/src/main/jniLibs/armeabi-v7a 33 | GOOS=android GOARCH=arm GOARM=7 go get -d 34 | CC="$PWD/android/toolchain/bin/arm-linux-androideabi-gcc" \ 35 | CXX="$PWD/android/toolchain/bin/arm-linux-androideabi-g++" \ 36 | CGO_ENABLED=1 CGO_CFLAGS="-march=armv7-a" \ 37 | GOOS=android GOARCH=arm GOARM=7 \ 38 | go build -i -buildmode=c-shared -o android/app/src/main/jniLibs/armeabi-v7a/libgomain.so 39 | 40 | # Copy assets if there are any 41 | if [ -d assets ]; then 42 | rm -rf android/app/src/main/assets 43 | cp -r assets android/app/src/main/assets 44 | fi 45 | 46 | # Create apk 47 | (cd android; ./gradlew build) 48 | cp android/app/build/outputs/apk/* android/ 49 | -------------------------------------------------------------------------------- /examples/minimal/README.md: -------------------------------------------------------------------------------- 1 | Minimal Go app 2 | ============== 3 | 4 | This is a simple Android Go app template. 5 | 6 | ### Prerequisites 7 | 8 | * Install the latest Android SDK or extract the Android SDK command line tools into your preferred Android SDK root (available as archive at https://developer.android.com/studio/index.html, see bottom of page). 9 | 10 | * Make sure you have the `$ANDROID_HOME` environment variable set to the Android SDK root (default is `$HOME/android-sdk`). 11 | 12 | #### Android project 13 | 14 | Directory `android` is a standard NDK project that has the `AndroidManifest.xml` 15 | as well gradle build files and the shared library we will built as a `PREBUILT_SHARED_LIBRARY`. 16 | 17 | ### Build 18 | 19 | Change to the `examples/minimal` directory and run 20 | `ANDROID_HOME=path/to/sdk ../build-android.sh"` 21 | to build an APK ready for deployment. 22 | 23 | #### Test 24 | 25 | Execute `../build-android.sh && (adb uninstall com.go_android.minimal; adb install android/app-debug.apk) && adb logcat -c && adb logcat | grep "GolangExample:"` to build the apk and then install and test on a connected device. 26 | 27 | ### Clean-up 28 | 29 | Delete the gradle build folders `android/build`, `android/app/build` and `android/app/src/jniLibs`, which contains the compiled shared libraries. 30 | -------------------------------------------------------------------------------- /examples/minimal/android/.gitignore: -------------------------------------------------------------------------------- 1 | /*.apk 2 | /.gradle 3 | /build 4 | /toolchain 5 | /app/build 6 | /app/src/main/jniLibs 7 | -------------------------------------------------------------------------------- /examples/minimal/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion = 25 5 | buildToolsVersion = '25.0.0' 6 | 7 | defaultConfig { 8 | ndk { 9 | abiFilters 'armeabi-v7a' 10 | } 11 | } 12 | buildTypes { 13 | release 14 | debug { 15 | jniDebuggable true 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/minimal/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/minimal/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | jcenter() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:2.3.0' 8 | } 9 | } 10 | 11 | allprojects { 12 | repositories { 13 | jcenter() 14 | } 15 | } 16 | 17 | task clean(type: Delete) { 18 | delete rootProject.buildDir 19 | } 20 | -------------------------------------------------------------------------------- /examples/minimal/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlab/android-go/3cc54d5032fa0527fca83f107744654cf5bc0196/examples/minimal/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/minimal/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Feb 05 19:39:12 IST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip 7 | -------------------------------------------------------------------------------- /examples/minimal/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /examples/minimal/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | -------------------------------------------------------------------------------- /examples/minimal/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "runtime" 6 | 7 | "github.com/xlab/android-go/app" 8 | ) 9 | 10 | func init() { 11 | app.SetLogTag("GolangExample") 12 | } 13 | 14 | func main() { 15 | log.Println("NativeActivity has started ^_^") 16 | log.Printf("Platform: %s %s", runtime.GOOS, runtime.GOARCH) 17 | nativeWindowEvents := make(chan app.NativeWindowEvent) 18 | 19 | app.Main(func(a app.NativeActivity) { 20 | a.HandleNativeWindowEvents(nativeWindowEvents) 21 | a.InitDone() 22 | for { 23 | select { 24 | case event := <-a.LifecycleEvents(): 25 | switch event.Kind { 26 | case app.OnCreate: 27 | log.Println(event.Kind, "handled") 28 | default: 29 | log.Println(event.Kind, "event ignored") 30 | } 31 | case event := <-nativeWindowEvents: 32 | switch event.Kind { 33 | case app.NativeWindowRedrawNeeded: 34 | a.NativeWindowRedrawDone() 35 | log.Println(event.Kind, "handled") 36 | default: 37 | log.Println(event.Kind, "event ignored") 38 | } 39 | } 40 | } 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /examples/tests/README.md: -------------------------------------------------------------------------------- 1 | Test app 2 | ======== 3 | 4 | This app is used for testing. See `examples/minimal` more information on the build system. 5 | 6 | #### Test 7 | 8 | Execute `../build-android.sh && (adb uninstall com.go_android.tests; adb install android/app-debug.apk) && adb logcat -c && adb logcat | grep "android-go/tests:"` to build the apk and then install and test on a connected device. -------------------------------------------------------------------------------- /examples/tests/android/.gitignore: -------------------------------------------------------------------------------- 1 | /*.apk 2 | /.gradle 3 | /build 4 | /toolchain 5 | /app/build 6 | /app/src/main/jniLibs 7 | /app/src/main/assets 8 | -------------------------------------------------------------------------------- /examples/tests/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion = 25 5 | buildToolsVersion = '25.0.0' 6 | 7 | defaultConfig { 8 | ndk { 9 | abiFilters 'armeabi-v7a' 10 | } 11 | } 12 | buildTypes { 13 | release 14 | debug { 15 | jniDebuggable true 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/tests/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/tests/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | jcenter() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:2.3.0' 8 | } 9 | } 10 | 11 | allprojects { 12 | repositories { 13 | jcenter() 14 | } 15 | } 16 | 17 | task clean(type: Delete) { 18 | delete rootProject.buildDir 19 | } 20 | -------------------------------------------------------------------------------- /examples/tests/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlab/android-go/3cc54d5032fa0527fca83f107744654cf5bc0196/examples/tests/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/tests/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Feb 05 19:39:12 IST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip 7 | -------------------------------------------------------------------------------- /examples/tests/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /examples/tests/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | -------------------------------------------------------------------------------- /examples/tests/assets.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "runtime" 6 | "sync" 7 | 8 | "github.com/xlab/android-go/app" 9 | ) 10 | 11 | const assetSize = 1 << 20 12 | 13 | // Read the same asset concurrently with one reader per go routines and check the returned values. 14 | var testAssetsConcurrent = test{ 15 | name: "assetsConcurrent", 16 | run: func(t test, a app.NativeActivity) { 17 | var wg sync.WaitGroup 18 | // Dispatch goroutines 19 | for i := 0; i < 3; i++ { 20 | wg.Add(1) 21 | go func(i int) { 22 | // Open AssetReader 23 | var r, err = a.OpenAsset("testAsset") 24 | t.failIf(err != nil, "Can't open asset:", err) 25 | // Continue reading until there is a read error 26 | var b [32]byte 27 | for count := 0; count < assetSize; count += len(b) { 28 | // Read 32 bytes 29 | _, err = io.ReadFull(r, b[:]) 30 | // Check for read errors 31 | t.failIf(err != nil, "Read error:", err) 32 | // Check content 33 | for j := range b { 34 | t.failIf(b[j] != byte(count+j), "Wrong content") 35 | } 36 | } 37 | // Read whole asset. Check for io.EOF 38 | _, err = r.Read(b[:]) 39 | t.failIf(err != io.EOF, "Expected io.EOF, got:", err) 40 | // Tell parent goroutine that we are done 41 | wg.Done() 42 | }(i) 43 | } 44 | // Wait for child goroutines to finish 45 | wg.Wait() 46 | }, 47 | } 48 | 49 | // Use the same asset reader alternatingly on two goroutines and check the returned values. 50 | var testAssetsShared = test{ 51 | name: "assetsShared", 52 | run: func(t test, a app.NativeActivity) { 53 | var wg sync.WaitGroup 54 | // Open shared AssetReader 55 | var r, err = a.OpenAsset("testAsset") 56 | t.failIf(err != nil, "Can't open asset:", err) 57 | // Channel for signalling goroutines that it is their turn to read. 58 | var c = make(chan int) 59 | // Dispatch go routines 60 | for i := 0; i < 2; i++ { 61 | wg.Add(1) 62 | go func(i int) { 63 | // Force goroutine to run on different thread than the other 64 | runtime.LockOSThread() 65 | // Loop over "my turn to read"-signals until channel is closed 66 | for count := range c { 67 | // Read 32 bytes 68 | var b [32]byte 69 | var _, err = io.ReadFull(r, b[:]) 70 | // Check for io.EOF if the whole asset was read in the previous read. 71 | if count == assetSize { 72 | // The other goroutine read the last bytes, check for io.EOF 73 | t.failIf(err != io.EOF, "Expected io.EOF, got:", err) 74 | // Success. Tell the other goroutine to exit by closing the channel. 75 | close(c) 76 | break 77 | } 78 | // Check for read errors 79 | t.failIf(err != nil, "Read error:", err) 80 | // Check content 81 | for j := range b { 82 | t.failIf(b[j] != byte(count+j), "Wrong content") 83 | } 84 | // Send new offset as read signal 85 | c <- count + len(b) 86 | } 87 | // Tell parent goroutine that we are done. 88 | wg.Done() 89 | }(i) 90 | } 91 | // Send initial read signal to one of the goroutines 92 | c <- 0 93 | // Wait for child goroutines to finish 94 | wg.Wait() 95 | }, 96 | } 97 | -------------------------------------------------------------------------------- /examples/tests/assets/testAsset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlab/android-go/3cc54d5032fa0527fca83f107744654cf5bc0196/examples/tests/assets/testAsset -------------------------------------------------------------------------------- /examples/tests/createTestAsset.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // This program creates a 1MB file whose bytes set to o%256, where o is the offset of the byte in the file, starting with 0. 4 | package main 5 | 6 | import ( 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | var bytes = make([]byte, 1<<20) 13 | for i := range bytes { 14 | bytes[i] = byte(i) 15 | } 16 | var err = ioutil.WriteFile("assets/testAsset", bytes, 0666) 17 | if err != nil { 18 | log.Fatalln(err) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/tests/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "runtime" 7 | 8 | "github.com/xlab/android-go/app" 9 | ) 10 | 11 | func init() { 12 | app.SetLogTag("android-go/tests") 13 | } 14 | 15 | func main() { 16 | log.Printf("NativeActivity started. Platform: %s %s", runtime.GOOS, runtime.GOARCH) 17 | nativeWindowEvents := make(chan app.NativeWindowEvent) 18 | 19 | app.Main(func(a app.NativeActivity) { 20 | a.HandleNativeWindowEvents(nativeWindowEvents) 21 | a.InitDone() 22 | for { 23 | select { 24 | case event := <-a.LifecycleEvents(): 25 | log.Println("Received lifecycle event:", event.Kind) 26 | if event.Kind == app.OnCreate { 27 | go func() { 28 | runTests(a) 29 | os.Exit(0) 30 | }() 31 | } 32 | case event := <-nativeWindowEvents: 33 | log.Println("Received window event:", event.Kind) 34 | if event.Kind == app.NativeWindowRedrawNeeded { 35 | a.NativeWindowRedrawDone() 36 | } 37 | } 38 | } 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /examples/tests/tests.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "sync" 7 | 8 | "github.com/xlab/android-go/app" 9 | ) 10 | 11 | var tests = []test{testAssetsConcurrent, testAssetsShared} 12 | 13 | func runTests(a app.NativeActivity) { 14 | var wg sync.WaitGroup 15 | for _, t := range tests { 16 | wg.Add(1) 17 | go func(t test) { 18 | t.log("Started") 19 | t.run(t, a) 20 | t.log("Completed") 21 | wg.Done() 22 | }(t) 23 | } 24 | wg.Wait() 25 | log.Println("Completed all tests") 26 | } 27 | 28 | type test struct { 29 | name string 30 | run func(test, app.NativeActivity) 31 | } 32 | 33 | func (t test) fail(v ...interface{}) { 34 | t.log("Failed -", fmt.Sprintln(v...)) 35 | panic(fmt.Sprintln(v...)) 36 | } 37 | 38 | func (t test) failIf(cond bool, v ...interface{}) { 39 | if cond { 40 | t.fail(v...) 41 | } 42 | } 43 | 44 | func (t test) log(v ...interface{}) { 45 | log.Print(t.name, ": ", fmt.Sprintln(v...)) 46 | } 47 | -------------------------------------------------------------------------------- /gles.yml: -------------------------------------------------------------------------------- 1 | --- 2 | GENERATOR: 3 | PackageName: gles 4 | PackageDescription: "Package gles provides Go bindings for the OpenGL ES v1 API." 5 | PackageLicense: "THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS." 6 | FlagGroups: 7 | - {name: LDFLAGS, flags: [-lGLESv1_CM]} 8 | SysIncludes: 9 | - GLES/gl.h 10 | 11 | PARSER: 12 | Arch: arm 13 | SourcesPaths: 14 | - GLES/gl.h 15 | IncludePaths: 16 | # NOTE: Replace these paths if you want to re-generate. 17 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include 18 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include/linux 19 | Defines: 20 | __ANDROID__: 1 21 | 22 | TRANSLATOR: 23 | ConstRules: 24 | defines: expand 25 | enum: expand 26 | TypeTips: 27 | function: 28 | # do not stick with GL types, use Go types for API instead 29 | - {target: ., self: plain, tips: [plain,plain,plain,plain,plain,plain,plain,plain,plain]} 30 | Rules: 31 | global: 32 | - {action: accept, from: "^GL"} 33 | - {action: replace, from: "^GL"} 34 | function: 35 | - {action: accept, from: ^gl} 36 | - {action: replace, from: ^gl} 37 | - {transform: export} 38 | type: 39 | - {action: replace, from: "_t$"} 40 | - {transform: export} 41 | - {load: snakecase} 42 | const: 43 | - {action: replace, from: "^_"} 44 | private: 45 | - {transform: unexport} 46 | - {load: snakecase} 47 | post-global: 48 | - {action: doc, from: "^gl", 49 | to: "https://www.khronos.org/opengles/sdk/1.1/docs/man/$name.xml"} 50 | -------------------------------------------------------------------------------- /gles/cgo_helpers.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package gles 7 | 8 | /* 9 | #cgo LDFLAGS: -lGLESv1_CM 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | import ( 16 | "sync" 17 | "unsafe" 18 | ) 19 | 20 | // cgoAllocMap stores pointers to C allocated memory for future reference. 21 | type cgoAllocMap struct { 22 | mux sync.RWMutex 23 | m map[unsafe.Pointer]struct{} 24 | } 25 | 26 | var cgoAllocsUnknown = new(cgoAllocMap) 27 | 28 | func (a *cgoAllocMap) Add(ptr unsafe.Pointer) { 29 | a.mux.Lock() 30 | if a.m == nil { 31 | a.m = make(map[unsafe.Pointer]struct{}) 32 | } 33 | a.m[ptr] = struct{}{} 34 | a.mux.Unlock() 35 | } 36 | 37 | func (a *cgoAllocMap) IsEmpty() bool { 38 | a.mux.RLock() 39 | isEmpty := len(a.m) == 0 40 | a.mux.RUnlock() 41 | return isEmpty 42 | } 43 | 44 | func (a *cgoAllocMap) Borrow(b *cgoAllocMap) { 45 | if b == nil || b.IsEmpty() { 46 | return 47 | } 48 | b.mux.Lock() 49 | a.mux.Lock() 50 | for ptr := range b.m { 51 | if a.m == nil { 52 | a.m = make(map[unsafe.Pointer]struct{}) 53 | } 54 | a.m[ptr] = struct{}{} 55 | delete(b.m, ptr) 56 | } 57 | a.mux.Unlock() 58 | b.mux.Unlock() 59 | } 60 | 61 | func (a *cgoAllocMap) Free() { 62 | a.mux.Lock() 63 | for ptr := range a.m { 64 | C.free(ptr) 65 | delete(a.m, ptr) 66 | } 67 | a.mux.Unlock() 68 | } 69 | 70 | type sliceHeader struct { 71 | Data uintptr 72 | Len int 73 | Cap int 74 | } 75 | 76 | // packPUbyteString creates a Go string backed by *C.GLubyte and avoids copying. 77 | func packPUbyteString(p *C.GLubyte) (raw string) { 78 | if p != nil && *p != 0 { 79 | h := (*stringHeader)(unsafe.Pointer(&raw)) 80 | h.Data = uintptr(unsafe.Pointer(p)) 81 | for *p != 0 { 82 | p = (*C.GLubyte)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++ 83 | } 84 | h.Len = int(uintptr(unsafe.Pointer(p)) - h.Data) 85 | } 86 | return 87 | } 88 | 89 | type stringHeader struct { 90 | Data uintptr 91 | Len int 92 | } 93 | 94 | // RawString reperesents a string backed by data on the C side. 95 | type RawString string 96 | 97 | // Copy returns a Go-managed copy of raw string. 98 | func (raw RawString) Copy() string { 99 | if len(raw) == 0 { 100 | return "" 101 | } 102 | h := (*stringHeader)(unsafe.Pointer(&raw)) 103 | return C.GoStringN((*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len)) 104 | } 105 | -------------------------------------------------------------------------------- /gles/cgo_helpers.h: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | #include 7 | #include 8 | #pragma once 9 | 10 | #define __CGOGEN 1 11 | 12 | -------------------------------------------------------------------------------- /gles/doc.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | /* 7 | Package gles provides Go bindings for the OpenGL ES v1 API. 8 | */ 9 | package gles 10 | -------------------------------------------------------------------------------- /gles/types.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package gles 7 | 8 | /* 9 | #cgo LDFLAGS: -lGLESv1_CM 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | 16 | // Void type as declared in GLES/gl.h:17 17 | type Void [0]byte 18 | 19 | // Char type as declared in GLES/gl.h:18 20 | type Char byte 21 | 22 | // Enum type as declared in GLES/gl.h:19 23 | type Enum uint32 24 | 25 | // Boolean type as declared in GLES/gl.h:20 26 | type Boolean byte 27 | 28 | // Bitfield type as declared in GLES/gl.h:21 29 | type Bitfield uint32 30 | 31 | // Byte type as declared in GLES/gl.h:22 32 | type Byte byte 33 | 34 | // Short type as declared in GLES/gl.h:23 35 | type Short int16 36 | 37 | // Int type as declared in GLES/gl.h:24 38 | type Int int32 39 | 40 | // Sizei type as declared in GLES/gl.h:25 41 | type Sizei int32 42 | 43 | // Ubyte type as declared in GLES/gl.h:26 44 | type Ubyte byte 45 | 46 | // Ushort type as declared in GLES/gl.h:27 47 | type Ushort uint16 48 | 49 | // Uint type as declared in GLES/gl.h:28 50 | type Uint uint32 51 | 52 | // Float type as declared in GLES/gl.h:29 53 | type Float float32 54 | 55 | // Clampf type as declared in GLES/gl.h:30 56 | type Clampf float32 57 | 58 | // Fixed type as declared in GLES/gl.h:31 59 | type Fixed int32 60 | 61 | // Clampx type as declared in GLES/gl.h:32 62 | type Clampx int32 63 | 64 | // Intptr type as declared in GLES/gl.h:34 65 | type Intptr int 66 | 67 | // Sizeiptr type as declared in GLES/gl.h:35 68 | type Sizeiptr int 69 | -------------------------------------------------------------------------------- /gles2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | GENERATOR: 3 | PackageName: gles2 4 | PackageDescription: "Package gles2 provides Go bindings for the OpenGL ES v2 API." 5 | PackageLicense: "THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS." 6 | FlagGroups: 7 | - {name: LDFLAGS, flags: [-lGLESv2]} 8 | SysIncludes: 9 | - GLES2/gl2.h 10 | 11 | PARSER: 12 | Arch: arm 13 | SourcesPaths: 14 | - GLES2/gl2.h 15 | IncludePaths: 16 | # NOTE: Replace these paths if you want to re-generate. 17 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include 18 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include/linux 19 | Defines: 20 | __ANDROID__: 1 21 | 22 | TRANSLATOR: 23 | ConstRules: 24 | defines: expand 25 | enum: expand 26 | PtrTips: 27 | function: 28 | - {target: ^glGenBuffers$, tips: [size,arr]} 29 | - {target: ^glGenFramebuffers$, tips: [size,arr]} 30 | - {target: ^glGenRenderbuffers$, tips: [size,arr]} 31 | - {target: ^glGenTextures$, tips: [size,arr]} 32 | - {target: ^glGetActiveAttrib$, tips: [0,0,size,ref,ref,ref,arr]} 33 | - {target: ^glGetActiveUniform$, tips: [0,0,size,ref,ref,ref,arr]} 34 | - {target: ^glGetAttachedShaders$, tips: [0,size,ref,arr]} 35 | - {target: ^glGetShaderSource$, tips: [0,size,ref,arr]} 36 | - {target: ^glGetShaderInfoLog$, tips: [0,size,ref,arr]} 37 | - {target: ^glGetProgramInfoLog$, tips: [0,size,ref,arr]} 38 | - {target: ^glGetShaderPrecisionFormat$, tips: [0,0,arr,ref]} 39 | - {target: ^glGetVertexAttribPointerv$, tips: [0,0,ref]} 40 | # parameter at the end: 41 | - {target: ^glUniformMatrix, tips: [0,0,0,ref]} 42 | - {target: iv$, tips: [0,0,ref]} 43 | - {target: fv$, tips: [0,0,ref]} 44 | 45 | TypeTips: 46 | function: 47 | # do not stick with GL types, use Go types for API instead 48 | - {target: ., self: plain, tips: [plain,plain,plain,plain,plain,plain,plain,plain,plain]} 49 | 50 | Rules: 51 | global: 52 | - {action: accept, from: "^GL"} 53 | - {action: replace, from: "^GL"} 54 | function: 55 | - {action: accept, from: ^gl} 56 | - {action: replace, from: ^gl} 57 | - {transform: export} 58 | type: 59 | - {action: replace, from: "_t$"} 60 | - {transform: export} 61 | - {load: snakecase} 62 | const: 63 | - {action: replace, from: "^_"} 64 | private: 65 | - {transform: unexport} 66 | - {load: snakecase} 67 | post-global: 68 | - {action: doc, from: "^gl", 69 | to: "https://www.khronos.org/opengles/sdk/docs/man/xhtml/$name.xml"} 70 | -------------------------------------------------------------------------------- /gles2/cgo_helpers.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package gles2 7 | 8 | /* 9 | #cgo LDFLAGS: -lGLESv2 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | import ( 16 | "runtime" 17 | "sync" 18 | "unsafe" 19 | ) 20 | 21 | // cgoAllocMap stores pointers to C allocated memory for future reference. 22 | type cgoAllocMap struct { 23 | mux sync.RWMutex 24 | m map[unsafe.Pointer]struct{} 25 | } 26 | 27 | var cgoAllocsUnknown = new(cgoAllocMap) 28 | 29 | func (a *cgoAllocMap) Add(ptr unsafe.Pointer) { 30 | a.mux.Lock() 31 | if a.m == nil { 32 | a.m = make(map[unsafe.Pointer]struct{}) 33 | } 34 | a.m[ptr] = struct{}{} 35 | a.mux.Unlock() 36 | } 37 | 38 | func (a *cgoAllocMap) IsEmpty() bool { 39 | a.mux.RLock() 40 | isEmpty := len(a.m) == 0 41 | a.mux.RUnlock() 42 | return isEmpty 43 | } 44 | 45 | func (a *cgoAllocMap) Borrow(b *cgoAllocMap) { 46 | if b == nil || b.IsEmpty() { 47 | return 48 | } 49 | b.mux.Lock() 50 | a.mux.Lock() 51 | for ptr := range b.m { 52 | if a.m == nil { 53 | a.m = make(map[unsafe.Pointer]struct{}) 54 | } 55 | a.m[ptr] = struct{}{} 56 | delete(b.m, ptr) 57 | } 58 | a.mux.Unlock() 59 | b.mux.Unlock() 60 | } 61 | 62 | func (a *cgoAllocMap) Free() { 63 | a.mux.Lock() 64 | for ptr := range a.m { 65 | C.free(ptr) 66 | delete(a.m, ptr) 67 | } 68 | a.mux.Unlock() 69 | } 70 | 71 | // unpackPCharString represents the data from Go string as *C.GLchar and avoids copying. 72 | func unpackPCharString(str string) (*C.GLchar, *cgoAllocMap) { 73 | h := (*stringHeader)(unsafe.Pointer(&str)) 74 | return (*C.GLchar)(unsafe.Pointer(h.Data)), cgoAllocsUnknown 75 | } 76 | 77 | type stringHeader struct { 78 | Data uintptr 79 | Len int 80 | } 81 | 82 | type sliceHeader struct { 83 | Data uintptr 84 | Len int 85 | Cap int 86 | } 87 | 88 | // packPUbyteString creates a Go string backed by *C.GLubyte and avoids copying. 89 | func packPUbyteString(p *C.GLubyte) (raw string) { 90 | if p != nil && *p != 0 { 91 | h := (*stringHeader)(unsafe.Pointer(&raw)) 92 | h.Data = uintptr(unsafe.Pointer(p)) 93 | for *p != 0 { 94 | p = (*C.GLubyte)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++ 95 | } 96 | h.Len = int(uintptr(unsafe.Pointer(p)) - h.Data) 97 | } 98 | return 99 | } 100 | 101 | // RawString reperesents a string backed by data on the C side. 102 | type RawString string 103 | 104 | // Copy returns a Go-managed copy of raw string. 105 | func (raw RawString) Copy() string { 106 | if len(raw) == 0 { 107 | return "" 108 | } 109 | h := (*stringHeader)(unsafe.Pointer(&raw)) 110 | return C.GoStringN((*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len)) 111 | } 112 | 113 | // allocPCharMemory allocates memory for type *C.GLchar in C. 114 | // The caller is responsible for freeing the this memory via C.free. 115 | func allocPCharMemory(n int) unsafe.Pointer { 116 | mem, err := C.calloc(C.size_t(n), (C.size_t)(sizeOfPCharValue)) 117 | if err != nil { 118 | panic("memory alloc error: " + err.Error()) 119 | } 120 | return mem 121 | } 122 | 123 | const sizeOfPCharValue = unsafe.Sizeof([1]*C.GLchar{}) 124 | 125 | const sizeOfPtr = unsafe.Sizeof(&struct{}{}) 126 | 127 | // unpackArgSString transforms a sliced Go data structure into plain C format. 128 | func unpackArgSString(x []string) (unpacked **C.GLchar, allocs *cgoAllocMap) { 129 | if x == nil { 130 | return nil, nil 131 | } 132 | allocs = new(cgoAllocMap) 133 | defer runtime.SetFinalizer(&unpacked, func(***C.GLchar) { 134 | go allocs.Free() 135 | }) 136 | 137 | len0 := len(x) 138 | mem0 := allocPCharMemory(len0) 139 | allocs.Add(mem0) 140 | h0 := &sliceHeader{ 141 | Data: uintptr(mem0), 142 | Cap: len0, 143 | Len: len0, 144 | } 145 | v0 := *(*[]*C.GLchar)(unsafe.Pointer(h0)) 146 | for i0 := range x { 147 | v0[i0], _ = unpackPCharString(x[i0]) 148 | } 149 | h := (*sliceHeader)(unsafe.Pointer(&v0)) 150 | unpacked = (**C.GLchar)(unsafe.Pointer(h.Data)) 151 | return 152 | } 153 | 154 | // packSString reads sliced Go data structure out from plain C format. 155 | func packSString(v []string, ptr0 **C.GLchar) { 156 | const m = 0x7fffffff 157 | for i0 := range v { 158 | ptr1 := (*(*[m / sizeOfPtr]*C.GLchar)(unsafe.Pointer(ptr0)))[i0] 159 | v[i0] = packPCharString(ptr1) 160 | } 161 | } 162 | 163 | // packPCharString creates a Go string backed by *C.GLchar and avoids copying. 164 | func packPCharString(p *C.GLchar) (raw string) { 165 | if p != nil && *p != 0 { 166 | h := (*stringHeader)(unsafe.Pointer(&raw)) 167 | h.Data = uintptr(unsafe.Pointer(p)) 168 | for *p != 0 { 169 | p = (*C.GLchar)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++ 170 | } 171 | h.Len = int(uintptr(unsafe.Pointer(p)) - h.Data) 172 | } 173 | return 174 | } 175 | -------------------------------------------------------------------------------- /gles2/cgo_helpers.h: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | #include 7 | #include 8 | #pragma once 9 | 10 | #define __CGOGEN 1 11 | 12 | -------------------------------------------------------------------------------- /gles2/doc.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | /* 7 | Package gles2 provides Go bindings for the OpenGL ES v2 API. 8 | */ 9 | package gles2 10 | -------------------------------------------------------------------------------- /gles2/types.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package gles2 7 | 8 | /* 9 | #cgo LDFLAGS: -lGLESv2 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | 16 | // Byte type as declared in GLES2/gl2.h:56 17 | type Byte byte 18 | 19 | // Clampf type as declared in GLES2/gl2.h:57 20 | type Clampf float32 21 | 22 | // Fixed type as declared in GLES2/gl2.h:58 23 | type Fixed int32 24 | 25 | // Short type as declared in GLES2/gl2.h:59 26 | type Short int16 27 | 28 | // Ushort type as declared in GLES2/gl2.h:60 29 | type Ushort uint16 30 | 31 | // Void type as declared in GLES2/gl2.h:61 32 | type Void [0]byte 33 | 34 | // Sync as declared in GLES2/gl2.h:62 35 | type Sync C.GLsync 36 | 37 | // Int64 type as declared in GLES2/gl2.h:63 38 | type Int64 int64 39 | 40 | // Uint64 type as declared in GLES2/gl2.h:64 41 | type Uint64 uint64 42 | 43 | // Enum type as declared in GLES2/gl2.h:65 44 | type Enum uint32 45 | 46 | // Uint type as declared in GLES2/gl2.h:66 47 | type Uint uint32 48 | 49 | // Char type as declared in GLES2/gl2.h:67 50 | type Char byte 51 | 52 | // Float type as declared in GLES2/gl2.h:68 53 | type Float float32 54 | 55 | // Sizeiptr type as declared in GLES2/gl2.h:69 56 | type Sizeiptr int 57 | 58 | // Intptr type as declared in GLES2/gl2.h:70 59 | type Intptr int 60 | 61 | // Bitfield type as declared in GLES2/gl2.h:71 62 | type Bitfield uint32 63 | 64 | // Int type as declared in GLES2/gl2.h:72 65 | type Int int32 66 | 67 | // Boolean type as declared in GLES2/gl2.h:73 68 | type Boolean byte 69 | 70 | // Sizei type as declared in GLES2/gl2.h:74 71 | type Sizei int32 72 | 73 | // Ubyte type as declared in GLES2/gl2.h:75 74 | type Ubyte byte 75 | -------------------------------------------------------------------------------- /gles3.yml: -------------------------------------------------------------------------------- 1 | --- 2 | GENERATOR: 3 | PackageName: gles3 4 | PackageDescription: "Package gles3 provides Go bindings for the OpenGL ES v3 API." 5 | PackageLicense: "THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS." 6 | FlagGroups: 7 | - {name: LDFLAGS, flags: [-lGLESv3]} 8 | SysIncludes: 9 | - GLES3/gl3.h 10 | 11 | PARSER: 12 | Arch: arm 13 | SourcesPaths: 14 | - GLES3/gl3.h 15 | IncludePaths: 16 | # NOTE: Replace these paths if you want to re-generate. 17 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include 18 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include/linux 19 | Defines: 20 | __ANDROID__: 1 21 | 22 | TRANSLATOR: 23 | ConstRules: 24 | defines: expand 25 | enum: expand 26 | PtrTips: 27 | function: 28 | - {target: ^glGenBuffers$, tips: [size,arr]} 29 | - {target: ^glGenFramebuffers$, tips: [size,arr]} 30 | - {target: ^glGenRenderbuffers$, tips: [size,arr]} 31 | - {target: ^glGenTextures$, tips: [size,arr]} 32 | - {target: ^glGetActiveAttrib$, tips: [0,0,size,ref,ref,ref,arr]} 33 | - {target: ^glGetActiveUniform$, tips: [0,0,size,ref,ref,ref,arr]} 34 | - {target: ^glGetAttachedShaders$, tips: [0,size,ref,arr]} 35 | - {target: ^glGetShaderSource$, tips: [0,size,ref,arr]} 36 | - {target: ^glGetShaderInfoLog$, tips: [0,size,ref,arr]} 37 | - {target: ^glGetProgramInfoLog$, tips: [0,size,ref,arr]} 38 | - {target: ^glGetShaderPrecisionFormat$, tips: [0,0,arr,ref]} 39 | - {target: ^glGetVertexAttribPointerv$, tips: [0,0,ref]} 40 | # parameter at the end: 41 | - {target: ^glUniformMatrix, tips: [0,0,0,ref]} 42 | - {target: iv$, tips: [0,0,ref]} 43 | - {target: fv$, tips: [0,0,ref]} 44 | 45 | TypeTips: 46 | function: 47 | # do not stick with GL types, use Go types for API instead 48 | - {target: ., self: plain, tips: [plain,plain,plain,plain,plain,plain,plain,plain,plain]} 49 | 50 | Rules: 51 | global: 52 | - {action: accept, from: "^GL"} 53 | - {action: replace, from: "^GL"} 54 | function: 55 | - {action: accept, from: ^gl} 56 | - {action: replace, from: ^gl} 57 | - {transform: export} 58 | type: 59 | - {action: replace, from: "_t$"} 60 | - {transform: export} 61 | - {load: snakecase} 62 | const: 63 | - {action: replace, from: "^_"} 64 | private: 65 | - {transform: unexport} 66 | - {load: snakecase} 67 | post-global: 68 | - {action: doc, from: "^gl", 69 | to: "https://www.khronos.org/opengles/sdk/docs/man3/html/$name.xhtml"} 70 | -------------------------------------------------------------------------------- /gles3/cgo_helpers.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package gles3 7 | 8 | /* 9 | #cgo LDFLAGS: -lGLESv3 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | import ( 16 | "runtime" 17 | "sync" 18 | "unsafe" 19 | ) 20 | 21 | // cgoAllocMap stores pointers to C allocated memory for future reference. 22 | type cgoAllocMap struct { 23 | mux sync.RWMutex 24 | m map[unsafe.Pointer]struct{} 25 | } 26 | 27 | var cgoAllocsUnknown = new(cgoAllocMap) 28 | 29 | func (a *cgoAllocMap) Add(ptr unsafe.Pointer) { 30 | a.mux.Lock() 31 | if a.m == nil { 32 | a.m = make(map[unsafe.Pointer]struct{}) 33 | } 34 | a.m[ptr] = struct{}{} 35 | a.mux.Unlock() 36 | } 37 | 38 | func (a *cgoAllocMap) IsEmpty() bool { 39 | a.mux.RLock() 40 | isEmpty := len(a.m) == 0 41 | a.mux.RUnlock() 42 | return isEmpty 43 | } 44 | 45 | func (a *cgoAllocMap) Borrow(b *cgoAllocMap) { 46 | if b == nil || b.IsEmpty() { 47 | return 48 | } 49 | b.mux.Lock() 50 | a.mux.Lock() 51 | for ptr := range b.m { 52 | if a.m == nil { 53 | a.m = make(map[unsafe.Pointer]struct{}) 54 | } 55 | a.m[ptr] = struct{}{} 56 | delete(b.m, ptr) 57 | } 58 | a.mux.Unlock() 59 | b.mux.Unlock() 60 | } 61 | 62 | func (a *cgoAllocMap) Free() { 63 | a.mux.Lock() 64 | for ptr := range a.m { 65 | C.free(ptr) 66 | delete(a.m, ptr) 67 | } 68 | a.mux.Unlock() 69 | } 70 | 71 | // unpackPCharString represents the data from Go string as *C.GLchar and avoids copying. 72 | func unpackPCharString(str string) (*C.GLchar, *cgoAllocMap) { 73 | h := (*stringHeader)(unsafe.Pointer(&str)) 74 | return (*C.GLchar)(unsafe.Pointer(h.Data)), cgoAllocsUnknown 75 | } 76 | 77 | type stringHeader struct { 78 | Data uintptr 79 | Len int 80 | } 81 | 82 | type sliceHeader struct { 83 | Data uintptr 84 | Len int 85 | Cap int 86 | } 87 | 88 | // packPUbyteString creates a Go string backed by *C.GLubyte and avoids copying. 89 | func packPUbyteString(p *C.GLubyte) (raw string) { 90 | if p != nil && *p != 0 { 91 | h := (*stringHeader)(unsafe.Pointer(&raw)) 92 | h.Data = uintptr(unsafe.Pointer(p)) 93 | for *p != 0 { 94 | p = (*C.GLubyte)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++ 95 | } 96 | h.Len = int(uintptr(unsafe.Pointer(p)) - h.Data) 97 | } 98 | return 99 | } 100 | 101 | // RawString reperesents a string backed by data on the C side. 102 | type RawString string 103 | 104 | // Copy returns a Go-managed copy of raw string. 105 | func (raw RawString) Copy() string { 106 | if len(raw) == 0 { 107 | return "" 108 | } 109 | h := (*stringHeader)(unsafe.Pointer(&raw)) 110 | return C.GoStringN((*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len)) 111 | } 112 | 113 | // allocPCharMemory allocates memory for type *C.GLchar in C. 114 | // The caller is responsible for freeing the this memory via C.free. 115 | func allocPCharMemory(n int) unsafe.Pointer { 116 | mem, err := C.calloc(C.size_t(n), (C.size_t)(sizeOfPCharValue)) 117 | if err != nil { 118 | panic("memory alloc error: " + err.Error()) 119 | } 120 | return mem 121 | } 122 | 123 | const sizeOfPCharValue = unsafe.Sizeof([1]*C.GLchar{}) 124 | 125 | const sizeOfPtr = unsafe.Sizeof(&struct{}{}) 126 | 127 | // unpackArgSString transforms a sliced Go data structure into plain C format. 128 | func unpackArgSString(x []string) (unpacked **C.GLchar, allocs *cgoAllocMap) { 129 | if x == nil { 130 | return nil, nil 131 | } 132 | allocs = new(cgoAllocMap) 133 | defer runtime.SetFinalizer(&unpacked, func(***C.GLchar) { 134 | go allocs.Free() 135 | }) 136 | 137 | len0 := len(x) 138 | mem0 := allocPCharMemory(len0) 139 | allocs.Add(mem0) 140 | h0 := &sliceHeader{ 141 | Data: uintptr(mem0), 142 | Cap: len0, 143 | Len: len0, 144 | } 145 | v0 := *(*[]*C.GLchar)(unsafe.Pointer(h0)) 146 | for i0 := range x { 147 | v0[i0], _ = unpackPCharString(x[i0]) 148 | } 149 | h := (*sliceHeader)(unsafe.Pointer(&v0)) 150 | unpacked = (**C.GLchar)(unsafe.Pointer(h.Data)) 151 | return 152 | } 153 | 154 | // packSString reads sliced Go data structure out from plain C format. 155 | func packSString(v []string, ptr0 **C.GLchar) { 156 | const m = 0x7fffffff 157 | for i0 := range v { 158 | ptr1 := (*(*[m / sizeOfPtr]*C.GLchar)(unsafe.Pointer(ptr0)))[i0] 159 | v[i0] = packPCharString(ptr1) 160 | } 161 | } 162 | 163 | // packPCharString creates a Go string backed by *C.GLchar and avoids copying. 164 | func packPCharString(p *C.GLchar) (raw string) { 165 | if p != nil && *p != 0 { 166 | h := (*stringHeader)(unsafe.Pointer(&raw)) 167 | h.Data = uintptr(unsafe.Pointer(p)) 168 | for *p != 0 { 169 | p = (*C.GLchar)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++ 170 | } 171 | h.Len = int(uintptr(unsafe.Pointer(p)) - h.Data) 172 | } 173 | return 174 | } 175 | -------------------------------------------------------------------------------- /gles3/cgo_helpers.h: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | #include 7 | #include 8 | #pragma once 9 | 10 | #define __CGOGEN 1 11 | 12 | -------------------------------------------------------------------------------- /gles3/doc.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | /* 7 | Package gles3 provides Go bindings for the OpenGL ES v3 API. 8 | */ 9 | package gles3 10 | -------------------------------------------------------------------------------- /gles3/types.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package gles3 7 | 8 | /* 9 | #cgo LDFLAGS: -lGLESv3 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | 16 | // Byte type as declared in GLES3/gl3.h:56 17 | type Byte byte 18 | 19 | // Clampf type as declared in GLES3/gl3.h:57 20 | type Clampf float32 21 | 22 | // Fixed type as declared in GLES3/gl3.h:58 23 | type Fixed int32 24 | 25 | // Short type as declared in GLES3/gl3.h:59 26 | type Short int16 27 | 28 | // Ushort type as declared in GLES3/gl3.h:60 29 | type Ushort uint16 30 | 31 | // Void type as declared in GLES3/gl3.h:61 32 | type Void [0]byte 33 | 34 | // Sync as declared in GLES3/gl3.h:62 35 | type Sync C.GLsync 36 | 37 | // Int64 type as declared in GLES3/gl3.h:63 38 | type Int64 int64 39 | 40 | // Uint64 type as declared in GLES3/gl3.h:64 41 | type Uint64 uint64 42 | 43 | // Enum type as declared in GLES3/gl3.h:65 44 | type Enum uint32 45 | 46 | // Uint type as declared in GLES3/gl3.h:66 47 | type Uint uint32 48 | 49 | // Char type as declared in GLES3/gl3.h:67 50 | type Char byte 51 | 52 | // Float type as declared in GLES3/gl3.h:68 53 | type Float float32 54 | 55 | // Sizeiptr type as declared in GLES3/gl3.h:69 56 | type Sizeiptr int 57 | 58 | // Intptr type as declared in GLES3/gl3.h:70 59 | type Intptr int 60 | 61 | // Bitfield type as declared in GLES3/gl3.h:71 62 | type Bitfield uint32 63 | 64 | // Int type as declared in GLES3/gl3.h:72 65 | type Int int32 66 | 67 | // Boolean type as declared in GLES3/gl3.h:73 68 | type Boolean byte 69 | 70 | // Sizei type as declared in GLES3/gl3.h:74 71 | type Sizei int32 72 | 73 | // Ubyte type as declared in GLES3/gl3.h:75 74 | type Ubyte byte 75 | 76 | // Half type as declared in GLES3/gl3.h:523 77 | type Half uint16 78 | -------------------------------------------------------------------------------- /gles31.yml: -------------------------------------------------------------------------------- 1 | --- 2 | GENERATOR: 3 | PackageName: gles31 4 | PackageDescription: "Package gles31 provides Go bindings for the OpenGL ES v3.1 API." 5 | PackageLicense: "THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS." 6 | FlagGroups: 7 | - {name: LDFLAGS, flags: [-lGLESv3]} 8 | SysIncludes: 9 | - GLES3/gl31.h 10 | 11 | PARSER: 12 | Arch: arm 13 | SourcesPaths: 14 | - GLES3/gl31.h 15 | IncludePaths: 16 | # NOTE: Replace these paths if you want to re-generate. 17 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include 18 | - /Users/xlab/Library/Android/sdk/ndk-bundle/platforms/android-23/arch-arm/usr/include/linux 19 | Defines: 20 | __ANDROID__: 1 21 | 22 | TRANSLATOR: 23 | ConstRules: 24 | defines: expand 25 | enum: expand 26 | PtrTips: 27 | function: 28 | - {target: ^glGenBuffers$, tips: [size,arr]} 29 | - {target: ^glGenFramebuffers$, tips: [size,arr]} 30 | - {target: ^glGenRenderbuffers$, tips: [size,arr]} 31 | - {target: ^glGenTextures$, tips: [size,arr]} 32 | - {target: ^glGetActiveAttrib$, tips: [0,0,size,ref,ref,ref,arr]} 33 | - {target: ^glGetActiveUniform$, tips: [0,0,size,ref,ref,ref,arr]} 34 | - {target: ^glGetAttachedShaders$, tips: [0,size,ref,arr]} 35 | - {target: ^glGetShaderSource$, tips: [0,size,ref,arr]} 36 | - {target: ^glGetShaderInfoLog$, tips: [0,size,ref,arr]} 37 | - {target: ^glGetProgramInfoLog$, tips: [0,size,ref,arr]} 38 | - {target: ^glGetShaderPrecisionFormat$, tips: [0,0,arr,ref]} 39 | - {target: ^glGetVertexAttribPointerv$, tips: [0,0,ref]} 40 | # parameter at the end: 41 | - {target: ^glUniformMatrix, tips: [0,0,0,ref]} 42 | - {target: iv$, tips: [0,0,ref]} 43 | - {target: fv$, tips: [0,0,ref]} 44 | 45 | TypeTips: 46 | function: 47 | # do not stick with GL types, use Go types for API instead 48 | - {target: ., self: plain, tips: [plain,plain,plain,plain,plain,plain,plain,plain,plain]} 49 | 50 | Rules: 51 | global: 52 | - {action: accept, from: "^GL"} 53 | - {action: replace, from: "^GL"} 54 | function: 55 | - {action: accept, from: ^gl} 56 | - {action: replace, from: ^gl} 57 | - {transform: export} 58 | type: 59 | - {action: replace, from: "_t$"} 60 | - {transform: export} 61 | - {load: snakecase} 62 | const: 63 | - {action: replace, from: "^_"} 64 | private: 65 | - {transform: unexport} 66 | - {load: snakecase} 67 | post-global: 68 | - {action: doc, from: "^gl", 69 | to: "https://www.khronos.org/opengles/sdk/docs/man31/html/$name.xhtml"} 70 | -------------------------------------------------------------------------------- /gles31/cgo_helpers.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package gles31 7 | 8 | /* 9 | #cgo LDFLAGS: -lGLESv3 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | import ( 16 | "runtime" 17 | "sync" 18 | "unsafe" 19 | ) 20 | 21 | // cgoAllocMap stores pointers to C allocated memory for future reference. 22 | type cgoAllocMap struct { 23 | mux sync.RWMutex 24 | m map[unsafe.Pointer]struct{} 25 | } 26 | 27 | var cgoAllocsUnknown = new(cgoAllocMap) 28 | 29 | func (a *cgoAllocMap) Add(ptr unsafe.Pointer) { 30 | a.mux.Lock() 31 | if a.m == nil { 32 | a.m = make(map[unsafe.Pointer]struct{}) 33 | } 34 | a.m[ptr] = struct{}{} 35 | a.mux.Unlock() 36 | } 37 | 38 | func (a *cgoAllocMap) IsEmpty() bool { 39 | a.mux.RLock() 40 | isEmpty := len(a.m) == 0 41 | a.mux.RUnlock() 42 | return isEmpty 43 | } 44 | 45 | func (a *cgoAllocMap) Borrow(b *cgoAllocMap) { 46 | if b == nil || b.IsEmpty() { 47 | return 48 | } 49 | b.mux.Lock() 50 | a.mux.Lock() 51 | for ptr := range b.m { 52 | if a.m == nil { 53 | a.m = make(map[unsafe.Pointer]struct{}) 54 | } 55 | a.m[ptr] = struct{}{} 56 | delete(b.m, ptr) 57 | } 58 | a.mux.Unlock() 59 | b.mux.Unlock() 60 | } 61 | 62 | func (a *cgoAllocMap) Free() { 63 | a.mux.Lock() 64 | for ptr := range a.m { 65 | C.free(ptr) 66 | delete(a.m, ptr) 67 | } 68 | a.mux.Unlock() 69 | } 70 | 71 | // unpackPCharString represents the data from Go string as *C.GLchar and avoids copying. 72 | func unpackPCharString(str string) (*C.GLchar, *cgoAllocMap) { 73 | h := (*stringHeader)(unsafe.Pointer(&str)) 74 | return (*C.GLchar)(unsafe.Pointer(h.Data)), cgoAllocsUnknown 75 | } 76 | 77 | type stringHeader struct { 78 | Data uintptr 79 | Len int 80 | } 81 | 82 | type sliceHeader struct { 83 | Data uintptr 84 | Len int 85 | Cap int 86 | } 87 | 88 | // packPUbyteString creates a Go string backed by *C.GLubyte and avoids copying. 89 | func packPUbyteString(p *C.GLubyte) (raw string) { 90 | if p != nil && *p != 0 { 91 | h := (*stringHeader)(unsafe.Pointer(&raw)) 92 | h.Data = uintptr(unsafe.Pointer(p)) 93 | for *p != 0 { 94 | p = (*C.GLubyte)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++ 95 | } 96 | h.Len = int(uintptr(unsafe.Pointer(p)) - h.Data) 97 | } 98 | return 99 | } 100 | 101 | // RawString reperesents a string backed by data on the C side. 102 | type RawString string 103 | 104 | // Copy returns a Go-managed copy of raw string. 105 | func (raw RawString) Copy() string { 106 | if len(raw) == 0 { 107 | return "" 108 | } 109 | h := (*stringHeader)(unsafe.Pointer(&raw)) 110 | return C.GoStringN((*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len)) 111 | } 112 | 113 | // allocPCharMemory allocates memory for type *C.GLchar in C. 114 | // The caller is responsible for freeing the this memory via C.free. 115 | func allocPCharMemory(n int) unsafe.Pointer { 116 | mem, err := C.calloc(C.size_t(n), (C.size_t)(sizeOfPCharValue)) 117 | if err != nil { 118 | panic("memory alloc error: " + err.Error()) 119 | } 120 | return mem 121 | } 122 | 123 | const sizeOfPCharValue = unsafe.Sizeof([1]*C.GLchar{}) 124 | 125 | const sizeOfPtr = unsafe.Sizeof(&struct{}{}) 126 | 127 | // unpackArgSString transforms a sliced Go data structure into plain C format. 128 | func unpackArgSString(x []string) (unpacked **C.GLchar, allocs *cgoAllocMap) { 129 | if x == nil { 130 | return nil, nil 131 | } 132 | allocs = new(cgoAllocMap) 133 | defer runtime.SetFinalizer(&unpacked, func(***C.GLchar) { 134 | go allocs.Free() 135 | }) 136 | 137 | len0 := len(x) 138 | mem0 := allocPCharMemory(len0) 139 | allocs.Add(mem0) 140 | h0 := &sliceHeader{ 141 | Data: uintptr(mem0), 142 | Cap: len0, 143 | Len: len0, 144 | } 145 | v0 := *(*[]*C.GLchar)(unsafe.Pointer(h0)) 146 | for i0 := range x { 147 | v0[i0], _ = unpackPCharString(x[i0]) 148 | } 149 | h := (*sliceHeader)(unsafe.Pointer(&v0)) 150 | unpacked = (**C.GLchar)(unsafe.Pointer(h.Data)) 151 | return 152 | } 153 | 154 | // packSString reads sliced Go data structure out from plain C format. 155 | func packSString(v []string, ptr0 **C.GLchar) { 156 | const m = 0x7fffffff 157 | for i0 := range v { 158 | ptr1 := (*(*[m / sizeOfPtr]*C.GLchar)(unsafe.Pointer(ptr0)))[i0] 159 | v[i0] = packPCharString(ptr1) 160 | } 161 | } 162 | 163 | // packPCharString creates a Go string backed by *C.GLchar and avoids copying. 164 | func packPCharString(p *C.GLchar) (raw string) { 165 | if p != nil && *p != 0 { 166 | h := (*stringHeader)(unsafe.Pointer(&raw)) 167 | h.Data = uintptr(unsafe.Pointer(p)) 168 | for *p != 0 { 169 | p = (*C.GLchar)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++ 170 | } 171 | h.Len = int(uintptr(unsafe.Pointer(p)) - h.Data) 172 | } 173 | return 174 | } 175 | -------------------------------------------------------------------------------- /gles31/cgo_helpers.h: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | #include 7 | #include 8 | #pragma once 9 | 10 | #define __CGOGEN 1 11 | 12 | -------------------------------------------------------------------------------- /gles31/doc.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | /* 7 | Package gles31 provides Go bindings for the OpenGL ES v3.1 API. 8 | */ 9 | package gles31 10 | -------------------------------------------------------------------------------- /gles31/types.go: -------------------------------------------------------------------------------- 1 | // THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS. 2 | 3 | // WARNING: This file has automatically been generated on Tue, 05 Sep 2017 19:50:45 MSK. 4 | // By https://git.io/c-for-go. DO NOT EDIT. 5 | 6 | package gles31 7 | 8 | /* 9 | #cgo LDFLAGS: -lGLESv3 10 | #include 11 | #include 12 | #include "cgo_helpers.h" 13 | */ 14 | import "C" 15 | 16 | // Byte type as declared in GLES3/gl31.h:56 17 | type Byte byte 18 | 19 | // Clampf type as declared in GLES3/gl31.h:57 20 | type Clampf float32 21 | 22 | // Fixed type as declared in GLES3/gl31.h:58 23 | type Fixed int32 24 | 25 | // Short type as declared in GLES3/gl31.h:59 26 | type Short int16 27 | 28 | // Ushort type as declared in GLES3/gl31.h:60 29 | type Ushort uint16 30 | 31 | // Void type as declared in GLES3/gl31.h:61 32 | type Void [0]byte 33 | 34 | // Sync as declared in GLES3/gl31.h:62 35 | type Sync C.GLsync 36 | 37 | // Int64 type as declared in GLES3/gl31.h:63 38 | type Int64 int64 39 | 40 | // Uint64 type as declared in GLES3/gl31.h:64 41 | type Uint64 uint64 42 | 43 | // Enum type as declared in GLES3/gl31.h:65 44 | type Enum uint32 45 | 46 | // Uint type as declared in GLES3/gl31.h:66 47 | type Uint uint32 48 | 49 | // Char type as declared in GLES3/gl31.h:67 50 | type Char byte 51 | 52 | // Float type as declared in GLES3/gl31.h:68 53 | type Float float32 54 | 55 | // Sizeiptr type as declared in GLES3/gl31.h:69 56 | type Sizeiptr int 57 | 58 | // Intptr type as declared in GLES3/gl31.h:70 59 | type Intptr int 60 | 61 | // Bitfield type as declared in GLES3/gl31.h:71 62 | type Bitfield uint32 63 | 64 | // Int type as declared in GLES3/gl31.h:72 65 | type Int int32 66 | 67 | // Boolean type as declared in GLES3/gl31.h:73 68 | type Boolean byte 69 | 70 | // Sizei type as declared in GLES3/gl31.h:74 71 | type Sizei int32 72 | 73 | // Ubyte type as declared in GLES3/gl31.h:75 74 | type Ubyte byte 75 | 76 | // Half type as declared in GLES3/gl31.h:523 77 | type Half uint16 78 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/xlab/android-go 2 | 3 | go 1.16 4 | --------------------------------------------------------------------------------