commit 18df716784c2faf487d437fece087b85aa09cfb9 Author: empathicqubit Date: Fri Apr 15 18:09:46 2022 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..15c2342 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/keys.store +/build +debug +__debug_bin +R.java +*.env +.DS_Store +*.jar +*.aar +*.[xX]cframework +*.[fF]ramework diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..f4b80e8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,33 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "In integrated terminal. Breaks bluetooth", + "type": "go", + "request": "launch", + "cwd": "${workspaceFolder}", + "program": "./desktop" + }, + { + "name": "In separate Mac OS Terminal with command: dlv dap --listen :6868", + "type": "go", + "request": "launch", + "cwd": "${workspaceFolder}", + "envFile": "${workspaceFolder}/.env", + "program": "${workspaceFolder}/desktop", + "port": 6868 + }, + { + "name": "Remote device", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 4334, + "host": "127.0.0.1", + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..443e2bf --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "java.project.referencedLibraries": { + + "include": [ + "build/jars/**/*.jar", + ] + }, + "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx8G -Xms100m", + "java.project.sourcePaths": [ + "android/java" + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..59bc5c4 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,21 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "makeDebug", + "type": "shell", + "command": "make debug", + }, + { + "label": "build", + "type": "shell", + "group": { + "kind": "build", + "isDefault": true + }, + "command": "go build -o debug github.com/empathicqubit/giouibind/desktop" + } + ] +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cbb9ad1 --- /dev/null +++ b/Makefile @@ -0,0 +1,178 @@ +# FIXME Explain wth we're doing +MIN_SDK_VERSION ?= 21 +ANDROID_SDK_VERSION ?= 30.0.3 +ANDROID_HOME ?= $(HOME)/Android/Sdk +ANDROID_NDK_HOME ?= $(ANDROID_HOME)/ndk/24.0.8215888 +MAX_SDK_VERSION ?= 32 + +GDB_PORT ?= 4334 + +# Target package name. +ANDROID_PACKAGE ?= gl.entan.giouibind + +# Settings for keystore which is used to sign APK. +KEYS_DN=DC=gl,CN=entan +KEYS_PASS=123456 +KEYS_VALIDITY=365 +KEYS_ALGORITHM=RSA +KEYS_SIZE=2048 + +# Target build dir. Resulting APK file will be available here. +BUILD_DIR=build + +_BUILD_TOOLS=$(ANDROID_HOME)/build-tools/$(ANDROID_SDK_VERSION) +_ANDROID_JAR_PATH=$(ANDROID_HOME)/platforms/android-$(MAX_SDK_VERSION)/android.jar +_SWIFT_SRC=$(shell find ios -iname '*.swift') +_JAVA_SRC=$(shell find android/java -iname '*.java') +_GO_SRC=$(shell find . -iname '*.go') +_JAVA_ROOT_PATH=android/java/$(subst .,/,$(ANDROID_PACKAGE)) +_ADB_PATH=$(ANDROID_HOME)/platform-tools/adb +_JARS=build/jars/ble/classes.jar build/jars/go-android/classes.jar + + +build: build-ios build-android + +install-ios: build/ios-app.ipa + ideviceinstaller -i build/ios-app.ipa/giouibind.ipa + +ios: build-ios +build-ios: build/ios-app.ipa + +android: build-android +build-android: build/android-app.apk + +run-android: install-android + $(_ADB_PATH) shell am start -n $(ANDROID_PACKAGE)/.MainActivity + $(_ADB_PATH) shell 'while ! dumpsys window windows | grep -o "$(ANDROID_PACKAGE)" 2>&1 > /dev/null ; do sleep 1 ; done' + +debug-android: run-android +#FIXME Delve + $(_ADB_PATH) push $(ANDROID_NDK_HOME)/prebuilt/android-arm64/gdbserver/gdbserver /data/local/tmp + $(_ADB_PATH) shell "chmod 777 /data/local/tmp/gdbserver" + $(_ADB_PATH) forward tcp:$(GDB_PORT) tcp:$(GDB_PORT) + $(_ADB_PATH) shell 'su -c killall gdbserver || exit 0' + $(_ADB_PATH) shell 'su -c set enforce 0' + $(_ADB_PATH) shell 'su -c /data/local/tmp/gdbserver :$(GDB_PORT) --attach $$(ps -A -o NAME,PID | grep "$(ANDROID_PACKAGE)" | cut -F 2)' + +install-android: build-android + $(_ADB_PATH) install build/android-app.apk + +# Initialize keystore to sign APK. +keys.store: + keytool -genkeypair \ + -validity $(KEYS_VALIDITY) \ + -keystore $@ \ + -keyalg $(KEYS_ALGORITHM) \ + -keysize $(KEYS_SIZE) \ + -storepass $(KEYS_PASS) \ + -keypass $(KEYS_PASS) \ + -dname $(KEYS_DN) \ + -deststoretype pkcs12 + +build/Mobile.xcframework: $(_GO_SRC) + CGO_ENABLED=1 GO386=softfloat gomobile bind \ + -target ios \ + -o "$@" \ + github.com/empathicqubit/giouibind/mobile + +build/ios-app.ipa: build/ios.xcarchive + xcodebuild -allowProvisioningUpdates -exportArchive -archivePath build/ios.xcarchive -exportOptionsPlist ios/export-options.plist -exportPath "$@" + +build/ios.xcarchive: $(_SWIFT_SRC) build/Mobile.xcframework + xcodebuild -project ios/giouibind/giouibind.xcodeproj -scheme giouibind -sdk iphoneos -configuration AppStoreDistribution archive -archivePath "$@" + +build/jars/ble/classes.jar: + @mkdir -p build/jars/ble + + curl -L -o "build/ble.aar" https://repo1.maven.org/maven2/no/nordicsemi/android/ble/2.4.0/ble-2.4.0.aar + cd build/jars/ble && unzip -o ../../ble.aar + touch "$@" + +build/jars/go-android/classes.jar: $(_GO_SRC) $(ANDROID_NDK_HOME) + @mkdir -p build/jars/go-android + + CGO_ENABLED=1 ANDROID_NDK_HOME=$(ANDROID_NDK_HOME) GO386=softfloat gomobile bind \ + -target android \ + -javapkg $(ANDROID_PACKAGE) \ + -o "build/go-android.aar" \ + github.com/empathicqubit/giouibind/mobile + + # Unpack resulting AAR library to link it to APK during further stages. + @unzip -o -qq "build/go-android.aar" -d build/jars/go-android + @ln -sf jars/go-android/jni build/lib + touch "$@" + +# Collect resources and generate R.java. +$(_JAVA_ROOT_PATH)/R.java: $(wildcard android/res/*/*.*) android/AndroidManifest.xml $(_ANDROID_JAR_PATH) + $(_BUILD_TOOLS)/aapt package \ + -f \ + -m \ + -J android/java \ + -M android/AndroidManifest.xml \ + -S android/res \ + -I $(_ANDROID_JAR_PATH) + +# Generate a JAR suitable for code completion (less java.* classes) +build/jars/android-meta.jar: $(_ANDROID_JAR_PATH) + @mkdir -p build/jars + + cp "$(_ANDROID_JAR_PATH)" "$@" + zip -d "$@" 'java/*' + +build/obj.jar: build/jars/android-meta.jar $(_JARS) $(_JAVA_SRC) $(_JAVA_ROOT_PATH)/R.java + @mkdir -p build/obj + + javac \ + -source 8 \ + -target 8 \ + -d build/obj \ + -classpath $(_ANDROID_JAR_PATH):android/java:$(subst $() $(),:,$(_JARS)) \ + $(_JAVA_SRC) + + jar cvf "$@" -C build/obj/ . + +# Convert compiled Java code into DEX file (required by Android). +build/classes.dex: build/d8.jar + $(_BUILD_TOOLS)/dx \ + --dex \ + --min-sdk-version $(MIN_SDK_VERSION) \ + --output build/classes.dex \ + build/d8.jar + +build/d8.jar: build/obj.jar + $(_BUILD_TOOLS)/d8 \ + --output build/d8.jar \ + --classpath $(_ANDROID_JAR_PATH) \ + $(_JARS) \ + build/obj.jar + +# Package everything into unaligned APK file. +build/app.apk.unaligned: build/classes.dex + $(_BUILD_TOOLS)/aapt package \ + -f \ + -m \ + -F build/app.apk.unaligned \ + -M android/AndroidManifest.xml \ + -S android/res \ + -I $(_ANDROID_JAR_PATH) + + cd build && $(_BUILD_TOOLS)/aapt add \ + app.apk.unaligned \ + classes.dex \ + lib/*/* + +# Align unaligned APK file and sign it using keystore. +build/android-app.apk: keys.store build/app.apk.unaligned + $(_BUILD_TOOLS)/zipalign \ + -f 4 \ + build/app.apk.unaligned \ + "$@" + + $(_BUILD_TOOLS)/apksigner sign \ + --ks keys.store \ + --ks-pass pass:$(KEYS_PASS) \ + "$@" + +clean: + @rm -rf build + @rm -rf $(_JAVA_ROOT_PATH)/R.java diff --git a/README.md b/README.md new file mode 100644 index 0000000..20fef6b --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# Minimal Gio-Powered Android/iOS/desktop app + +This project serves as an example how to build minimal working Gio-powered +Android/iOS/desktop application **without** Android Studio or Gradle. The example +was intended to connect to a BLE device with a specific service identifier. +Please search for FIXME in the project and replace information as appropriate. +Alternatively you can remove this stuff and replace it with your own. + +The interface INativeBridge in native/native.go contains the methods which +bridge go to either Java on Android, ObjC/Swift on iOS, or more Go classes +on desktop. + +Makefile targets: +* **build**: Build for both iOS and Android. Only works on Mac OS because of iOS +* **build-ios**, **build-android**: Build for single platform +* **install-ios**, **install-android**: Install to a real device. Your signing +team ID in /ios/export-options.plist must be correct. +* **run-android**: Tells the application to start on Android +* **debug-android**: Doesn't work yet. + +## Requirements + +To be able to build, following dependencies are +required: + +* Android SDK version 32, be sure to set ANDROID\_HOME environment variable +* Android NDK version 24.0.8215888 +* Android build-tools version 30.0.3 +* Java on your PATH +* gomobile `go install "golang.org/x/mobile/cmd/gomobile"` + +## Description of different project files +* **build**: All the build stuff goes here +* **android**: All the Android-specific files here. If you want to include +images in your application, it's probably better to do that in Go +with //go:embed, instead of including images in the res folder. GodObject +is the main class which implements the bridge with Go. The Gio classes are +overridden to work around some issues with using Gio with `gomobile bind` +* **ios**: XCode project which contains iOS specific INativeBridge implementation. +* **mobile**: The entrypoint for `gomobile bind` +* **mobile/gio**: A stub entrypoint for Gio. You shouldn't need to change this. +* **desktop**: Entrypoint for the desktop application. The example only works +on Mac OS because the cbgo library is made for Mac OS bluetooth only, but you +can replace it with whatever you want and that should work on MacOS/Linux/Windows. +* **gio**: Stubs for Gio packages which fail to build on Linux when targeting Android. + +## Credits + +Thanks to [seletskiy/ebiten-android-minimal](https://github.com/seletskiy/ebiten-android-minimal) and [GioUI](https://gioui.org/) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml new file mode 100644 index 0000000..352be93 --- /dev/null +++ b/android/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + diff --git a/android/java/gl/entan/giouibind/GodObject.java b/android/java/gl/entan/giouibind/GodObject.java new file mode 100644 index 0000000..3d788fe --- /dev/null +++ b/android/java/gl/entan/giouibind/GodObject.java @@ -0,0 +1,108 @@ +package gl.entan.giouibind; + +import java.util.ArrayList; +import java.util.List; + +import android.Manifest.permission; +import android.app.Activity; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothSocket; +import android.content.Context; +import android.content.pm.PackageManager; +import android.util.Log; +import gl.entan.giouibind.mobile.IGodObject; +import gl.entan.giouibind.mobile.Mobile; + +public class GodObject implements IGodObject { + private static GodObject instance = null; + + private BluetoothSocket socket = null; + private Context context = null; + private List managers; + + private GodObject(Context context) { + this.context = context; + this.managers = new ArrayList<>(); + } + + public static GodObject getGodObject(Context context) { + if(GodObject.instance == null) { + GodObject.instance = new GodObject(context); + } + + return GodObject.instance; + } + + public void disconnectFromDevice() { + if(this.socket != null) { + try { + this.socket.close(); + } + catch (Exception e) { + Log.e("bananas", "Couldn't close socket", e); + } + } + } + + public void connectToDevice() { + GodObject self = this; + + this.disconnectFromDevice(); + + BluetoothAdapter.getDefaultAdapter().getProfileProxy(this.context, new BluetoothProfile.ServiceListener() { + @Override + public void onServiceDisconnected(int arg0) { + } + + @Override + public void onServiceConnected(int profile, BluetoothProfile proxy) { + Log.i("bananas", "Called service connected"); + + for (BluetoothDevice device : proxy.getConnectedDevices()) { + MyBleManager manager = new MyBleManager(context); + + manager + .connect(device) + .retry(20) + .timeout(5000) + .useAutoConnect(true) + .enqueue(); + + self.managers.add(manager); + } + + BluetoothAdapter.getDefaultAdapter().closeProfileProxy(profile, proxy); + } + }, BluetoothProfile.HEADSET); + } + + @Override + public boolean enableBluetooth() { + Context context = this.context; + + if(context.checkSelfPermission(permission.BLUETOOTH) == PackageManager.PERMISSION_DENIED) { + ((Activity)context).requestPermissions(new String[] { permission.BLUETOOTH }, 0); + return false; + } + + if(context.checkSelfPermission(permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_DENIED) { + ((Activity)context).requestPermissions(new String[] { permission.ACCESS_BACKGROUND_LOCATION }, 0); + return false; + } + + return true; + } + + @Override + public boolean writeChar(byte[] data) { + for(MyBleManager manager: this.managers) { + if(manager.isReady()) { + manager.writeChar(data); + break; + } + } + return false; + } +} diff --git a/android/java/gl/entan/giouibind/MainActivity.java b/android/java/gl/entan/giouibind/MainActivity.java new file mode 100644 index 0000000..04184d9 --- /dev/null +++ b/android/java/gl/entan/giouibind/MainActivity.java @@ -0,0 +1,65 @@ +package gl.entan.giouibind; + +import org.gioui.GioView; + +import android.app.Activity; +import android.app.ActivityManager; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.Bundle; +import android.util.Log; +import go.Seq; +import gl.entan.giouibind.mobile.Mobile; + +public class MainActivity extends Activity { + private GioView view; + + @Override public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + Context context = getApplicationContext(); + Seq.setContext(context); + + this.view = findViewById(R.id.gioview); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + this.setTaskDescription( + new ActivityManager.TaskDescription( + null, // Leave the default title. + BitmapFactory.decodeResource(getResources(), R.drawable.icon) + )); + } + } + + @Override public void onDestroy() { + view.destroy(); + super.onDestroy(); + } + + @Override public void onStart() { + super.onStart(); + view.start(); + } + + @Override public void onStop() { + view.stop(); + super.onStop(); + } + + @Override public void onConfigurationChanged(Configuration c) { + super.onConfigurationChanged(c); + view.configurationChanged(); + } + + @Override public void onLowMemory() { + super.onLowMemory(); + GioView.onLowMemory(); + } + + @Override public void onBackPressed() { + if (!view.backPressed()) + super.onBackPressed(); + } +} diff --git a/android/java/gl/entan/giouibind/MyBleManager.java b/android/java/gl/entan/giouibind/MyBleManager.java new file mode 100644 index 0000000..d575e71 --- /dev/null +++ b/android/java/gl/entan/giouibind/MyBleManager.java @@ -0,0 +1,114 @@ +package gl.entan.giouibind; + +import java.util.List; +import java.util.UUID; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattService; +import android.bluetooth.BluetoothProfile; +import android.content.Context; +import android.os.Handler; +import android.util.Log; +import gl.entan.giouibind.mobile.Mobile; +import no.nordicsemi.android.ble.BleManager; + +public class MyBleManager extends BleManager { + public static UUID shortServiceUuid = UUID.fromString("FIXME"); + public static UUID longServiceUuid = UUID.fromString("FIXME"); + + public static UUID writeUuid = UUID.fromString("FIXME"); + public static UUID readUuid = UUID.fromString("FIXME"); + + private BluetoothGattService service; + private BluetoothGattCharacteristic writeChr; + private BluetoothGattCharacteristic readChr; + + public MyBleManager(Context context) { + super(context); + } + + public MyBleManager(Context context, Handler handler) { + super(context, handler); + } + + public void readChar() { + readCharacteristic(readChr) + .with((d, data) -> { + Mobile.bluetoothGotData(data.getValue()); + }) + .enqueue(); + } + + public boolean writeChar(byte[] data) { + writeCharacteristic(writeChr, data, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT).enqueue(); + return true; + } + + @Override + protected BleManagerGattCallback getGattCallback() { + return new MyGattCallbackImpl(); + } + + @Override + public int getMinLogPriority() { + return Log.WARN; + } + + @Override + public void log(int priority, String message) { + Log.println(priority, "bananas", message); + } + + private class MyGattCallbackImpl extends BleManagerGattCallback { + @Override + protected void onCharacteristicNotified(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + Mobile.bluetoothGotData(characteristic.getValue()); + super.onCharacteristicNotified(gatt, characteristic); + } + + @Override + protected boolean isRequiredServiceSupported(BluetoothGatt gatt) { + BluetoothGattService s = gatt.getService(shortServiceUuid); + if(s == null) { + s = gatt.getService(longServiceUuid); + } + if(s == null) { + Log.i("bananas", "Could not find GATT service"); + Mobile.finishedConnect(false, ""); + return false; + } + + service = s; + writeChr = s.getCharacteristic(writeUuid); + readChr = s.getCharacteristic(readUuid); + + return service != null + && writeChr != null + && readChr != null; + } + + @Override + protected void initialize() { + requestMtu(165) + .done(d -> { + enableNotifications(readChr).enqueue(); + + writeCharacteristic(writeChr, new byte[] { 0x04, (byte)0x95, 0x06, 0x03 }, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT) + .done(g -> { + Mobile.finishedConnect(true, g.getName()); + }) + .enqueue(); + }) + .enqueue(); + } + + @Override + protected void onServicesInvalidated() { + readChr = writeChr = null; + } + } + +} \ No newline at end of file diff --git a/android/java/org/gioui/Gio.java b/android/java/org/gioui/Gio.java new file mode 100644 index 0000000..d79556c --- /dev/null +++ b/android/java/org/gioui/Gio.java @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package org.gioui; + +import android.content.ClipboardManager; +import android.content.ClipData; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import gl.entan.giouibind.GodObject; +import gl.entan.giouibind.mobile.Mobile; + +import java.io.UnsupportedEncodingException; + +public final class Gio { + private static final Object initLock = new Object(); + private static boolean jniLoaded; + private static final Handler handler = new Handler(Looper.getMainLooper()); + + /** + * init loads and initializes the Go native library and runs + * the Go main function. + * + * It is exported for use by Android apps that need to run Go code + * outside the lifecycle of the Gio activity. + */ + public static synchronized void init(Context appCtx) { + synchronized (initLock) { + if (jniLoaded) { + return; + } + String dataDir = appCtx.getFilesDir().getAbsolutePath(); + byte[] dataDirUTF8; + try { + dataDirUTF8 = dataDir.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + System.loadLibrary("gojni"); + Mobile.inventGod(GodObject.getGodObject(appCtx)); + runGoMain(dataDirUTF8, appCtx); + jniLoaded = true; + } + } + + static private native void runGoMain(byte[] dataDir, Context context); + + static void writeClipboard(Context ctx, String s) { + ClipboardManager m = (ClipboardManager)ctx.getSystemService(Context.CLIPBOARD_SERVICE); + m.setPrimaryClip(ClipData.newPlainText(null, s)); + } + + static String readClipboard(Context ctx) { + ClipboardManager m = (ClipboardManager)ctx.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData c = m.getPrimaryClip(); + if (c == null || c.getItemCount() < 1) { + return null; + } + return c.getItemAt(0).coerceToText(ctx).toString(); + } + + static void wakeupMainThread() { + handler.post(new Runnable() { + @Override public void run() { + scheduleMainFuncs(); + } + }); + } + + static private native void scheduleMainFuncs(); +} \ No newline at end of file diff --git a/android/java/org/gioui/GioView.java b/android/java/org/gioui/GioView.java new file mode 100644 index 0000000..a03d725 --- /dev/null +++ b/android/java/org/gioui/GioView.java @@ -0,0 +1,752 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package org.gioui; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.SystemClock; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.Choreographer; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.PointerIcon; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.Window; +import android.view.WindowInsetsController; +import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeProvider; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.CorrectionInfo; +import android.view.inputmethod.CursorAnchorInfo; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputContentInfo; +import android.view.inputmethod.InputMethodManager; +import gl.entan.giouibind.GodObject; +import gl.entan.giouibind.mobile.Mobile; + +public final class GioView extends SurfaceView implements Choreographer.FrameCallback { + private static boolean jniLoaded; + + private final SurfaceHolder.Callback surfCallbacks; + private final View.OnFocusChangeListener focusCallback; + private final InputMethodManager imm; + private final float scrollXScale; + private final float scrollYScale; + private int keyboardHint; + private AccessibilityManager accessManager; + + private long nhandle; + + public GioView(Context context) { + this(context, null); + } + + public GioView(Context context, AttributeSet attrs) { + super(context, attrs); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + } + setLayoutParams(new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT)); + + // Late initialization of the Go runtime to wait for a valid context. + Gio.init(context); + + // Set background color to transparent to avoid a flickering + // issue on ChromeOS. + setBackgroundColor(Color.argb(0, 0, 0, 0)); + + ViewConfiguration conf = ViewConfiguration.get(context); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + scrollXScale = conf.getScaledHorizontalScrollFactor(); + scrollYScale = conf.getScaledVerticalScrollFactor(); + + // The platform focus highlight is not aware of Gio's widgets. + setDefaultFocusHighlightEnabled(false); + } else { + float listItemHeight = 48; // dp + float px = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + listItemHeight, + getResources().getDisplayMetrics() + ); + scrollXScale = px; + scrollYScale = px; + } + + accessManager = (AccessibilityManager)context.getSystemService(Context.ACCESSIBILITY_SERVICE); + imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); + nhandle = onCreateView(this); + setFocusable(true); + setFocusableInTouchMode(true); + focusCallback = new View.OnFocusChangeListener() { + @Override public void onFocusChange(View v, boolean focus) { + GioView.this.onFocusChange(nhandle, focus); + } + }; + setOnFocusChangeListener(focusCallback); + surfCallbacks = new SurfaceHolder.Callback() { + @Override public void surfaceCreated(SurfaceHolder holder) { + // Ignore; surfaceChanged is guaranteed to be called immediately after this. + } + @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + onSurfaceChanged(nhandle, getHolder().getSurface()); + } + @Override public void surfaceDestroyed(SurfaceHolder holder) { + onSurfaceDestroyed(nhandle); + } + }; + getHolder().addCallback(surfCallbacks); + } + + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { + if (nhandle != 0) { + onKeyEvent(nhandle, keyCode, event.getUnicodeChar(), true, event.getEventTime()); + } + return false; + } + + @Override public boolean onKeyUp(int keyCode, KeyEvent event) { + if (nhandle != 0) { + onKeyEvent(nhandle, keyCode, event.getUnicodeChar(), false, event.getEventTime()); + } + return false; + } + + @Override public boolean onGenericMotionEvent(MotionEvent event) { + dispatchMotionEvent(event); + return true; + } + + @Override public boolean onTouchEvent(MotionEvent event) { + // Ask for unbuffered events. Flutter and Chrome do it + // so assume it's good for us as well. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + requestUnbufferedDispatch(event); + } + + dispatchMotionEvent(event); + return true; + } + + private void setCursor(int id) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + return; + } + PointerIcon pointerIcon = PointerIcon.getSystemIcon(getContext(), id); + setPointerIcon(pointerIcon); + } + + private void setOrientation(int id, int fallback) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + id = fallback; + } + ((Activity) this.getContext()).setRequestedOrientation(id); + } + + private void setFullscreen(boolean enabled) { + int flags = this.getSystemUiVisibility(); + if (enabled) { + flags |= SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + flags |= SYSTEM_UI_FLAG_HIDE_NAVIGATION; + flags |= SYSTEM_UI_FLAG_FULLSCREEN; + flags |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + } else { + flags &= ~SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + flags &= ~SYSTEM_UI_FLAG_HIDE_NAVIGATION; + flags &= ~SYSTEM_UI_FLAG_FULLSCREEN; + flags &= ~SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + } + this.setSystemUiVisibility(flags); + } + + private enum Bar { + NAVIGATION, + STATUS, + } + + private void setBarColor(Bar t, int color, int luminance) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + return; + } + + Window window = ((Activity) this.getContext()).getWindow(); + + int insetsMask; + int viewMask; + + switch (t) { + case STATUS: + insetsMask = WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; + viewMask = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + window.setStatusBarColor(color); + break; + case NAVIGATION: + insetsMask = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; + viewMask = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; + window.setNavigationBarColor(color); + break; + default: + throw new RuntimeException("invalid bar type"); + } + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + return; + } + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + int flags = this.getSystemUiVisibility(); + if (luminance > 128) { + flags |= viewMask; + } else { + flags &= ~viewMask; + } + this.setSystemUiVisibility(flags); + return; + } + + WindowInsetsController insetsController = window.getInsetsController(); + if (insetsController == null) { + return; + } + if (luminance > 128) { + insetsController.setSystemBarsAppearance(insetsMask, insetsMask); + } else { + insetsController.setSystemBarsAppearance(0, insetsMask); + } + } + + private void setStatusColor(int color, int luminance) { + this.setBarColor(Bar.STATUS, color, luminance); + } + + private void setNavigationColor(int color, int luminance) { + this.setBarColor(Bar.NAVIGATION, color, luminance); + } + + @Override protected boolean dispatchHoverEvent(MotionEvent event) { + if (!accessManager.isTouchExplorationEnabled()) { + return super.dispatchHoverEvent(event); + } + switch (event.getAction()) { + case MotionEvent.ACTION_HOVER_ENTER: + // Fall through. + case MotionEvent.ACTION_HOVER_MOVE: + onTouchExploration(nhandle, event.getX(), event.getY()); + break; + case MotionEvent.ACTION_HOVER_EXIT: + onExitTouchExploration(nhandle); + break; + } + return true; + } + + void sendA11yEvent(int eventType, int viewId) { + if (!accessManager.isEnabled()) { + return; + } + AccessibilityEvent event = obtainA11yEvent(eventType, viewId); + getParent().requestSendAccessibilityEvent(this, event); + } + + AccessibilityEvent obtainA11yEvent(int eventType, int viewId) { + AccessibilityEvent event = AccessibilityEvent.obtain(eventType); + event.setPackageName(getContext().getPackageName()); + event.setSource(this, viewId); + return event; + } + + boolean isA11yActive() { + return accessManager.isEnabled(); + } + + void sendA11yChange(int viewId) { + if (!accessManager.isEnabled()) { + return; + } + AccessibilityEvent event = obtainA11yEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED, viewId); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE); + } + getParent().requestSendAccessibilityEvent(this, event); + } + + private void dispatchMotionEvent(MotionEvent event) { + if (nhandle == 0) { + return; + } + for (int j = 0; j < event.getHistorySize(); j++) { + long time = event.getHistoricalEventTime(j); + for (int i = 0; i < event.getPointerCount(); i++) { + onTouchEvent( + nhandle, + event.ACTION_MOVE, + event.getPointerId(i), + event.getToolType(i), + event.getHistoricalX(i, j), + event.getHistoricalY(i, j), + scrollXScale*event.getHistoricalAxisValue(MotionEvent.AXIS_HSCROLL, i, j), + scrollYScale*event.getHistoricalAxisValue(MotionEvent.AXIS_VSCROLL, i, j), + event.getButtonState(), + time); + } + } + int act = event.getActionMasked(); + int idx = event.getActionIndex(); + for (int i = 0; i < event.getPointerCount(); i++) { + int pact = event.ACTION_MOVE; + if (i == idx) { + pact = act; + } + onTouchEvent( + nhandle, + pact, + event.getPointerId(i), + event.getToolType(i), + event.getX(i), event.getY(i), + scrollXScale*event.getAxisValue(MotionEvent.AXIS_HSCROLL, i), + scrollYScale*event.getAxisValue(MotionEvent.AXIS_VSCROLL, i), + event.getButtonState(), + event.getEventTime()); + } + } + + @Override public InputConnection onCreateInputConnection(EditorInfo editor) { + Snippet snip = getSnippet(); + editor.inputType = this.keyboardHint; + editor.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FLAG_NO_EXTRACT_UI; + editor.initialSelStart = imeToUTF16(nhandle, imeSelectionStart(nhandle)); + editor.initialSelEnd = imeToUTF16(nhandle, imeSelectionEnd(nhandle)); + int selStart = editor.initialSelStart - snip.offset; + editor.initialCapsMode = TextUtils.getCapsMode(snip.snippet, selStart, this.keyboardHint); + imeSetComposingRegion(nhandle, -1, -1); + return new GioInputConnection(); + } + + void setInputHint(int hint) { + if (hint == this.keyboardHint) { + return; + } + this.keyboardHint = hint; + restartInput(); + } + + void showTextInput() { + GioView.this.requestFocus(); + imm.showSoftInput(GioView.this, 0); + } + + void hideTextInput() { + imm.hideSoftInputFromWindow(getWindowToken(), 0); + } + + @Override protected boolean fitSystemWindows(Rect insets) { + if (nhandle != 0) { + onWindowInsets(nhandle, insets.top, insets.right, insets.bottom, insets.left); + } + return true; + } + + void postFrameCallback() { + Choreographer.getInstance().removeFrameCallback(this); + Choreographer.getInstance().postFrameCallback(this); + } + + @Override public void doFrame(long nanos) { + if (nhandle != 0) { + onFrameCallback(nhandle); + } + } + + int getDensity() { + return getResources().getDisplayMetrics().densityDpi; + } + + float getFontScale() { + return getResources().getConfiguration().fontScale; + } + + public void start() { + if (nhandle != 0) { + onStartView(nhandle); + } + } + + public void stop() { + if (nhandle != 0) { + onStopView(nhandle); + } + } + + public void destroy() { + if (nhandle != 0) { + onDestroyView(nhandle); + } + } + + protected void unregister() { + setOnFocusChangeListener(null); + getHolder().removeCallback(surfCallbacks); + nhandle = 0; + } + + public void configurationChanged() { + if (nhandle != 0) { + onConfigurationChanged(nhandle); + } + } + + public boolean backPressed() { + if (nhandle == 0) { + return false; + } + return onBack(nhandle); + } + + void restartInput() { + imm.restartInput(this); + } + + void updateSelection() { + int selStart = imeToUTF16(nhandle, imeSelectionStart(nhandle)); + int selEnd = imeToUTF16(nhandle, imeSelectionEnd(nhandle)); + int compStart = imeToUTF16(nhandle, imeComposingStart(nhandle)); + int compEnd = imeToUTF16(nhandle, imeComposingEnd(nhandle)); + imm.updateSelection(this, selStart, selEnd, compStart, compEnd); + } + + void updateCaret(float m00, float m01, float m02, float m10, float m11, float m12, float caretX, float caretTop, float caretBase, float caretBottom) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + return; + } + Matrix m = new Matrix(); + m.setValues(new float[]{m00, m01, m02, m10, m11, m12, 0.0f, 0.0f, 1.0f}); + m.setConcat(getMatrix(), m); + int selStart = imeSelectionStart(nhandle); + int selEnd = imeSelectionEnd(nhandle); + int compStart = imeComposingStart(nhandle); + int compEnd = imeComposingEnd(nhandle); + Snippet snip = getSnippet(); + String composing = ""; + if (compStart != -1) { + composing = snip.substringRunes(compStart, compEnd); + } + CursorAnchorInfo inf = new CursorAnchorInfo.Builder() + .setMatrix(m) + .setComposingText(imeToUTF16(nhandle, compStart), composing) + .setSelectionRange(imeToUTF16(nhandle, selStart), imeToUTF16(nhandle, selEnd)) + .setInsertionMarkerLocation(caretX, caretTop, caretBase, caretBottom, 0) + .build(); + imm.updateCursorAnchorInfo(this, inf); + } + + static private native long onCreateView(GioView view); + static private native void onDestroyView(long handle); + static private native void onStartView(long handle); + static private native void onStopView(long handle); + static private native void onSurfaceDestroyed(long handle); + static private native void onSurfaceChanged(long handle, Surface surface); + static private native void onConfigurationChanged(long handle); + static private native void onWindowInsets(long handle, int top, int right, int bottom, int left); + static public native void onLowMemory(); + static private native void onTouchEvent(long handle, int action, int pointerID, int tool, float x, float y, float scrollX, float scrollY, int buttons, long time); + static private native void onKeyEvent(long handle, int code, int character, boolean pressed, long time); + static private native void onFrameCallback(long handle); + static private native boolean onBack(long handle); + static private native void onFocusChange(long handle, boolean focus); + static private native AccessibilityNodeInfo initializeAccessibilityNodeInfo(long handle, int viewId, int screenX, int screenY, AccessibilityNodeInfo info); + static private native void onTouchExploration(long handle, float x, float y); + static private native void onExitTouchExploration(long handle); + static private native void onA11yFocus(long handle, int viewId); + static private native void onClearA11yFocus(long handle, int viewId); + static private native void imeSetSnippet(long handle, int start, int end); + static private native String imeSnippet(long handle); + static private native int imeSnippetStart(long handle); + static private native int imeSelectionStart(long handle); + static private native int imeSelectionEnd(long handle); + static private native int imeComposingStart(long handle); + static private native int imeComposingEnd(long handle); + static private native int imeReplace(long handle, int start, int end, String text); + static private native int imeSetSelection(long handle, int start, int end); + static private native int imeSetComposingRegion(long handle, int start, int end); + // imeToRunes converts the Java character index into runes (Java code points). + static private native int imeToRunes(long handle, int chars); + // imeToUTF16 converts the rune index into Java characters. + static private native int imeToUTF16(long handle, int runes); + + private class GioInputConnection implements InputConnection { + private int batchDepth; + + @Override public boolean beginBatchEdit() { + batchDepth++; + return true; + } + + @Override public boolean endBatchEdit() { + batchDepth--; + return batchDepth > 0; + } + + @Override public boolean clearMetaKeyStates(int states) { + return false; + } + + @Override public boolean commitCompletion(CompletionInfo text) { + return false; + } + + @Override public boolean commitCorrection(CorrectionInfo info) { + return false; + } + + @Override public boolean commitText(CharSequence text, int cursor) { + setComposingText(text, cursor); + return finishComposingText(); + } + + @Override public boolean deleteSurroundingText(int beforeChars, int afterChars) { + // translate before and after to runes. + int selStart = imeSelectionStart(nhandle); + int selEnd = imeSelectionEnd(nhandle); + int before = selStart - imeToRunes(nhandle, imeToUTF16(nhandle, selStart) - beforeChars); + int after = selEnd - imeToRunes(nhandle, imeToUTF16(nhandle, selEnd) - afterChars); + return deleteSurroundingTextInCodePoints(before, after); + } + + @Override public boolean finishComposingText() { + imeSetComposingRegion(nhandle, -1, -1); + return true; + } + + @Override public int getCursorCapsMode(int reqModes) { + Snippet snip = getSnippet(); + int selStart = imeSelectionStart(nhandle); + return TextUtils.getCapsMode(snip.snippet, imeToUTF16(nhandle, selStart), reqModes); + } + + @Override public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) { + return null; + } + + @Override public CharSequence getSelectedText(int flags) { + Snippet snip = getSnippet(); + int selStart = imeSelectionStart(nhandle); + int selEnd = imeSelectionEnd(nhandle); + String sub = snip.substringRunes(selStart, selEnd); + return sub; + } + + @Override public CharSequence getTextAfterCursor(int n, int flags) { + Snippet snip = getSnippet(); + int selStart = imeSelectionStart(nhandle); + int selEnd = imeSelectionEnd(nhandle); + // n are in Java characters, but in worst case we'll just ask for more runes + // than wanted. + imeSetSnippet(nhandle, selStart - n, selEnd + n); + int start = selEnd; + int end = imeToRunes(nhandle, imeToUTF16(nhandle, selEnd) + n); + String ret = snip.substringRunes(start, end); + return ret; + } + + @Override public CharSequence getTextBeforeCursor(int n, int flags) { + Snippet snip = getSnippet(); + int selStart = imeSelectionStart(nhandle); + int selEnd = imeSelectionEnd(nhandle); + // n are in Java characters, but in worst case we'll just ask for more runes + // than wanted. + imeSetSnippet(nhandle, selStart - n, selEnd + n); + int start = imeToRunes(nhandle, imeToUTF16(nhandle, selStart) - n); + int end = selStart; + String ret = snip.substringRunes(start, end); + return ret; + } + + @Override public boolean performContextMenuAction(int id) { + return false; + } + + @Override public boolean performEditorAction(int editorAction) { + long eventTime = SystemClock.uptimeMillis(); + // Translate to enter key. + onKeyEvent(nhandle, KeyEvent.KEYCODE_ENTER, '\n', true, eventTime); + onKeyEvent(nhandle, KeyEvent.KEYCODE_ENTER, '\n', false, eventTime); + return true; + } + + @Override public boolean performPrivateCommand(String action, Bundle data) { + return false; + } + + @Override public boolean reportFullscreenMode(boolean enabled) { + return false; + } + + @Override public boolean sendKeyEvent(KeyEvent event) { + boolean pressed = event.getAction() == KeyEvent.ACTION_DOWN; + onKeyEvent(nhandle, event.getKeyCode(), event.getUnicodeChar(), pressed, event.getEventTime()); + return true; + } + + @Override public boolean setComposingRegion(int startChars, int endChars) { + int compStart = imeToRunes(nhandle, startChars); + int compEnd = imeToRunes(nhandle, endChars); + imeSetComposingRegion(nhandle, compStart, compEnd); + return true; + } + + @Override public boolean setComposingText(CharSequence text, int relCursor) { + int start = imeComposingStart(nhandle); + int end = imeComposingEnd(nhandle); + if (start == -1 || end == -1) { + start = imeSelectionStart(nhandle); + end = imeSelectionEnd(nhandle); + } + String str = text.toString(); + imeReplace(nhandle, start, end, str); + int cursor = start; + int runes = str.codePointCount(0, str.length()); + if (relCursor > 0) { + cursor += runes; + relCursor--; + } + imeSetComposingRegion(nhandle, start, start + runes); + + // Move cursor. + Snippet snip = getSnippet(); + cursor = imeToRunes(nhandle, imeToUTF16(nhandle, cursor) + relCursor); + imeSetSelection(nhandle, cursor, cursor); + return true; + } + + @Override public boolean setSelection(int startChars, int endChars) { + int start = imeToRunes(nhandle, startChars); + int end = imeToRunes(nhandle, endChars); + imeSetSelection(nhandle, start, end); + return true; + } + + /*@Override*/ public boolean requestCursorUpdates(int cursorUpdateMode) { + // We always provide cursor updates. + return true; + } + + /*@Override*/ public void closeConnection() { + } + + /*@Override*/ public Handler getHandler() { + return null; + } + + /*@Override*/ public boolean commitContent(InputContentInfo info, int flags, Bundle opts) { + return false; + } + + /*@Override*/ public boolean deleteSurroundingTextInCodePoints(int before, int after) { + if (after > 0) { + int selEnd = imeSelectionEnd(nhandle); + imeReplace(nhandle, selEnd, selEnd + after, ""); + } + if (before > 0) { + int selStart = imeSelectionStart(nhandle); + imeReplace(nhandle, selStart - before, selStart, ""); + } + return true; + } + } + + private Snippet getSnippet() { + Snippet snip = new Snippet(); + snip.snippet = imeSnippet(nhandle); + snip.offset = imeSnippetStart(nhandle); + return snip; + } + + // Snippet is like android.view.inputmethod.SurroundingText but available for Android < 31. + private static class Snippet { + String snippet; + // offset of snippet into the entire editor content. It is in runes because we won't require + // Gio editors to keep track of UTF-16 offsets. The distinction won't matter in practice because IMEs only + // ever see snippets. + int offset; + + // substringRunes returns the substring from start to end in runes. The resuls is + // truncated to the snippet. + String substringRunes(int start, int end) { + start -= this.offset; + end -= this.offset; + int runes = snippet.codePointCount(0, snippet.length()); + if (start < 0) { + start = 0; + } + if (end < 0) { + end = 0; + } + if (start > runes) { + start = runes; + } + if (end > runes) { + end = runes; + } + return snippet.substring( + snippet.offsetByCodePoints(0, start), + snippet.offsetByCodePoints(0, end) + ); + } + } + + @Override public AccessibilityNodeProvider getAccessibilityNodeProvider() { + return new AccessibilityNodeProvider() { + private final int[] screenOff = new int[2]; + + @Override public AccessibilityNodeInfo createAccessibilityNodeInfo(int viewId) { + AccessibilityNodeInfo info = null; + if (viewId == View.NO_ID) { + info = AccessibilityNodeInfo.obtain(GioView.this); + GioView.this.onInitializeAccessibilityNodeInfo(info); + } else { + info = AccessibilityNodeInfo.obtain(GioView.this, viewId); + info.setPackageName(getContext().getPackageName()); + info.setVisibleToUser(true); + } + GioView.this.getLocationOnScreen(screenOff); + info = GioView.this.initializeAccessibilityNodeInfo(nhandle, viewId, screenOff[0], screenOff[1], info); + return info; + } + + @Override public boolean performAction(int viewId, int action, Bundle arguments) { + if (viewId == View.NO_ID) { + return GioView.this.performAccessibilityAction(action, arguments); + } + switch (action) { + case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: + GioView.this.onA11yFocus(nhandle, viewId); + GioView.this.sendA11yEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, viewId); + return true; + case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: + GioView.this.onClearA11yFocus(nhandle, viewId); + GioView.this.sendA11yEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED, viewId); + return true; + } + return false; + } + }; + } +} diff --git a/android/res/drawable/icon.png b/android/res/drawable/icon.png new file mode 100644 index 0000000..8635cb2 Binary files /dev/null and b/android/res/drawable/icon.png differ diff --git a/android/res/layout/main.xml b/android/res/layout/main.xml new file mode 100644 index 0000000..4fb84e3 --- /dev/null +++ b/android/res/layout/main.xml @@ -0,0 +1,11 @@ + + + diff --git a/android/res/values-de/strings.xml b/android/res/values-de/strings.xml new file mode 100644 index 0000000..b18c886 --- /dev/null +++ b/android/res/values-de/strings.xml @@ -0,0 +1,5 @@ + + + Benachrichtigungen + Wunder + \ No newline at end of file diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml new file mode 100644 index 0000000..27c4254 --- /dev/null +++ b/android/res/values/strings.xml @@ -0,0 +1,5 @@ + + + Notifications + Wow + \ No newline at end of file diff --git a/app_state.go b/app_state.go new file mode 100644 index 0000000..d59c2a8 --- /dev/null +++ b/app_state.go @@ -0,0 +1,21 @@ +package giouibind + +import ( + "gioui.org/app" + "github.com/empathicqubit/giouibind/native" +) + +type AppSettings struct { +} + +type AppState struct { + settings *AppSettings + window *app.Window + bluetoothEnabled bool + loaded bool + connected bool + connecting bool + initted bool + deviceName string + nativeBridge native.INativeBridge +} diff --git a/desktop/god.go b/desktop/god.go new file mode 100644 index 0000000..14e1966 --- /dev/null +++ b/desktop/god.go @@ -0,0 +1,51 @@ +package main + +import ( + "strconv" + "strings" + + "github.com/JuulLabs-OSS/cbgo" + "github.com/empathicqubit/giouibind/native" +) + +var _ native.INativeBridge = (*NativeBridge)(nil) + +type NativeBridge struct { + fd int + central *cbgo.CentralManager + delegate *MyDelegate +} + +// str2ba converts MAC address string representation to little-endian byte array +func str2ba(addr string) [6]byte { + a := strings.Split(addr, ":") + var b [6]byte + for i, tmp := range a { + u, _ := strconv.ParseUint(tmp, 16, 8) + b[len(b)-1-i] = byte(u) + } + return b +} + +func (god *NativeBridge) EnableBluetooth() bool { + central := cbgo.NewCentralManager(&cbgo.ManagerOpts{}) + god.central = ¢ral + delegate := &MyDelegate{} + god.delegate = delegate + god.central.SetDelegate(delegate) + + return true +} + +var localName string = "" + +func (god *NativeBridge) WriteChar(data []byte) bool { + if data == nil { + return false + } + + return god.delegate.writeChar(data) +} + +func (god *NativeBridge) ConnectToDevice() { +} diff --git a/desktop/main.go b/desktop/main.go new file mode 100644 index 0000000..63b71bf --- /dev/null +++ b/desktop/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "log" + "os" + + "gioui.org/app" + "gioui.org/unit" + "github.com/empathicqubit/giouibind" + "github.com/empathicqubit/giouibind/native" +) + +var nativeBridge *NativeBridge = &NativeBridge{} +var dumbApp *giouibind.AppState = &giouibind.AppState{} + +func main() { + var igod native.INativeBridge = nativeBridge + log.Println("Called main") + err := dumbApp.Load() + if err != nil { + panic(err) + } + err = dumbApp.InventGod(igod) + if err != nil { + panic(err) + } + + go func() { + w := app.NewWindow( + app.Size(unit.Dp(450), unit.Dp(800)), + ) + err := dumbApp.RunApp(w) + if err != nil { + log.Fatal(err) + } + os.Exit(0) + }() + app.Main() +} diff --git a/desktop/my_delegate.go b/desktop/my_delegate.go new file mode 100644 index 0000000..b170c0f --- /dev/null +++ b/desktop/my_delegate.go @@ -0,0 +1,163 @@ +package main + +import ( + "log" + + "github.com/JuulLabs-OSS/cbgo" +) + +type MyDelegate struct { + cbgo.CentralManagerDelegateBase + cbgo.PeripheralDelegateBase + connectedPeripheral *cbgo.Peripheral + service *cbgo.Service + readChr cbgo.Characteristic + writeChr cbgo.Characteristic + encryptedChr cbgo.Characteristic + pairingChr cbgo.Characteristic + peripheral *cbgo.Peripheral + finishedConnect bool +} + +var shortServiceUuid, _ = cbgo.ParseUUID16("FIXME") +var longServiceUuid, _ = cbgo.ParseUUID("FIXME") + +var writeUuid, _ = cbgo.ParseUUID("FIXME") +var readUuid, _ = cbgo.ParseUUID("FIXME") + +func (d *MyDelegate) writeChar(data []byte) bool { + if d.connectedPeripheral == nil { + return false + } + + d.connectedPeripheral.WriteCharacteristic(data, d.writeChr, true) + + return true +} + +func (d *MyDelegate) readChar() []byte { + if d.connectedPeripheral == nil { + return []byte{} + } + + d.connectedPeripheral.ReadCharacteristic(d.readChr) + + return d.readChr.Value() +} + +func (d *MyDelegate) CentralManagerDidUpdateState(cmgr cbgo.CentralManager) { + if cmgr.State() == cbgo.ManagerStatePoweredOn { + log.Println("Start scanning") + go func() { + nativeBridge.central.Scan([]cbgo.UUID{shortServiceUuid, longServiceUuid}, &cbgo.CentralManagerScanOpts{ + AllowDuplicates: false, + SolicitedServiceUUIDs: []cbgo.UUID{longServiceUuid, shortServiceUuid}, + }) + }() + } +} + +func (d *MyDelegate) DidDiscoverPeripheral(cm cbgo.CentralManager, prph cbgo.Peripheral, + advFields cbgo.AdvFields, rssi int) { + log.Println("Found peripheral", prph.Name()) + nativeBridge.central.Connect(prph, nil) +} + +func (d *MyDelegate) DidConnectPeripheral(cm cbgo.CentralManager, prph cbgo.Peripheral) { + if d.connectedPeripheral == nil { + prph.SetDelegate(d) + prph.DiscoverServices([]cbgo.UUID{longServiceUuid, shortServiceUuid}) + } +} + +func (d *MyDelegate) DidFailToConnectPeripheral(cm cbgo.CentralManager, prph cbgo.Peripheral, err error) { + log.Printf("failed to connect: %v", err) +} + +func (d *MyDelegate) DidDisconnectPeripheral(cm cbgo.CentralManager, prph cbgo.Peripheral, err error) { + log.Printf("peripheral disconnected: %v", err) +} + +func (d *MyDelegate) DidDiscoverServices(prph cbgo.Peripheral, err error) { + if err != nil || len(prph.Services()) == 0 { + log.Println("Error discovering services", err) + dumbApp.FinishedConnect(false, "") + return + } + + d.service = &prph.Services()[0] + prph.DiscoverCharacteristics([]cbgo.UUID{writeUuid, readUuid, encryptedUuid, pairingUuid}, *d.service) +} + +func (d *MyDelegate) DidDiscoverCharacteristics(prph cbgo.Peripheral, svc cbgo.Service, err error) { + if svc.UUID().String() != d.service.UUID().String() { + return + } + + if err != nil || len(svc.Characteristics()) == 0 { + log.Println("No characteristics") + dumbApp.FinishedConnect(false, "") + return + } + + foundCount := 0 + for _, chr := range d.service.Characteristics() { + log.Println("Found char", chr.UUID().String()) + + uuid := chr.UUID().String() + if uuid == writeUuid.String() { + d.writeChr = chr + foundCount += 1 + } else if uuid == readUuid.String() { + d.readChr = chr + foundCount += 1 + } + } + + if foundCount < 2 || d.service == nil { + log.Println("Couldn't find matching service or characteristics") + dumbApp.FinishedConnect(false, "") + return + } + + nativeBridge.central.StopScan() + d.connectedPeripheral = &prph + + log.Println("Finished connect. Writing test command") + + d.connectedPeripheral.SetNotify(true, d.readChr) +} + +func (d *MyDelegate) DidDiscoverDescriptors(prph cbgo.Peripheral, chr cbgo.Characteristic, err error) { +} + +func (d *MyDelegate) DidUpdateValueForCharacteristic(prph cbgo.Peripheral, chr cbgo.Characteristic, err error) { + if err != nil { + log.Printf("Error getting descriptor value: %s", chr.UUID().String()) + return + } + + if chr.Value() == nil { + return + } + data := chr.Value() + + if chr.UUID().String() != d.readChr.UUID().String() { + return + } + + dumbApp.BluetoothGotData(data) + + if !d.finishedConnect { + d.finishedConnect = true + dumbApp.FinishedConnect(true, d.connectedPeripheral.Name()) + } +} + +func (d *MyDelegate) DidUpdateValueForDescriptor(prph cbgo.Peripheral, dsc cbgo.Descriptor, err error) { + if dsc.Characteristic().Service().UUID().String() != d.service.UUID().String() { + return + } + + d.DidUpdateValueForCharacteristic(prph, dsc.Characteristic(), err) +} diff --git a/gio/cpu/abi.h b/gio/cpu/abi.h new file mode 100644 index 0000000..365d936 --- /dev/null +++ b/gio/cpu/abi.h @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +#define ALIGN(bytes, type) type __attribute__((aligned(bytes))) + +typedef ALIGN(8, uint8_t) byte8[8]; +typedef ALIGN(8, uint16_t) word4[4]; +typedef ALIGN(4, uint32_t) dword; +typedef ALIGN(16, uint32_t) dword4[4]; +typedef ALIGN(8, uint64_t) qword; +typedef ALIGN(16, uint64_t) qword2[2]; +typedef ALIGN(16, unsigned int) uint4[4]; +typedef ALIGN(8, uint32_t) dword2[2]; +typedef ALIGN(8, unsigned short) ushort4[4]; +typedef ALIGN(16, float) float4[4]; +typedef ALIGN(16, int) int4[4]; + +typedef unsigned short half; + +typedef unsigned char bool; + +enum { + MAX_BOUND_DESCRIPTOR_SETS = 4, + MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC = 8, + MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC = 4, + MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC = + MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC + + MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC, + MAX_PUSH_CONSTANT_SIZE = 128, + + MIN_STORAGE_BUFFER_OFFSET_ALIGNMENT = 256, + + REQUIRED_MEMORY_ALIGNMENT = 16, + + SIMD_WIDTH = 4, +}; + +struct image_descriptor { + ALIGN(16, void *ptr); + int width; + int height; + int depth; + int row_pitch_bytes; + int slice_pitch_bytes; + int sample_pitch_bytes; + int sample_count; + int size_in_bytes; + + void *stencil_ptr; + int stencil_row_pitch_bytes; + int stencil_slice_pitch_bytes; + int stencil_sample_pitch_bytes; + + // TODO: unused? + void *memoryOwner; +}; + +struct buffer_descriptor { + ALIGN(16, void *ptr); + int size_in_bytes; + int robustness_size; +}; + +struct program_data { + uint8_t *descriptor_sets[MAX_BOUND_DESCRIPTOR_SETS]; + uint32_t descriptor_dynamic_offsets[MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC]; + uint4 num_workgroups; + uint4 workgroup_size; + uint32_t invocations_per_subgroup; + uint32_t subgroups_per_workgroup; + uint32_t invocations_per_workgroup; + unsigned char push_constants[MAX_PUSH_CONSTANT_SIZE]; + // Unused. + void *constants; +}; + +typedef int32_t yield_result; + +typedef void * coroutine; + +typedef coroutine (*routine_begin)(struct program_data *data, + int32_t workgroupX, + int32_t workgroupY, + int32_t workgroupZ, + void *workgroupMemory, + int32_t firstSubgroup, + int32_t subgroupCount); + +typedef bool (*routine_await)(coroutine r, yield_result *res); + +typedef void (*routine_destroy)(coroutine r); + diff --git a/gio/cpu/driver_nosupport.go b/gio/cpu/driver_nosupport.go new file mode 100644 index 0000000..59e5178 --- /dev/null +++ b/gio/cpu/driver_nosupport.go @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package cpu + +import "unsafe" + +type ( + BufferDescriptor struct{} + ImageDescriptor struct{} + SamplerDescriptor struct{} + + DispatchContext struct{} + ThreadContext struct{} + ProgramInfo struct{} +) + +const Supported = false + +func NewBuffer(size int) BufferDescriptor { + panic("unsupported") +} + +func (d *BufferDescriptor) Data() []byte { + panic("unsupported") +} + +func (d *BufferDescriptor) Free() { +} + +func NewImageRGBA(width, height int) ImageDescriptor { + panic("unsupported") +} + +func (d *ImageDescriptor) Data() []byte { + panic("unsupported") +} + +func (d *ImageDescriptor) Free() { +} + +func NewDispatchContext() *DispatchContext { + panic("unsupported") +} + +func (c *DispatchContext) Free() { +} + +func (c *DispatchContext) Prepare(numThreads int, prog *ProgramInfo, descSet unsafe.Pointer, x, y, z int) { + panic("unsupported") +} + +func (c *DispatchContext) Dispatch(threadIdx int, ctx *ThreadContext) { + panic("unsupported") +} + +func NewThreadContext() *ThreadContext { + panic("unsupported") +} + +func (c *ThreadContext) Free() { +} diff --git a/gio/cpu/embed.go b/gio/cpu/embed.go new file mode 100644 index 0000000..9d3b944 --- /dev/null +++ b/gio/cpu/embed.go @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package cpu + +import _ "embed" + +//go:embed abi.h +var ABIH []byte + +//go:embed runtime.h +var RuntimeH []byte diff --git a/gio/cpu/go.mod b/gio/cpu/go.mod new file mode 100644 index 0000000..af5af9c --- /dev/null +++ b/gio/cpu/go.mod @@ -0,0 +1,3 @@ +module github.com/empathicqubit/giouibind/gio/cpu + +go 1.17 diff --git a/gio/cpu/runtime.h b/gio/cpu/runtime.h new file mode 100644 index 0000000..cfae912 --- /dev/null +++ b/gio/cpu/runtime.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +#define ATTR_HIDDEN __attribute__ ((visibility ("hidden"))) + +// program_info contains constant parameters for a program. +struct program_info { + // MinMemorySize is the minimum size of memory passed to dispatch. + size_t min_memory_size; + // has_cbarriers is 1 when the program contains control barriers. + bool has_cbarriers; + // desc_set_size is the size of the first descriptor set for the program. + size_t desc_set_size; + int workgroup_size_x; + int workgroup_size_y; + int workgroup_size_z; + // Program entrypoints. + routine_begin begin; + routine_await await; + routine_destroy destroy; +}; + +// dispatch_context contains the information a program dispatch. +struct dispatch_context; + +// thread_context contains the working memory of a batch. It may be +// reused, but not concurrently. +struct thread_context; + +extern struct buffer_descriptor alloc_buffer(size_t size) ATTR_HIDDEN; +extern struct image_descriptor alloc_image_rgba(int width, int height) ATTR_HIDDEN; + +extern struct dispatch_context *alloc_dispatch_context(void) ATTR_HIDDEN; + +extern void free_dispatch_context(struct dispatch_context *c) ATTR_HIDDEN; + +extern struct thread_context *alloc_thread_context(void) ATTR_HIDDEN; + +extern void free_thread_context(struct thread_context *c) ATTR_HIDDEN; + +// prepare_dispatch initializes ctx to run a dispatch of a program distributed +// among nthreads threads. +extern void prepare_dispatch(struct dispatch_context *ctx, int nthreads, struct program_info *info, uint8_t *desc_set, int ngroupx, int ngroupy, int ngroupz) ATTR_HIDDEN; + +// dispatch_batch executes a dispatch batch. +extern void dispatch_thread(struct dispatch_context *ctx, int thread_idx, struct thread_context *thread) ATTR_HIDDEN; diff --git a/gio/shader/LICENSE b/gio/shader/LICENSE new file mode 100644 index 0000000..81f4733 --- /dev/null +++ b/gio/shader/LICENSE @@ -0,0 +1,63 @@ +This project is provided under the terms of the UNLICENSE or +the MIT license denoted by the following SPDX identifier: + +SPDX-License-Identifier: Unlicense OR MIT + +You may use the project under the terms of either license. + +Both licenses are reproduced below. + +---- +The MIT License (MIT) + +Copyright (c) 2019 The Gio authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +--- + + + +--- +The UNLICENSE + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +--- diff --git a/gio/shader/README.md b/gio/shader/README.md new file mode 100644 index 0000000..4ea4867 --- /dev/null +++ b/gio/shader/README.md @@ -0,0 +1,18 @@ +# GPU programs for the Gio project + +This repository contains the source code for the [Gio](https://gioui.org) +project. It also contains the generators and dereived versions for use with the +GPU APIs supported by Gio. + +# Generating CPU fallbacks + +The `piet/gencpu.sh` script updates the piet-gpu binaries: + +``` +$ cd piet +$ ./gencpu.sh +``` + +## Issues and contributions + +See the [Gio contribution guide](https://gioui.org/doc/contribute). diff --git a/gio/shader/cmd/convertshaders/glslvalidate.go b/gio/shader/cmd/convertshaders/glslvalidate.go new file mode 100644 index 0000000..b17150f --- /dev/null +++ b/gio/shader/cmd/convertshaders/glslvalidate.go @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "os/exec" + "path/filepath" + "strings" +) + +// GLSLValidator is OpenGL reference compiler. +type GLSLValidator struct { + Bin string + WorkDir WorkDir +} + +func NewGLSLValidator() *GLSLValidator { return &GLSLValidator{Bin: "glslangValidator"} } + +// Convert converts a glsl shader to spirv. +func (glsl *GLSLValidator) Convert(path, variant string, lang string, input []byte) ([]byte, error) { + base := glsl.WorkDir.Path(filepath.Base(path), variant) + pathout := base + ".out" + + cmd := exec.Command(glsl.Bin, + "--stdin", + "-DLANG_"+strings.ToUpper(lang), + "-I"+filepath.Dir(path), + "-V", // OpenGL ES 3.1. + "-w", // Suppress warnings. + "-S", filepath.Ext(path)[1:], + "-o", pathout, + ) + cmd.Stdin = bytes.NewBuffer(input) + + out, err := cmd.Output() + if err != nil { + return nil, fmt.Errorf("%s\nfailed to run %v: %w", out, cmd.Args, err) + } + + compiled, err := ioutil.ReadFile(pathout) + if err != nil { + return nil, fmt.Errorf("unable to read output %q: %w", pathout, err) + } + + return compiled, nil +} + +func spirvOpt(spirv []byte) ([]byte, error) { + cmd := exec.Command("spirv-opt", + "-O", + "-", + "-o", "-", + ) + cmd.Stdin = bytes.NewBuffer(spirv) + + out, err := cmd.Output() + if err != nil { + return nil, fmt.Errorf("%s\nfailed to run %v: %w", out, cmd.Args, err) + } + return out, nil +} diff --git a/gio/shader/cmd/convertshaders/hlsl.go b/gio/shader/cmd/convertshaders/hlsl.go new file mode 100644 index 0000000..def3e3e --- /dev/null +++ b/gio/shader/cmd/convertshaders/hlsl.go @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package main + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os/exec" + "path/filepath" + "runtime" + "strings" +) + +// FXC is hlsl compiler that targets ShaderModel 5.x and lower. +type FXC struct { + Bin string + WorkDir WorkDir +} + +func NewFXC() *FXC { return &FXC{Bin: "fxc.exe"} } + +// Compile compiles the input shader. +func (fxc *FXC) Compile(path, variant string, input []byte, entryPoint string, profileVersion string) ([]byte, error) { + base := fxc.WorkDir.Path(filepath.Base(path), variant, profileVersion) + pathin := base + ".in" + pathout := base + ".out" + result := pathout + + if err := fxc.WorkDir.WriteFile(pathin, input); err != nil { + return nil, fmt.Errorf("unable to write shader to disk: %w", err) + } + + cmd := exec.Command(fxc.Bin) + if runtime.GOOS != "windows" { + cmd = exec.Command("wine", fxc.Bin) + if err := winepath(&pathin, &pathout); err != nil { + return nil, err + } + } + + var profile string + switch filepath.Ext(path) { + case ".frag": + profile = "ps_" + profileVersion + case ".vert": + profile = "vs_" + profileVersion + case ".comp": + profile = "cs_" + profileVersion + default: + return nil, fmt.Errorf("unrecognized shader type %s", path) + } + + cmd.Args = append(cmd.Args, + "/Fo", pathout, + "/T", profile, + "/E", entryPoint, + pathin, + ) + + output, err := cmd.CombinedOutput() + if err != nil { + info := "" + if runtime.GOOS != "windows" { + info = "If the fxc tool cannot be found, set WINEPATH to the Windows path for the Windows SDK.\n" + } + return nil, fmt.Errorf("%s\n%sfailed to run %v: %w", output, info, cmd.Args, err) + } + + compiled, err := ioutil.ReadFile(result) + if err != nil { + return nil, fmt.Errorf("unable to read output %q: %w", pathout, err) + } + + return compiled, nil +} + +// DXC is hlsl compiler that targets ShaderModel 6.0 and newer. +type DXC struct { + Bin string + WorkDir WorkDir +} + +func NewDXC() *DXC { return &DXC{Bin: "dxc"} } + +// Compile compiles the input shader. +func (dxc *DXC) Compile(path, variant string, input []byte, entryPoint string, profile string) (string, error) { + base := dxc.WorkDir.Path(filepath.Base(path), variant, profile) + pathin := base + ".in" + pathout := base + ".out" + result := pathout + + if err := dxc.WorkDir.WriteFile(pathin, input); err != nil { + return "", fmt.Errorf("unable to write shader to disk: %w", err) + } + + cmd := exec.Command(dxc.Bin) + + cmd.Args = append(cmd.Args, + "-Fo", pathout, + "-T", profile, + "-E", entryPoint, + "-Qstrip_reflect", + pathin, + ) + + output, err := cmd.CombinedOutput() + if err != nil { + return "", fmt.Errorf("%s\nfailed to run %v: %w", output, cmd.Args, err) + } + + compiled, err := ioutil.ReadFile(result) + if err != nil { + return "", fmt.Errorf("unable to read output %q: %w", pathout, err) + } + + return string(compiled), nil +} + +// winepath uses the winepath tool to convert a paths to Windows format. +// The returned path can be used as arguments for Windows command line tools. +func winepath(paths ...*string) error { + winepath := exec.Command("winepath", "--windows") + for _, path := range paths { + winepath.Args = append(winepath.Args, *path) + } + // Use a pipe instead of Output, because winepath may have left wineserver + // running for several seconds as a grandchild. + out, err := winepath.StdoutPipe() + if err != nil { + return fmt.Errorf("unable to start winepath: %w", err) + } + if err := winepath.Start(); err != nil { + return fmt.Errorf("unable to start winepath: %w", err) + } + var buf bytes.Buffer + if _, err := io.Copy(&buf, out); err != nil { + return fmt.Errorf("unable to run winepath: %w", err) + } + winPaths := strings.Split(strings.TrimSpace(buf.String()), "\n") + for i, path := range paths { + *path = winPaths[i] + } + return nil +} diff --git a/gio/shader/cmd/convertshaders/main.go b/gio/shader/cmd/convertshaders/main.go new file mode 100644 index 0000000..22baa95 --- /dev/null +++ b/gio/shader/cmd/convertshaders/main.go @@ -0,0 +1,547 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package main + +import ( + "bytes" + "errors" + "flag" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "sort" + "strconv" + "strings" + "sync" + "text/template" +) + +type shaderSources struct { + Name string + SPIRV []byte + GLSL100ES []byte + GLSL150 []byte + DXBC []byte + MetalLibs MetalLibs + Reflect Metadata +} + +func main() { + packageName := flag.String("package", "", "specify Go package name") + workdir := flag.String("work", "", "temporary working directory (default TEMP)") + shadersDir := flag.String("dir", "shaders", "shaders directory") + + flag.Parse() + + var work WorkDir + cleanup := func() {} + if *workdir == "" { + tempdir, err := ioutil.TempDir("", "shader-convert") + if err != nil { + fmt.Fprintf(os.Stderr, "failed to create tempdir: %v\n", err) + os.Exit(1) + } + cleanup = func() { os.RemoveAll(tempdir) } + defer cleanup() + + work = WorkDir(tempdir) + } else { + if abs, err := filepath.Abs(*workdir); err == nil { + *workdir = abs + } + work = WorkDir(*workdir) + } + + var out bytes.Buffer + conv := NewConverter(work, *packageName, *shadersDir) + if err := conv.Run(&out); err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + cleanup() + os.Exit(1) + } + + if err := ioutil.WriteFile("shaders.go", out.Bytes(), 0644); err != nil { + fmt.Fprintf(os.Stderr, "failed to create shaders: %v\n", err) + cleanup() + os.Exit(1) + } + + cmd := exec.Command("gofmt", "-s", "-w", "shaders.go") + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if err := cmd.Run(); err != nil { + fmt.Fprintf(os.Stderr, "formatting shaders.go failed: %v\n", err) + cleanup() + os.Exit(1) + } +} + +type Converter struct { + workDir WorkDir + shadersDir string + + packageName string + + glslvalidator *GLSLValidator + spirv *SPIRVCross + fxc *FXC + msl *MSL +} + +func NewConverter(workDir WorkDir, packageName, shadersDir string) *Converter { + if abs, err := filepath.Abs(shadersDir); err == nil { + shadersDir = abs + } + + conv := &Converter{} + conv.workDir = workDir + conv.shadersDir = shadersDir + + conv.packageName = packageName + + conv.glslvalidator = NewGLSLValidator() + conv.spirv = NewSPIRVCross() + conv.fxc = NewFXC() + conv.msl = &MSL{ + WorkDir: workDir.Dir("msl"), + } + + verifyBinaryPath(&conv.glslvalidator.Bin) + verifyBinaryPath(&conv.spirv.Bin) + // We cannot check fxc nor msl since they may depend on wine. + + conv.glslvalidator.WorkDir = workDir.Dir("glslvalidator") + conv.fxc.WorkDir = workDir.Dir("fxc") + conv.spirv.WorkDir = workDir.Dir("spirv") + + return conv +} + +func verifyBinaryPath(bin *string) { + new, err := exec.LookPath(*bin) + if err != nil { + fmt.Fprintf(os.Stderr, "unable to find %q: %v\n", *bin, err) + } else { + *bin = new + } +} + +func (conv *Converter) Run(out io.Writer) error { + shaders, err := filepath.Glob(filepath.Join(conv.shadersDir, "*")) + if err != nil { + return fmt.Errorf("failed to list shaders in %q: %w", conv.shadersDir, err) + } + + sort.Strings(shaders) + + var workers Workers + + type ShaderResult struct { + Path string + Shaders []shaderSources + Error error + } + shaderResults := make([]ShaderResult, len(shaders)) + + for i, shaderPath := range shaders { + i, shaderPath := i, shaderPath + + switch filepath.Ext(shaderPath) { + case ".vert", ".frag": + workers.Go(func() { + shaders, err := conv.Shader(shaderPath) + shaderResults[i] = ShaderResult{ + Path: shaderPath, + Shaders: shaders, + Error: err, + } + }) + case ".comp": + workers.Go(func() { + shaders, err := conv.ComputeShader(shaderPath) + shaderResults[i] = ShaderResult{ + Path: shaderPath, + Shaders: shaders, + Error: err, + } + }) + default: + continue + } + } + + workers.Wait() + + var allErrors string + for _, r := range shaderResults { + if r.Error != nil { + if len(allErrors) > 0 { + allErrors += "\n\n" + } + allErrors += "--- " + r.Path + " --- \n\n" + r.Error.Error() + "\n" + } + } + if len(allErrors) > 0 { + return errors.New(allErrors) + } + + fmt.Fprintf(out, "// Code generated by build.go. DO NOT EDIT.\n\n") + fmt.Fprintf(out, "package %s\n\n", conv.packageName) + fmt.Fprintf(out, "import (\n") + fmt.Fprintf(out, "\t%q\n", "runtime") + fmt.Fprintf(out, "\t_ %q\n", "embed") + fmt.Fprintln(out) + fmt.Fprintf(out, "\t%q\n", "gioui.org/shader") + fmt.Fprintf(out, ")\n\n") + + fmt.Fprintf(out, "var (\n") + + var genErr error + for _, r := range shaderResults { + if len(r.Shaders) == 0 { + continue + } + + name := filepath.Base(r.Path) + name = strings.ReplaceAll(name, ".", "_") + fmt.Fprintf(out, "\tShader_%s = ", name) + + multiVariant := len(r.Shaders) > 1 + if multiVariant { + fmt.Fprintf(out, "[...]shader.Sources{\n") + } + + writeGenerated := func(src []byte, prefix, path string, idx int) { + if len(src) == 0 || genErr != nil { + return + } + base := fmt.Sprintf("z%s.%d.%s", filepath.Base(path), idx, strings.ToLower(prefix)) + p := filepath.Join(filepath.Dir(path), base) + genErr = os.WriteFile(p, src, 0o644) + } + for i, src := range r.Shaders { + fmt.Fprintf(out, "shader.Sources{\n") + fmt.Fprintf(out, "Name: %#v,\n", src.Name) + if inp := src.Reflect.Inputs; len(inp) > 0 { + fmt.Fprintf(out, "Inputs: %#v,\n", inp) + } + if u := src.Reflect.Uniforms; u.Size > 0 { + fmt.Fprintf(out, "Uniforms: shader.UniformsReflection{\n") + fmt.Fprintf(out, "Locations: %#v,\n", u.Locations) + fmt.Fprintf(out, "Size: %d,\n", u.Size) + fmt.Fprintf(out, "},\n") + } + if tex := src.Reflect.Textures; len(tex) > 0 { + fmt.Fprintf(out, "Textures: %#v,\n", tex) + } + if imgs := src.Reflect.Images; len(imgs) > 0 { + fmt.Fprintf(out, "Images: %#v,\n", imgs) + } + if bufs := src.Reflect.StorageBuffers; len(bufs) > 0 { + fmt.Fprintf(out, "StorageBuffers: %#v,\n", bufs) + } + if wg := src.Reflect.WorkgroupSize; wg != [3]int{} { + fmt.Fprintf(out, "WorkgroupSize: %#v,\n", wg) + } + writeGenerated(src.SPIRV, "SPIRV", r.Path, i) + writeGenerated(src.GLSL100ES, "GLSL100ES", r.Path, i) + writeGenerated(src.GLSL150, "GLSL150", r.Path, i) + writeGenerated(src.DXBC, "DXBC", r.Path, i) + writeGenerated(src.MetalLibs.MacOS, "MetalLibMacOS", r.Path, i) + writeGenerated(src.MetalLibs.IOS, "MetalLibIOS", r.Path, i) + writeGenerated(src.MetalLibs.IOSSimulator, "MetalLibIOSSimulator", r.Path, i) + fmt.Fprintf(out, "}") + if multiVariant { + fmt.Fprintf(out, ",") + } + fmt.Fprintf(out, "\n") + } + if multiVariant { + fmt.Fprintf(out, "}\n") + } + writeEmbedded := func(src []byte, prefix, path string, idx int) { + base := fmt.Sprintf("z%s.%d.%s", filepath.Base(path), idx, strings.ToLower(prefix)) + if _, err := os.Stat(base); err != nil { + return + } + field := strings.ReplaceAll(base, ".", "_") + fmt.Fprintf(out, "//go:embed %s\n", base) + fmt.Fprintf(out, "%s string\n", field) + } + for i, src := range r.Shaders { + writeEmbedded(src.SPIRV, "SPIRV", r.Path, i) + writeEmbedded(src.GLSL100ES, "GLSL100ES", r.Path, i) + writeEmbedded(src.GLSL150, "GLSL150", r.Path, i) + writeEmbedded(src.DXBC, "DXBC", r.Path, i) + writeEmbedded(src.MetalLibs.MacOS, "MetalLibMacOS", r.Path, i) + writeEmbedded(src.MetalLibs.IOS, "MetalLibIOS", r.Path, i) + writeEmbedded(src.MetalLibs.IOSSimulator, "MetalLibIOSSimulator", r.Path, i) + } + } + fmt.Fprintf(out, ")\n") + writeInit := func(src []byte, prefix, field, path string, idx int, variants bool) { + name := filepath.Base(path) + name = strings.ReplaceAll(name, ".", "_") + base := fmt.Sprintf("z%s.%d.%s", filepath.Base(path), idx, strings.ToLower(prefix)) + if _, err := os.Stat(base); err != nil { + return + } + variable := strings.ReplaceAll(base, ".", "_") + index := "" + if variants { + index = fmt.Sprintf("[%d]", idx) + } + fmt.Fprintf(out, "\t\tShader_%s%s.%s = %s\n", name, index, field, variable) + } + fmt.Fprintf(out, "func init() {\n") + fmt.Fprintf(out, "\tconst (\n") + fmt.Fprintf(out, "\t\topengles = %s\n", geeseExpr("linux", "freebsd", "openbsd", "windows", "js", "android", "darwin", "ios")) + fmt.Fprintf(out, "\t\topengl = %s\n", geeseExpr("darwin")) + fmt.Fprintf(out, "\t\td3d11 = %s\n", geeseExpr("windows")) + fmt.Fprintf(out, "\t\tvulkan = %s\n", geeseExpr("linux", "android")) + fmt.Fprintf(out, "\t)\n") + for _, r := range shaderResults { + variants := len(r.Shaders) > 1 + for i, src := range r.Shaders { + fmt.Fprintf(out, "\tif vulkan {\n") + writeInit(src.SPIRV, "SPIRV", "SPIRV", r.Path, i, variants) + fmt.Fprintf(out, "\t}\n") + fmt.Fprintf(out, "\tif opengles {\n") + writeInit(src.GLSL100ES, "GLSL100ES", "GLSL100ES", r.Path, i, variants) + fmt.Fprintf(out, "\t}\n") + fmt.Fprintf(out, "\tif opengl {\n") + writeInit(src.GLSL150, "GLSL150", "GLSL150", r.Path, i, variants) + fmt.Fprintf(out, "\t}\n") + fmt.Fprintf(out, "\tif d3d11 {\n") + writeInit(src.DXBC, "DXBC", "DXBC", r.Path, i, variants) + fmt.Fprintf(out, "\t}\n") + fmt.Fprintf(out, "\tif runtime.GOOS == \"darwin\" {\n") + writeInit(src.MetalLibs.MacOS, "MetalLibMacOS", "MetalLib", r.Path, i, variants) + fmt.Fprintf(out, "\t}\n") + fmt.Fprintf(out, "\tif runtime.GOOS == \"ios\" {\n") + fmt.Fprintf(out, "if runtime.GOARCH == \"amd64\" {\n") + writeInit(src.MetalLibs.IOSSimulator, "MetalLibIOSSimulator", "MetalLib", r.Path, i, variants) + fmt.Fprintf(out, "\t\t} else {\n") + writeInit(src.MetalLibs.IOS, "MetalLibIOS", "MetalLib", r.Path, i, variants) + fmt.Fprintf(out, "\t\t}\n") + fmt.Fprintf(out, "\t}\n") + } + } + fmt.Fprintf(out, "}\n") + + return genErr +} + +func geeseExpr(geese ...string) string { + var checks []string + for _, goos := range geese { + checks = append(checks, fmt.Sprintf("runtime.GOOS == %q", goos)) + } + return strings.Join(checks, " || ") +} + +func (conv *Converter) Shader(shaderPath string) ([]shaderSources, error) { + type Variant struct { + FetchColorExpr string + Header string + } + variantArgs := [...]Variant{ + { + FetchColorExpr: `_color.color`, + Header: `layout(push_constant) uniform Color { layout(offset=112) vec4 color; } _color;`, + }, + { + FetchColorExpr: `mix(_gradient.color1, _gradient.color2, clamp(vUV.x, 0.0, 1.0))`, + Header: `layout(push_constant) uniform Gradient { layout(offset=96) vec4 color1; vec4 color2; } _gradient;`, + }, + { + FetchColorExpr: `texture(tex, vUV)`, + Header: `layout(binding=0) uniform sampler2D tex;`, + }, + } + + shaderTemplate, err := template.ParseFiles(shaderPath) + if err != nil { + return nil, fmt.Errorf("failed to parse template %q: %w", shaderPath, err) + } + + var variants []shaderSources + for i, variantArg := range variantArgs { + variantName := strconv.Itoa(i) + var buf bytes.Buffer + err := shaderTemplate.Execute(&buf, variantArg) + if err != nil { + return nil, fmt.Errorf("failed to execute template %q with %#v: %w", shaderPath, variantArg, err) + } + + var sources shaderSources + sources.Name = filepath.Base(shaderPath) + + src := buf.Bytes() + sources.SPIRV, err = conv.glslvalidator.Convert(shaderPath, variantName, "vulkan", src) + if err != nil { + return nil, fmt.Errorf("failed to generate SPIR-V for %q: %w", shaderPath, err) + } + + sources.SPIRV, err = spirvOpt(sources.SPIRV) + if err != nil { + return nil, fmt.Errorf("failed to optimize SPIR-V for %q: %w", shaderPath, err) + } + + var reflect Metadata + sources.GLSL100ES, reflect, err = conv.ShaderVariant(shaderPath, variantName, src, "es", "100") + if err != nil { + return nil, fmt.Errorf("failed to convert GLSL100ES:\n%w", err) + } + + metal, _, err := conv.ShaderVariant(shaderPath, variantName, src, "msl", "10000") + if err != nil { + return nil, fmt.Errorf("failed to convert to Metal:\n%w", err) + } + + metalIOS, _, err := conv.ShaderVariant(shaderPath, variantName, src, "mslios", "10000") + if err != nil { + return nil, fmt.Errorf("failed to convert to Metal:\n%w", err) + } + + sources.MetalLibs, err = conv.msl.Compile(shaderPath, variantName, metal, metalIOS) + if err != nil { + if !errors.Is(err, exec.ErrNotFound) { + return nil, fmt.Errorf("failed to build .metallib library:\n%w", err) + } + } + + hlsl, _, err := conv.ShaderVariant(shaderPath, variantName, src, "hlsl", "40") + if err != nil { + return nil, fmt.Errorf("failed to convert HLSL:\n%w", err) + } + + sources.DXBC, err = conv.fxc.Compile(shaderPath, variantName, []byte(hlsl), "main", "4_0_level_9_1") + if err != nil { + // Attempt shader model 4.0. Only the gpu/headless + // test shaders use features not supported by level + // 9.1. + sources.DXBC, err = conv.fxc.Compile(shaderPath, variantName, []byte(hlsl), "main", "4_0") + if err != nil { + if !errors.Is(err, exec.ErrNotFound) { + return nil, fmt.Errorf("failed to compile HLSL: %w", err) + } + } + } + + sources.GLSL150, _, err = conv.ShaderVariant(shaderPath, variantName, src, "glsl", "150") + if err != nil { + return nil, fmt.Errorf("failed to convert GLSL150:\n%w", err) + } + + sources.Reflect = reflect + + variants = append(variants, sources) + } + + // If the shader don't use the variant arguments, output only a single version. + if bytes.Equal(variants[0].GLSL100ES, variants[1].GLSL100ES) { + variants = variants[:1] + } + + return variants, nil +} + +func (conv *Converter) ShaderVariant(shaderPath, variant string, src []byte, lang, profile string) ([]byte, Metadata, error) { + spirv, err := conv.glslvalidator.Convert(shaderPath, variant, lang, src) + if err != nil { + return nil, Metadata{}, fmt.Errorf("failed to generate SPIR-V for %q: %w", shaderPath, err) + } + + dst, err := conv.spirv.Convert(shaderPath, variant, spirv, lang, profile) + if err != nil { + return nil, Metadata{}, fmt.Errorf("failed to convert shader %q: %w", shaderPath, err) + } + + meta, err := conv.spirv.Metadata(shaderPath, variant, spirv) + if err != nil { + return nil, Metadata{}, fmt.Errorf("failed to extract metadata for shader %q: %w", shaderPath, err) + } + + return dst, meta, nil +} + +func (conv *Converter) ComputeShader(shaderPath string) ([]shaderSources, error) { + sh, err := ioutil.ReadFile(shaderPath) + if err != nil { + return nil, fmt.Errorf("failed to load shader %q: %w", shaderPath, err) + } + + sources := shaderSources{ + Name: filepath.Base(shaderPath), + } + spirv, err := conv.glslvalidator.Convert(shaderPath, "", "glsl", sh) + if err != nil { + return nil, fmt.Errorf("failed to convert compute shader %q: %w", shaderPath, err) + } + + sources.SPIRV, err = spirvOpt(spirv) + if err != nil { + return nil, fmt.Errorf("failed to optimize SPIR-V for %q: %w", shaderPath, err) + } + + meta, err := conv.spirv.Metadata(shaderPath, "", spirv) + if err != nil { + return nil, fmt.Errorf("failed to extract metadata for shader %q: %w", shaderPath, err) + } + sources.Reflect = meta + + metal, err := conv.spirv.Convert(shaderPath, "", spirv, "msl", "10000") + if err != nil { + return nil, fmt.Errorf("failed to convert GLSL130:\n%w", err) + } + + metalIOS, err := conv.spirv.Convert(shaderPath, "", spirv, "mslios", "10000") + if err != nil { + return nil, fmt.Errorf("failed to convert GLSL130:\n%w", err) + } + + sources.MetalLibs, err = conv.msl.Compile(shaderPath, "", metal, metalIOS) + if err != nil { + if !errors.Is(err, exec.ErrNotFound) { + return nil, fmt.Errorf("failed to build .metallib library:\n%w", err) + } + } + + hlslSource, err := conv.spirv.Convert(shaderPath, "", spirv, "hlsl", "50") + if err != nil { + return nil, fmt.Errorf("failed to convert hlsl compute shader %q: %w", shaderPath, err) + } + + sources.DXBC, err = conv.fxc.Compile(shaderPath, "0", []byte(hlslSource), "main", "5_0") + if err != nil { + if !errors.Is(err, exec.ErrNotFound) { + return nil, fmt.Errorf("failed to compile hlsl compute shader %q: %w", shaderPath, err) + } + } + + return []shaderSources{sources}, nil +} + +// Workers implements wait group with synchronous logging. +type Workers struct { + running sync.WaitGroup +} + +func (lg *Workers) Go(fn func()) { + lg.running.Add(1) + go func() { + defer lg.running.Done() + fn() + }() +} + +func (lg *Workers) Wait() { + lg.running.Wait() +} + +func unixLineEnding(s []byte) []byte { + return bytes.ReplaceAll(s, []byte("\r\n"), []byte("\n")) +} diff --git a/gio/shader/cmd/convertshaders/msl.go b/gio/shader/cmd/convertshaders/msl.go new file mode 100644 index 0000000..c97dba3 --- /dev/null +++ b/gio/shader/cmd/convertshaders/msl.go @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package main + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" +) + +// MSL is hlsl compiler that targets the Metal shading language +type MSL struct { + WorkDir WorkDir +} + +// MetalLibs contains compiled .metallib programs for all supported platforms. +type MetalLibs struct { + MacOS []byte + IOS []byte + IOSSimulator []byte +} + +// Compile compiles the input .metal program and converts it into .metallib libraries. +func (msl *MSL) Compile(path, variant string, src, srcIOS []byte) (MetalLibs, error) { + base := msl.WorkDir.Path(filepath.Base(path), variant) + pathinMacOS := base + ".macos.metal" + pathinIOS := base + ".ios.metal" + + var libs MetalLibs + if err := msl.WorkDir.WriteFile(pathinMacOS, []byte(src)); err != nil { + return libs, fmt.Errorf("unable to write shader to disk: %w", err) + } + if err := msl.WorkDir.WriteFile(pathinIOS, []byte(srcIOS)); err != nil { + return libs, fmt.Errorf("unable to write shader to disk: %w", err) + } + + var err error + libs.MacOS, err = msl.compileFor("macosx", "-mmacosx-version-min=10.11", pathinMacOS) + if err != nil { + return libs, err + } + libs.IOS, err = msl.compileFor("iphoneos", "-mios-version-min=10.0", pathinIOS) + if err != nil { + return libs, err + } + libs.IOSSimulator, err = msl.compileFor("iphonesimulator", "-miphonesimulator-version-min=8.0", pathinIOS) + if err != nil { + return libs, err + } + + return libs, nil +} + +// compileFor compiles the input .metal program and converts it into a +// .metallib library for a particular SDK. +func (msl *MSL) compileFor(sdk, minVer, path string) ([]byte, error) { + var metal *exec.Cmd + + pathout := path + ".metallib" + result := pathout + + if runtime.GOOS == "darwin" { + metal = exec.Command("xcrun", "--sdk", sdk, "metal") + } else { + sdkDir := os.Getenv("METAL_SDK_ROOT") + if sdkDir == "" { + return nil, exec.ErrNotFound + } + switch sdk { + case "macosx": + sdkDir = filepath.Join(sdkDir, "macos") + case "iphoneos", "iphonesimulator": + sdkDir = filepath.Join(sdkDir, "ios") + default: + panic("unknown sdk") + } + bin := filepath.Join(sdkDir, "bin", "metal.exe") + if runtime.GOOS == "windows" { + metal = exec.Command(bin) + } else { + if err := winepath(&path, &pathout); err != nil { + return nil, err + } + metal = exec.Command("wine", bin) + } + } + + metal.Args = append(metal.Args, + minVer, + "-o", pathout, + path, + ) + + output, err := metal.CombinedOutput() + if err != nil { + return nil, fmt.Errorf("%s\nfailed to run %v: %w", output, metal.Args, err) + } + + compiled, err := ioutil.ReadFile(result) + if err != nil { + return nil, fmt.Errorf("unable to read output %q: %w", pathout, err) + } + + return compiled, nil +} diff --git a/gio/shader/cmd/convertshaders/spirvcross.go b/gio/shader/cmd/convertshaders/spirvcross.go new file mode 100644 index 0000000..a55e05e --- /dev/null +++ b/gio/shader/cmd/convertshaders/spirvcross.go @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package main + +import ( + "encoding/json" + "fmt" + "math" + "os/exec" + "path/filepath" + "sort" + + "gioui.org/shader" +) + +// Metadata contains reflection data about a shader. +type Metadata struct { + Uniforms shader.UniformsReflection + Inputs []shader.InputLocation + Textures []shader.TextureBinding + Images []shader.ImageBinding + StorageBuffers []shader.BufferBinding + WorkgroupSize [3]int +} + +// SPIRVCross cross-compiles spirv shaders to es, hlsl and others. +type SPIRVCross struct { + Bin string + WorkDir WorkDir +} + +func NewSPIRVCross() *SPIRVCross { return &SPIRVCross{Bin: "spirv-cross"} } + +// Convert converts compute shader from spirv format to a target format. +func (spirv *SPIRVCross) Convert(path, variant string, shader []byte, target, version string) ([]byte, error) { + base := spirv.WorkDir.Path(filepath.Base(path), variant) + + if err := spirv.WorkDir.WriteFile(base, shader); err != nil { + return nil, fmt.Errorf("unable to write shader to disk: %w", err) + } + + var cmd *exec.Cmd + switch target { + case "glsl": + cmd = exec.Command(spirv.Bin, + "--no-es", + "--version", version, + ) + case "es": + cmd = exec.Command(spirv.Bin, + "--es", + "--version", version, + ) + case "hlsl": + cmd = exec.Command(spirv.Bin, + "--hlsl", + "--shader-model", version, + ) + case "msl", "mslios": + cmd = exec.Command(spirv.Bin, + "--msl", + "--msl-decoration-binding", + "--msl-version", version, + ) + if target == "mslios" { + cmd.Args = append(cmd.Args, "--msl-ios") + } + default: + return nil, fmt.Errorf("unknown target %q", target) + } + cmd.Args = append(cmd.Args, "--no-420pack-extension", base) + + out, err := cmd.CombinedOutput() + if err != nil { + return nil, fmt.Errorf("%s\nfailed to run %v: %w", out, cmd.Args, err) + } + if target != "hlsl" { + // Strip Windows \r in line endings. + out = unixLineEnding(out) + } + + return out, nil +} + +// Metadata extracts metadata for a SPIR-V shader. +func (spirv *SPIRVCross) Metadata(path, variant string, shader []byte) (Metadata, error) { + base := spirv.WorkDir.Path(filepath.Base(path), variant) + + if err := spirv.WorkDir.WriteFile(base, shader); err != nil { + return Metadata{}, fmt.Errorf("unable to write shader to disk: %w", err) + } + + cmd := exec.Command(spirv.Bin, + base, + "--reflect", + ) + + out, err := cmd.Output() + if err != nil { + return Metadata{}, fmt.Errorf("failed to run %v: %w", cmd.Args, err) + } + + meta, err := parseMetadata(out) + if err != nil { + return Metadata{}, fmt.Errorf("%s\nfailed to parse metadata: %w", out, err) + } + + return meta, nil +} + +func parseMetadata(data []byte) (Metadata, error) { + var reflect struct { + Types map[string]struct { + Name string `json:"name"` + Members []struct { + Name string `json:"name"` + Type string `json:"type"` + Offset int `json:"offset"` + } `json:"members"` + } `json:"types"` + Inputs []struct { + Name string `json:"name"` + Type string `json:"type"` + Location int `json:"location"` + } `json:"inputs"` + Textures []struct { + Name string `json:"name"` + Type string `json:"type"` + Set int `json:"set"` + Binding int `json:"binding"` + } `json:"textures"` + UBOs []struct { + Name string `json:"name"` + Type string `json:"type"` + BlockSize int `json:"block_size"` + Set int `json:"set"` + Binding int `json:"binding"` + } `json:"ubos"` + PushConstants []struct { + Name string `json:"name"` + Type string `json:"type"` + PushConstant bool `json:"push_constant"` + } `json:"push_constants"` + EntryPoints []struct { + Name string `json:"name"` + Mode string `json:"mode"` + WorkgroupSize [3]int `json:"workgroup_size"` + } `json:"entryPoints"` + StorageBuffers []struct { + Name string `json:"name"` + Type string `json:"type"` + Binding int `json:"binding"` + } `json:"ssbos"` + Images []struct { + Name string `json:"name"` + Type string `json:"type"` + Binding int `json:"binding"` + } `json:"images"` + } + if err := json.Unmarshal(data, &reflect); err != nil { + return Metadata{}, fmt.Errorf("failed to parse reflection data: %w", err) + } + + var m Metadata + + for _, input := range reflect.Inputs { + dataType, dataSize, err := parseDataType(input.Type) + if err != nil { + return Metadata{}, fmt.Errorf("parseReflection: %v", err) + } + m.Inputs = append(m.Inputs, shader.InputLocation{ + Name: input.Name, + Location: input.Location, + Semantic: "TEXCOORD", + SemanticIndex: input.Location, + Type: dataType, + Size: dataSize, + }) + } + + sort.Slice(m.Inputs, func(i, j int) bool { + return m.Inputs[i].Location < m.Inputs[j].Location + }) + + blockSize := 0 + minOffset := math.MaxInt + for _, block := range reflect.PushConstants { + t := reflect.Types[block.Type] + for _, member := range t.Members { + dataType, size, err := parseDataType(member.Type) + if err != nil { + return Metadata{}, fmt.Errorf("failed to parse reflection data: %v", err) + } + blockSize += size * 4 + if member.Offset < minOffset { + minOffset = member.Offset + } + m.Uniforms.Locations = append(m.Uniforms.Locations, shader.UniformLocation{ + Name: fmt.Sprintf("%s.%s", block.Name, member.Name), + Type: dataType, + Size: size, + Offset: member.Offset, + }) + } + } + m.Uniforms.Size = blockSize + + for _, texture := range reflect.Textures { + m.Textures = append(m.Textures, shader.TextureBinding{ + Name: texture.Name, + Binding: texture.Binding, + }) + } + + for _, img := range reflect.Images { + m.Images = append(m.Images, shader.ImageBinding{ + Name: img.Name, + Binding: img.Binding, + }) + } + + for _, sb := range reflect.StorageBuffers { + m.StorageBuffers = append(m.StorageBuffers, shader.BufferBinding{ + Name: sb.Name, + Binding: sb.Binding, + }) + } + + for _, e := range reflect.EntryPoints { + if e.Name == "main" && e.Mode == "comp" { + m.WorkgroupSize = e.WorkgroupSize + } + } + + return m, nil +} + +func parseDataType(t string) (shader.DataType, int, error) { + switch t { + case "float": + return shader.DataTypeFloat, 1, nil + case "vec2": + return shader.DataTypeFloat, 2, nil + case "vec3": + return shader.DataTypeFloat, 3, nil + case "vec4": + return shader.DataTypeFloat, 4, nil + case "int": + return shader.DataTypeInt, 1, nil + case "int2": + return shader.DataTypeInt, 2, nil + case "int3": + return shader.DataTypeInt, 3, nil + case "int4": + return shader.DataTypeInt, 4, nil + default: + return 0, 0, fmt.Errorf("unsupported input data type: %s", t) + } +} diff --git a/gio/shader/cmd/convertshaders/workdir.go b/gio/shader/cmd/convertshaders/workdir.go new file mode 100644 index 0000000..4c1c092 --- /dev/null +++ b/gio/shader/cmd/convertshaders/workdir.go @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package main + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" +) + +type WorkDir string + +func (wd WorkDir) Dir(path string) WorkDir { + dirname := filepath.Join(string(wd), path) + if err := os.Mkdir(dirname, 0755); err != nil { + if !os.IsExist(err) { + fmt.Fprintf(os.Stderr, "failed to create %q: %v\n", dirname, err) + } + } + return WorkDir(dirname) +} + +func (wd WorkDir) Path(path ...string) (fullpath string) { + return filepath.Join(string(wd), strings.Join(path, ".")) +} + +func (wd WorkDir) WriteFile(path string, data []byte) error { + err := ioutil.WriteFile(path, data, 0644) + if err != nil { + return fmt.Errorf("unable to create %v: %w", path, err) + } + return nil +} diff --git a/gio/shader/gio/blit.frag b/gio/shader/gio/blit.frag new file mode 100644 index 0000000..a88f4dc --- /dev/null +++ b/gio/shader/gio/blit.frag @@ -0,0 +1,15 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +precision mediump float; + +layout(location=0) in highp vec2 vUV; + +{{.Header}} + +layout(location = 0) out vec4 fragColor; + +void main() { + fragColor = {{.FetchColorExpr}}; +} diff --git a/gio/shader/gio/blit.vert b/gio/shader/gio/blit.vert new file mode 100644 index 0000000..83d041f --- /dev/null +++ b/gio/shader/gio/blit.vert @@ -0,0 +1,27 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +#include "common.h" + +layout(push_constant) uniform Block { + vec4 transform; + vec4 uvTransformR1; + vec4 uvTransformR2; +} _block; + +layout(location = 0) in vec2 pos; + +layout(location = 1) in vec2 uv; + +layout(location = 0) out vec2 vUV; + +void main() { + vec2 p = pos*_block.transform.xy + _block.transform.zw; + gl_Position = vec4(transform3x2(windowTransform, vec3(p, 0)), 1); + vUV = transform3x2(m3x2(_block.uvTransformR1.xyz, _block.uvTransformR2.xyz), vec3(uv,1)).xy; +} diff --git a/gio/shader/gio/common.h b/gio/shader/gio/common.h new file mode 100644 index 0000000..9b6dc59 --- /dev/null +++ b/gio/shader/gio/common.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +struct m3x2 { + vec3 r0; + vec3 r1; +}; + +// fboTransform is the transformation that cancels the implied transformation +// between the clip space and the framebuffer. Only two rows are returned. The +// last is implied to be [0, 0, 1]. +const m3x2 fboTransform = m3x2( +#if defined(LANG_HLSL) || defined(LANG_MSL) || defined(LANG_MSLIOS) + vec3(1.0, 0.0, 0.0), + vec3(0.0, -1.0, 0.0) +#else + vec3(1.0, 0.0, 0.0), + vec3(0.0, 1.0, 0.0) +#endif +); + +// windowTransform is the transformation that cancels the implied transformation +// between framebuffer space and window system coordinates. +const m3x2 windowTransform = m3x2( +#if defined(LANG_VULKAN) + vec3(1.0, 0.0, 0.0), + vec3(0.0, 1.0, 0.0) +#else + vec3(1.0, 0.0, 0.0), + vec3(0.0, -1.0, 0.0) +#endif +); + +vec3 transform3x2(m3x2 t, vec3 v) { + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} diff --git a/gio/shader/gio/copy.frag b/gio/shader/gio/copy.frag new file mode 100644 index 0000000..048d9e7 --- /dev/null +++ b/gio/shader/gio/copy.frag @@ -0,0 +1,24 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +precision mediump float; + +layout(binding = 0) uniform sampler2D tex; + +layout(location = 0) in highp vec2 vUV; + +layout(location = 0) out vec4 fragColor; + +vec3 sRGBtoRGB(vec3 rgb) { + bvec3 cutoff = greaterThanEqual(rgb, vec3(0.04045)); + vec3 below = rgb/vec3(12.92); + vec3 above = pow((rgb + vec3(0.055))/vec3(1.055), vec3(2.4)); + return mix(below, above, cutoff); +} + +void main() { + vec4 texel = texture(tex, vUV); + texel.rgb = sRGBtoRGB(texel.rgb); + fragColor = texel; +} diff --git a/gio/shader/gio/copy.vert b/gio/shader/gio/copy.vert new file mode 100644 index 0000000..c079b96 --- /dev/null +++ b/gio/shader/gio/copy.vert @@ -0,0 +1,26 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +#include "common.h" + +layout(push_constant) uniform Block { + vec2 scale; + vec2 pos; + vec2 uvScale; +} _block; + +layout(location = 0) in vec2 pos; +layout(location = 1) in vec2 uv; + +layout(location = 0) out vec2 vUV; + +void main() { + vUV = vec2(uv*_block.uvScale); + vec2 p = vec2(pos*_block.scale + _block.pos); + gl_Position = vec4(transform3x2(windowTransform, vec3(p, 0)), 1); +} diff --git a/gio/shader/gio/cover.frag b/gio/shader/gio/cover.frag new file mode 100644 index 0000000..34c5e4c --- /dev/null +++ b/gio/shader/gio/cover.frag @@ -0,0 +1,20 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +precision mediump float; + +{{.Header}} + +layout(location = 0) in highp vec2 vCoverUV; +layout(location = 1) in highp vec2 vUV; + +layout(binding = 1) uniform sampler2D cover; + +layout(location = 0) out vec4 fragColor; + +void main() { + fragColor = {{.FetchColorExpr}}; + float c = min(abs(texture(cover, vCoverUV).r), 1.0); + fragColor *= c; +} diff --git a/gio/shader/gio/cover.vert b/gio/shader/gio/cover.vert new file mode 100644 index 0000000..02fae50 --- /dev/null +++ b/gio/shader/gio/cover.vert @@ -0,0 +1,31 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +#include "common.h" + +layout(push_constant) uniform Block { + vec4 transform; + vec4 uvCoverTransform; + vec4 uvTransformR1; + vec4 uvTransformR2; +} _block; + +layout(location = 0) in vec2 pos; + +layout(location = 0) out vec2 vCoverUV; + +layout(location = 1) in vec2 uv; +layout(location = 1) out vec2 vUV; + +void main() { + vec2 p = vec2(pos*_block.transform.xy + _block.transform.zw); + gl_Position = vec4(transform3x2(windowTransform, vec3(p, 0)), 1); + vUV = transform3x2(m3x2(_block.uvTransformR1.xyz, _block.uvTransformR2.xyz), vec3(uv,1)).xy; + vec3 uv3 = vec3(uv, 1.0); + vCoverUV = (uv3*vec3(_block.uvCoverTransform.xy, 1.0)+vec3(_block.uvCoverTransform.zw, 0.0)).xy; +} diff --git a/gio/shader/gio/gen.go b/gio/shader/gio/gen.go new file mode 100644 index 0000000..f26056a --- /dev/null +++ b/gio/shader/gio/gen.go @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package gio + +//go:generate go run ../cmd/convertshaders -package gio -dir . diff --git a/gio/shader/gio/input.vert b/gio/shader/gio/input.vert new file mode 100644 index 0000000..3d0cd50 --- /dev/null +++ b/gio/shader/gio/input.vert @@ -0,0 +1,15 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +#include "common.h" + +layout(location=0) in vec4 position; + +void main() { + gl_Position = vec4(transform3x2(windowTransform, position.xyz), position.w); +} diff --git a/gio/shader/gio/intersect.frag b/gio/shader/gio/intersect.frag new file mode 100644 index 0000000..21a126f --- /dev/null +++ b/gio/shader/gio/intersect.frag @@ -0,0 +1,15 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +precision mediump float; + +layout(location = 0) in highp vec2 vUV; + +layout(binding = 0) uniform sampler2D cover; + +layout(location = 0) out vec4 fragColor; + +void main() { + fragColor.r = abs(texture(cover, vUV).r); +} diff --git a/gio/shader/gio/intersect.vert b/gio/shader/gio/intersect.vert new file mode 100644 index 0000000..e7ee2fe --- /dev/null +++ b/gio/shader/gio/intersect.vert @@ -0,0 +1,26 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +#include "common.h" + +layout(location = 0) in vec2 pos; +layout(location = 1) in vec2 uv; + +layout(push_constant) uniform Block { + vec4 uvTransform; + vec4 subUVTransform; +} _block; + +layout(location = 0) out vec2 vUV; + +void main() { + vec3 p = transform3x2(fboTransform, vec3(pos, 1.0)); + gl_Position = vec4(p, 1); + vUV = uv.xy*_block.subUVTransform.xy + _block.subUVTransform.zw; + vUV = vUV*_block.uvTransform.xy + _block.uvTransform.zw; +} diff --git a/gio/shader/gio/material.frag b/gio/shader/gio/material.frag new file mode 100644 index 0000000..489461e --- /dev/null +++ b/gio/shader/gio/material.frag @@ -0,0 +1,32 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +precision mediump float; + +layout(binding = 0) uniform sampler2D tex; + +layout(location = 0) in highp vec2 vUV; + +layout(location = 0) out vec4 fragColor; + +layout(push_constant) uniform Color { + // If emulateSRGB is set (!= 0), the input texels are sRGB encoded. We save the + // conversion step below, at the cost of texture filtering in sRGB space. + layout(offset=16) float emulateSRGB; +} _color; + +vec3 RGBtosRGB(vec3 rgb) { + bvec3 cutoff = greaterThanEqual(rgb, vec3(0.0031308)); + vec3 below = vec3(12.92)*rgb; + vec3 above = vec3(1.055)*pow(rgb, vec3(0.41666)) - vec3(0.055); + return mix(below, above, cutoff); +} + +void main() { + vec4 texel = texture(tex, vUV); + if (_color.emulateSRGB == 0.0) { + texel.rgb = RGBtosRGB(texel.rgb); + } + fragColor = texel; +} diff --git a/gio/shader/gio/material.vert b/gio/shader/gio/material.vert new file mode 100644 index 0000000..22c41a0 --- /dev/null +++ b/gio/shader/gio/material.vert @@ -0,0 +1,25 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +#include "common.h" + +layout(push_constant) uniform Block { + vec2 scale; + vec2 pos; +} _block; + +layout(location = 0) in vec2 pos; +layout(location = 1) in vec2 uv; + +layout(location = 0) out vec2 vUV; + +void main() { + vUV = uv; + vec2 p = vec2(pos*_block.scale + _block.pos); + gl_Position = vec4(transform3x2(fboTransform, vec3(p, 0)), 1); +} diff --git a/gio/shader/gio/shaders.go b/gio/shader/gio/shaders.go new file mode 100644 index 0000000..1166c1c --- /dev/null +++ b/gio/shader/gio/shaders.go @@ -0,0 +1,796 @@ +// Code generated by build.go. DO NOT EDIT. + +package gio + +import ( + _ "embed" + "runtime" + + "gioui.org/shader" +) + +var ( + Shader_blit_frag = [...]shader.Sources{ + { + Name: "blit.frag", + Inputs: []shader.InputLocation{{Name: "vUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_color.color", Type: 0x0, Size: 4, Offset: 112}}, + Size: 16, + }, + }, + { + Name: "blit.frag", + Inputs: []shader.InputLocation{{Name: "vUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_gradient.color1", Type: 0x0, Size: 4, Offset: 96}, {Name: "_gradient.color2", Type: 0x0, Size: 4, Offset: 112}}, + Size: 32, + }, + }, + { + Name: "blit.frag", + Inputs: []shader.InputLocation{{Name: "vUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}}, + Textures: []shader.TextureBinding{{Name: "tex", Binding: 0}}, + }, + } + //go:embed zblit.frag.0.spirv + zblit_frag_0_spirv string + //go:embed zblit.frag.0.glsl100es + zblit_frag_0_glsl100es string + //go:embed zblit.frag.0.glsl150 + zblit_frag_0_glsl150 string + //go:embed zblit.frag.0.dxbc + zblit_frag_0_dxbc string + //go:embed zblit.frag.0.metallibmacos + zblit_frag_0_metallibmacos string + //go:embed zblit.frag.0.metallibios + zblit_frag_0_metallibios string + //go:embed zblit.frag.0.metallibiossimulator + zblit_frag_0_metallibiossimulator string + //go:embed zblit.frag.1.spirv + zblit_frag_1_spirv string + //go:embed zblit.frag.1.glsl100es + zblit_frag_1_glsl100es string + //go:embed zblit.frag.1.glsl150 + zblit_frag_1_glsl150 string + //go:embed zblit.frag.1.dxbc + zblit_frag_1_dxbc string + //go:embed zblit.frag.1.metallibmacos + zblit_frag_1_metallibmacos string + //go:embed zblit.frag.1.metallibios + zblit_frag_1_metallibios string + //go:embed zblit.frag.1.metallibiossimulator + zblit_frag_1_metallibiossimulator string + //go:embed zblit.frag.2.spirv + zblit_frag_2_spirv string + //go:embed zblit.frag.2.glsl100es + zblit_frag_2_glsl100es string + //go:embed zblit.frag.2.glsl150 + zblit_frag_2_glsl150 string + //go:embed zblit.frag.2.dxbc + zblit_frag_2_dxbc string + //go:embed zblit.frag.2.metallibmacos + zblit_frag_2_metallibmacos string + //go:embed zblit.frag.2.metallibios + zblit_frag_2_metallibios string + //go:embed zblit.frag.2.metallibiossimulator + zblit_frag_2_metallibiossimulator string + Shader_blit_vert = shader.Sources{ + Name: "blit.vert", + Inputs: []shader.InputLocation{{Name: "pos", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}, {Name: "uv", Location: 1, Semantic: "TEXCOORD", SemanticIndex: 1, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_block.transform", Type: 0x0, Size: 4, Offset: 0}, {Name: "_block.uvTransformR1", Type: 0x0, Size: 4, Offset: 16}, {Name: "_block.uvTransformR2", Type: 0x0, Size: 4, Offset: 32}}, + Size: 48, + }, + } + //go:embed zblit.vert.0.spirv + zblit_vert_0_spirv string + //go:embed zblit.vert.0.glsl100es + zblit_vert_0_glsl100es string + //go:embed zblit.vert.0.glsl150 + zblit_vert_0_glsl150 string + //go:embed zblit.vert.0.dxbc + zblit_vert_0_dxbc string + //go:embed zblit.vert.0.metallibmacos + zblit_vert_0_metallibmacos string + //go:embed zblit.vert.0.metallibios + zblit_vert_0_metallibios string + //go:embed zblit.vert.0.metallibiossimulator + zblit_vert_0_metallibiossimulator string + Shader_copy_frag = shader.Sources{ + Name: "copy.frag", + Inputs: []shader.InputLocation{{Name: "vUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}}, + Textures: []shader.TextureBinding{{Name: "tex", Binding: 0}}, + } + //go:embed zcopy.frag.0.spirv + zcopy_frag_0_spirv string + //go:embed zcopy.frag.0.glsl100es + zcopy_frag_0_glsl100es string + //go:embed zcopy.frag.0.glsl150 + zcopy_frag_0_glsl150 string + //go:embed zcopy.frag.0.dxbc + zcopy_frag_0_dxbc string + //go:embed zcopy.frag.0.metallibmacos + zcopy_frag_0_metallibmacos string + //go:embed zcopy.frag.0.metallibios + zcopy_frag_0_metallibios string + //go:embed zcopy.frag.0.metallibiossimulator + zcopy_frag_0_metallibiossimulator string + Shader_copy_vert = shader.Sources{ + Name: "copy.vert", + Inputs: []shader.InputLocation{{Name: "pos", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}, {Name: "uv", Location: 1, Semantic: "TEXCOORD", SemanticIndex: 1, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_block.scale", Type: 0x0, Size: 2, Offset: 0}, {Name: "_block.pos", Type: 0x0, Size: 2, Offset: 8}, {Name: "_block.uvScale", Type: 0x0, Size: 2, Offset: 16}}, + Size: 24, + }, + } + //go:embed zcopy.vert.0.spirv + zcopy_vert_0_spirv string + //go:embed zcopy.vert.0.glsl100es + zcopy_vert_0_glsl100es string + //go:embed zcopy.vert.0.glsl150 + zcopy_vert_0_glsl150 string + //go:embed zcopy.vert.0.dxbc + zcopy_vert_0_dxbc string + //go:embed zcopy.vert.0.metallibmacos + zcopy_vert_0_metallibmacos string + //go:embed zcopy.vert.0.metallibios + zcopy_vert_0_metallibios string + //go:embed zcopy.vert.0.metallibiossimulator + zcopy_vert_0_metallibiossimulator string + Shader_cover_frag = [...]shader.Sources{ + { + Name: "cover.frag", + Inputs: []shader.InputLocation{{Name: "vCoverUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}, {Name: "vUV", Location: 1, Semantic: "TEXCOORD", SemanticIndex: 1, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_color.color", Type: 0x0, Size: 4, Offset: 112}}, + Size: 16, + }, + Textures: []shader.TextureBinding{{Name: "cover", Binding: 1}}, + }, + { + Name: "cover.frag", + Inputs: []shader.InputLocation{{Name: "vCoverUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}, {Name: "vUV", Location: 1, Semantic: "TEXCOORD", SemanticIndex: 1, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_gradient.color1", Type: 0x0, Size: 4, Offset: 96}, {Name: "_gradient.color2", Type: 0x0, Size: 4, Offset: 112}}, + Size: 32, + }, + Textures: []shader.TextureBinding{{Name: "cover", Binding: 1}}, + }, + { + Name: "cover.frag", + Inputs: []shader.InputLocation{{Name: "vCoverUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}, {Name: "vUV", Location: 1, Semantic: "TEXCOORD", SemanticIndex: 1, Type: 0x0, Size: 2}}, + Textures: []shader.TextureBinding{{Name: "tex", Binding: 0}, {Name: "cover", Binding: 1}}, + }, + } + //go:embed zcover.frag.0.spirv + zcover_frag_0_spirv string + //go:embed zcover.frag.0.glsl100es + zcover_frag_0_glsl100es string + //go:embed zcover.frag.0.glsl150 + zcover_frag_0_glsl150 string + //go:embed zcover.frag.0.dxbc + zcover_frag_0_dxbc string + //go:embed zcover.frag.0.metallibmacos + zcover_frag_0_metallibmacos string + //go:embed zcover.frag.0.metallibios + zcover_frag_0_metallibios string + //go:embed zcover.frag.0.metallibiossimulator + zcover_frag_0_metallibiossimulator string + //go:embed zcover.frag.1.spirv + zcover_frag_1_spirv string + //go:embed zcover.frag.1.glsl100es + zcover_frag_1_glsl100es string + //go:embed zcover.frag.1.glsl150 + zcover_frag_1_glsl150 string + //go:embed zcover.frag.1.dxbc + zcover_frag_1_dxbc string + //go:embed zcover.frag.1.metallibmacos + zcover_frag_1_metallibmacos string + //go:embed zcover.frag.1.metallibios + zcover_frag_1_metallibios string + //go:embed zcover.frag.1.metallibiossimulator + zcover_frag_1_metallibiossimulator string + //go:embed zcover.frag.2.spirv + zcover_frag_2_spirv string + //go:embed zcover.frag.2.glsl100es + zcover_frag_2_glsl100es string + //go:embed zcover.frag.2.glsl150 + zcover_frag_2_glsl150 string + //go:embed zcover.frag.2.dxbc + zcover_frag_2_dxbc string + //go:embed zcover.frag.2.metallibmacos + zcover_frag_2_metallibmacos string + //go:embed zcover.frag.2.metallibios + zcover_frag_2_metallibios string + //go:embed zcover.frag.2.metallibiossimulator + zcover_frag_2_metallibiossimulator string + Shader_cover_vert = shader.Sources{ + Name: "cover.vert", + Inputs: []shader.InputLocation{{Name: "pos", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}, {Name: "uv", Location: 1, Semantic: "TEXCOORD", SemanticIndex: 1, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_block.transform", Type: 0x0, Size: 4, Offset: 0}, {Name: "_block.uvCoverTransform", Type: 0x0, Size: 4, Offset: 16}, {Name: "_block.uvTransformR1", Type: 0x0, Size: 4, Offset: 32}, {Name: "_block.uvTransformR2", Type: 0x0, Size: 4, Offset: 48}}, + Size: 64, + }, + } + //go:embed zcover.vert.0.spirv + zcover_vert_0_spirv string + //go:embed zcover.vert.0.glsl100es + zcover_vert_0_glsl100es string + //go:embed zcover.vert.0.glsl150 + zcover_vert_0_glsl150 string + //go:embed zcover.vert.0.dxbc + zcover_vert_0_dxbc string + //go:embed zcover.vert.0.metallibmacos + zcover_vert_0_metallibmacos string + //go:embed zcover.vert.0.metallibios + zcover_vert_0_metallibios string + //go:embed zcover.vert.0.metallibiossimulator + zcover_vert_0_metallibiossimulator string + Shader_input_vert = shader.Sources{ + Name: "input.vert", + Inputs: []shader.InputLocation{{Name: "position", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 4}}, + } + //go:embed zinput.vert.0.spirv + zinput_vert_0_spirv string + //go:embed zinput.vert.0.glsl100es + zinput_vert_0_glsl100es string + //go:embed zinput.vert.0.glsl150 + zinput_vert_0_glsl150 string + //go:embed zinput.vert.0.dxbc + zinput_vert_0_dxbc string + //go:embed zinput.vert.0.metallibmacos + zinput_vert_0_metallibmacos string + //go:embed zinput.vert.0.metallibios + zinput_vert_0_metallibios string + //go:embed zinput.vert.0.metallibiossimulator + zinput_vert_0_metallibiossimulator string + Shader_intersect_frag = shader.Sources{ + Name: "intersect.frag", + Inputs: []shader.InputLocation{{Name: "vUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}}, + Textures: []shader.TextureBinding{{Name: "cover", Binding: 0}}, + } + //go:embed zintersect.frag.0.spirv + zintersect_frag_0_spirv string + //go:embed zintersect.frag.0.glsl100es + zintersect_frag_0_glsl100es string + //go:embed zintersect.frag.0.glsl150 + zintersect_frag_0_glsl150 string + //go:embed zintersect.frag.0.dxbc + zintersect_frag_0_dxbc string + //go:embed zintersect.frag.0.metallibmacos + zintersect_frag_0_metallibmacos string + //go:embed zintersect.frag.0.metallibios + zintersect_frag_0_metallibios string + //go:embed zintersect.frag.0.metallibiossimulator + zintersect_frag_0_metallibiossimulator string + Shader_intersect_vert = shader.Sources{ + Name: "intersect.vert", + Inputs: []shader.InputLocation{{Name: "pos", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}, {Name: "uv", Location: 1, Semantic: "TEXCOORD", SemanticIndex: 1, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_block.uvTransform", Type: 0x0, Size: 4, Offset: 0}, {Name: "_block.subUVTransform", Type: 0x0, Size: 4, Offset: 16}}, + Size: 32, + }, + } + //go:embed zintersect.vert.0.spirv + zintersect_vert_0_spirv string + //go:embed zintersect.vert.0.glsl100es + zintersect_vert_0_glsl100es string + //go:embed zintersect.vert.0.glsl150 + zintersect_vert_0_glsl150 string + //go:embed zintersect.vert.0.dxbc + zintersect_vert_0_dxbc string + //go:embed zintersect.vert.0.metallibmacos + zintersect_vert_0_metallibmacos string + //go:embed zintersect.vert.0.metallibios + zintersect_vert_0_metallibios string + //go:embed zintersect.vert.0.metallibiossimulator + zintersect_vert_0_metallibiossimulator string + Shader_material_frag = shader.Sources{ + Name: "material.frag", + Inputs: []shader.InputLocation{{Name: "vUV", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_color.emulateSRGB", Type: 0x0, Size: 1, Offset: 16}}, + Size: 4, + }, + Textures: []shader.TextureBinding{{Name: "tex", Binding: 0}}, + } + //go:embed zmaterial.frag.0.spirv + zmaterial_frag_0_spirv string + //go:embed zmaterial.frag.0.glsl100es + zmaterial_frag_0_glsl100es string + //go:embed zmaterial.frag.0.glsl150 + zmaterial_frag_0_glsl150 string + //go:embed zmaterial.frag.0.dxbc + zmaterial_frag_0_dxbc string + //go:embed zmaterial.frag.0.metallibmacos + zmaterial_frag_0_metallibmacos string + //go:embed zmaterial.frag.0.metallibios + zmaterial_frag_0_metallibios string + //go:embed zmaterial.frag.0.metallibiossimulator + zmaterial_frag_0_metallibiossimulator string + Shader_material_vert = shader.Sources{ + Name: "material.vert", + Inputs: []shader.InputLocation{{Name: "pos", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}, {Name: "uv", Location: 1, Semantic: "TEXCOORD", SemanticIndex: 1, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_block.scale", Type: 0x0, Size: 2, Offset: 0}, {Name: "_block.pos", Type: 0x0, Size: 2, Offset: 8}}, + Size: 16, + }, + } + //go:embed zmaterial.vert.0.spirv + zmaterial_vert_0_spirv string + //go:embed zmaterial.vert.0.glsl100es + zmaterial_vert_0_glsl100es string + //go:embed zmaterial.vert.0.glsl150 + zmaterial_vert_0_glsl150 string + //go:embed zmaterial.vert.0.dxbc + zmaterial_vert_0_dxbc string + //go:embed zmaterial.vert.0.metallibmacos + zmaterial_vert_0_metallibmacos string + //go:embed zmaterial.vert.0.metallibios + zmaterial_vert_0_metallibios string + //go:embed zmaterial.vert.0.metallibiossimulator + zmaterial_vert_0_metallibiossimulator string + Shader_simple_frag = shader.Sources{ + Name: "simple.frag", + } + //go:embed zsimple.frag.0.spirv + zsimple_frag_0_spirv string + //go:embed zsimple.frag.0.glsl100es + zsimple_frag_0_glsl100es string + //go:embed zsimple.frag.0.glsl150 + zsimple_frag_0_glsl150 string + //go:embed zsimple.frag.0.dxbc + zsimple_frag_0_dxbc string + //go:embed zsimple.frag.0.metallibmacos + zsimple_frag_0_metallibmacos string + //go:embed zsimple.frag.0.metallibios + zsimple_frag_0_metallibios string + //go:embed zsimple.frag.0.metallibiossimulator + zsimple_frag_0_metallibiossimulator string + Shader_stencil_frag = shader.Sources{ + Name: "stencil.frag", + Inputs: []shader.InputLocation{{Name: "vFrom", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 2}, {Name: "vCtrl", Location: 1, Semantic: "TEXCOORD", SemanticIndex: 1, Type: 0x0, Size: 2}, {Name: "vTo", Location: 2, Semantic: "TEXCOORD", SemanticIndex: 2, Type: 0x0, Size: 2}}, + } + //go:embed zstencil.frag.0.spirv + zstencil_frag_0_spirv string + //go:embed zstencil.frag.0.glsl100es + zstencil_frag_0_glsl100es string + //go:embed zstencil.frag.0.glsl150 + zstencil_frag_0_glsl150 string + //go:embed zstencil.frag.0.dxbc + zstencil_frag_0_dxbc string + //go:embed zstencil.frag.0.metallibmacos + zstencil_frag_0_metallibmacos string + //go:embed zstencil.frag.0.metallibios + zstencil_frag_0_metallibios string + //go:embed zstencil.frag.0.metallibiossimulator + zstencil_frag_0_metallibiossimulator string + Shader_stencil_vert = shader.Sources{ + Name: "stencil.vert", + Inputs: []shader.InputLocation{{Name: "corner", Location: 0, Semantic: "TEXCOORD", SemanticIndex: 0, Type: 0x0, Size: 1}, {Name: "maxy", Location: 1, Semantic: "TEXCOORD", SemanticIndex: 1, Type: 0x0, Size: 1}, {Name: "from", Location: 2, Semantic: "TEXCOORD", SemanticIndex: 2, Type: 0x0, Size: 2}, {Name: "ctrl", Location: 3, Semantic: "TEXCOORD", SemanticIndex: 3, Type: 0x0, Size: 2}, {Name: "to", Location: 4, Semantic: "TEXCOORD", SemanticIndex: 4, Type: 0x0, Size: 2}}, + Uniforms: shader.UniformsReflection{ + Locations: []shader.UniformLocation{{Name: "_block.transform", Type: 0x0, Size: 4, Offset: 0}, {Name: "_block.pathOffset", Type: 0x0, Size: 2, Offset: 16}}, + Size: 24, + }, + } + //go:embed zstencil.vert.0.spirv + zstencil_vert_0_spirv string + //go:embed zstencil.vert.0.glsl100es + zstencil_vert_0_glsl100es string + //go:embed zstencil.vert.0.glsl150 + zstencil_vert_0_glsl150 string + //go:embed zstencil.vert.0.dxbc + zstencil_vert_0_dxbc string + //go:embed zstencil.vert.0.metallibmacos + zstencil_vert_0_metallibmacos string + //go:embed zstencil.vert.0.metallibios + zstencil_vert_0_metallibios string + //go:embed zstencil.vert.0.metallibiossimulator + zstencil_vert_0_metallibiossimulator string +) + +func init() { + const ( + opengles = runtime.GOOS == "linux" || runtime.GOOS == "freebsd" || runtime.GOOS == "openbsd" || runtime.GOOS == "windows" || runtime.GOOS == "js" || runtime.GOOS == "android" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" + opengl = runtime.GOOS == "darwin" + d3d11 = runtime.GOOS == "windows" + vulkan = runtime.GOOS == "linux" || runtime.GOOS == "android" + ) + if vulkan { + Shader_blit_frag[0].SPIRV = zblit_frag_0_spirv + } + if opengles { + Shader_blit_frag[0].GLSL100ES = zblit_frag_0_glsl100es + } + if opengl { + Shader_blit_frag[0].GLSL150 = zblit_frag_0_glsl150 + } + if d3d11 { + Shader_blit_frag[0].DXBC = zblit_frag_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_blit_frag[0].MetalLib = zblit_frag_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_blit_frag[0].MetalLib = zblit_frag_0_metallibiossimulator + } else { + Shader_blit_frag[0].MetalLib = zblit_frag_0_metallibios + } + } + if vulkan { + Shader_blit_frag[1].SPIRV = zblit_frag_1_spirv + } + if opengles { + Shader_blit_frag[1].GLSL100ES = zblit_frag_1_glsl100es + } + if opengl { + Shader_blit_frag[1].GLSL150 = zblit_frag_1_glsl150 + } + if d3d11 { + Shader_blit_frag[1].DXBC = zblit_frag_1_dxbc + } + if runtime.GOOS == "darwin" { + Shader_blit_frag[1].MetalLib = zblit_frag_1_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_blit_frag[1].MetalLib = zblit_frag_1_metallibiossimulator + } else { + Shader_blit_frag[1].MetalLib = zblit_frag_1_metallibios + } + } + if vulkan { + Shader_blit_frag[2].SPIRV = zblit_frag_2_spirv + } + if opengles { + Shader_blit_frag[2].GLSL100ES = zblit_frag_2_glsl100es + } + if opengl { + Shader_blit_frag[2].GLSL150 = zblit_frag_2_glsl150 + } + if d3d11 { + Shader_blit_frag[2].DXBC = zblit_frag_2_dxbc + } + if runtime.GOOS == "darwin" { + Shader_blit_frag[2].MetalLib = zblit_frag_2_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_blit_frag[2].MetalLib = zblit_frag_2_metallibiossimulator + } else { + Shader_blit_frag[2].MetalLib = zblit_frag_2_metallibios + } + } + if vulkan { + Shader_blit_vert.SPIRV = zblit_vert_0_spirv + } + if opengles { + Shader_blit_vert.GLSL100ES = zblit_vert_0_glsl100es + } + if opengl { + Shader_blit_vert.GLSL150 = zblit_vert_0_glsl150 + } + if d3d11 { + Shader_blit_vert.DXBC = zblit_vert_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_blit_vert.MetalLib = zblit_vert_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_blit_vert.MetalLib = zblit_vert_0_metallibiossimulator + } else { + Shader_blit_vert.MetalLib = zblit_vert_0_metallibios + } + } + if vulkan { + Shader_copy_frag.SPIRV = zcopy_frag_0_spirv + } + if opengles { + Shader_copy_frag.GLSL100ES = zcopy_frag_0_glsl100es + } + if opengl { + Shader_copy_frag.GLSL150 = zcopy_frag_0_glsl150 + } + if d3d11 { + Shader_copy_frag.DXBC = zcopy_frag_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_copy_frag.MetalLib = zcopy_frag_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_copy_frag.MetalLib = zcopy_frag_0_metallibiossimulator + } else { + Shader_copy_frag.MetalLib = zcopy_frag_0_metallibios + } + } + if vulkan { + Shader_copy_vert.SPIRV = zcopy_vert_0_spirv + } + if opengles { + Shader_copy_vert.GLSL100ES = zcopy_vert_0_glsl100es + } + if opengl { + Shader_copy_vert.GLSL150 = zcopy_vert_0_glsl150 + } + if d3d11 { + Shader_copy_vert.DXBC = zcopy_vert_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_copy_vert.MetalLib = zcopy_vert_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_copy_vert.MetalLib = zcopy_vert_0_metallibiossimulator + } else { + Shader_copy_vert.MetalLib = zcopy_vert_0_metallibios + } + } + if vulkan { + Shader_cover_frag[0].SPIRV = zcover_frag_0_spirv + } + if opengles { + Shader_cover_frag[0].GLSL100ES = zcover_frag_0_glsl100es + } + if opengl { + Shader_cover_frag[0].GLSL150 = zcover_frag_0_glsl150 + } + if d3d11 { + Shader_cover_frag[0].DXBC = zcover_frag_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_cover_frag[0].MetalLib = zcover_frag_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_cover_frag[0].MetalLib = zcover_frag_0_metallibiossimulator + } else { + Shader_cover_frag[0].MetalLib = zcover_frag_0_metallibios + } + } + if vulkan { + Shader_cover_frag[1].SPIRV = zcover_frag_1_spirv + } + if opengles { + Shader_cover_frag[1].GLSL100ES = zcover_frag_1_glsl100es + } + if opengl { + Shader_cover_frag[1].GLSL150 = zcover_frag_1_glsl150 + } + if d3d11 { + Shader_cover_frag[1].DXBC = zcover_frag_1_dxbc + } + if runtime.GOOS == "darwin" { + Shader_cover_frag[1].MetalLib = zcover_frag_1_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_cover_frag[1].MetalLib = zcover_frag_1_metallibiossimulator + } else { + Shader_cover_frag[1].MetalLib = zcover_frag_1_metallibios + } + } + if vulkan { + Shader_cover_frag[2].SPIRV = zcover_frag_2_spirv + } + if opengles { + Shader_cover_frag[2].GLSL100ES = zcover_frag_2_glsl100es + } + if opengl { + Shader_cover_frag[2].GLSL150 = zcover_frag_2_glsl150 + } + if d3d11 { + Shader_cover_frag[2].DXBC = zcover_frag_2_dxbc + } + if runtime.GOOS == "darwin" { + Shader_cover_frag[2].MetalLib = zcover_frag_2_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_cover_frag[2].MetalLib = zcover_frag_2_metallibiossimulator + } else { + Shader_cover_frag[2].MetalLib = zcover_frag_2_metallibios + } + } + if vulkan { + Shader_cover_vert.SPIRV = zcover_vert_0_spirv + } + if opengles { + Shader_cover_vert.GLSL100ES = zcover_vert_0_glsl100es + } + if opengl { + Shader_cover_vert.GLSL150 = zcover_vert_0_glsl150 + } + if d3d11 { + Shader_cover_vert.DXBC = zcover_vert_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_cover_vert.MetalLib = zcover_vert_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_cover_vert.MetalLib = zcover_vert_0_metallibiossimulator + } else { + Shader_cover_vert.MetalLib = zcover_vert_0_metallibios + } + } + if vulkan { + Shader_input_vert.SPIRV = zinput_vert_0_spirv + } + if opengles { + Shader_input_vert.GLSL100ES = zinput_vert_0_glsl100es + } + if opengl { + Shader_input_vert.GLSL150 = zinput_vert_0_glsl150 + } + if d3d11 { + Shader_input_vert.DXBC = zinput_vert_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_input_vert.MetalLib = zinput_vert_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_input_vert.MetalLib = zinput_vert_0_metallibiossimulator + } else { + Shader_input_vert.MetalLib = zinput_vert_0_metallibios + } + } + if vulkan { + Shader_intersect_frag.SPIRV = zintersect_frag_0_spirv + } + if opengles { + Shader_intersect_frag.GLSL100ES = zintersect_frag_0_glsl100es + } + if opengl { + Shader_intersect_frag.GLSL150 = zintersect_frag_0_glsl150 + } + if d3d11 { + Shader_intersect_frag.DXBC = zintersect_frag_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_intersect_frag.MetalLib = zintersect_frag_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_intersect_frag.MetalLib = zintersect_frag_0_metallibiossimulator + } else { + Shader_intersect_frag.MetalLib = zintersect_frag_0_metallibios + } + } + if vulkan { + Shader_intersect_vert.SPIRV = zintersect_vert_0_spirv + } + if opengles { + Shader_intersect_vert.GLSL100ES = zintersect_vert_0_glsl100es + } + if opengl { + Shader_intersect_vert.GLSL150 = zintersect_vert_0_glsl150 + } + if d3d11 { + Shader_intersect_vert.DXBC = zintersect_vert_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_intersect_vert.MetalLib = zintersect_vert_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_intersect_vert.MetalLib = zintersect_vert_0_metallibiossimulator + } else { + Shader_intersect_vert.MetalLib = zintersect_vert_0_metallibios + } + } + if vulkan { + Shader_material_frag.SPIRV = zmaterial_frag_0_spirv + } + if opengles { + Shader_material_frag.GLSL100ES = zmaterial_frag_0_glsl100es + } + if opengl { + Shader_material_frag.GLSL150 = zmaterial_frag_0_glsl150 + } + if d3d11 { + Shader_material_frag.DXBC = zmaterial_frag_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_material_frag.MetalLib = zmaterial_frag_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_material_frag.MetalLib = zmaterial_frag_0_metallibiossimulator + } else { + Shader_material_frag.MetalLib = zmaterial_frag_0_metallibios + } + } + if vulkan { + Shader_material_vert.SPIRV = zmaterial_vert_0_spirv + } + if opengles { + Shader_material_vert.GLSL100ES = zmaterial_vert_0_glsl100es + } + if opengl { + Shader_material_vert.GLSL150 = zmaterial_vert_0_glsl150 + } + if d3d11 { + Shader_material_vert.DXBC = zmaterial_vert_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_material_vert.MetalLib = zmaterial_vert_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_material_vert.MetalLib = zmaterial_vert_0_metallibiossimulator + } else { + Shader_material_vert.MetalLib = zmaterial_vert_0_metallibios + } + } + if vulkan { + Shader_simple_frag.SPIRV = zsimple_frag_0_spirv + } + if opengles { + Shader_simple_frag.GLSL100ES = zsimple_frag_0_glsl100es + } + if opengl { + Shader_simple_frag.GLSL150 = zsimple_frag_0_glsl150 + } + if d3d11 { + Shader_simple_frag.DXBC = zsimple_frag_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_simple_frag.MetalLib = zsimple_frag_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_simple_frag.MetalLib = zsimple_frag_0_metallibiossimulator + } else { + Shader_simple_frag.MetalLib = zsimple_frag_0_metallibios + } + } + if vulkan { + Shader_stencil_frag.SPIRV = zstencil_frag_0_spirv + } + if opengles { + Shader_stencil_frag.GLSL100ES = zstencil_frag_0_glsl100es + } + if opengl { + Shader_stencil_frag.GLSL150 = zstencil_frag_0_glsl150 + } + if d3d11 { + Shader_stencil_frag.DXBC = zstencil_frag_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_stencil_frag.MetalLib = zstencil_frag_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_stencil_frag.MetalLib = zstencil_frag_0_metallibiossimulator + } else { + Shader_stencil_frag.MetalLib = zstencil_frag_0_metallibios + } + } + if vulkan { + Shader_stencil_vert.SPIRV = zstencil_vert_0_spirv + } + if opengles { + Shader_stencil_vert.GLSL100ES = zstencil_vert_0_glsl100es + } + if opengl { + Shader_stencil_vert.GLSL150 = zstencil_vert_0_glsl150 + } + if d3d11 { + Shader_stencil_vert.DXBC = zstencil_vert_0_dxbc + } + if runtime.GOOS == "darwin" { + Shader_stencil_vert.MetalLib = zstencil_vert_0_metallibmacos + } + if runtime.GOOS == "ios" { + if runtime.GOARCH == "amd64" { + Shader_stencil_vert.MetalLib = zstencil_vert_0_metallibiossimulator + } else { + Shader_stencil_vert.MetalLib = zstencil_vert_0_metallibios + } + } +} diff --git a/gio/shader/gio/simple.frag b/gio/shader/gio/simple.frag new file mode 100644 index 0000000..4614f33 --- /dev/null +++ b/gio/shader/gio/simple.frag @@ -0,0 +1,11 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +precision mediump float; + +layout(location = 0) out vec4 fragColor; + +void main() { + fragColor = vec4(.25, .55, .75, 1.0); +} diff --git a/gio/shader/gio/stencil.frag b/gio/shader/gio/stencil.frag new file mode 100644 index 0000000..956dae8 --- /dev/null +++ b/gio/shader/gio/stencil.frag @@ -0,0 +1,81 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +precision mediump float; + +layout(location=0) in highp vec2 vFrom; +layout(location=1) in highp vec2 vCtrl; +layout(location=2) in highp vec2 vTo; + +layout(location = 0) out vec4 fragCover; + +void main() { + float dx = vTo.x - vFrom.x; + // Sort from and to in increasing order so the root below + // is always the positive square root, if any. + // We need the direction of the curve below, so this can't be + // done from the vertex shader. + bool increasing = vTo.x >= vFrom.x; + vec2 left = increasing ? vFrom : vTo; + vec2 right = increasing ? vTo : vFrom; + + // The signed horizontal extent of the fragment. + vec2 extent = clamp(vec2(vFrom.x, vTo.x), -0.5, 0.5); + // Find the t where the curve crosses the middle of the + // extent, x₀. + // Given the Bézier curve with x coordinates P₀, P₁, P₂ + // where P₀ is at the origin, its x coordinate in t + // is given by: + // + // x(t) = 2(1-t)tP₁ + t²P₂ + // + // Rearranging: + // + // x(t) = (P₂ - 2P₁)t² + 2P₁t + // + // Setting x(t) = x₀ and using Muller's quadratic formula ("Citardauq") + // for robustnesss, + // + // t = 2x₀/(2P₁±√(4P₁²+4(P₂-2P₁)x₀)) + // + // which simplifies to + // + // t = x₀/(P₁±√(P₁²+(P₂-2P₁)x₀)) + // + // Setting v = P₂-P₁, + // + // t = x₀/(P₁±√(P₁²+(v-P₁)x₀)) + // + // t lie in [0; 1]; P₂ ≥ P₁ and P₁ ≥ 0 since we split curves where + // the control point lies before the start point or after the end point. + // It can then be shown that only the positive square root is valid. + float midx = mix(extent.x, extent.y, 0.5); + float x0 = midx - left.x; + vec2 p1 = vCtrl - left; + vec2 v = right - vCtrl; + float t = x0/(p1.x+sqrt(p1.x*p1.x+(v.x-p1.x)*x0)); + // Find y(t) on the curve. + float y = mix(mix(left.y, vCtrl.y, t), mix(vCtrl.y, right.y, t), t); + // And the slope. + vec2 d_half = mix(p1, v, t); + float dy = d_half.y/d_half.x; + // Together, y and dy form a line approximation. + + // Compute the fragment area above the line. + // The area is symmetric around dy = 0. Scale slope with extent width. + float width = extent.y - extent.x; + dy = abs(dy*width); + + vec4 sides = vec4(dy*+0.5 + y, dy*-0.5 + y, (+0.5-y)/dy, (-0.5-y)/dy); + sides = clamp(sides+0.5, 0.0, 1.0); + + float area = 0.5*(sides.z - sides.z*sides.y + 1.0 - sides.x+sides.x*sides.w); + area *= width; + + // Work around issue #13. + if (width == 0.0) + area = 0.0; + + fragCover.r = area; +} diff --git a/gio/shader/gio/stencil.vert b/gio/shader/gio/stencil.vert new file mode 100644 index 0000000..fd6f28b --- /dev/null +++ b/gio/shader/gio/stencil.vert @@ -0,0 +1,57 @@ +#version 310 es + +// SPDX-License-Identifier: Unlicense OR MIT + +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + +#include "common.h" + +layout(push_constant) uniform Block { + vec4 transform; + vec2 pathOffset; +} _block; + +layout(location=0) in float corner; +layout(location=1) in float maxy; +layout(location=2) in vec2 from; +layout(location=3) in vec2 ctrl; +layout(location=4) in vec2 to; + +layout(location=0) out vec2 vFrom; +layout(location=1) out vec2 vCtrl; +layout(location=2) out vec2 vTo; + +void main() { + // Add a one pixel overlap so curve quads cover their + // entire curves. Could use conservative rasterization + // if available. + vec2 from = from + _block.pathOffset; + vec2 ctrl = ctrl + _block.pathOffset; + vec2 to = to + _block.pathOffset; + float maxy = maxy + _block.pathOffset.y; + vec2 pos; + float c = corner; + if (c >= 0.375) { + // North. + c -= 0.5; + pos.y = maxy + 1.0; + } else { + // South. + pos.y = min(min(from.y, ctrl.y), to.y) - 1.0; + } + if (c >= 0.125) { + // East. + pos.x = max(max(from.x, ctrl.x), to.x)+1.0; + } else { + // West. + pos.x = min(min(from.x, ctrl.x), to.x)-1.0; + } + vFrom = from-pos; + vCtrl = ctrl-pos; + vTo = to-pos; + pos = pos*_block.transform.xy + _block.transform.zw; + gl_Position = vec4(transform3x2(fboTransform, vec3(pos, 0)), 1); +} + diff --git a/gio/shader/gio/zblit.frag.0.dxbc b/gio/shader/gio/zblit.frag.0.dxbc new file mode 100644 index 0000000..45e8355 Binary files /dev/null and b/gio/shader/gio/zblit.frag.0.dxbc differ diff --git a/gio/shader/gio/zblit.frag.0.glsl100es b/gio/shader/gio/zblit.frag.0.glsl100es new file mode 100644 index 0000000..d7ca41a --- /dev/null +++ b/gio/shader/gio/zblit.frag.0.glsl100es @@ -0,0 +1,18 @@ +#version 100 +precision mediump float; +precision highp int; + +struct Color +{ + vec4 color; +}; + +uniform Color _color; + +varying highp vec2 vUV; + +void main() +{ + gl_FragData[0] = _color.color; +} + diff --git a/gio/shader/gio/zblit.frag.0.glsl150 b/gio/shader/gio/zblit.frag.0.glsl150 new file mode 100644 index 0000000..9559c85 --- /dev/null +++ b/gio/shader/gio/zblit.frag.0.glsl150 @@ -0,0 +1,17 @@ +#version 150 + +struct Color +{ + vec4 color; +}; + +uniform Color _color; + +out vec4 fragColor; +in vec2 vUV; + +void main() +{ + fragColor = _color.color; +} + diff --git a/gio/shader/gio/zblit.frag.0.metallibios b/gio/shader/gio/zblit.frag.0.metallibios new file mode 100644 index 0000000..63e606f Binary files /dev/null and b/gio/shader/gio/zblit.frag.0.metallibios differ diff --git a/gio/shader/gio/zblit.frag.0.metallibiossimulator b/gio/shader/gio/zblit.frag.0.metallibiossimulator new file mode 100644 index 0000000..d8d2589 Binary files /dev/null and b/gio/shader/gio/zblit.frag.0.metallibiossimulator differ diff --git a/gio/shader/gio/zblit.frag.0.metallibmacos b/gio/shader/gio/zblit.frag.0.metallibmacos new file mode 100644 index 0000000..85946aa Binary files /dev/null and b/gio/shader/gio/zblit.frag.0.metallibmacos differ diff --git a/gio/shader/gio/zblit.frag.0.spirv b/gio/shader/gio/zblit.frag.0.spirv new file mode 100644 index 0000000..c2a88d2 Binary files /dev/null and b/gio/shader/gio/zblit.frag.0.spirv differ diff --git a/gio/shader/gio/zblit.frag.1.dxbc b/gio/shader/gio/zblit.frag.1.dxbc new file mode 100644 index 0000000..ddb8dad Binary files /dev/null and b/gio/shader/gio/zblit.frag.1.dxbc differ diff --git a/gio/shader/gio/zblit.frag.1.glsl100es b/gio/shader/gio/zblit.frag.1.glsl100es new file mode 100644 index 0000000..ccc6d2a --- /dev/null +++ b/gio/shader/gio/zblit.frag.1.glsl100es @@ -0,0 +1,19 @@ +#version 100 +precision mediump float; +precision highp int; + +struct Gradient +{ + vec4 color1; + vec4 color2; +}; + +uniform Gradient _gradient; + +varying highp vec2 vUV; + +void main() +{ + gl_FragData[0] = mix(_gradient.color1, _gradient.color2, vec4(clamp(vUV.x, 0.0, 1.0))); +} + diff --git a/gio/shader/gio/zblit.frag.1.glsl150 b/gio/shader/gio/zblit.frag.1.glsl150 new file mode 100644 index 0000000..a55f29f --- /dev/null +++ b/gio/shader/gio/zblit.frag.1.glsl150 @@ -0,0 +1,18 @@ +#version 150 + +struct Gradient +{ + vec4 color1; + vec4 color2; +}; + +uniform Gradient _gradient; + +out vec4 fragColor; +in vec2 vUV; + +void main() +{ + fragColor = mix(_gradient.color1, _gradient.color2, vec4(clamp(vUV.x, 0.0, 1.0))); +} + diff --git a/gio/shader/gio/zblit.frag.1.metallibios b/gio/shader/gio/zblit.frag.1.metallibios new file mode 100644 index 0000000..680c495 Binary files /dev/null and b/gio/shader/gio/zblit.frag.1.metallibios differ diff --git a/gio/shader/gio/zblit.frag.1.metallibiossimulator b/gio/shader/gio/zblit.frag.1.metallibiossimulator new file mode 100644 index 0000000..ef5ac86 Binary files /dev/null and b/gio/shader/gio/zblit.frag.1.metallibiossimulator differ diff --git a/gio/shader/gio/zblit.frag.1.metallibmacos b/gio/shader/gio/zblit.frag.1.metallibmacos new file mode 100644 index 0000000..5fbd2c2 Binary files /dev/null and b/gio/shader/gio/zblit.frag.1.metallibmacos differ diff --git a/gio/shader/gio/zblit.frag.1.spirv b/gio/shader/gio/zblit.frag.1.spirv new file mode 100644 index 0000000..88128fc Binary files /dev/null and b/gio/shader/gio/zblit.frag.1.spirv differ diff --git a/gio/shader/gio/zblit.frag.2.dxbc b/gio/shader/gio/zblit.frag.2.dxbc new file mode 100644 index 0000000..fd95db8 Binary files /dev/null and b/gio/shader/gio/zblit.frag.2.dxbc differ diff --git a/gio/shader/gio/zblit.frag.2.glsl100es b/gio/shader/gio/zblit.frag.2.glsl100es new file mode 100644 index 0000000..5c2d832 --- /dev/null +++ b/gio/shader/gio/zblit.frag.2.glsl100es @@ -0,0 +1,13 @@ +#version 100 +precision mediump float; +precision highp int; + +uniform mediump sampler2D tex; + +varying highp vec2 vUV; + +void main() +{ + gl_FragData[0] = texture2D(tex, vUV); +} + diff --git a/gio/shader/gio/zblit.frag.2.glsl150 b/gio/shader/gio/zblit.frag.2.glsl150 new file mode 100644 index 0000000..f5df869 --- /dev/null +++ b/gio/shader/gio/zblit.frag.2.glsl150 @@ -0,0 +1,12 @@ +#version 150 + +uniform sampler2D tex; + +out vec4 fragColor; +in vec2 vUV; + +void main() +{ + fragColor = texture(tex, vUV); +} + diff --git a/gio/shader/gio/zblit.frag.2.metallibios b/gio/shader/gio/zblit.frag.2.metallibios new file mode 100644 index 0000000..c4eb922 Binary files /dev/null and b/gio/shader/gio/zblit.frag.2.metallibios differ diff --git a/gio/shader/gio/zblit.frag.2.metallibiossimulator b/gio/shader/gio/zblit.frag.2.metallibiossimulator new file mode 100644 index 0000000..81f7aa3 Binary files /dev/null and b/gio/shader/gio/zblit.frag.2.metallibiossimulator differ diff --git a/gio/shader/gio/zblit.frag.2.metallibmacos b/gio/shader/gio/zblit.frag.2.metallibmacos new file mode 100644 index 0000000..70b3da8 Binary files /dev/null and b/gio/shader/gio/zblit.frag.2.metallibmacos differ diff --git a/gio/shader/gio/zblit.frag.2.spirv b/gio/shader/gio/zblit.frag.2.spirv new file mode 100644 index 0000000..efa380b Binary files /dev/null and b/gio/shader/gio/zblit.frag.2.spirv differ diff --git a/gio/shader/gio/zblit.vert.0.dxbc b/gio/shader/gio/zblit.vert.0.dxbc new file mode 100644 index 0000000..5ad9601 Binary files /dev/null and b/gio/shader/gio/zblit.vert.0.dxbc differ diff --git a/gio/shader/gio/zblit.vert.0.glsl100es b/gio/shader/gio/zblit.vert.0.glsl100es new file mode 100644 index 0000000..61dee04 --- /dev/null +++ b/gio/shader/gio/zblit.vert.0.glsl100es @@ -0,0 +1,37 @@ +#version 100 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec4 transform; + vec4 uvTransformR1; + vec4 uvTransformR2; +}; + +uniform Block _block; + +attribute vec2 pos; +varying vec2 vUV; +attribute vec2 uv; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + vec2 p = (pos * _block.transform.xy) + _block.transform.zw; + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0)); + vec3 param_1 = vec3(p, 0.0); + gl_Position = vec4(transform3x2(param, param_1), 1.0); + m3x2 param_2 = m3x2(_block.uvTransformR1.xyz, _block.uvTransformR2.xyz); + vec3 param_3 = vec3(uv, 1.0); + vUV = transform3x2(param_2, param_3).xy; +} + diff --git a/gio/shader/gio/zblit.vert.0.glsl150 b/gio/shader/gio/zblit.vert.0.glsl150 new file mode 100644 index 0000000..eba9f1a --- /dev/null +++ b/gio/shader/gio/zblit.vert.0.glsl150 @@ -0,0 +1,37 @@ +#version 150 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec4 transform; + vec4 uvTransformR1; + vec4 uvTransformR2; +}; + +uniform Block _block; + +in vec2 pos; +out vec2 vUV; +in vec2 uv; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + vec2 p = (pos * _block.transform.xy) + _block.transform.zw; + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0)); + vec3 param_1 = vec3(p, 0.0); + gl_Position = vec4(transform3x2(param, param_1), 1.0); + m3x2 param_2 = m3x2(_block.uvTransformR1.xyz, _block.uvTransformR2.xyz); + vec3 param_3 = vec3(uv, 1.0); + vUV = transform3x2(param_2, param_3).xy; +} + diff --git a/gio/shader/gio/zblit.vert.0.metallibios b/gio/shader/gio/zblit.vert.0.metallibios new file mode 100644 index 0000000..2450ec9 Binary files /dev/null and b/gio/shader/gio/zblit.vert.0.metallibios differ diff --git a/gio/shader/gio/zblit.vert.0.metallibiossimulator b/gio/shader/gio/zblit.vert.0.metallibiossimulator new file mode 100644 index 0000000..6b4960b Binary files /dev/null and b/gio/shader/gio/zblit.vert.0.metallibiossimulator differ diff --git a/gio/shader/gio/zblit.vert.0.metallibmacos b/gio/shader/gio/zblit.vert.0.metallibmacos new file mode 100644 index 0000000..d902b36 Binary files /dev/null and b/gio/shader/gio/zblit.vert.0.metallibmacos differ diff --git a/gio/shader/gio/zblit.vert.0.spirv b/gio/shader/gio/zblit.vert.0.spirv new file mode 100644 index 0000000..4f762bb Binary files /dev/null and b/gio/shader/gio/zblit.vert.0.spirv differ diff --git a/gio/shader/gio/zcopy.frag.0.dxbc b/gio/shader/gio/zcopy.frag.0.dxbc new file mode 100644 index 0000000..a521803 Binary files /dev/null and b/gio/shader/gio/zcopy.frag.0.dxbc differ diff --git a/gio/shader/gio/zcopy.frag.0.glsl100es b/gio/shader/gio/zcopy.frag.0.glsl100es new file mode 100644 index 0000000..b2dd95a --- /dev/null +++ b/gio/shader/gio/zcopy.frag.0.glsl100es @@ -0,0 +1,27 @@ +#version 100 +precision mediump float; +precision highp int; + +uniform mediump sampler2D tex; + +varying highp vec2 vUV; + +vec3 sRGBtoRGB(vec3 rgb) +{ + bvec3 cutoff = greaterThanEqual(rgb, vec3(0.040449999272823333740234375)); + vec3 below = rgb / vec3(12.9200000762939453125); + vec3 above = pow((rgb + vec3(0.054999999701976776123046875)) / vec3(1.05499994754791259765625), vec3(2.400000095367431640625)); + return vec3(cutoff.x ? above.x : below.x, cutoff.y ? above.y : below.y, cutoff.z ? above.z : below.z); +} + +void main() +{ + vec4 texel = texture2D(tex, vUV); + vec3 param = texel.xyz; + vec3 _59 = sRGBtoRGB(param); + texel.x = _59.x; + texel.y = _59.y; + texel.z = _59.z; + gl_FragData[0] = texel; +} + diff --git a/gio/shader/gio/zcopy.frag.0.glsl150 b/gio/shader/gio/zcopy.frag.0.glsl150 new file mode 100644 index 0000000..799add1 --- /dev/null +++ b/gio/shader/gio/zcopy.frag.0.glsl150 @@ -0,0 +1,26 @@ +#version 150 + +uniform sampler2D tex; + +in vec2 vUV; +out vec4 fragColor; + +vec3 sRGBtoRGB(vec3 rgb) +{ + bvec3 cutoff = greaterThanEqual(rgb, vec3(0.040449999272823333740234375)); + vec3 below = rgb / vec3(12.9200000762939453125); + vec3 above = pow((rgb + vec3(0.054999999701976776123046875)) / vec3(1.05499994754791259765625), vec3(2.400000095367431640625)); + return vec3(cutoff.x ? above.x : below.x, cutoff.y ? above.y : below.y, cutoff.z ? above.z : below.z); +} + +void main() +{ + vec4 texel = texture(tex, vUV); + vec3 param = texel.xyz; + vec3 _59 = sRGBtoRGB(param); + texel.x = _59.x; + texel.y = _59.y; + texel.z = _59.z; + fragColor = texel; +} + diff --git a/gio/shader/gio/zcopy.frag.0.metallibios b/gio/shader/gio/zcopy.frag.0.metallibios new file mode 100644 index 0000000..f143069 Binary files /dev/null and b/gio/shader/gio/zcopy.frag.0.metallibios differ diff --git a/gio/shader/gio/zcopy.frag.0.metallibiossimulator b/gio/shader/gio/zcopy.frag.0.metallibiossimulator new file mode 100644 index 0000000..8fe4c74 Binary files /dev/null and b/gio/shader/gio/zcopy.frag.0.metallibiossimulator differ diff --git a/gio/shader/gio/zcopy.frag.0.metallibmacos b/gio/shader/gio/zcopy.frag.0.metallibmacos new file mode 100644 index 0000000..2e43803 Binary files /dev/null and b/gio/shader/gio/zcopy.frag.0.metallibmacos differ diff --git a/gio/shader/gio/zcopy.frag.0.spirv b/gio/shader/gio/zcopy.frag.0.spirv new file mode 100644 index 0000000..3299552 Binary files /dev/null and b/gio/shader/gio/zcopy.frag.0.spirv differ diff --git a/gio/shader/gio/zcopy.vert.0.dxbc b/gio/shader/gio/zcopy.vert.0.dxbc new file mode 100644 index 0000000..acce7ab Binary files /dev/null and b/gio/shader/gio/zcopy.vert.0.dxbc differ diff --git a/gio/shader/gio/zcopy.vert.0.glsl100es b/gio/shader/gio/zcopy.vert.0.glsl100es new file mode 100644 index 0000000..ff0be47 --- /dev/null +++ b/gio/shader/gio/zcopy.vert.0.glsl100es @@ -0,0 +1,35 @@ +#version 100 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec2 scale; + vec2 pos; + vec2 uvScale; +}; + +uniform Block _block; + +varying vec2 vUV; +attribute vec2 uv; +attribute vec2 pos; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + vUV = vec2(uv * _block.uvScale); + vec2 p = vec2((pos * _block.scale) + _block.pos); + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0)); + vec3 param_1 = vec3(p, 0.0); + gl_Position = vec4(transform3x2(param, param_1), 1.0); +} + diff --git a/gio/shader/gio/zcopy.vert.0.glsl150 b/gio/shader/gio/zcopy.vert.0.glsl150 new file mode 100644 index 0000000..036cd39 --- /dev/null +++ b/gio/shader/gio/zcopy.vert.0.glsl150 @@ -0,0 +1,35 @@ +#version 150 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec2 scale; + vec2 pos; + vec2 uvScale; +}; + +uniform Block _block; + +out vec2 vUV; +in vec2 uv; +in vec2 pos; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + vUV = vec2(uv * _block.uvScale); + vec2 p = vec2((pos * _block.scale) + _block.pos); + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0)); + vec3 param_1 = vec3(p, 0.0); + gl_Position = vec4(transform3x2(param, param_1), 1.0); +} + diff --git a/gio/shader/gio/zcopy.vert.0.metallibios b/gio/shader/gio/zcopy.vert.0.metallibios new file mode 100644 index 0000000..25f5e56 Binary files /dev/null and b/gio/shader/gio/zcopy.vert.0.metallibios differ diff --git a/gio/shader/gio/zcopy.vert.0.metallibiossimulator b/gio/shader/gio/zcopy.vert.0.metallibiossimulator new file mode 100644 index 0000000..f696caf Binary files /dev/null and b/gio/shader/gio/zcopy.vert.0.metallibiossimulator differ diff --git a/gio/shader/gio/zcopy.vert.0.metallibmacos b/gio/shader/gio/zcopy.vert.0.metallibmacos new file mode 100644 index 0000000..d4a5777 Binary files /dev/null and b/gio/shader/gio/zcopy.vert.0.metallibmacos differ diff --git a/gio/shader/gio/zcopy.vert.0.spirv b/gio/shader/gio/zcopy.vert.0.spirv new file mode 100644 index 0000000..7251754 Binary files /dev/null and b/gio/shader/gio/zcopy.vert.0.spirv differ diff --git a/gio/shader/gio/zcover.frag.0.dxbc b/gio/shader/gio/zcover.frag.0.dxbc new file mode 100644 index 0000000..8b77ae4 Binary files /dev/null and b/gio/shader/gio/zcover.frag.0.dxbc differ diff --git a/gio/shader/gio/zcover.frag.0.glsl100es b/gio/shader/gio/zcover.frag.0.glsl100es new file mode 100644 index 0000000..2399901 --- /dev/null +++ b/gio/shader/gio/zcover.frag.0.glsl100es @@ -0,0 +1,23 @@ +#version 100 +precision mediump float; +precision highp int; + +struct Color +{ + vec4 color; +}; + +uniform Color _color; + +uniform mediump sampler2D cover; + +varying highp vec2 vCoverUV; +varying highp vec2 vUV; + +void main() +{ + gl_FragData[0] = _color.color; + float c = min(abs(texture2D(cover, vCoverUV).x), 1.0); + gl_FragData[0] *= c; +} + diff --git a/gio/shader/gio/zcover.frag.0.glsl150 b/gio/shader/gio/zcover.frag.0.glsl150 new file mode 100644 index 0000000..ce1beaa --- /dev/null +++ b/gio/shader/gio/zcover.frag.0.glsl150 @@ -0,0 +1,22 @@ +#version 150 + +struct Color +{ + vec4 color; +}; + +uniform Color _color; + +uniform sampler2D cover; + +out vec4 fragColor; +in vec2 vCoverUV; +in vec2 vUV; + +void main() +{ + fragColor = _color.color; + float c = min(abs(texture(cover, vCoverUV).x), 1.0); + fragColor *= c; +} + diff --git a/gio/shader/gio/zcover.frag.0.metallibios b/gio/shader/gio/zcover.frag.0.metallibios new file mode 100644 index 0000000..22256c8 Binary files /dev/null and b/gio/shader/gio/zcover.frag.0.metallibios differ diff --git a/gio/shader/gio/zcover.frag.0.metallibiossimulator b/gio/shader/gio/zcover.frag.0.metallibiossimulator new file mode 100644 index 0000000..c8040ad Binary files /dev/null and b/gio/shader/gio/zcover.frag.0.metallibiossimulator differ diff --git a/gio/shader/gio/zcover.frag.0.metallibmacos b/gio/shader/gio/zcover.frag.0.metallibmacos new file mode 100644 index 0000000..fe25160 Binary files /dev/null and b/gio/shader/gio/zcover.frag.0.metallibmacos differ diff --git a/gio/shader/gio/zcover.frag.0.spirv b/gio/shader/gio/zcover.frag.0.spirv new file mode 100644 index 0000000..2061ff1 Binary files /dev/null and b/gio/shader/gio/zcover.frag.0.spirv differ diff --git a/gio/shader/gio/zcover.frag.1.dxbc b/gio/shader/gio/zcover.frag.1.dxbc new file mode 100644 index 0000000..c9a44cf Binary files /dev/null and b/gio/shader/gio/zcover.frag.1.dxbc differ diff --git a/gio/shader/gio/zcover.frag.1.glsl100es b/gio/shader/gio/zcover.frag.1.glsl100es new file mode 100644 index 0000000..01cc88e --- /dev/null +++ b/gio/shader/gio/zcover.frag.1.glsl100es @@ -0,0 +1,24 @@ +#version 100 +precision mediump float; +precision highp int; + +struct Gradient +{ + vec4 color1; + vec4 color2; +}; + +uniform Gradient _gradient; + +uniform mediump sampler2D cover; + +varying highp vec2 vUV; +varying highp vec2 vCoverUV; + +void main() +{ + gl_FragData[0] = mix(_gradient.color1, _gradient.color2, vec4(clamp(vUV.x, 0.0, 1.0))); + float c = min(abs(texture2D(cover, vCoverUV).x), 1.0); + gl_FragData[0] *= c; +} + diff --git a/gio/shader/gio/zcover.frag.1.glsl150 b/gio/shader/gio/zcover.frag.1.glsl150 new file mode 100644 index 0000000..3f832c3 --- /dev/null +++ b/gio/shader/gio/zcover.frag.1.glsl150 @@ -0,0 +1,23 @@ +#version 150 + +struct Gradient +{ + vec4 color1; + vec4 color2; +}; + +uniform Gradient _gradient; + +uniform sampler2D cover; + +out vec4 fragColor; +in vec2 vUV; +in vec2 vCoverUV; + +void main() +{ + fragColor = mix(_gradient.color1, _gradient.color2, vec4(clamp(vUV.x, 0.0, 1.0))); + float c = min(abs(texture(cover, vCoverUV).x), 1.0); + fragColor *= c; +} + diff --git a/gio/shader/gio/zcover.frag.1.metallibios b/gio/shader/gio/zcover.frag.1.metallibios new file mode 100644 index 0000000..228996a Binary files /dev/null and b/gio/shader/gio/zcover.frag.1.metallibios differ diff --git a/gio/shader/gio/zcover.frag.1.metallibiossimulator b/gio/shader/gio/zcover.frag.1.metallibiossimulator new file mode 100644 index 0000000..1c99553 Binary files /dev/null and b/gio/shader/gio/zcover.frag.1.metallibiossimulator differ diff --git a/gio/shader/gio/zcover.frag.1.metallibmacos b/gio/shader/gio/zcover.frag.1.metallibmacos new file mode 100644 index 0000000..889e249 Binary files /dev/null and b/gio/shader/gio/zcover.frag.1.metallibmacos differ diff --git a/gio/shader/gio/zcover.frag.1.spirv b/gio/shader/gio/zcover.frag.1.spirv new file mode 100644 index 0000000..4c48d20 Binary files /dev/null and b/gio/shader/gio/zcover.frag.1.spirv differ diff --git a/gio/shader/gio/zcover.frag.2.dxbc b/gio/shader/gio/zcover.frag.2.dxbc new file mode 100644 index 0000000..d8c6a80 Binary files /dev/null and b/gio/shader/gio/zcover.frag.2.dxbc differ diff --git a/gio/shader/gio/zcover.frag.2.glsl100es b/gio/shader/gio/zcover.frag.2.glsl100es new file mode 100644 index 0000000..7cfde4b --- /dev/null +++ b/gio/shader/gio/zcover.frag.2.glsl100es @@ -0,0 +1,17 @@ +#version 100 +precision mediump float; +precision highp int; + +uniform mediump sampler2D tex; +uniform mediump sampler2D cover; + +varying highp vec2 vUV; +varying highp vec2 vCoverUV; + +void main() +{ + gl_FragData[0] = texture2D(tex, vUV); + float c = min(abs(texture2D(cover, vCoverUV).x), 1.0); + gl_FragData[0] *= c; +} + diff --git a/gio/shader/gio/zcover.frag.2.glsl150 b/gio/shader/gio/zcover.frag.2.glsl150 new file mode 100644 index 0000000..939baee --- /dev/null +++ b/gio/shader/gio/zcover.frag.2.glsl150 @@ -0,0 +1,16 @@ +#version 150 + +uniform sampler2D tex; +uniform sampler2D cover; + +out vec4 fragColor; +in vec2 vUV; +in vec2 vCoverUV; + +void main() +{ + fragColor = texture(tex, vUV); + float c = min(abs(texture(cover, vCoverUV).x), 1.0); + fragColor *= c; +} + diff --git a/gio/shader/gio/zcover.frag.2.metallibios b/gio/shader/gio/zcover.frag.2.metallibios new file mode 100644 index 0000000..6eba400 Binary files /dev/null and b/gio/shader/gio/zcover.frag.2.metallibios differ diff --git a/gio/shader/gio/zcover.frag.2.metallibiossimulator b/gio/shader/gio/zcover.frag.2.metallibiossimulator new file mode 100644 index 0000000..09ddb1f Binary files /dev/null and b/gio/shader/gio/zcover.frag.2.metallibiossimulator differ diff --git a/gio/shader/gio/zcover.frag.2.metallibmacos b/gio/shader/gio/zcover.frag.2.metallibmacos new file mode 100644 index 0000000..3ba9105 Binary files /dev/null and b/gio/shader/gio/zcover.frag.2.metallibmacos differ diff --git a/gio/shader/gio/zcover.frag.2.spirv b/gio/shader/gio/zcover.frag.2.spirv new file mode 100644 index 0000000..cd618ce Binary files /dev/null and b/gio/shader/gio/zcover.frag.2.spirv differ diff --git a/gio/shader/gio/zcover.vert.0.dxbc b/gio/shader/gio/zcover.vert.0.dxbc new file mode 100644 index 0000000..3b6cf6b Binary files /dev/null and b/gio/shader/gio/zcover.vert.0.dxbc differ diff --git a/gio/shader/gio/zcover.vert.0.glsl100es b/gio/shader/gio/zcover.vert.0.glsl100es new file mode 100644 index 0000000..423ca60 --- /dev/null +++ b/gio/shader/gio/zcover.vert.0.glsl100es @@ -0,0 +1,41 @@ +#version 100 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec4 transform; + vec4 uvCoverTransform; + vec4 uvTransformR1; + vec4 uvTransformR2; +}; + +uniform Block _block; + +attribute vec2 pos; +varying vec2 vUV; +attribute vec2 uv; +varying vec2 vCoverUV; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + vec2 p = vec2((pos * _block.transform.xy) + _block.transform.zw); + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0)); + vec3 param_1 = vec3(p, 0.0); + gl_Position = vec4(transform3x2(param, param_1), 1.0); + m3x2 param_2 = m3x2(_block.uvTransformR1.xyz, _block.uvTransformR2.xyz); + vec3 param_3 = vec3(uv, 1.0); + vUV = transform3x2(param_2, param_3).xy; + vec3 uv3 = vec3(uv, 1.0); + vCoverUV = ((uv3 * vec3(_block.uvCoverTransform.xy, 1.0)) + vec3(_block.uvCoverTransform.zw, 0.0)).xy; +} + diff --git a/gio/shader/gio/zcover.vert.0.glsl150 b/gio/shader/gio/zcover.vert.0.glsl150 new file mode 100644 index 0000000..a5005d6 --- /dev/null +++ b/gio/shader/gio/zcover.vert.0.glsl150 @@ -0,0 +1,41 @@ +#version 150 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec4 transform; + vec4 uvCoverTransform; + vec4 uvTransformR1; + vec4 uvTransformR2; +}; + +uniform Block _block; + +in vec2 pos; +out vec2 vUV; +in vec2 uv; +out vec2 vCoverUV; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + vec2 p = vec2((pos * _block.transform.xy) + _block.transform.zw); + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0)); + vec3 param_1 = vec3(p, 0.0); + gl_Position = vec4(transform3x2(param, param_1), 1.0); + m3x2 param_2 = m3x2(_block.uvTransformR1.xyz, _block.uvTransformR2.xyz); + vec3 param_3 = vec3(uv, 1.0); + vUV = transform3x2(param_2, param_3).xy; + vec3 uv3 = vec3(uv, 1.0); + vCoverUV = ((uv3 * vec3(_block.uvCoverTransform.xy, 1.0)) + vec3(_block.uvCoverTransform.zw, 0.0)).xy; +} + diff --git a/gio/shader/gio/zcover.vert.0.metallibios b/gio/shader/gio/zcover.vert.0.metallibios new file mode 100644 index 0000000..335704b Binary files /dev/null and b/gio/shader/gio/zcover.vert.0.metallibios differ diff --git a/gio/shader/gio/zcover.vert.0.metallibiossimulator b/gio/shader/gio/zcover.vert.0.metallibiossimulator new file mode 100644 index 0000000..96470cd Binary files /dev/null and b/gio/shader/gio/zcover.vert.0.metallibiossimulator differ diff --git a/gio/shader/gio/zcover.vert.0.metallibmacos b/gio/shader/gio/zcover.vert.0.metallibmacos new file mode 100644 index 0000000..629e82b Binary files /dev/null and b/gio/shader/gio/zcover.vert.0.metallibmacos differ diff --git a/gio/shader/gio/zcover.vert.0.spirv b/gio/shader/gio/zcover.vert.0.spirv new file mode 100644 index 0000000..f9af8ab Binary files /dev/null and b/gio/shader/gio/zcover.vert.0.spirv differ diff --git a/gio/shader/gio/zinput.vert.0.dxbc b/gio/shader/gio/zinput.vert.0.dxbc new file mode 100644 index 0000000..096bd01 Binary files /dev/null and b/gio/shader/gio/zinput.vert.0.dxbc differ diff --git a/gio/shader/gio/zinput.vert.0.glsl100es b/gio/shader/gio/zinput.vert.0.glsl100es new file mode 100644 index 0000000..d1d4c8d --- /dev/null +++ b/gio/shader/gio/zinput.vert.0.glsl100es @@ -0,0 +1,22 @@ +#version 100 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +attribute vec4 position; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0)); + vec3 param_1 = position.xyz; + gl_Position = vec4(transform3x2(param, param_1), position.w); +} + diff --git a/gio/shader/gio/zinput.vert.0.glsl150 b/gio/shader/gio/zinput.vert.0.glsl150 new file mode 100644 index 0000000..ab28308 --- /dev/null +++ b/gio/shader/gio/zinput.vert.0.glsl150 @@ -0,0 +1,22 @@ +#version 150 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +in vec4 position; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0)); + vec3 param_1 = position.xyz; + gl_Position = vec4(transform3x2(param, param_1), position.w); +} + diff --git a/gio/shader/gio/zinput.vert.0.metallibios b/gio/shader/gio/zinput.vert.0.metallibios new file mode 100644 index 0000000..6fdc427 Binary files /dev/null and b/gio/shader/gio/zinput.vert.0.metallibios differ diff --git a/gio/shader/gio/zinput.vert.0.metallibiossimulator b/gio/shader/gio/zinput.vert.0.metallibiossimulator new file mode 100644 index 0000000..da28890 Binary files /dev/null and b/gio/shader/gio/zinput.vert.0.metallibiossimulator differ diff --git a/gio/shader/gio/zinput.vert.0.metallibmacos b/gio/shader/gio/zinput.vert.0.metallibmacos new file mode 100644 index 0000000..064c501 Binary files /dev/null and b/gio/shader/gio/zinput.vert.0.metallibmacos differ diff --git a/gio/shader/gio/zinput.vert.0.spirv b/gio/shader/gio/zinput.vert.0.spirv new file mode 100644 index 0000000..eb999e5 Binary files /dev/null and b/gio/shader/gio/zinput.vert.0.spirv differ diff --git a/gio/shader/gio/zintersect.frag.0.dxbc b/gio/shader/gio/zintersect.frag.0.dxbc new file mode 100644 index 0000000..f2081ee Binary files /dev/null and b/gio/shader/gio/zintersect.frag.0.dxbc differ diff --git a/gio/shader/gio/zintersect.frag.0.glsl100es b/gio/shader/gio/zintersect.frag.0.glsl100es new file mode 100644 index 0000000..90fe2f9 --- /dev/null +++ b/gio/shader/gio/zintersect.frag.0.glsl100es @@ -0,0 +1,13 @@ +#version 100 +precision mediump float; +precision highp int; + +uniform mediump sampler2D cover; + +varying highp vec2 vUV; + +void main() +{ + gl_FragData[0].x = abs(texture2D(cover, vUV).x); +} + diff --git a/gio/shader/gio/zintersect.frag.0.glsl150 b/gio/shader/gio/zintersect.frag.0.glsl150 new file mode 100644 index 0000000..f574aae --- /dev/null +++ b/gio/shader/gio/zintersect.frag.0.glsl150 @@ -0,0 +1,12 @@ +#version 150 + +uniform sampler2D cover; + +out vec4 fragColor; +in vec2 vUV; + +void main() +{ + fragColor.x = abs(texture(cover, vUV).x); +} + diff --git a/gio/shader/gio/zintersect.frag.0.metallibios b/gio/shader/gio/zintersect.frag.0.metallibios new file mode 100644 index 0000000..f48da4e Binary files /dev/null and b/gio/shader/gio/zintersect.frag.0.metallibios differ diff --git a/gio/shader/gio/zintersect.frag.0.metallibiossimulator b/gio/shader/gio/zintersect.frag.0.metallibiossimulator new file mode 100644 index 0000000..b1a40c4 Binary files /dev/null and b/gio/shader/gio/zintersect.frag.0.metallibiossimulator differ diff --git a/gio/shader/gio/zintersect.frag.0.metallibmacos b/gio/shader/gio/zintersect.frag.0.metallibmacos new file mode 100644 index 0000000..f16d190 Binary files /dev/null and b/gio/shader/gio/zintersect.frag.0.metallibmacos differ diff --git a/gio/shader/gio/zintersect.frag.0.spirv b/gio/shader/gio/zintersect.frag.0.spirv new file mode 100644 index 0000000..6c28644 Binary files /dev/null and b/gio/shader/gio/zintersect.frag.0.spirv differ diff --git a/gio/shader/gio/zintersect.vert.0.dxbc b/gio/shader/gio/zintersect.vert.0.dxbc new file mode 100644 index 0000000..03005ea Binary files /dev/null and b/gio/shader/gio/zintersect.vert.0.dxbc differ diff --git a/gio/shader/gio/zintersect.vert.0.glsl100es b/gio/shader/gio/zintersect.vert.0.glsl100es new file mode 100644 index 0000000..4441763 --- /dev/null +++ b/gio/shader/gio/zintersect.vert.0.glsl100es @@ -0,0 +1,35 @@ +#version 100 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec4 uvTransform; + vec4 subUVTransform; +}; + +uniform Block _block; + +attribute vec2 pos; +varying vec2 vUV; +attribute vec2 uv; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0)); + vec3 param_1 = vec3(pos, 1.0); + vec3 p = transform3x2(param, param_1); + gl_Position = vec4(p, 1.0); + vUV = (uv * _block.subUVTransform.xy) + _block.subUVTransform.zw; + vUV = (vUV * _block.uvTransform.xy) + _block.uvTransform.zw; +} + diff --git a/gio/shader/gio/zintersect.vert.0.glsl150 b/gio/shader/gio/zintersect.vert.0.glsl150 new file mode 100644 index 0000000..656b4c9 --- /dev/null +++ b/gio/shader/gio/zintersect.vert.0.glsl150 @@ -0,0 +1,35 @@ +#version 150 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec4 uvTransform; + vec4 subUVTransform; +}; + +uniform Block _block; + +in vec2 pos; +out vec2 vUV; +in vec2 uv; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0)); + vec3 param_1 = vec3(pos, 1.0); + vec3 p = transform3x2(param, param_1); + gl_Position = vec4(p, 1.0); + vUV = (uv * _block.subUVTransform.xy) + _block.subUVTransform.zw; + vUV = (vUV * _block.uvTransform.xy) + _block.uvTransform.zw; +} + diff --git a/gio/shader/gio/zintersect.vert.0.metallibios b/gio/shader/gio/zintersect.vert.0.metallibios new file mode 100644 index 0000000..975fbb8 Binary files /dev/null and b/gio/shader/gio/zintersect.vert.0.metallibios differ diff --git a/gio/shader/gio/zintersect.vert.0.metallibiossimulator b/gio/shader/gio/zintersect.vert.0.metallibiossimulator new file mode 100644 index 0000000..682bad1 Binary files /dev/null and b/gio/shader/gio/zintersect.vert.0.metallibiossimulator differ diff --git a/gio/shader/gio/zintersect.vert.0.metallibmacos b/gio/shader/gio/zintersect.vert.0.metallibmacos new file mode 100644 index 0000000..a43236d Binary files /dev/null and b/gio/shader/gio/zintersect.vert.0.metallibmacos differ diff --git a/gio/shader/gio/zintersect.vert.0.spirv b/gio/shader/gio/zintersect.vert.0.spirv new file mode 100644 index 0000000..13e7335 Binary files /dev/null and b/gio/shader/gio/zintersect.vert.0.spirv differ diff --git a/gio/shader/gio/zmaterial.frag.0.dxbc b/gio/shader/gio/zmaterial.frag.0.dxbc new file mode 100644 index 0000000..e250378 Binary files /dev/null and b/gio/shader/gio/zmaterial.frag.0.dxbc differ diff --git a/gio/shader/gio/zmaterial.frag.0.glsl100es b/gio/shader/gio/zmaterial.frag.0.glsl100es new file mode 100644 index 0000000..f2f2a30 --- /dev/null +++ b/gio/shader/gio/zmaterial.frag.0.glsl100es @@ -0,0 +1,37 @@ +#version 100 +precision mediump float; +precision highp int; + +struct Color +{ + float emulateSRGB; +}; + +uniform Color _color; + +uniform mediump sampler2D tex; + +varying highp vec2 vUV; + +vec3 RGBtosRGB(vec3 rgb) +{ + bvec3 cutoff = greaterThanEqual(rgb, vec3(0.003130800090730190277099609375)); + vec3 below = vec3(12.9200000762939453125) * rgb; + vec3 above = (vec3(1.05499994754791259765625) * pow(rgb, vec3(0.416660010814666748046875))) - vec3(0.054999999701976776123046875); + return vec3(cutoff.x ? above.x : below.x, cutoff.y ? above.y : below.y, cutoff.z ? above.z : below.z); +} + +void main() +{ + vec4 texel = texture2D(tex, vUV); + if (_color.emulateSRGB == 0.0) + { + vec3 param = texel.xyz; + vec3 _71 = RGBtosRGB(param); + texel.x = _71.x; + texel.y = _71.y; + texel.z = _71.z; + } + gl_FragData[0] = texel; +} + diff --git a/gio/shader/gio/zmaterial.frag.0.glsl150 b/gio/shader/gio/zmaterial.frag.0.glsl150 new file mode 100644 index 0000000..6b8bed3 --- /dev/null +++ b/gio/shader/gio/zmaterial.frag.0.glsl150 @@ -0,0 +1,36 @@ +#version 150 + +struct Color +{ + float emulateSRGB; +}; + +uniform Color _color; + +uniform sampler2D tex; + +in vec2 vUV; +out vec4 fragColor; + +vec3 RGBtosRGB(vec3 rgb) +{ + bvec3 cutoff = greaterThanEqual(rgb, vec3(0.003130800090730190277099609375)); + vec3 below = vec3(12.9200000762939453125) * rgb; + vec3 above = (vec3(1.05499994754791259765625) * pow(rgb, vec3(0.416660010814666748046875))) - vec3(0.054999999701976776123046875); + return vec3(cutoff.x ? above.x : below.x, cutoff.y ? above.y : below.y, cutoff.z ? above.z : below.z); +} + +void main() +{ + vec4 texel = texture(tex, vUV); + if (_color.emulateSRGB == 0.0) + { + vec3 param = texel.xyz; + vec3 _71 = RGBtosRGB(param); + texel.x = _71.x; + texel.y = _71.y; + texel.z = _71.z; + } + fragColor = texel; +} + diff --git a/gio/shader/gio/zmaterial.frag.0.metallibios b/gio/shader/gio/zmaterial.frag.0.metallibios new file mode 100644 index 0000000..8679f2a Binary files /dev/null and b/gio/shader/gio/zmaterial.frag.0.metallibios differ diff --git a/gio/shader/gio/zmaterial.frag.0.metallibiossimulator b/gio/shader/gio/zmaterial.frag.0.metallibiossimulator new file mode 100644 index 0000000..6306d9a Binary files /dev/null and b/gio/shader/gio/zmaterial.frag.0.metallibiossimulator differ diff --git a/gio/shader/gio/zmaterial.frag.0.metallibmacos b/gio/shader/gio/zmaterial.frag.0.metallibmacos new file mode 100644 index 0000000..911948e Binary files /dev/null and b/gio/shader/gio/zmaterial.frag.0.metallibmacos differ diff --git a/gio/shader/gio/zmaterial.frag.0.spirv b/gio/shader/gio/zmaterial.frag.0.spirv new file mode 100644 index 0000000..475cfb8 Binary files /dev/null and b/gio/shader/gio/zmaterial.frag.0.spirv differ diff --git a/gio/shader/gio/zmaterial.vert.0.dxbc b/gio/shader/gio/zmaterial.vert.0.dxbc new file mode 100644 index 0000000..a5056cc Binary files /dev/null and b/gio/shader/gio/zmaterial.vert.0.dxbc differ diff --git a/gio/shader/gio/zmaterial.vert.0.glsl100es b/gio/shader/gio/zmaterial.vert.0.glsl100es new file mode 100644 index 0000000..39a7b50 --- /dev/null +++ b/gio/shader/gio/zmaterial.vert.0.glsl100es @@ -0,0 +1,34 @@ +#version 100 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec2 scale; + vec2 pos; +}; + +uniform Block _block; + +varying vec2 vUV; +attribute vec2 uv; +attribute vec2 pos; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + vUV = uv; + vec2 p = vec2((pos * _block.scale) + _block.pos); + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0)); + vec3 param_1 = vec3(p, 0.0); + gl_Position = vec4(transform3x2(param, param_1), 1.0); +} + diff --git a/gio/shader/gio/zmaterial.vert.0.glsl150 b/gio/shader/gio/zmaterial.vert.0.glsl150 new file mode 100644 index 0000000..be02b44 --- /dev/null +++ b/gio/shader/gio/zmaterial.vert.0.glsl150 @@ -0,0 +1,34 @@ +#version 150 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec2 scale; + vec2 pos; +}; + +uniform Block _block; + +out vec2 vUV; +in vec2 uv; +in vec2 pos; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + vUV = uv; + vec2 p = vec2((pos * _block.scale) + _block.pos); + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0)); + vec3 param_1 = vec3(p, 0.0); + gl_Position = vec4(transform3x2(param, param_1), 1.0); +} + diff --git a/gio/shader/gio/zmaterial.vert.0.metallibios b/gio/shader/gio/zmaterial.vert.0.metallibios new file mode 100644 index 0000000..19cf6d8 Binary files /dev/null and b/gio/shader/gio/zmaterial.vert.0.metallibios differ diff --git a/gio/shader/gio/zmaterial.vert.0.metallibiossimulator b/gio/shader/gio/zmaterial.vert.0.metallibiossimulator new file mode 100644 index 0000000..c710ca9 Binary files /dev/null and b/gio/shader/gio/zmaterial.vert.0.metallibiossimulator differ diff --git a/gio/shader/gio/zmaterial.vert.0.metallibmacos b/gio/shader/gio/zmaterial.vert.0.metallibmacos new file mode 100644 index 0000000..cfbdfbc Binary files /dev/null and b/gio/shader/gio/zmaterial.vert.0.metallibmacos differ diff --git a/gio/shader/gio/zmaterial.vert.0.spirv b/gio/shader/gio/zmaterial.vert.0.spirv new file mode 100644 index 0000000..18e731f Binary files /dev/null and b/gio/shader/gio/zmaterial.vert.0.spirv differ diff --git a/gio/shader/gio/zsimple.frag.0.dxbc b/gio/shader/gio/zsimple.frag.0.dxbc new file mode 100644 index 0000000..f4f8894 Binary files /dev/null and b/gio/shader/gio/zsimple.frag.0.dxbc differ diff --git a/gio/shader/gio/zsimple.frag.0.glsl100es b/gio/shader/gio/zsimple.frag.0.glsl100es new file mode 100644 index 0000000..0f86af5 --- /dev/null +++ b/gio/shader/gio/zsimple.frag.0.glsl100es @@ -0,0 +1,9 @@ +#version 100 +precision mediump float; +precision highp int; + +void main() +{ + gl_FragData[0] = vec4(0.25, 0.550000011920928955078125, 0.75, 1.0); +} + diff --git a/gio/shader/gio/zsimple.frag.0.glsl150 b/gio/shader/gio/zsimple.frag.0.glsl150 new file mode 100644 index 0000000..db4c060 --- /dev/null +++ b/gio/shader/gio/zsimple.frag.0.glsl150 @@ -0,0 +1,9 @@ +#version 150 + +out vec4 fragColor; + +void main() +{ + fragColor = vec4(0.25, 0.550000011920928955078125, 0.75, 1.0); +} + diff --git a/gio/shader/gio/zsimple.frag.0.metallibios b/gio/shader/gio/zsimple.frag.0.metallibios new file mode 100644 index 0000000..05e6329 Binary files /dev/null and b/gio/shader/gio/zsimple.frag.0.metallibios differ diff --git a/gio/shader/gio/zsimple.frag.0.metallibiossimulator b/gio/shader/gio/zsimple.frag.0.metallibiossimulator new file mode 100644 index 0000000..2c87af9 Binary files /dev/null and b/gio/shader/gio/zsimple.frag.0.metallibiossimulator differ diff --git a/gio/shader/gio/zsimple.frag.0.metallibmacos b/gio/shader/gio/zsimple.frag.0.metallibmacos new file mode 100644 index 0000000..407d7ea Binary files /dev/null and b/gio/shader/gio/zsimple.frag.0.metallibmacos differ diff --git a/gio/shader/gio/zsimple.frag.0.spirv b/gio/shader/gio/zsimple.frag.0.spirv new file mode 100644 index 0000000..2b2aba3 Binary files /dev/null and b/gio/shader/gio/zsimple.frag.0.spirv differ diff --git a/gio/shader/gio/zstencil.frag.0.dxbc b/gio/shader/gio/zstencil.frag.0.dxbc new file mode 100644 index 0000000..ded34dc Binary files /dev/null and b/gio/shader/gio/zstencil.frag.0.dxbc differ diff --git a/gio/shader/gio/zstencil.frag.0.glsl100es b/gio/shader/gio/zstencil.frag.0.glsl100es new file mode 100644 index 0000000..15530e3 --- /dev/null +++ b/gio/shader/gio/zstencil.frag.0.glsl100es @@ -0,0 +1,38 @@ +#version 100 +precision mediump float; +precision highp int; + +varying highp vec2 vTo; +varying highp vec2 vFrom; +varying highp vec2 vCtrl; + +void main() +{ + float dx = vTo.x - vFrom.x; + bool increasing = vTo.x >= vFrom.x; + bvec2 _35 = bvec2(increasing); + vec2 left = vec2(_35.x ? vFrom.x : vTo.x, _35.y ? vFrom.y : vTo.y); + bvec2 _41 = bvec2(increasing); + vec2 right = vec2(_41.x ? vTo.x : vFrom.x, _41.y ? vTo.y : vFrom.y); + vec2 extent = clamp(vec2(vFrom.x, vTo.x), vec2(-0.5), vec2(0.5)); + float midx = mix(extent.x, extent.y, 0.5); + float x0 = midx - left.x; + vec2 p1 = vCtrl - left; + vec2 v = right - vCtrl; + float t = x0 / (p1.x + sqrt((p1.x * p1.x) + ((v.x - p1.x) * x0))); + float y = mix(mix(left.y, vCtrl.y, t), mix(vCtrl.y, right.y, t), t); + vec2 d_half = mix(p1, v, vec2(t)); + float dy = d_half.y / d_half.x; + float width = extent.y - extent.x; + dy = abs(dy * width); + vec4 sides = vec4((dy * 0.5) + y, (dy * (-0.5)) + y, (0.5 - y) / dy, ((-0.5) - y) / dy); + sides = clamp(sides + vec4(0.5), vec4(0.0), vec4(1.0)); + float area = 0.5 * ((((sides.z - (sides.z * sides.y)) + 1.0) - sides.x) + (sides.x * sides.w)); + area *= width; + if (width == 0.0) + { + area = 0.0; + } + gl_FragData[0].x = area; +} + diff --git a/gio/shader/gio/zstencil.frag.0.glsl150 b/gio/shader/gio/zstencil.frag.0.glsl150 new file mode 100644 index 0000000..8e2abd8 --- /dev/null +++ b/gio/shader/gio/zstencil.frag.0.glsl150 @@ -0,0 +1,37 @@ +#version 150 + +in vec2 vTo; +in vec2 vFrom; +in vec2 vCtrl; +out vec4 fragCover; + +void main() +{ + float dx = vTo.x - vFrom.x; + bool increasing = vTo.x >= vFrom.x; + bvec2 _35 = bvec2(increasing); + vec2 left = vec2(_35.x ? vFrom.x : vTo.x, _35.y ? vFrom.y : vTo.y); + bvec2 _41 = bvec2(increasing); + vec2 right = vec2(_41.x ? vTo.x : vFrom.x, _41.y ? vTo.y : vFrom.y); + vec2 extent = clamp(vec2(vFrom.x, vTo.x), vec2(-0.5), vec2(0.5)); + float midx = mix(extent.x, extent.y, 0.5); + float x0 = midx - left.x; + vec2 p1 = vCtrl - left; + vec2 v = right - vCtrl; + float t = x0 / (p1.x + sqrt((p1.x * p1.x) + ((v.x - p1.x) * x0))); + float y = mix(mix(left.y, vCtrl.y, t), mix(vCtrl.y, right.y, t), t); + vec2 d_half = mix(p1, v, vec2(t)); + float dy = d_half.y / d_half.x; + float width = extent.y - extent.x; + dy = abs(dy * width); + vec4 sides = vec4((dy * 0.5) + y, (dy * (-0.5)) + y, (0.5 - y) / dy, ((-0.5) - y) / dy); + sides = clamp(sides + vec4(0.5), vec4(0.0), vec4(1.0)); + float area = 0.5 * ((((sides.z - (sides.z * sides.y)) + 1.0) - sides.x) + (sides.x * sides.w)); + area *= width; + if (width == 0.0) + { + area = 0.0; + } + fragCover.x = area; +} + diff --git a/gio/shader/gio/zstencil.frag.0.metallibios b/gio/shader/gio/zstencil.frag.0.metallibios new file mode 100644 index 0000000..52f668f Binary files /dev/null and b/gio/shader/gio/zstencil.frag.0.metallibios differ diff --git a/gio/shader/gio/zstencil.frag.0.metallibiossimulator b/gio/shader/gio/zstencil.frag.0.metallibiossimulator new file mode 100644 index 0000000..3fbfa8f Binary files /dev/null and b/gio/shader/gio/zstencil.frag.0.metallibiossimulator differ diff --git a/gio/shader/gio/zstencil.frag.0.metallibmacos b/gio/shader/gio/zstencil.frag.0.metallibmacos new file mode 100644 index 0000000..358a02a Binary files /dev/null and b/gio/shader/gio/zstencil.frag.0.metallibmacos differ diff --git a/gio/shader/gio/zstencil.frag.0.spirv b/gio/shader/gio/zstencil.frag.0.spirv new file mode 100644 index 0000000..9a22d9e Binary files /dev/null and b/gio/shader/gio/zstencil.frag.0.spirv differ diff --git a/gio/shader/gio/zstencil.vert.0.dxbc b/gio/shader/gio/zstencil.vert.0.dxbc new file mode 100644 index 0000000..505672f Binary files /dev/null and b/gio/shader/gio/zstencil.vert.0.dxbc differ diff --git a/gio/shader/gio/zstencil.vert.0.glsl100es b/gio/shader/gio/zstencil.vert.0.glsl100es new file mode 100644 index 0000000..c8e1261 --- /dev/null +++ b/gio/shader/gio/zstencil.vert.0.glsl100es @@ -0,0 +1,64 @@ +#version 100 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec4 transform; + vec2 pathOffset; +}; + +uniform Block _block; + +attribute vec2 from; +attribute vec2 ctrl; +attribute vec2 to; +attribute float maxy; +attribute float corner; +varying vec2 vFrom; +varying vec2 vCtrl; +varying vec2 vTo; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + vec2 from_1 = from + _block.pathOffset; + vec2 ctrl_1 = ctrl + _block.pathOffset; + vec2 to_1 = to + _block.pathOffset; + float maxy_1 = maxy + _block.pathOffset.y; + float c = corner; + vec2 pos; + if (c >= 0.375) + { + c -= 0.5; + pos.y = maxy_1 + 1.0; + } + else + { + pos.y = min(min(from_1.y, ctrl_1.y), to_1.y) - 1.0; + } + if (c >= 0.125) + { + pos.x = max(max(from_1.x, ctrl_1.x), to_1.x) + 1.0; + } + else + { + pos.x = min(min(from_1.x, ctrl_1.x), to_1.x) - 1.0; + } + vFrom = from_1 - pos; + vCtrl = ctrl_1 - pos; + vTo = to_1 - pos; + pos = (pos * _block.transform.xy) + _block.transform.zw; + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0)); + vec3 param_1 = vec3(pos, 0.0); + gl_Position = vec4(transform3x2(param, param_1), 1.0); +} + diff --git a/gio/shader/gio/zstencil.vert.0.glsl150 b/gio/shader/gio/zstencil.vert.0.glsl150 new file mode 100644 index 0000000..9ae6c9b --- /dev/null +++ b/gio/shader/gio/zstencil.vert.0.glsl150 @@ -0,0 +1,64 @@ +#version 150 + +struct m3x2 +{ + vec3 r0; + vec3 r1; +}; + +struct Block +{ + vec4 transform; + vec2 pathOffset; +}; + +uniform Block _block; + +in vec2 from; +in vec2 ctrl; +in vec2 to; +in float maxy; +in float corner; +out vec2 vFrom; +out vec2 vCtrl; +out vec2 vTo; + +vec3 transform3x2(m3x2 t, vec3 v) +{ + return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); +} + +void main() +{ + vec2 from_1 = from + _block.pathOffset; + vec2 ctrl_1 = ctrl + _block.pathOffset; + vec2 to_1 = to + _block.pathOffset; + float maxy_1 = maxy + _block.pathOffset.y; + float c = corner; + vec2 pos; + if (c >= 0.375) + { + c -= 0.5; + pos.y = maxy_1 + 1.0; + } + else + { + pos.y = min(min(from_1.y, ctrl_1.y), to_1.y) - 1.0; + } + if (c >= 0.125) + { + pos.x = max(max(from_1.x, ctrl_1.x), to_1.x) + 1.0; + } + else + { + pos.x = min(min(from_1.x, ctrl_1.x), to_1.x) - 1.0; + } + vFrom = from_1 - pos; + vCtrl = ctrl_1 - pos; + vTo = to_1 - pos; + pos = (pos * _block.transform.xy) + _block.transform.zw; + m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0)); + vec3 param_1 = vec3(pos, 0.0); + gl_Position = vec4(transform3x2(param, param_1), 1.0); +} + diff --git a/gio/shader/gio/zstencil.vert.0.metallibios b/gio/shader/gio/zstencil.vert.0.metallibios new file mode 100644 index 0000000..75ac068 Binary files /dev/null and b/gio/shader/gio/zstencil.vert.0.metallibios differ diff --git a/gio/shader/gio/zstencil.vert.0.metallibiossimulator b/gio/shader/gio/zstencil.vert.0.metallibiossimulator new file mode 100644 index 0000000..9ba5f58 Binary files /dev/null and b/gio/shader/gio/zstencil.vert.0.metallibiossimulator differ diff --git a/gio/shader/gio/zstencil.vert.0.metallibmacos b/gio/shader/gio/zstencil.vert.0.metallibmacos new file mode 100644 index 0000000..4de454d Binary files /dev/null and b/gio/shader/gio/zstencil.vert.0.metallibmacos differ diff --git a/gio/shader/gio/zstencil.vert.0.spirv b/gio/shader/gio/zstencil.vert.0.spirv new file mode 100644 index 0000000..b45803f Binary files /dev/null and b/gio/shader/gio/zstencil.vert.0.spirv differ diff --git a/gio/shader/go.mod b/gio/shader/go.mod new file mode 100644 index 0000000..dcb1581 --- /dev/null +++ b/gio/shader/go.mod @@ -0,0 +1,3 @@ +module gioui.org/shader + +go 1.16 diff --git a/gio/shader/go.sum b/gio/shader/go.sum new file mode 100644 index 0000000..e69de29 diff --git a/gio/shader/piet/abi.h b/gio/shader/piet/abi.h new file mode 100644 index 0000000..365d936 --- /dev/null +++ b/gio/shader/piet/abi.h @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +#define ALIGN(bytes, type) type __attribute__((aligned(bytes))) + +typedef ALIGN(8, uint8_t) byte8[8]; +typedef ALIGN(8, uint16_t) word4[4]; +typedef ALIGN(4, uint32_t) dword; +typedef ALIGN(16, uint32_t) dword4[4]; +typedef ALIGN(8, uint64_t) qword; +typedef ALIGN(16, uint64_t) qword2[2]; +typedef ALIGN(16, unsigned int) uint4[4]; +typedef ALIGN(8, uint32_t) dword2[2]; +typedef ALIGN(8, unsigned short) ushort4[4]; +typedef ALIGN(16, float) float4[4]; +typedef ALIGN(16, int) int4[4]; + +typedef unsigned short half; + +typedef unsigned char bool; + +enum { + MAX_BOUND_DESCRIPTOR_SETS = 4, + MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC = 8, + MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC = 4, + MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC = + MAX_DESCRIPTOR_SET_UNIFORM_BUFFERS_DYNAMIC + + MAX_DESCRIPTOR_SET_STORAGE_BUFFERS_DYNAMIC, + MAX_PUSH_CONSTANT_SIZE = 128, + + MIN_STORAGE_BUFFER_OFFSET_ALIGNMENT = 256, + + REQUIRED_MEMORY_ALIGNMENT = 16, + + SIMD_WIDTH = 4, +}; + +struct image_descriptor { + ALIGN(16, void *ptr); + int width; + int height; + int depth; + int row_pitch_bytes; + int slice_pitch_bytes; + int sample_pitch_bytes; + int sample_count; + int size_in_bytes; + + void *stencil_ptr; + int stencil_row_pitch_bytes; + int stencil_slice_pitch_bytes; + int stencil_sample_pitch_bytes; + + // TODO: unused? + void *memoryOwner; +}; + +struct buffer_descriptor { + ALIGN(16, void *ptr); + int size_in_bytes; + int robustness_size; +}; + +struct program_data { + uint8_t *descriptor_sets[MAX_BOUND_DESCRIPTOR_SETS]; + uint32_t descriptor_dynamic_offsets[MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC]; + uint4 num_workgroups; + uint4 workgroup_size; + uint32_t invocations_per_subgroup; + uint32_t subgroups_per_workgroup; + uint32_t invocations_per_workgroup; + unsigned char push_constants[MAX_PUSH_CONSTANT_SIZE]; + // Unused. + void *constants; +}; + +typedef int32_t yield_result; + +typedef void * coroutine; + +typedef coroutine (*routine_begin)(struct program_data *data, + int32_t workgroupX, + int32_t workgroupY, + int32_t workgroupZ, + void *workgroupMemory, + int32_t firstSubgroup, + int32_t subgroupCount); + +typedef bool (*routine_await)(coroutine r, yield_result *res); + +typedef void (*routine_destroy)(coroutine r); + diff --git a/gio/shader/piet/annotated.h b/gio/shader/piet/annotated.h new file mode 100644 index 0000000..6b18155 --- /dev/null +++ b/gio/shader/piet/annotated.h @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense + +// Code auto-generated by piet-gpu-derive + +struct AnnoImageRef { + uint offset; +}; + +struct AnnoColorRef { + uint offset; +}; + +struct AnnoBeginClipRef { + uint offset; +}; + +struct AnnoEndClipRef { + uint offset; +}; + +struct AnnotatedRef { + uint offset; +}; + +struct AnnoImage { + vec4 bbox; + float linewidth; + uint index; + ivec2 offset; +}; + +#define AnnoImage_size 28 + +AnnoImageRef AnnoImage_index(AnnoImageRef ref, uint index) { + return AnnoImageRef(ref.offset + index * AnnoImage_size); +} + +struct AnnoColor { + vec4 bbox; + float linewidth; + uint rgba_color; +}; + +#define AnnoColor_size 24 + +AnnoColorRef AnnoColor_index(AnnoColorRef ref, uint index) { + return AnnoColorRef(ref.offset + index * AnnoColor_size); +} + +struct AnnoBeginClip { + vec4 bbox; + float linewidth; +}; + +#define AnnoBeginClip_size 20 + +AnnoBeginClipRef AnnoBeginClip_index(AnnoBeginClipRef ref, uint index) { + return AnnoBeginClipRef(ref.offset + index * AnnoBeginClip_size); +} + +struct AnnoEndClip { + vec4 bbox; +}; + +#define AnnoEndClip_size 16 + +AnnoEndClipRef AnnoEndClip_index(AnnoEndClipRef ref, uint index) { + return AnnoEndClipRef(ref.offset + index * AnnoEndClip_size); +} + +#define Annotated_Nop 0 +#define Annotated_Color 1 +#define Annotated_Image 2 +#define Annotated_BeginClip 3 +#define Annotated_EndClip 4 +#define Annotated_size 32 + +AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) { + return AnnotatedRef(ref.offset + index * Annotated_size); +} + +struct AnnotatedTag { + uint tag; + uint flags; +}; + +AnnoImage AnnoImage_read(Alloc a, AnnoImageRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + uint raw2 = read_mem(a, ix + 2); + uint raw3 = read_mem(a, ix + 3); + uint raw4 = read_mem(a, ix + 4); + uint raw5 = read_mem(a, ix + 5); + uint raw6 = read_mem(a, ix + 6); + AnnoImage s; + s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.linewidth = uintBitsToFloat(raw4); + s.index = raw5; + s.offset = ivec2(int(raw6 << 16) >> 16, int(raw6) >> 16); + return s; +} + +void AnnoImage_write(Alloc a, AnnoImageRef ref, AnnoImage s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, floatBitsToUint(s.bbox.x)); + write_mem(a, ix + 1, floatBitsToUint(s.bbox.y)); + write_mem(a, ix + 2, floatBitsToUint(s.bbox.z)); + write_mem(a, ix + 3, floatBitsToUint(s.bbox.w)); + write_mem(a, ix + 4, floatBitsToUint(s.linewidth)); + write_mem(a, ix + 5, s.index); + write_mem(a, ix + 6, (uint(s.offset.x) & 0xffff) | (uint(s.offset.y) << 16)); +} + +AnnoColor AnnoColor_read(Alloc a, AnnoColorRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + uint raw2 = read_mem(a, ix + 2); + uint raw3 = read_mem(a, ix + 3); + uint raw4 = read_mem(a, ix + 4); + uint raw5 = read_mem(a, ix + 5); + AnnoColor s; + s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.linewidth = uintBitsToFloat(raw4); + s.rgba_color = raw5; + return s; +} + +void AnnoColor_write(Alloc a, AnnoColorRef ref, AnnoColor s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, floatBitsToUint(s.bbox.x)); + write_mem(a, ix + 1, floatBitsToUint(s.bbox.y)); + write_mem(a, ix + 2, floatBitsToUint(s.bbox.z)); + write_mem(a, ix + 3, floatBitsToUint(s.bbox.w)); + write_mem(a, ix + 4, floatBitsToUint(s.linewidth)); + write_mem(a, ix + 5, s.rgba_color); +} + +AnnoBeginClip AnnoBeginClip_read(Alloc a, AnnoBeginClipRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + uint raw2 = read_mem(a, ix + 2); + uint raw3 = read_mem(a, ix + 3); + uint raw4 = read_mem(a, ix + 4); + AnnoBeginClip s; + s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.linewidth = uintBitsToFloat(raw4); + return s; +} + +void AnnoBeginClip_write(Alloc a, AnnoBeginClipRef ref, AnnoBeginClip s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, floatBitsToUint(s.bbox.x)); + write_mem(a, ix + 1, floatBitsToUint(s.bbox.y)); + write_mem(a, ix + 2, floatBitsToUint(s.bbox.z)); + write_mem(a, ix + 3, floatBitsToUint(s.bbox.w)); + write_mem(a, ix + 4, floatBitsToUint(s.linewidth)); +} + +AnnoEndClip AnnoEndClip_read(Alloc a, AnnoEndClipRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + uint raw2 = read_mem(a, ix + 2); + uint raw3 = read_mem(a, ix + 3); + AnnoEndClip s; + s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + return s; +} + +void AnnoEndClip_write(Alloc a, AnnoEndClipRef ref, AnnoEndClip s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, floatBitsToUint(s.bbox.x)); + write_mem(a, ix + 1, floatBitsToUint(s.bbox.y)); + write_mem(a, ix + 2, floatBitsToUint(s.bbox.z)); + write_mem(a, ix + 3, floatBitsToUint(s.bbox.w)); +} + +AnnotatedTag Annotated_tag(Alloc a, AnnotatedRef ref) { + uint tag_and_flags = read_mem(a, ref.offset >> 2); + return AnnotatedTag(tag_and_flags & 0xffff, tag_and_flags >> 16); +} + +AnnoColor Annotated_Color_read(Alloc a, AnnotatedRef ref) { + return AnnoColor_read(a, AnnoColorRef(ref.offset + 4)); +} + +AnnoImage Annotated_Image_read(Alloc a, AnnotatedRef ref) { + return AnnoImage_read(a, AnnoImageRef(ref.offset + 4)); +} + +AnnoBeginClip Annotated_BeginClip_read(Alloc a, AnnotatedRef ref) { + return AnnoBeginClip_read(a, AnnoBeginClipRef(ref.offset + 4)); +} + +AnnoEndClip Annotated_EndClip_read(Alloc a, AnnotatedRef ref) { + return AnnoEndClip_read(a, AnnoEndClipRef(ref.offset + 4)); +} + +void Annotated_Nop_write(Alloc a, AnnotatedRef ref) { + write_mem(a, ref.offset >> 2, Annotated_Nop); +} + +void Annotated_Color_write(Alloc a, AnnotatedRef ref, uint flags, AnnoColor s) { + write_mem(a, ref.offset >> 2, (flags << 16) | Annotated_Color); + AnnoColor_write(a, AnnoColorRef(ref.offset + 4), s); +} + +void Annotated_Image_write(Alloc a, AnnotatedRef ref, uint flags, AnnoImage s) { + write_mem(a, ref.offset >> 2, (flags << 16) | Annotated_Image); + AnnoImage_write(a, AnnoImageRef(ref.offset + 4), s); +} + +void Annotated_BeginClip_write(Alloc a, AnnotatedRef ref, uint flags, AnnoBeginClip s) { + write_mem(a, ref.offset >> 2, (flags << 16) | Annotated_BeginClip); + AnnoBeginClip_write(a, AnnoBeginClipRef(ref.offset + 4), s); +} + +void Annotated_EndClip_write(Alloc a, AnnotatedRef ref, AnnoEndClip s) { + write_mem(a, ref.offset >> 2, Annotated_EndClip); + AnnoEndClip_write(a, AnnoEndClipRef(ref.offset + 4), s); +} + diff --git a/gio/shader/piet/backdrop_abi.h b/gio/shader/piet/backdrop_abi.h new file mode 100644 index 0000000..f5c0303 --- /dev/null +++ b/gio/shader/piet/backdrop_abi.h @@ -0,0 +1,17 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +struct backdrop_descriptor_set_layout { + struct buffer_descriptor binding0; + struct buffer_descriptor binding1; +}; + +extern coroutine backdrop_coroutine_begin(struct program_data *data, + int32_t workgroupX, int32_t workgroupY, int32_t workgroupZ, + void *workgroupMemory, + int32_t firstSubgroup, + int32_t subgroupCount) ATTR_HIDDEN; + +extern bool backdrop_coroutine_await(coroutine r, yield_result *res) ATTR_HIDDEN; +extern void backdrop_coroutine_destroy(coroutine r) ATTR_HIDDEN; + +extern const struct program_info backdrop_program_info ATTR_HIDDEN; diff --git a/gio/shader/piet/backdrop_abi_nosupport.go b/gio/shader/piet/backdrop_abi_nosupport.go new file mode 100644 index 0000000..cb0bafd --- /dev/null +++ b/gio/shader/piet/backdrop_abi_nosupport.go @@ -0,0 +1,19 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +package piet + +import "gioui.org/cpu" + +var BackdropProgramInfo *cpu.ProgramInfo + +type BackdropDescriptorSetLayout struct{} + +const BackdropHash = "" + +func (l *BackdropDescriptorSetLayout) Binding0() *cpu.BufferDescriptor { + panic("unsupported") +} + +func (l *BackdropDescriptorSetLayout) Binding1() *cpu.BufferDescriptor { + panic("unsupported") +} diff --git a/gio/shader/piet/binning_abi.h b/gio/shader/piet/binning_abi.h new file mode 100644 index 0000000..0152f34 --- /dev/null +++ b/gio/shader/piet/binning_abi.h @@ -0,0 +1,17 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +struct binning_descriptor_set_layout { + struct buffer_descriptor binding0; + struct buffer_descriptor binding1; +}; + +extern coroutine binning_coroutine_begin(struct program_data *data, + int32_t workgroupX, int32_t workgroupY, int32_t workgroupZ, + void *workgroupMemory, + int32_t firstSubgroup, + int32_t subgroupCount) ATTR_HIDDEN; + +extern bool binning_coroutine_await(coroutine r, yield_result *res) ATTR_HIDDEN; +extern void binning_coroutine_destroy(coroutine r) ATTR_HIDDEN; + +extern const struct program_info binning_program_info ATTR_HIDDEN; diff --git a/gio/shader/piet/binning_abi_nosupport.go b/gio/shader/piet/binning_abi_nosupport.go new file mode 100644 index 0000000..71cbc6b --- /dev/null +++ b/gio/shader/piet/binning_abi_nosupport.go @@ -0,0 +1,19 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +package piet + +import "gioui.org/cpu" + +var BinningProgramInfo *cpu.ProgramInfo + +type BinningDescriptorSetLayout struct{} + +const BinningHash = "" + +func (l *BinningDescriptorSetLayout) Binding0() *cpu.BufferDescriptor { + panic("unsupported") +} + +func (l *BinningDescriptorSetLayout) Binding1() *cpu.BufferDescriptor { + panic("unsupported") +} diff --git a/gio/shader/piet/bins.h b/gio/shader/piet/bins.h new file mode 100644 index 0000000..853adab --- /dev/null +++ b/gio/shader/piet/bins.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense + +// Code auto-generated by piet-gpu-derive + +struct BinInstanceRef { + uint offset; +}; + +struct BinInstance { + uint element_ix; +}; + +#define BinInstance_size 4 + +BinInstanceRef BinInstance_index(BinInstanceRef ref, uint index) { + return BinInstanceRef(ref.offset + index * BinInstance_size); +} + +BinInstance BinInstance_read(Alloc a, BinInstanceRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + BinInstance s; + s.element_ix = raw0; + return s; +} + +void BinInstance_write(Alloc a, BinInstanceRef ref, BinInstance s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, s.element_ix); +} + diff --git a/gio/shader/piet/coarse_abi.h b/gio/shader/piet/coarse_abi.h new file mode 100644 index 0000000..24d874d --- /dev/null +++ b/gio/shader/piet/coarse_abi.h @@ -0,0 +1,17 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +struct coarse_descriptor_set_layout { + struct buffer_descriptor binding0; + struct buffer_descriptor binding1; +}; + +extern coroutine coarse_coroutine_begin(struct program_data *data, + int32_t workgroupX, int32_t workgroupY, int32_t workgroupZ, + void *workgroupMemory, + int32_t firstSubgroup, + int32_t subgroupCount) ATTR_HIDDEN; + +extern bool coarse_coroutine_await(coroutine r, yield_result *res) ATTR_HIDDEN; +extern void coarse_coroutine_destroy(coroutine r) ATTR_HIDDEN; + +extern const struct program_info coarse_program_info ATTR_HIDDEN; diff --git a/gio/shader/piet/coarse_abi_nosupport.go b/gio/shader/piet/coarse_abi_nosupport.go new file mode 100644 index 0000000..8be6263 --- /dev/null +++ b/gio/shader/piet/coarse_abi_nosupport.go @@ -0,0 +1,19 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +package piet + +import "gioui.org/cpu" + +var CoarseProgramInfo *cpu.ProgramInfo + +type CoarseDescriptorSetLayout struct{} + +const CoarseHash = "" + +func (l *CoarseDescriptorSetLayout) Binding0() *cpu.BufferDescriptor { + panic("unsupported") +} + +func (l *CoarseDescriptorSetLayout) Binding1() *cpu.BufferDescriptor { + panic("unsupported") +} diff --git a/gio/shader/piet/elements_abi.h b/gio/shader/piet/elements_abi.h new file mode 100644 index 0000000..c455224 --- /dev/null +++ b/gio/shader/piet/elements_abi.h @@ -0,0 +1,19 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +struct elements_descriptor_set_layout { + struct buffer_descriptor binding0; + struct buffer_descriptor binding1; + struct buffer_descriptor binding2; + struct buffer_descriptor binding3; +}; + +extern coroutine elements_coroutine_begin(struct program_data *data, + int32_t workgroupX, int32_t workgroupY, int32_t workgroupZ, + void *workgroupMemory, + int32_t firstSubgroup, + int32_t subgroupCount) ATTR_HIDDEN; + +extern bool elements_coroutine_await(coroutine r, yield_result *res) ATTR_HIDDEN; +extern void elements_coroutine_destroy(coroutine r) ATTR_HIDDEN; + +extern const struct program_info elements_program_info ATTR_HIDDEN; diff --git a/gio/shader/piet/elements_abi_nosupport.go b/gio/shader/piet/elements_abi_nosupport.go new file mode 100644 index 0000000..b0ebe95 --- /dev/null +++ b/gio/shader/piet/elements_abi_nosupport.go @@ -0,0 +1,27 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +package piet + +import "gioui.org/cpu" + +var ElementsProgramInfo *cpu.ProgramInfo + +type ElementsDescriptorSetLayout struct{} + +const ElementsHash = "" + +func (l *ElementsDescriptorSetLayout) Binding0() *cpu.BufferDescriptor { + panic("unsupported") +} + +func (l *ElementsDescriptorSetLayout) Binding1() *cpu.BufferDescriptor { + panic("unsupported") +} + +func (l *ElementsDescriptorSetLayout) Binding2() *cpu.BufferDescriptor { + panic("unsupported") +} + +func (l *ElementsDescriptorSetLayout) Binding3() *cpu.BufferDescriptor { + panic("unsupported") +} diff --git a/gio/shader/piet/kernel4_abi.h b/gio/shader/piet/kernel4_abi.h new file mode 100644 index 0000000..0d3b4c9 --- /dev/null +++ b/gio/shader/piet/kernel4_abi.h @@ -0,0 +1,19 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +struct kernel4_descriptor_set_layout { + struct buffer_descriptor binding0; + struct buffer_descriptor binding1; + struct image_descriptor binding2; + struct image_descriptor binding3; +}; + +extern coroutine kernel4_coroutine_begin(struct program_data *data, + int32_t workgroupX, int32_t workgroupY, int32_t workgroupZ, + void *workgroupMemory, + int32_t firstSubgroup, + int32_t subgroupCount) ATTR_HIDDEN; + +extern bool kernel4_coroutine_await(coroutine r, yield_result *res) ATTR_HIDDEN; +extern void kernel4_coroutine_destroy(coroutine r) ATTR_HIDDEN; + +extern const struct program_info kernel4_program_info ATTR_HIDDEN; diff --git a/gio/shader/piet/kernel4_abi_nosupport.go b/gio/shader/piet/kernel4_abi_nosupport.go new file mode 100644 index 0000000..81da2dd --- /dev/null +++ b/gio/shader/piet/kernel4_abi_nosupport.go @@ -0,0 +1,27 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +package piet + +import "gioui.org/cpu" + +var Kernel4ProgramInfo *cpu.ProgramInfo + +type Kernel4DescriptorSetLayout struct{} + +const Kernel4Hash = "" + +func (l *Kernel4DescriptorSetLayout) Binding0() *cpu.BufferDescriptor { + panic("unsupported") +} + +func (l *Kernel4DescriptorSetLayout) Binding1() *cpu.BufferDescriptor { + panic("unsupported") +} + +func (l *Kernel4DescriptorSetLayout) Binding2() *cpu.ImageDescriptor { + panic("unsupported") +} + +func (l *Kernel4DescriptorSetLayout) Binding3() *cpu.ImageDescriptor { + panic("unsupported") +} diff --git a/gio/shader/piet/mem.h b/gio/shader/piet/mem.h new file mode 100644 index 0000000..9e81f04 --- /dev/null +++ b/gio/shader/piet/mem.h @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense + +layout(set = 0, binding = 0) buffer Memory { + // offset into memory of the next allocation, initialized by the user. + uint mem_offset; + // mem_error tracks the status of memory accesses, initialized to NO_ERROR + // by the user. ERR_MALLOC_FAILED is reported for insufficient memory. + // If MEM_DEBUG is defined the following errors are reported: + // - ERR_OUT_OF_BOUNDS is reported for out of bounds writes. + // - ERR_UNALIGNED_ACCESS for memory access not aligned to 32-bit words. + uint mem_error; + uint[] memory; +}; + +// Uncomment this line to add the size field to Alloc and enable memory checks. +// Note that the Config struct in setup.h grows size fields as well. +//#define MEM_DEBUG + +#define NO_ERROR 0 +#define ERR_MALLOC_FAILED 1 +#define ERR_OUT_OF_BOUNDS 2 +#define ERR_UNALIGNED_ACCESS 3 + +#ifdef MEM_DEBUG +#define Alloc_size 16 +#else +#define Alloc_size 8 +#endif + +// Alloc represents a memory allocation. +struct Alloc { + // offset in bytes into memory. + uint offset; +#ifdef MEM_DEBUG + // size in bytes of the allocation. + uint size; +#endif +}; + +struct MallocResult { + Alloc alloc; + // failed is true if the allocation overflowed memory. + bool failed; +}; + +// new_alloc synthesizes an Alloc from an offset and size. +Alloc new_alloc(uint offset, uint size, bool mem_ok) { + Alloc a; + a.offset = offset; +#ifdef MEM_DEBUG + if (mem_ok) { + a.size = size; + } else { + a.size = 0; + } +#endif + return a; +} + +// malloc allocates size bytes of memory. +MallocResult malloc(uint size) { + MallocResult r; + uint offset = atomicAdd(mem_offset, size); + r.failed = offset + size > memory.length() * 4; + r.alloc = new_alloc(offset, size, !r.failed); + if (r.failed) { + atomicMax(mem_error, ERR_MALLOC_FAILED); + return r; + } +#ifdef MEM_DEBUG + if ((size & 3) != 0) { + r.failed = true; + atomicMax(mem_error, ERR_UNALIGNED_ACCESS); + return r; + } +#endif + return r; +} + +// touch_mem checks whether access to the memory word at offset is valid. +// If MEM_DEBUG is defined, touch_mem returns false if offset is out of bounds. +// Offset is in words. +bool touch_mem(Alloc alloc, uint offset) { +#ifdef MEM_DEBUG + if (offset < alloc.offset/4 || offset >= (alloc.offset + alloc.size)/4) { + atomicMax(mem_error, ERR_OUT_OF_BOUNDS); + return false; + } +#endif + return true; +} + +// write_mem writes val to memory at offset. +// Offset is in words. +void write_mem(Alloc alloc, uint offset, uint val) { + if (!touch_mem(alloc, offset)) { + return; + } + memory[offset] = val; +} + +// read_mem reads the value from memory at offset. +// Offset is in words. +uint read_mem(Alloc alloc, uint offset) { + if (!touch_mem(alloc, offset)) { + return 0; + } + uint v = memory[offset]; + return v; +} + +// slice_mem returns a sub-allocation inside another. Offset and size are in +// bytes, relative to a.offset. +Alloc slice_mem(Alloc a, uint offset, uint size) { +#ifdef MEM_DEBUG + if ((offset & 3) != 0 || (size & 3) != 0) { + atomicMax(mem_error, ERR_UNALIGNED_ACCESS); + return Alloc(0, 0); + } + if (offset + size > a.size) { + // slice_mem is sometimes used for slices outside bounds, + // but never written. + return Alloc(0, 0); + } + return Alloc(a.offset + offset, size); +#else + return Alloc(a.offset + offset); +#endif +} + +// alloc_write writes alloc to memory at offset bytes. +void alloc_write(Alloc a, uint offset, Alloc alloc) { + write_mem(a, offset >> 2, alloc.offset); +#ifdef MEM_DEBUG + write_mem(a, (offset >> 2) + 1, alloc.size); +#endif +} + +// alloc_read reads an Alloc from memory at offset bytes. +Alloc alloc_read(Alloc a, uint offset) { + Alloc alloc; + alloc.offset = read_mem(a, offset >> 2); +#ifdef MEM_DEBUG + alloc.size = read_mem(a, (offset >> 2) + 1); +#endif + return alloc; +} diff --git a/gio/shader/piet/path_coarse_abi.h b/gio/shader/piet/path_coarse_abi.h new file mode 100644 index 0000000..9e43e8e --- /dev/null +++ b/gio/shader/piet/path_coarse_abi.h @@ -0,0 +1,17 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +struct path_coarse_descriptor_set_layout { + struct buffer_descriptor binding0; + struct buffer_descriptor binding1; +}; + +extern coroutine path_coarse_coroutine_begin(struct program_data *data, + int32_t workgroupX, int32_t workgroupY, int32_t workgroupZ, + void *workgroupMemory, + int32_t firstSubgroup, + int32_t subgroupCount) ATTR_HIDDEN; + +extern bool path_coarse_coroutine_await(coroutine r, yield_result *res) ATTR_HIDDEN; +extern void path_coarse_coroutine_destroy(coroutine r) ATTR_HIDDEN; + +extern const struct program_info path_coarse_program_info ATTR_HIDDEN; diff --git a/gio/shader/piet/path_coarse_abi_nosupport.go b/gio/shader/piet/path_coarse_abi_nosupport.go new file mode 100644 index 0000000..ba72c74 --- /dev/null +++ b/gio/shader/piet/path_coarse_abi_nosupport.go @@ -0,0 +1,19 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +package piet + +import "gioui.org/cpu" + +var Path_coarseProgramInfo *cpu.ProgramInfo + +type Path_coarseDescriptorSetLayout struct{} + +const Path_coarseHash = "" + +func (l *Path_coarseDescriptorSetLayout) Binding0() *cpu.BufferDescriptor { + panic("unsupported") +} + +func (l *Path_coarseDescriptorSetLayout) Binding1() *cpu.BufferDescriptor { + panic("unsupported") +} diff --git a/gio/shader/piet/pathseg.h b/gio/shader/piet/pathseg.h new file mode 100644 index 0000000..749771e --- /dev/null +++ b/gio/shader/piet/pathseg.h @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense + +// Code auto-generated by piet-gpu-derive + +struct PathCubicRef { + uint offset; +}; + +struct PathSegRef { + uint offset; +}; + +struct PathCubic { + vec2 p0; + vec2 p1; + vec2 p2; + vec2 p3; + uint path_ix; + uint trans_ix; + vec2 stroke; +}; + +#define PathCubic_size 48 + +PathCubicRef PathCubic_index(PathCubicRef ref, uint index) { + return PathCubicRef(ref.offset + index * PathCubic_size); +} + +#define PathSeg_Nop 0 +#define PathSeg_Cubic 1 +#define PathSeg_size 52 + +PathSegRef PathSeg_index(PathSegRef ref, uint index) { + return PathSegRef(ref.offset + index * PathSeg_size); +} + +struct PathSegTag { + uint tag; + uint flags; +}; + +PathCubic PathCubic_read(Alloc a, PathCubicRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + uint raw2 = read_mem(a, ix + 2); + uint raw3 = read_mem(a, ix + 3); + uint raw4 = read_mem(a, ix + 4); + uint raw5 = read_mem(a, ix + 5); + uint raw6 = read_mem(a, ix + 6); + uint raw7 = read_mem(a, ix + 7); + uint raw8 = read_mem(a, ix + 8); + uint raw9 = read_mem(a, ix + 9); + uint raw10 = read_mem(a, ix + 10); + uint raw11 = read_mem(a, ix + 11); + PathCubic s; + s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); + s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.p2 = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); + s.p3 = vec2(uintBitsToFloat(raw6), uintBitsToFloat(raw7)); + s.path_ix = raw8; + s.trans_ix = raw9; + s.stroke = vec2(uintBitsToFloat(raw10), uintBitsToFloat(raw11)); + return s; +} + +void PathCubic_write(Alloc a, PathCubicRef ref, PathCubic s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, floatBitsToUint(s.p0.x)); + write_mem(a, ix + 1, floatBitsToUint(s.p0.y)); + write_mem(a, ix + 2, floatBitsToUint(s.p1.x)); + write_mem(a, ix + 3, floatBitsToUint(s.p1.y)); + write_mem(a, ix + 4, floatBitsToUint(s.p2.x)); + write_mem(a, ix + 5, floatBitsToUint(s.p2.y)); + write_mem(a, ix + 6, floatBitsToUint(s.p3.x)); + write_mem(a, ix + 7, floatBitsToUint(s.p3.y)); + write_mem(a, ix + 8, s.path_ix); + write_mem(a, ix + 9, s.trans_ix); + write_mem(a, ix + 10, floatBitsToUint(s.stroke.x)); + write_mem(a, ix + 11, floatBitsToUint(s.stroke.y)); +} + +PathSegTag PathSeg_tag(Alloc a, PathSegRef ref) { + uint tag_and_flags = read_mem(a, ref.offset >> 2); + return PathSegTag(tag_and_flags & 0xffff, tag_and_flags >> 16); +} + +PathCubic PathSeg_Cubic_read(Alloc a, PathSegRef ref) { + return PathCubic_read(a, PathCubicRef(ref.offset + 4)); +} + +void PathSeg_Nop_write(Alloc a, PathSegRef ref) { + write_mem(a, ref.offset >> 2, PathSeg_Nop); +} + +void PathSeg_Cubic_write(Alloc a, PathSegRef ref, uint flags, PathCubic s) { + write_mem(a, ref.offset >> 2, (flags << 16) | PathSeg_Cubic); + PathCubic_write(a, PathCubicRef(ref.offset + 4), s); +} + diff --git a/gio/shader/piet/ptcl.h b/gio/shader/piet/ptcl.h new file mode 100644 index 0000000..6267fc5 --- /dev/null +++ b/gio/shader/piet/ptcl.h @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense + +// Code auto-generated by piet-gpu-derive + +struct CmdStrokeRef { + uint offset; +}; + +struct CmdFillRef { + uint offset; +}; + +struct CmdColorRef { + uint offset; +}; + +struct CmdImageRef { + uint offset; +}; + +struct CmdAlphaRef { + uint offset; +}; + +struct CmdJumpRef { + uint offset; +}; + +struct CmdRef { + uint offset; +}; + +struct CmdStroke { + uint tile_ref; + float half_width; +}; + +#define CmdStroke_size 8 + +CmdStrokeRef CmdStroke_index(CmdStrokeRef ref, uint index) { + return CmdStrokeRef(ref.offset + index * CmdStroke_size); +} + +struct CmdFill { + uint tile_ref; + int backdrop; +}; + +#define CmdFill_size 8 + +CmdFillRef CmdFill_index(CmdFillRef ref, uint index) { + return CmdFillRef(ref.offset + index * CmdFill_size); +} + +struct CmdColor { + uint rgba_color; +}; + +#define CmdColor_size 4 + +CmdColorRef CmdColor_index(CmdColorRef ref, uint index) { + return CmdColorRef(ref.offset + index * CmdColor_size); +} + +struct CmdImage { + uint index; + ivec2 offset; +}; + +#define CmdImage_size 8 + +CmdImageRef CmdImage_index(CmdImageRef ref, uint index) { + return CmdImageRef(ref.offset + index * CmdImage_size); +} + +struct CmdAlpha { + float alpha; +}; + +#define CmdAlpha_size 4 + +CmdAlphaRef CmdAlpha_index(CmdAlphaRef ref, uint index) { + return CmdAlphaRef(ref.offset + index * CmdAlpha_size); +} + +struct CmdJump { + uint new_ref; +}; + +#define CmdJump_size 4 + +CmdJumpRef CmdJump_index(CmdJumpRef ref, uint index) { + return CmdJumpRef(ref.offset + index * CmdJump_size); +} + +#define Cmd_End 0 +#define Cmd_Fill 1 +#define Cmd_Stroke 2 +#define Cmd_Solid 3 +#define Cmd_Alpha 4 +#define Cmd_Color 5 +#define Cmd_Image 6 +#define Cmd_BeginClip 7 +#define Cmd_EndClip 8 +#define Cmd_Jump 9 +#define Cmd_size 12 + +CmdRef Cmd_index(CmdRef ref, uint index) { + return CmdRef(ref.offset + index * Cmd_size); +} + +struct CmdTag { + uint tag; + uint flags; +}; + +CmdStroke CmdStroke_read(Alloc a, CmdStrokeRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + CmdStroke s; + s.tile_ref = raw0; + s.half_width = uintBitsToFloat(raw1); + return s; +} + +void CmdStroke_write(Alloc a, CmdStrokeRef ref, CmdStroke s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, s.tile_ref); + write_mem(a, ix + 1, floatBitsToUint(s.half_width)); +} + +CmdFill CmdFill_read(Alloc a, CmdFillRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + CmdFill s; + s.tile_ref = raw0; + s.backdrop = int(raw1); + return s; +} + +void CmdFill_write(Alloc a, CmdFillRef ref, CmdFill s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, s.tile_ref); + write_mem(a, ix + 1, uint(s.backdrop)); +} + +CmdColor CmdColor_read(Alloc a, CmdColorRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + CmdColor s; + s.rgba_color = raw0; + return s; +} + +void CmdColor_write(Alloc a, CmdColorRef ref, CmdColor s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, s.rgba_color); +} + +CmdImage CmdImage_read(Alloc a, CmdImageRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + CmdImage s; + s.index = raw0; + s.offset = ivec2(int(raw1 << 16) >> 16, int(raw1) >> 16); + return s; +} + +void CmdImage_write(Alloc a, CmdImageRef ref, CmdImage s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, s.index); + write_mem(a, ix + 1, (uint(s.offset.x) & 0xffff) | (uint(s.offset.y) << 16)); +} + +CmdAlpha CmdAlpha_read(Alloc a, CmdAlphaRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + CmdAlpha s; + s.alpha = uintBitsToFloat(raw0); + return s; +} + +void CmdAlpha_write(Alloc a, CmdAlphaRef ref, CmdAlpha s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, floatBitsToUint(s.alpha)); +} + +CmdJump CmdJump_read(Alloc a, CmdJumpRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + CmdJump s; + s.new_ref = raw0; + return s; +} + +void CmdJump_write(Alloc a, CmdJumpRef ref, CmdJump s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, s.new_ref); +} + +CmdTag Cmd_tag(Alloc a, CmdRef ref) { + uint tag_and_flags = read_mem(a, ref.offset >> 2); + return CmdTag(tag_and_flags & 0xffff, tag_and_flags >> 16); +} + +CmdFill Cmd_Fill_read(Alloc a, CmdRef ref) { + return CmdFill_read(a, CmdFillRef(ref.offset + 4)); +} + +CmdStroke Cmd_Stroke_read(Alloc a, CmdRef ref) { + return CmdStroke_read(a, CmdStrokeRef(ref.offset + 4)); +} + +CmdAlpha Cmd_Alpha_read(Alloc a, CmdRef ref) { + return CmdAlpha_read(a, CmdAlphaRef(ref.offset + 4)); +} + +CmdColor Cmd_Color_read(Alloc a, CmdRef ref) { + return CmdColor_read(a, CmdColorRef(ref.offset + 4)); +} + +CmdImage Cmd_Image_read(Alloc a, CmdRef ref) { + return CmdImage_read(a, CmdImageRef(ref.offset + 4)); +} + +CmdJump Cmd_Jump_read(Alloc a, CmdRef ref) { + return CmdJump_read(a, CmdJumpRef(ref.offset + 4)); +} + +void Cmd_End_write(Alloc a, CmdRef ref) { + write_mem(a, ref.offset >> 2, Cmd_End); +} + +void Cmd_Fill_write(Alloc a, CmdRef ref, CmdFill s) { + write_mem(a, ref.offset >> 2, Cmd_Fill); + CmdFill_write(a, CmdFillRef(ref.offset + 4), s); +} + +void Cmd_Stroke_write(Alloc a, CmdRef ref, CmdStroke s) { + write_mem(a, ref.offset >> 2, Cmd_Stroke); + CmdStroke_write(a, CmdStrokeRef(ref.offset + 4), s); +} + +void Cmd_Solid_write(Alloc a, CmdRef ref) { + write_mem(a, ref.offset >> 2, Cmd_Solid); +} + +void Cmd_Alpha_write(Alloc a, CmdRef ref, CmdAlpha s) { + write_mem(a, ref.offset >> 2, Cmd_Alpha); + CmdAlpha_write(a, CmdAlphaRef(ref.offset + 4), s); +} + +void Cmd_Color_write(Alloc a, CmdRef ref, CmdColor s) { + write_mem(a, ref.offset >> 2, Cmd_Color); + CmdColor_write(a, CmdColorRef(ref.offset + 4), s); +} + +void Cmd_Image_write(Alloc a, CmdRef ref, CmdImage s) { + write_mem(a, ref.offset >> 2, Cmd_Image); + CmdImage_write(a, CmdImageRef(ref.offset + 4), s); +} + +void Cmd_BeginClip_write(Alloc a, CmdRef ref) { + write_mem(a, ref.offset >> 2, Cmd_BeginClip); +} + +void Cmd_EndClip_write(Alloc a, CmdRef ref) { + write_mem(a, ref.offset >> 2, Cmd_EndClip); +} + +void Cmd_Jump_write(Alloc a, CmdRef ref, CmdJump s) { + write_mem(a, ref.offset >> 2, Cmd_Jump); + CmdJump_write(a, CmdJumpRef(ref.offset + 4), s); +} + diff --git a/gio/shader/piet/runtime.h b/gio/shader/piet/runtime.h new file mode 100644 index 0000000..cfae912 --- /dev/null +++ b/gio/shader/piet/runtime.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +#define ATTR_HIDDEN __attribute__ ((visibility ("hidden"))) + +// program_info contains constant parameters for a program. +struct program_info { + // MinMemorySize is the minimum size of memory passed to dispatch. + size_t min_memory_size; + // has_cbarriers is 1 when the program contains control barriers. + bool has_cbarriers; + // desc_set_size is the size of the first descriptor set for the program. + size_t desc_set_size; + int workgroup_size_x; + int workgroup_size_y; + int workgroup_size_z; + // Program entrypoints. + routine_begin begin; + routine_await await; + routine_destroy destroy; +}; + +// dispatch_context contains the information a program dispatch. +struct dispatch_context; + +// thread_context contains the working memory of a batch. It may be +// reused, but not concurrently. +struct thread_context; + +extern struct buffer_descriptor alloc_buffer(size_t size) ATTR_HIDDEN; +extern struct image_descriptor alloc_image_rgba(int width, int height) ATTR_HIDDEN; + +extern struct dispatch_context *alloc_dispatch_context(void) ATTR_HIDDEN; + +extern void free_dispatch_context(struct dispatch_context *c) ATTR_HIDDEN; + +extern struct thread_context *alloc_thread_context(void) ATTR_HIDDEN; + +extern void free_thread_context(struct thread_context *c) ATTR_HIDDEN; + +// prepare_dispatch initializes ctx to run a dispatch of a program distributed +// among nthreads threads. +extern void prepare_dispatch(struct dispatch_context *ctx, int nthreads, struct program_info *info, uint8_t *desc_set, int ngroupx, int ngroupy, int ngroupz) ATTR_HIDDEN; + +// dispatch_batch executes a dispatch batch. +extern void dispatch_thread(struct dispatch_context *ctx, int thread_idx, struct thread_context *thread) ATTR_HIDDEN; diff --git a/gio/shader/piet/scene.h b/gio/shader/piet/scene.h new file mode 100644 index 0000000..38c2549 --- /dev/null +++ b/gio/shader/piet/scene.h @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense + +// Code auto-generated by piet-gpu-derive + +struct LineSegRef { + uint offset; +}; + +struct QuadSegRef { + uint offset; +}; + +struct CubicSegRef { + uint offset; +}; + +struct FillColorRef { + uint offset; +}; + +struct FillImageRef { + uint offset; +}; + +struct SetLineWidthRef { + uint offset; +}; + +struct TransformRef { + uint offset; +}; + +struct ClipRef { + uint offset; +}; + +struct SetFillModeRef { + uint offset; +}; + +struct ElementRef { + uint offset; +}; + +struct LineSeg { + vec2 p0; + vec2 p1; +}; + +#define LineSeg_size 16 + +LineSegRef LineSeg_index(LineSegRef ref, uint index) { + return LineSegRef(ref.offset + index * LineSeg_size); +} + +struct QuadSeg { + vec2 p0; + vec2 p1; + vec2 p2; +}; + +#define QuadSeg_size 24 + +QuadSegRef QuadSeg_index(QuadSegRef ref, uint index) { + return QuadSegRef(ref.offset + index * QuadSeg_size); +} + +struct CubicSeg { + vec2 p0; + vec2 p1; + vec2 p2; + vec2 p3; +}; + +#define CubicSeg_size 32 + +CubicSegRef CubicSeg_index(CubicSegRef ref, uint index) { + return CubicSegRef(ref.offset + index * CubicSeg_size); +} + +struct FillColor { + uint rgba_color; +}; + +#define FillColor_size 4 + +FillColorRef FillColor_index(FillColorRef ref, uint index) { + return FillColorRef(ref.offset + index * FillColor_size); +} + +struct FillImage { + uint index; + ivec2 offset; +}; + +#define FillImage_size 8 + +FillImageRef FillImage_index(FillImageRef ref, uint index) { + return FillImageRef(ref.offset + index * FillImage_size); +} + +struct SetLineWidth { + float width; +}; + +#define SetLineWidth_size 4 + +SetLineWidthRef SetLineWidth_index(SetLineWidthRef ref, uint index) { + return SetLineWidthRef(ref.offset + index * SetLineWidth_size); +} + +struct Transform { + vec4 mat; + vec2 translate; +}; + +#define Transform_size 24 + +TransformRef Transform_index(TransformRef ref, uint index) { + return TransformRef(ref.offset + index * Transform_size); +} + +struct Clip { + vec4 bbox; +}; + +#define Clip_size 16 + +ClipRef Clip_index(ClipRef ref, uint index) { + return ClipRef(ref.offset + index * Clip_size); +} + +struct SetFillMode { + uint fill_mode; +}; + +#define SetFillMode_size 4 + +SetFillModeRef SetFillMode_index(SetFillModeRef ref, uint index) { + return SetFillModeRef(ref.offset + index * SetFillMode_size); +} + +#define Element_Nop 0 +#define Element_Line 1 +#define Element_Quad 2 +#define Element_Cubic 3 +#define Element_FillColor 4 +#define Element_SetLineWidth 5 +#define Element_Transform 6 +#define Element_BeginClip 7 +#define Element_EndClip 8 +#define Element_FillImage 9 +#define Element_SetFillMode 10 +#define Element_size 36 + +ElementRef Element_index(ElementRef ref, uint index) { + return ElementRef(ref.offset + index * Element_size); +} + +struct ElementTag { + uint tag; + uint flags; +}; + +LineSeg LineSeg_read(LineSegRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + uint raw1 = scene[ix + 1]; + uint raw2 = scene[ix + 2]; + uint raw3 = scene[ix + 3]; + LineSeg s; + s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); + s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + return s; +} + +QuadSeg QuadSeg_read(QuadSegRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + uint raw1 = scene[ix + 1]; + uint raw2 = scene[ix + 2]; + uint raw3 = scene[ix + 3]; + uint raw4 = scene[ix + 4]; + uint raw5 = scene[ix + 5]; + QuadSeg s; + s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); + s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.p2 = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); + return s; +} + +CubicSeg CubicSeg_read(CubicSegRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + uint raw1 = scene[ix + 1]; + uint raw2 = scene[ix + 2]; + uint raw3 = scene[ix + 3]; + uint raw4 = scene[ix + 4]; + uint raw5 = scene[ix + 5]; + uint raw6 = scene[ix + 6]; + uint raw7 = scene[ix + 7]; + CubicSeg s; + s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); + s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.p2 = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); + s.p3 = vec2(uintBitsToFloat(raw6), uintBitsToFloat(raw7)); + return s; +} + +FillColor FillColor_read(FillColorRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + FillColor s; + s.rgba_color = raw0; + return s; +} + +FillImage FillImage_read(FillImageRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + uint raw1 = scene[ix + 1]; + FillImage s; + s.index = raw0; + s.offset = ivec2(int(raw1 << 16) >> 16, int(raw1) >> 16); + return s; +} + +SetLineWidth SetLineWidth_read(SetLineWidthRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + SetLineWidth s; + s.width = uintBitsToFloat(raw0); + return s; +} + +Transform Transform_read(TransformRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + uint raw1 = scene[ix + 1]; + uint raw2 = scene[ix + 2]; + uint raw3 = scene[ix + 3]; + uint raw4 = scene[ix + 4]; + uint raw5 = scene[ix + 5]; + Transform s; + s.mat = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.translate = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); + return s; +} + +Clip Clip_read(ClipRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + uint raw1 = scene[ix + 1]; + uint raw2 = scene[ix + 2]; + uint raw3 = scene[ix + 3]; + Clip s; + s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + return s; +} + +SetFillMode SetFillMode_read(SetFillModeRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + SetFillMode s; + s.fill_mode = raw0; + return s; +} + +ElementTag Element_tag(ElementRef ref) { + uint tag_and_flags = scene[ref.offset >> 2]; + return ElementTag(tag_and_flags & 0xffff, tag_and_flags >> 16); +} + +LineSeg Element_Line_read(ElementRef ref) { + return LineSeg_read(LineSegRef(ref.offset + 4)); +} + +QuadSeg Element_Quad_read(ElementRef ref) { + return QuadSeg_read(QuadSegRef(ref.offset + 4)); +} + +CubicSeg Element_Cubic_read(ElementRef ref) { + return CubicSeg_read(CubicSegRef(ref.offset + 4)); +} + +FillColor Element_FillColor_read(ElementRef ref) { + return FillColor_read(FillColorRef(ref.offset + 4)); +} + +SetLineWidth Element_SetLineWidth_read(ElementRef ref) { + return SetLineWidth_read(SetLineWidthRef(ref.offset + 4)); +} + +Transform Element_Transform_read(ElementRef ref) { + return Transform_read(TransformRef(ref.offset + 4)); +} + +Clip Element_BeginClip_read(ElementRef ref) { + return Clip_read(ClipRef(ref.offset + 4)); +} + +Clip Element_EndClip_read(ElementRef ref) { + return Clip_read(ClipRef(ref.offset + 4)); +} + +FillImage Element_FillImage_read(ElementRef ref) { + return FillImage_read(FillImageRef(ref.offset + 4)); +} + +SetFillMode Element_SetFillMode_read(ElementRef ref) { + return SetFillMode_read(SetFillModeRef(ref.offset + 4)); +} + diff --git a/gio/shader/piet/setup.h b/gio/shader/piet/setup.h new file mode 100644 index 0000000..83b6d1d --- /dev/null +++ b/gio/shader/piet/setup.h @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense + +// Various constants for the sizes of groups and tiles. + +// Much of this will be made dynamic in various ways, but for now it's easiest +// to hardcode and keep all in one place. + +// A LG_WG_FACTOR of n scales workgroup sizes by 2^n. Use 0 for a +// maximum workgroup size of 128, or 1 for a maximum size of 256. +#define LG_WG_FACTOR 0 +#define WG_FACTOR (1<> 2; + uint raw0 = state[ix + 0]; + uint raw1 = state[ix + 1]; + uint raw2 = state[ix + 2]; + uint raw3 = state[ix + 3]; + uint raw4 = state[ix + 4]; + uint raw5 = state[ix + 5]; + uint raw6 = state[ix + 6]; + uint raw7 = state[ix + 7]; + uint raw8 = state[ix + 8]; + uint raw9 = state[ix + 9]; + uint raw10 = state[ix + 10]; + uint raw11 = state[ix + 11]; + uint raw12 = state[ix + 12]; + uint raw13 = state[ix + 13]; + uint raw14 = state[ix + 14]; + State s; + s.mat = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.translate = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); + s.bbox = vec4(uintBitsToFloat(raw6), uintBitsToFloat(raw7), uintBitsToFloat(raw8), uintBitsToFloat(raw9)); + s.linewidth = uintBitsToFloat(raw10); + s.flags = raw11; + s.path_count = raw12; + s.pathseg_count = raw13; + s.trans_count = raw14; + return s; +} + +void State_write(StateRef ref, State s) { + uint ix = ref.offset >> 2; + state[ix + 0] = floatBitsToUint(s.mat.x); + state[ix + 1] = floatBitsToUint(s.mat.y); + state[ix + 2] = floatBitsToUint(s.mat.z); + state[ix + 3] = floatBitsToUint(s.mat.w); + state[ix + 4] = floatBitsToUint(s.translate.x); + state[ix + 5] = floatBitsToUint(s.translate.y); + state[ix + 6] = floatBitsToUint(s.bbox.x); + state[ix + 7] = floatBitsToUint(s.bbox.y); + state[ix + 8] = floatBitsToUint(s.bbox.z); + state[ix + 9] = floatBitsToUint(s.bbox.w); + state[ix + 10] = floatBitsToUint(s.linewidth); + state[ix + 11] = s.flags; + state[ix + 12] = s.path_count; + state[ix + 13] = s.pathseg_count; + state[ix + 14] = s.trans_count; +} + diff --git a/gio/shader/piet/tile.h b/gio/shader/piet/tile.h new file mode 100644 index 0000000..e11329c --- /dev/null +++ b/gio/shader/piet/tile.h @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense + +// Code auto-generated by piet-gpu-derive + +struct PathRef { + uint offset; +}; + +struct TileRef { + uint offset; +}; + +struct TileSegRef { + uint offset; +}; + +struct TransformSegRef { + uint offset; +}; + +struct Path { + uvec4 bbox; + TileRef tiles; +}; + +#define Path_size 12 + +PathRef Path_index(PathRef ref, uint index) { + return PathRef(ref.offset + index * Path_size); +} + +struct Tile { + TileSegRef tile; + int backdrop; +}; + +#define Tile_size 8 + +TileRef Tile_index(TileRef ref, uint index) { + return TileRef(ref.offset + index * Tile_size); +} + +struct TileSeg { + vec2 origin; + vec2 vector; + float y_edge; + TileSegRef next; +}; + +#define TileSeg_size 24 + +TileSegRef TileSeg_index(TileSegRef ref, uint index) { + return TileSegRef(ref.offset + index * TileSeg_size); +} + +struct TransformSeg { + vec4 mat; + vec2 translate; +}; + +#define TransformSeg_size 24 + +TransformSegRef TransformSeg_index(TransformSegRef ref, uint index) { + return TransformSegRef(ref.offset + index * TransformSeg_size); +} + +Path Path_read(Alloc a, PathRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + uint raw2 = read_mem(a, ix + 2); + Path s; + s.bbox = uvec4(raw0 & 0xffff, raw0 >> 16, raw1 & 0xffff, raw1 >> 16); + s.tiles = TileRef(raw2); + return s; +} + +void Path_write(Alloc a, PathRef ref, Path s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, s.bbox.x | (s.bbox.y << 16)); + write_mem(a, ix + 1, s.bbox.z | (s.bbox.w << 16)); + write_mem(a, ix + 2, s.tiles.offset); +} + +Tile Tile_read(Alloc a, TileRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + Tile s; + s.tile = TileSegRef(raw0); + s.backdrop = int(raw1); + return s; +} + +void Tile_write(Alloc a, TileRef ref, Tile s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, s.tile.offset); + write_mem(a, ix + 1, uint(s.backdrop)); +} + +TileSeg TileSeg_read(Alloc a, TileSegRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + uint raw2 = read_mem(a, ix + 2); + uint raw3 = read_mem(a, ix + 3); + uint raw4 = read_mem(a, ix + 4); + uint raw5 = read_mem(a, ix + 5); + TileSeg s; + s.origin = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); + s.vector = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.y_edge = uintBitsToFloat(raw4); + s.next = TileSegRef(raw5); + return s; +} + +void TileSeg_write(Alloc a, TileSegRef ref, TileSeg s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, floatBitsToUint(s.origin.x)); + write_mem(a, ix + 1, floatBitsToUint(s.origin.y)); + write_mem(a, ix + 2, floatBitsToUint(s.vector.x)); + write_mem(a, ix + 3, floatBitsToUint(s.vector.y)); + write_mem(a, ix + 4, floatBitsToUint(s.y_edge)); + write_mem(a, ix + 5, s.next.offset); +} + +TransformSeg TransformSeg_read(Alloc a, TransformSegRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + uint raw2 = read_mem(a, ix + 2); + uint raw3 = read_mem(a, ix + 3); + uint raw4 = read_mem(a, ix + 4); + uint raw5 = read_mem(a, ix + 5); + TransformSeg s; + s.mat = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.translate = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); + return s; +} + +void TransformSeg_write(Alloc a, TransformSegRef ref, TransformSeg s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, floatBitsToUint(s.mat.x)); + write_mem(a, ix + 1, floatBitsToUint(s.mat.y)); + write_mem(a, ix + 2, floatBitsToUint(s.mat.z)); + write_mem(a, ix + 3, floatBitsToUint(s.mat.w)); + write_mem(a, ix + 4, floatBitsToUint(s.translate.x)); + write_mem(a, ix + 5, floatBitsToUint(s.translate.y)); +} + diff --git a/gio/shader/piet/tile_alloc_abi.h b/gio/shader/piet/tile_alloc_abi.h new file mode 100644 index 0000000..aac2706 --- /dev/null +++ b/gio/shader/piet/tile_alloc_abi.h @@ -0,0 +1,17 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +struct tile_alloc_descriptor_set_layout { + struct buffer_descriptor binding0; + struct buffer_descriptor binding1; +}; + +extern coroutine tile_alloc_coroutine_begin(struct program_data *data, + int32_t workgroupX, int32_t workgroupY, int32_t workgroupZ, + void *workgroupMemory, + int32_t firstSubgroup, + int32_t subgroupCount) ATTR_HIDDEN; + +extern bool tile_alloc_coroutine_await(coroutine r, yield_result *res) ATTR_HIDDEN; +extern void tile_alloc_coroutine_destroy(coroutine r) ATTR_HIDDEN; + +extern const struct program_info tile_alloc_program_info ATTR_HIDDEN; diff --git a/gio/shader/piet/tile_alloc_abi_nosupport.go b/gio/shader/piet/tile_alloc_abi_nosupport.go new file mode 100644 index 0000000..b781c21 --- /dev/null +++ b/gio/shader/piet/tile_alloc_abi_nosupport.go @@ -0,0 +1,19 @@ +// Code generated by gioui.org/cpu/cmd/compile DO NOT EDIT. + +package piet + +import "gioui.org/cpu" + +var Tile_allocProgramInfo *cpu.ProgramInfo + +type Tile_allocDescriptorSetLayout struct{} + +const Tile_allocHash = "" + +func (l *Tile_allocDescriptorSetLayout) Binding0() *cpu.BufferDescriptor { + panic("unsupported") +} + +func (l *Tile_allocDescriptorSetLayout) Binding1() *cpu.BufferDescriptor { + panic("unsupported") +} diff --git a/gio/shader/shader.go b/gio/shader/shader.go new file mode 100644 index 0000000..e1263c1 --- /dev/null +++ b/gio/shader/shader.go @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package shader + +type Sources struct { + Name string + SPIRV string + GLSL100ES string + GLSL150 string + DXBC string + MetalLib string + Uniforms UniformsReflection + Inputs []InputLocation + Textures []TextureBinding + StorageBuffers []BufferBinding + Images []ImageBinding + WorkgroupSize [3]int +} + +type UniformsReflection struct { + Locations []UniformLocation + Size int +} + +type ImageBinding struct { + Name string + Binding int +} + +type BufferBinding struct { + Name string + Binding int +} + +type TextureBinding struct { + Name string + Binding int +} + +type UniformLocation struct { + Name string + Type DataType + Size int + Offset int +} + +type InputLocation struct { + // For GLSL. + Name string + Location int + // For HLSL. + Semantic string + SemanticIndex int + + Type DataType + Size int +} + +type DataType uint8 + +const ( + DataTypeFloat DataType = iota + DataTypeInt + DataTypeShort +) diff --git a/giouibind.go b/giouibind.go new file mode 100644 index 0000000..698cb01 --- /dev/null +++ b/giouibind.go @@ -0,0 +1,99 @@ +package giouibind + +import ( + "fmt" + "image/color" + + "gioui.org/app" + "gioui.org/font/gofont" + "gioui.org/io/system" + "gioui.org/layout" + "gioui.org/op" + "gioui.org/text" + "gioui.org/unit" + "gioui.org/widget/material" + "github.com/empathicqubit/giouibind/native" + + "log" +) + +const ( + screenW = 320 + screenH = 320 +) + +func (a *AppState) FinishedConnect(success bool, name string) { + a.connected = success + a.connecting = false + a.deviceName = name + log.Printf("Device %s connected: %t\n", name, success) + a.window.Invalidate() +} + +func (a *AppState) FinishedDisconnect() { +} + +func (app *AppState) BluetoothGotData(data []byte) { + log.Printf("Received: %v\n", data) +} + +func (app *AppState) Update() error { + if !app.connected && !app.connecting { + app.connecting = true + app.nativeBridge.ConnectToDevice() + return nil + } + + if !app.connected { + return nil + } + + return nil +} + +func (app *AppState) Load() error { + app.loaded = true + + return nil +} + +func (app *AppState) InventGod(god native.INativeBridge) error { + log.Println("God has been invented") + app.nativeBridge = god + + if !app.bluetoothEnabled { + app.nativeBridge.EnableBluetooth() + app.bluetoothEnabled = true + } + + return nil +} + +func (app *AppState) RunApp(w *app.Window) error { + app.window = w + th := material.NewTheme(gofont.Collection()) + th.TextSize = unit.Sp(8) + var ops op.Ops + for { + go app.Update() + e := <-w.Events() + switch e := e.(type) { + case system.DestroyEvent: + return e.Err + case system.FrameEvent: + gtx := layout.NewContext(&ops, e) + + titleText := "Not connected" + if app.connected { + titleText = fmt.Sprintf("Connected to %s", app.deviceName) + } + title := material.H1(th, titleText) + maroon := color.NRGBA{R: 127, G: 0, B: 0, A: 255} + title.Color = maroon + title.Alignment = text.Middle + title.Layout(gtx) + + e.Frame(gtx.Ops) + } + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..27f7cde --- /dev/null +++ b/go.mod @@ -0,0 +1,30 @@ +module github.com/empathicqubit/giouibind + +go 1.17 + +replace gioui.org/cpu => ./gio/cpu + +replace gioui.org/shader => ./gio/shader + +require ( + gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 // indirect + gioui.org/shader v1.0.6 // indirect + github.com/benoitkugler/textlayout v0.0.10 // indirect + github.com/gioui/uax v0.2.1-0.20220325163150-e3d987515a12 // indirect + github.com/go-text/typesetting v0.0.0-20220411150340-35994bc27a7b // indirect + github.com/stretchr/testify v1.7.0 // indirect + golang.org/x/text v0.3.7 // indirect +) + +require ( + gioui.org v0.0.0-20220412162123-38ff78df5dbe + github.com/JuulLabs-OSS/cbgo v0.0.2 + github.com/sirupsen/logrus v1.8.1 // indirect + golang.org/x/exp v0.0.0-20210722180016-6781d3edade3 // indirect + golang.org/x/image v0.0.0-20220321031419-a8550c1d254a // indirect + golang.org/x/mobile v0.0.0-20220104184238-4a8be17bd2e3 + golang.org/x/mod v0.4.2 // indirect + golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886 // indirect + golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ba013e3 --- /dev/null +++ b/go.sum @@ -0,0 +1,471 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +eliasnaur.com/font v0.0.0-20220124212145-832bb8fc08c3 h1:djFprmHZgrSepsHAIRMp5UJn3PzsoTg9drI+BDmif5Q= +eliasnaur.com/font v0.0.0-20220124212145-832bb8fc08c3/go.mod h1:OYVuxibdk9OSLX8vAqydtRPP87PyTFcT9uH3MlEGBQA= +gioui.org v0.0.0-20220412162123-38ff78df5dbe h1:rCZdcdRmpZStw7LoHsjQc1G3Bf0/c1zhw7So/XMyQm8= +gioui.org v0.0.0-20220412162123-38ff78df5dbe/go.mod h1:A0rb8LTFy1Hhi6/2zppz6CRiGJLAk0akcD1p+77l+fg= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/JuulLabs-OSS/cbgo v0.0.2 h1:gCDyT0+EPuI8GOFyvAksFcVD2vF4CXBAVwT6uVnD9oo= +github.com/JuulLabs-OSS/cbgo v0.0.2/go.mod h1:L4YtGP+gnyD84w7+jN66ncspFRfOYB5aj9QSXaFHmBA= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/benoitkugler/pstokenizer v1.0.0/go.mod h1:l1G2Voirz0q/jj0TQfabNxVsa8HZXh/VMxFSRALWTiE= +github.com/benoitkugler/textlayout v0.0.5/go.mod h1:puH4v13Uz7uIhIH0XMk5jgc8U3MXcn5r3VlV9K8n0D8= +github.com/benoitkugler/textlayout v0.0.10 h1:uIaQgH4pBFw1LQ0tPkfjgxo94WYcckzzQaB41L2X84w= +github.com/benoitkugler/textlayout v0.0.10/go.mod h1:puH4v13Uz7uIhIH0XMk5jgc8U3MXcn5r3VlV9K8n0D8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:po7NpZ/QiTKzBKyrsEAxwnTamCoh8uDk/egRpQ7siIc= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gioui/uax v0.2.1-0.20220325163150-e3d987515a12 h1:1bjaB/5IIicfKpP4k0s30T2WEw//Kh00zULa8DQ0cxA= +github.com/gioui/uax v0.2.1-0.20220325163150-e3d987515a12/go.mod h1:kDhBRTA/i3H46PVdhqcw26TdGSIj42TOKNWKY+Kipnw= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-text/typesetting v0.0.0-20220411150340-35994bc27a7b h1:WINlj3ANt+CVrO2B4NGDHRlPvEWZPxjhb7z+JKypwXI= +github.com/go-text/typesetting v0.0.0-20220411150340-35994bc27a7b/go.mod h1:ZNYu5saGoMOqtkVH5T8onTwhzenDUVszI+5WFHJRaxQ= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= +golang.org/x/exp v0.0.0-20210722180016-6781d3edade3 h1:IlrJD2AM5p8JhN/wVny9jt6gJ9hut2VALhSeZ3SYluk= +golang.org/x/exp v0.0.0-20210722180016-6781d3edade3/go.mod h1:DVyR6MI7P4kEQgvZJSj1fQGrWIi2RzIrfYWycwheUAc= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210504121937-7319ad40d33e/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220321031419-a8550c1d254a h1:LnH9RNcpPv5Kzi15lXg42lYMPUf0x8CuPv1YnvBWZAg= +golang.org/x/image v0.0.0-20220321031419-a8550c1d254a/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= +golang.org/x/mobile v0.0.0-20220104184238-4a8be17bd2e3 h1:A6xMk9ozH8+K90r7CpnP00jZ92Io02pQ/XLd55pZuf0= +golang.org/x/mobile v0.0.0-20220104184238-4a8be17bd2e3/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886 h1:eJv7u3ksNXoLbGSKuv2s/SIO4tJVxc/A+MTpzxDgz/Q= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098 h1:YuekqPskqwCCPM79F1X5Dhv4ezTCj+Ki1oNwiafxkA0= +golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..f4b4526 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,66 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +*.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ diff --git a/ios/export-options.plist b/ios/export-options.plist new file mode 100644 index 0000000..84bab3e --- /dev/null +++ b/ios/export-options.plist @@ -0,0 +1,12 @@ + + + + + teamID + FIXME + method + development + uploadSymbols + + + diff --git a/ios/giouibind/giouibind.xcodeproj/project.pbxproj b/ios/giouibind/giouibind.xcodeproj/project.pbxproj new file mode 100644 index 0000000..18d2a28 --- /dev/null +++ b/ios/giouibind/giouibind.xcodeproj/project.pbxproj @@ -0,0 +1,648 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 2422052D280388F30075E3DF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2422052C280388F30075E3DF /* AppDelegate.swift */; }; + 24220531280388F30075E3DF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24220530280388F30075E3DF /* ViewController.swift */; }; + 24220544280388F50075E3DF /* giouibindTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24220543280388F50075E3DF /* giouibindTests.swift */; }; + 2422054E280388F50075E3DF /* giouibindUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2422054D280388F50075E3DF /* giouibindUITests.swift */; }; + 24220550280388F50075E3DF /* giouibindUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2422054F280388F50075E3DF /* giouibindUITestsLaunchTests.swift */; }; + 2422055E280389530075E3DF /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2422055D280389530075E3DF /* GameController.framework */; }; + 24220560280389580075E3DF /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2422055F280389580075E3DF /* AudioToolbox.framework */; }; + 242205622803895E0075E3DF /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 242205612803895E0075E3DF /* OpenGLES.framework */; }; + 24220564280389670075E3DF /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24220563280389670075E3DF /* AVFoundation.framework */; }; + 242205662803896D0075E3DF /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 242205652803896D0075E3DF /* GLKit.framework */; }; + 2422056D28039C680075E3DF /* GodObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2422056C28039C680075E3DF /* GodObject.swift */; }; + 24A5E8E42804545E007CBEF9 /* ExternalAccessory.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24A5E8E32804545E007CBEF9 /* ExternalAccessory.framework */; }; + 24D0447E2806A14B00C93659 /* Mobile.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24D0447D2806A14B00C93659 /* Mobile.xcframework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 24220540280388F50075E3DF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 24220521280388F30075E3DF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 24220528280388F30075E3DF; + remoteInfo = giouibind; + }; + 2422054A280388F50075E3DF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 24220521280388F30075E3DF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 24220528280388F30075E3DF; + remoteInfo = giouibind; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 2422056A280389800075E3DF /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 24220529280388F30075E3DF /* giouibind.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = giouibind.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2422052C280388F30075E3DF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 24220530280388F30075E3DF /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 2422053A280388F50075E3DF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 2422053F280388F50075E3DF /* giouibindTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = giouibindTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 24220543280388F50075E3DF /* giouibindTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = giouibindTests.swift; sourceTree = ""; }; + 24220549280388F50075E3DF /* giouibindUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = giouibindUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 2422054D280388F50075E3DF /* giouibindUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = giouibindUITests.swift; sourceTree = ""; }; + 2422054F280388F50075E3DF /* giouibindUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = giouibindUITestsLaunchTests.swift; sourceTree = ""; }; + 2422055D280389530075E3DF /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; }; + 2422055F280389580075E3DF /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 242205612803895E0075E3DF /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; + 24220563280389670075E3DF /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + 242205652803896D0075E3DF /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; + 2422056C28039C680075E3DF /* GodObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GodObject.swift; sourceTree = ""; }; + 24A5E8E32804545E007CBEF9 /* ExternalAccessory.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ExternalAccessory.framework; path = System/Library/Frameworks/ExternalAccessory.framework; sourceTree = SDKROOT; }; + 24D044752806938A00C93659 /* giouibind-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "giouibind-Bridging-Header.h"; sourceTree = ""; }; + 24D0447D2806A14B00C93659 /* Mobile.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Mobile.xcframework; path = ../../build/Mobile.xcframework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 24220526280388F30075E3DF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 24A5E8E42804545E007CBEF9 /* ExternalAccessory.framework in Frameworks */, + 24220564280389670075E3DF /* AVFoundation.framework in Frameworks */, + 24D0447E2806A14B00C93659 /* Mobile.xcframework in Frameworks */, + 2422055E280389530075E3DF /* GameController.framework in Frameworks */, + 24220560280389580075E3DF /* AudioToolbox.framework in Frameworks */, + 242205662803896D0075E3DF /* GLKit.framework in Frameworks */, + 242205622803895E0075E3DF /* OpenGLES.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2422053C280388F50075E3DF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 24220546280388F50075E3DF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 24220520280388F30075E3DF = { + isa = PBXGroup; + children = ( + 2422052B280388F30075E3DF /* giouibind */, + 24220542280388F50075E3DF /* giouibindTests */, + 2422054C280388F50075E3DF /* giouibindUITests */, + 2422052A280388F30075E3DF /* Products */, + 2422055C280389530075E3DF /* Frameworks */, + ); + sourceTree = ""; + }; + 2422052A280388F30075E3DF /* Products */ = { + isa = PBXGroup; + children = ( + 24220529280388F30075E3DF /* giouibind.app */, + 2422053F280388F50075E3DF /* giouibindTests.xctest */, + 24220549280388F50075E3DF /* giouibindUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 2422052B280388F30075E3DF /* giouibind */ = { + isa = PBXGroup; + children = ( + 2422052C280388F30075E3DF /* AppDelegate.swift */, + 24220530280388F30075E3DF /* ViewController.swift */, + 2422053A280388F50075E3DF /* Info.plist */, + 2422056C28039C680075E3DF /* GodObject.swift */, + 24D044752806938A00C93659 /* giouibind-Bridging-Header.h */, + ); + path = giouibind; + sourceTree = ""; + }; + 24220542280388F50075E3DF /* giouibindTests */ = { + isa = PBXGroup; + children = ( + 24220543280388F50075E3DF /* giouibindTests.swift */, + ); + path = giouibindTests; + sourceTree = ""; + }; + 2422054C280388F50075E3DF /* giouibindUITests */ = { + isa = PBXGroup; + children = ( + 2422054D280388F50075E3DF /* giouibindUITests.swift */, + 2422054F280388F50075E3DF /* giouibindUITestsLaunchTests.swift */, + ); + path = giouibindUITests; + sourceTree = ""; + }; + 2422055C280389530075E3DF /* Frameworks */ = { + isa = PBXGroup; + children = ( + 24D0447D2806A14B00C93659 /* Mobile.xcframework */, + 24A5E8E32804545E007CBEF9 /* ExternalAccessory.framework */, + 242205652803896D0075E3DF /* GLKit.framework */, + 24220563280389670075E3DF /* AVFoundation.framework */, + 242205612803895E0075E3DF /* OpenGLES.framework */, + 2422055F280389580075E3DF /* AudioToolbox.framework */, + 2422055D280389530075E3DF /* GameController.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 24220528280388F30075E3DF /* giouibind */ = { + isa = PBXNativeTarget; + buildConfigurationList = 24220553280388F50075E3DF /* Build configuration list for PBXNativeTarget "giouibind" */; + buildPhases = ( + 24220525280388F30075E3DF /* Sources */, + 24220526280388F30075E3DF /* Frameworks */, + 24220527280388F30075E3DF /* Resources */, + 2422056A280389800075E3DF /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = giouibind; + productName = giouibind; + productReference = 24220529280388F30075E3DF /* giouibind.app */; + productType = "com.apple.product-type.application"; + }; + 2422053E280388F50075E3DF /* giouibindTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 24220556280388F50075E3DF /* Build configuration list for PBXNativeTarget "giouibindTests" */; + buildPhases = ( + 2422053B280388F50075E3DF /* Sources */, + 2422053C280388F50075E3DF /* Frameworks */, + 2422053D280388F50075E3DF /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 24220541280388F50075E3DF /* PBXTargetDependency */, + ); + name = giouibindTests; + productName = giouibindTests; + productReference = 2422053F280388F50075E3DF /* giouibindTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 24220548280388F50075E3DF /* giouibindUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 24220559280388F50075E3DF /* Build configuration list for PBXNativeTarget "giouibindUITests" */; + buildPhases = ( + 24220545280388F50075E3DF /* Sources */, + 24220546280388F50075E3DF /* Frameworks */, + 24220547280388F50075E3DF /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 2422054B280388F50075E3DF /* PBXTargetDependency */, + ); + name = giouibindUITests; + productName = giouibindUITests; + productReference = 24220549280388F50075E3DF /* giouibindUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 24220521280388F30075E3DF /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1320; + LastUpgradeCheck = 1320; + TargetAttributes = { + 24220528280388F30075E3DF = { + CreatedOnToolsVersion = 13.2.1; + LastSwiftMigration = 1330; + }; + 2422053E280388F50075E3DF = { + CreatedOnToolsVersion = 13.2.1; + TestTargetID = 24220528280388F30075E3DF; + }; + 24220548280388F50075E3DF = { + CreatedOnToolsVersion = 13.2.1; + TestTargetID = 24220528280388F30075E3DF; + }; + }; + }; + buildConfigurationList = 24220524280388F30075E3DF /* Build configuration list for PBXProject "giouibind" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 24220520280388F30075E3DF; + productRefGroup = 2422052A280388F30075E3DF /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 24220528280388F30075E3DF /* giouibind */, + 2422053E280388F50075E3DF /* giouibindTests */, + 24220548280388F50075E3DF /* giouibindUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 24220527280388F30075E3DF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2422053D280388F50075E3DF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 24220547280388F50075E3DF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 24220525280388F30075E3DF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 24220531280388F30075E3DF /* ViewController.swift in Sources */, + 2422052D280388F30075E3DF /* AppDelegate.swift in Sources */, + 2422056D28039C680075E3DF /* GodObject.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2422053B280388F50075E3DF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 24220544280388F50075E3DF /* giouibindTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 24220545280388F50075E3DF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 24220550280388F50075E3DF /* giouibindUITestsLaunchTests.swift in Sources */, + 2422054E280388F50075E3DF /* giouibindUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 24220541280388F50075E3DF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 24220528280388F30075E3DF /* giouibind */; + targetProxy = 24220540280388F50075E3DF /* PBXContainerItemProxy */; + }; + 2422054B280388F50075E3DF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 24220528280388F30075E3DF /* giouibind */; + targetProxy = 2422054A280388F50075E3DF /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 24220551280388F50075E3DF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 5FL95D4X28; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CODE_SIGN_FLAGS = "--deep"; + SDKROOT = iphoneos; + STRIP_BITCODE_FROM_COPIED_FILES = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 24220552280388F50075E3DF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 5FL95D4X28; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_CODE_SIGN_FLAGS = "--deep"; + SDKROOT = iphoneos; + STRIP_BITCODE_FROM_COPIED_FILES = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 24220554280388F50075E3DF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5FL95D4X28; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = giouibind/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_CODE_SIGN_FLAGS = "--deep"; + PRODUCT_BUNDLE_IDENTIFIER = gl.entan.giouibind; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + STRIP_BITCODE_FROM_COPIED_FILES = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "giouibind/giouibind-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 24220555280388F50075E3DF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5FL95D4X28; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = giouibind/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_CODE_SIGN_FLAGS = "--deep"; + PRODUCT_BUNDLE_IDENTIFIER = gl.entan.giouibind; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + STRIP_BITCODE_FROM_COPIED_FILES = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "giouibind/giouibind-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 24220557280388F50075E3DF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5FL95D4X28; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.2; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = gl.entan.giouibindTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/giouibind.app/giouibind"; + }; + name = Debug; + }; + 24220558280388F50075E3DF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5FL95D4X28; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.2; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = gl.entan.giouibindTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/giouibind.app/giouibind"; + }; + name = Release; + }; + 2422055A280388F50075E3DF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5FL95D4X28; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = gl.entan.giouibindUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = giouibind; + }; + name = Debug; + }; + 2422055B280388F50075E3DF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5FL95D4X28; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = gl.entan.giouibindUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = giouibind; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 24220524280388F30075E3DF /* Build configuration list for PBXProject "giouibind" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 24220551280388F50075E3DF /* Debug */, + 24220552280388F50075E3DF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 24220553280388F50075E3DF /* Build configuration list for PBXNativeTarget "giouibind" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 24220554280388F50075E3DF /* Debug */, + 24220555280388F50075E3DF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 24220556280388F50075E3DF /* Build configuration list for PBXNativeTarget "giouibindTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 24220557280388F50075E3DF /* Debug */, + 24220558280388F50075E3DF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 24220559280388F50075E3DF /* Build configuration list for PBXNativeTarget "giouibindUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2422055A280388F50075E3DF /* Debug */, + 2422055B280388F50075E3DF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 24220521280388F30075E3DF /* Project object */; +} diff --git a/ios/giouibind/giouibind/AppDelegate.swift b/ios/giouibind/giouibind/AppDelegate.swift new file mode 100644 index 0000000..926b9b1 --- /dev/null +++ b/ios/giouibind/giouibind/AppDelegate.swift @@ -0,0 +1,37 @@ +// +// AppDelegate.swift +// giouibind +// +// Created by Jessica Fleming on 10.04.22. +// + +import UIKit +import Mobile + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window:UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + + self.window = UIWindow(frame: CGRect( + x: UIScreen.main.bounds.minX, + y: UIScreen.main.bounds.minY + 40, + width: UIScreen.main.bounds.width, + height: UIScreen.main.bounds.height - 40 + )) + window?.rootViewController = ViewController() + window?.makeKeyAndVisible() + MobileInventGod(GodObject()) + + return true + } + + var gioView : ViewController { + get { + return self.window!.rootViewController! as! ViewController + } + } +} + diff --git a/ios/giouibind/giouibind/Base.lproj/Main.storyboard b/ios/giouibind/giouibind/Base.lproj/Main.storyboard new file mode 100644 index 0000000..a3a8013 --- /dev/null +++ b/ios/giouibind/giouibind/Base.lproj/Main.storyboard @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/giouibind/giouibind/GodObject.swift b/ios/giouibind/giouibind/GodObject.swift new file mode 100644 index 0000000..3ae506d --- /dev/null +++ b/ios/giouibind/giouibind/GodObject.swift @@ -0,0 +1,203 @@ +// +// GodObject.swift +// giouibind +// +// Created by Jessica Fleming on 11.04.22. +// + +import Foundation +import Mobile +import ExternalAccessory +import os +import CoreBluetooth + +// FIXME This should come from gocode +let shortServiceUuid = CBUUID(string: "FIXME") +let longServiceUuid = CBUUID(string: "FIXME") + +let writeUuid = CBUUID(string: "FIXME") +let readUuid = CBUUID(string: "FIXME") + +class MyDelegate : NSObject, CBCentralManagerDelegate, CBPeripheralDelegate { + var service : CBService? + var writeChr : CBCharacteristic? + var readChr : CBCharacteristic? + var connectedPeripheral : CBPeripheral? + var finishedConnect = false + + override init() { + super.init() + } + + func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: + Error?) { + if error != nil || (peripheral.services?.isEmpty ?? true) { + os_log("Error discovering services", log: .default, type: .info) + MobileFinishedConnect(false, "") + return + } + + service = peripheral.services![0] + peripheral.discoverCharacteristics([readUuid, writeUuid], for: service!) + + } + func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) { + if descriptor.characteristic == nil || descriptor.characteristic?.service?.uuid.uuidString != service?.uuid.uuidString { + return + } + + self.peripheral(peripheral, didUpdateValueFor: descriptor.characteristic!, error: error) + } + + func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { + + if error != nil { + os_log("Error getting descriptor value: %s", log: .default, type: .info, characteristic.uuid.uuidString) + return + } + + if characteristic.value == nil { + return + } + let data = characteristic.value! + + if characteristic.uuid.uuidString != readChr?.uuid.uuidString { + return + } + + MobileBluetoothGotData(data) + } + + func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { + if connectedPeripheral == nil { + peripheral.discoverServices([longServiceUuid, shortServiceUuid]) + return + } + } + + func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { + connectedPeripheral = nil + } + + func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor s: CBService, error: Error?) { + if s.uuid.uuidString != service?.uuid.uuidString { + return + } + + if(error != nil || (service?.characteristics?.isEmpty ?? true)) { + os_log("No chars", log: .default, type: .info) + MobileFinishedConnect(false, "") + return + } + + var foundCount = 0 + for chr in service!.characteristics! { + os_log("Found char: %s", log: .default, type: .info, chr.uuid.uuidString) + + let uuid = chr.uuid.uuidString + if uuid == writeUuid.uuidString { + writeChr = chr + foundCount += 1 + } else if uuid == readUuid.uuidString { + readChr = chr + foundCount += 1 + } + } + + if foundCount < 2 || service == nil { + os_log("Couldn't find matching service or characteristics", log: .default, type: .info) + MobileFinishedConnect(false, "") + return + } + + connectedPeripheral = peripheral + + os_log("Finished connect. Writing test command", log: .default, type: .info) + + peripheral.setNotifyValue(true, for: readChr!) + + if !finishedConnect { + finishedConnect = true + MobileFinishedConnect(true, peripheral.name) + } + } + + func writeChar(_ d: Data) -> Bool { + if connectedPeripheral == nil { + return false + } + + connectedPeripheral!.writeValue(d, for: writeChr! , type: CBCharacteristicWriteType.withResponse) + + return true + } + + func readChar() -> Data { + if connectedPeripheral == nil { + return Data() + } + + let ret = readChr!.value ?? Data() + + return ret + } + + func centralManagerDidUpdateState(_ central: CBCentralManager){ + os_log("Central Manager intialized", log: .default, type: .info) + + switch central.state{ + case CBManagerState.unauthorized: + os_log("Central Manager unauthorized", log: .default, type: .info) + case CBManagerState.poweredOff: + os_log("Central Manager powered off", log: .default, type: .info) + case CBManagerState.poweredOn: + os_log("Central Manager powered on", log: .default, type: .info) + default:break + } + } +} + +class GodObject : NSObject, MobileIGodObjectProtocol { + func readChar() -> Data? { + return delegate.readChar() + } + + func writeChar(_ data: Data?) -> Bool { + if data == nil { + return false + } + + return delegate.writeChar(data!) + } + + let delegate : MyDelegate + let manager : CBCentralManager + var peris : [CBPeripheral] = [] + + override init() { + delegate = MyDelegate() + manager = CBCentralManager(delegate: delegate, queue: DispatchQueue(label: "BT_queue")) + super.init() + } + + func connectToDevice() { + let peris = manager.retrieveConnectedPeripherals(withServices: [shortServiceUuid, longServiceUuid]) + + if(peris.isEmpty) { + os_log("No connected devices", log: .default, type: .info) + MobileFinishedConnect(false, "") + return + } + + self.peris = peris + for peri in peris { + os_log("Found device: %s", log: .default, type: .info, peri.name!) + peri.delegate = delegate + manager.connect(peri) + } + } + + func enableBluetooth() -> Bool { + return true + } +} diff --git a/ios/giouibind/giouibind/Info.plist b/ios/giouibind/giouibind/Info.plist new file mode 100644 index 0000000..f675fa8 --- /dev/null +++ b/ios/giouibind/giouibind/Info.plist @@ -0,0 +1,8 @@ + + + + + NSBluetoothAlwaysUsageDescription + Poop + + diff --git a/ios/giouibind/giouibind/ViewController.swift b/ios/giouibind/giouibind/ViewController.swift new file mode 100644 index 0000000..7cccc81 --- /dev/null +++ b/ios/giouibind/giouibind/ViewController.swift @@ -0,0 +1,11 @@ +// +// ViewController.swift +// giouibind +// +// Created by Jessica Fleming on 10.04.22. +// + +import UIKit + +class ViewController : GioViewController { +} diff --git a/ios/giouibind/giouibind/giouibind-Bridging-Header.h b/ios/giouibind/giouibind/giouibind-Bridging-Header.h new file mode 100644 index 0000000..ffe92bb --- /dev/null +++ b/ios/giouibind/giouibind/giouibind-Bridging-Header.h @@ -0,0 +1,8 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#include + +@interface GioViewController : UIViewController +@end diff --git a/ios/giouibind/giouibindTests/dumbcontrolTests.swift b/ios/giouibind/giouibindTests/dumbcontrolTests.swift new file mode 100644 index 0000000..7ef8fcb --- /dev/null +++ b/ios/giouibind/giouibindTests/dumbcontrolTests.swift @@ -0,0 +1,36 @@ +// +// giouibindTests.swift +// giouibindTests +// +// Created by Jessica Fleming on 10.04.22. +// + +import XCTest +@testable import giouibind + +class giouibindTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/ios/giouibind/giouibindUITests/dumbcontrolUITests.swift b/ios/giouibind/giouibindUITests/dumbcontrolUITests.swift new file mode 100644 index 0000000..fbc53bc --- /dev/null +++ b/ios/giouibind/giouibindUITests/dumbcontrolUITests.swift @@ -0,0 +1,42 @@ +// +// giouibindUITests.swift +// giouibindUITests +// +// Created by Jessica Fleming on 10.04.22. +// + +import XCTest + +class giouibindUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use recording to get started writing UI tests. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/ios/giouibind/giouibindUITests/dumbcontrolUITestsLaunchTests.swift b/ios/giouibind/giouibindUITests/dumbcontrolUITestsLaunchTests.swift new file mode 100644 index 0000000..cf5d124 --- /dev/null +++ b/ios/giouibind/giouibindUITests/dumbcontrolUITestsLaunchTests.swift @@ -0,0 +1,32 @@ +// +// giouibindUITestsLaunchTests.swift +// giouibindUITests +// +// Created by Jessica Fleming on 10.04.22. +// + +import XCTest + +class giouibindUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +} diff --git a/mobile/gio/main.go b/mobile/gio/main.go new file mode 100644 index 0000000..da29a2c --- /dev/null +++ b/mobile/gio/main.go @@ -0,0 +1,4 @@ +package main + +func main() { +} diff --git a/mobile/mobile.go b/mobile/mobile.go new file mode 100644 index 0000000..c06786d --- /dev/null +++ b/mobile/mobile.go @@ -0,0 +1,58 @@ +package mobile + +import ( + "log" + "os" + + "gioui.org/app" + "github.com/empathicqubit/giouibind" + "github.com/empathicqubit/giouibind/native" +) + +type IGodObject interface { + native.INativeBridge +} + +var dumbApp *giouibind.AppState = &giouibind.AppState{} + +func init() { + log.Println("Called gomobile entrypoint") + Main() +} + +func Main() { + log.Println("Called main") + err := dumbApp.Load() + if err != nil { + panic(err) + } + + go func() { + w := app.NewWindow() + err := dumbApp.RunApp(w) + if err != nil { + log.Fatal(err) + } + os.Exit(0) + }() + app.Main() +} + +func FinishedConnect(success bool, name string) { + dumbApp.FinishedConnect(success, name) +} + +func BluetoothGotData(data []byte) { + dumbApp.BluetoothGotData(data) +} + +func InventGod(god IGodObject) { + log.Println("Inventing God...") + dumb, ok := god.(native.INativeBridge) + if !ok { + log.Println("God is not okay!") + } else { + log.Println("God is fine and dandy!") + } + dumbApp.InventGod(dumb) +} diff --git a/native/native.go b/native/native.go new file mode 100644 index 0000000..0a92508 --- /dev/null +++ b/native/native.go @@ -0,0 +1,13 @@ +// Interfaces for the binding bridge. This should only contain a bare minimum +// of functions to communicate with the host and should avoid storing anything +package native + +type INativeBluetooth interface { + WriteChar([]byte) bool + ConnectToDevice() + EnableBluetooth() bool +} + +type INativeBridge interface { + INativeBluetooth +} diff --git a/tools.go b/tools.go new file mode 100644 index 0000000..3cd1243 --- /dev/null +++ b/tools.go @@ -0,0 +1,8 @@ +//go:build tools +// +build tools + +package main + +import ( + _ "golang.org/x/mobile/cmd/gomobile" +)