commit 304defa642f4f952c184156e956d1502857f65e6 Author: IllusionMan1212 Date: Tue Aug 6 02:01:10 2024 +0200 WIP diff --git a/android_native_app_glue.odin b/android_native_app_glue.odin new file mode 100644 index 0000000..7944dd5 --- /dev/null +++ b/android_native_app_glue.odin @@ -0,0 +1,207 @@ +//+build android +package android + +import "core:c" +import "core:sys/unix" + +foreign import android "system:android" + +// NOTE: As far as I know and have tested, pthread from sys/unix SHOULD work fine on android. +// Android doesn't support thread cancellation so those procs need to be commented out when compiling the native shared lib. +// Odin's threading library has been tested with Cat & Onion and it seems to work just fine there. + +AppCmd :: enum c.int32_t { + /** + * Command from main thread: the AInputQueue has changed. Upon processing + * this command, android_app->inputQueue will be updated to the new queue + * (or NULL). + */ + INPUT_CHANGED, + + /** + * Command from main thread: a new ANativeWindow is ready for use. Upon + * receiving this command, android_app->window will contain the new window + * surface. + */ + INIT_WINDOW, + + /** + * Command from main thread: the existing ANativeWindow needs to be + * terminated. Upon receiving this command, android_app->window still + * contains the existing window; after calling android_app_exec_cmd + * it will be set to NULL. + */ + TERM_WINDOW, + + /** + * Command from main thread: the current ANativeWindow has been resized. + * Please redraw with its new size. + */ + WINDOW_RESIZED, + + /** + * Command from main thread: the system needs that the current ANativeWindow + * be redrawn. You should redraw the window before handing this to + * android_app_exec_cmd() in order to avoid transient drawing glitches. + */ + WINDOW_REDRAW_NEEDED, + + /** + * Command from main thread: the content area of the window has changed, + * such as from the soft input window being shown or hidden. You can + * find the new content rect in android_app::contentRect. + */ + CONTENT_RECT_CHANGED, + + /** + * Command from main thread: the app's activity window has gained + * input focus. + */ + GAINED_FOCUS, + + /** + * Command from main thread: the app's activity window has lost + * input focus. + */ + LOST_FOCUS, + + /** + * Command from main thread: the current device configuration has changed. + */ + CONFIG_CHANGED, + + /** + * Command from main thread: the system is running low on memory. + * Try to reduce your memory use. + */ + LOW_MEMORY, + + /** + * Command from main thread: the app's activity has been started. + */ + START, + + /** + * Command from main thread: the app's activity has been resumed. + */ + RESUME, + + /** + * Command from main thread: the app should generate a new saved state + * for itself, to restore from later if needed. If you have saved state, + * allocate it with malloc and place it in android_app.savedState with + * the size in android_app.savedStateSize. The will be freed for you + * later. + */ + SAVE_STATE, + + /** + * Command from main thread: the app's activity has been paused. + */ + PAUSE, + + /** + * Command from main thread: the app's activity has been stopped. + */ + STOP, + + /** + * Command from main thread: the app's activity is being destroyed, + * and waiting for the app thread to clean up and exit before proceeding. + */ + DESTROY, +} + +android_poll_source :: struct { + // The identifier of this source. May be LOOPER_ID_MAIN or + // LOOPER_ID_INPUT. + id: c.int32_t, + + // The android_app this ident is associated with. + app: ^android_app, + + // Function to call to perform the standard processing of data from + // this source. + //void (*process)(struct android_app* app, struct android_poll_source* source), + process: #type proc "c" (app: ^android_app, source: ^android_poll_source), +} + +android_app :: struct { + // The application can place a pointer to its own state object + // here if it likes. + userData: rawptr, + + // Fill this in with the function to process main app commands (APP_CMD_*) + onAppCmd: #type proc "c" (app: ^android_app, cmd: AppCmd), + + // Fill this in with the function to process input events. At this point + // the event has already been pre-dispatched, and it will be finished upon + // return. Return 1 if you have handled the event, 0 for any default + // dispatching. + onInputEvent: #type proc "c" (app: ^android_app, event: ^AInputEvent) -> c.int32_t, + + // The ANativeActivity object instance that this app is running in. + activity: ^ANativeActivity, + + // The current configuration the app is running in. + config: ^AConfiguration, + + // This is the last instance's saved state, as provided at creation time. + // It is NULL if there was no state. You can use this as you need, the + // memory will remain around until you call android_app_exec_cmd() for + // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL. + // These variables should only be changed when processing a APP_CMD_SAVE_STATE, + // at which point they will be initialized to NULL and you can malloc your + // state and place the information here. In that case the memory will be + // freed for you later. + savedState: rawptr, + savedStateSize: c.size_t, + + // The ALooper associated with the app's thread. + looper: ^ALooper, + + // When non-NULL, this is the input queue from which the app will + // receive user input events. + inputQueue: ^AInputQueue, + + // When non-NULL, this is the window surface that the app can draw in. + window: ^ANativeWindow, + + // Current content rectangle of the window, this is the area where the + // window's content should be placed to be seen by the user. + contentRect: ARect, + + // Current state of the app's activity. May be either APP_CMD_START, + // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP, see below. + activityState: c.int, + + // This is non-zero when the application's NativeActivity is being + // destroyed and waiting for the app thread to complete. + destroyRequested: c.int, + + // ------------------------------------------------- + // Below are "private" implementation of the glue code. + + mutex: unix.pthread_mutex_t, + cond: unix.pthread_cond_t, + + msgread: c.int, + msgwrite: c.int, + + thread: unix.pthread_t, + + cmdPollSource: android_poll_source, + inputPollSource: android_poll_source, + + running: c.int, + stateSaved: c.int, + destroyed: c.int, + redrawNeeded: c.int, + pendingInputQueue: ^AInputQueue, + pendingWindow: ^ANativeWindow, + pendingContentRect: ARect, +} + +foreign android { + app_dummy :: proc() --- +} diff --git a/asset_manager.odin b/asset_manager.odin new file mode 100644 index 0000000..46e4374 --- /dev/null +++ b/asset_manager.odin @@ -0,0 +1,185 @@ +//+build android +package android + +import "core:c" + +foreign import android "system:android" + +/** Available access modes for opening assets with {@link AAssetManager_open} */ +AssetOpenMode :: enum c.int { + /** No specific information about how data will be accessed. **/ + UNKNOWN = 0, + /** Read chunks, and seek forward and backward. */ + RANDOM = 1, + /** Read sequentially, with an occasional forward seek. */ + STREAMING = 2, + /** Caller plans to ask for a read-only buffer with all data. */ + BUFFER = 3 +} + +// Same as sys/linux but this is i32 instead of i16 +Seek_Whence :: enum i32 { + SET = 0, + CUR = 1, + END = 2, + DATA = 3, + HOLE = 4, +} + +/** + * {@link AAssetManager} provides access to an application's raw assets by + * creating {@link AAsset} objects. + * + * AAssetManager is a wrapper to the low-level native implementation + * of the java {@link AAssetManager}, a pointer can be obtained using + * AAssetManager_fromJava(). + * + * The asset hierarchy may be examined like a filesystem, using + * {@link AAssetDir} objects to peruse a single directory. + * + * A native {@link AAssetManager} pointer may be shared across multiple threads. + */ +AAssetManager :: struct{} + +/** + * {@link AAssetDir} provides access to a chunk of the asset hierarchy as if + * it were a single directory. The contents are populated by the + * {@link AAssetManager}. + * + * The list of files will be sorted in ascending order by ASCII value. + */ + AAssetDir :: struct{} + +/** + * {@link AAsset} provides access to a read-only asset. + * + * {@link AAsset} objects are NOT thread-safe, and should not be shared across + * threads. + */ +AAsset :: struct{} + +foreign android { + /** + * Open an asset. + * + * The object returned here should be freed by calling AAsset_close(). + */ + AAssetManager_open :: proc(mgr: ^AAssetManager, filename: cstring, mode: AssetOpenMode) -> ^AAsset --- + + /** + * Iterate over the files in an asset directory. A NULL string is returned + * when all the file names have been returned. + * + * The returned file name is suitable for passing to AAssetManager_open(). + * + * The string returned here is owned by the AssetDir implementation and is not + * guaranteed to remain valid if any other calls are made on this AAssetDir + * instance. + */ + AAssetDir_getNextFileName :: proc(assetDir: ^AAssetDir) -> cstring --- + + /** + * Reset the iteration state of AAssetDir_getNextFileName() to the beginning. + */ + AAssetDir_rewind :: proc(assetDir: ^AAssetDir) --- + + /** + * Close an opened AAssetDir, freeing any related resources. + */ + AAssetDir_close :: proc(assetDir: ^AAssetDir) --- + + /** + * Attempt to read 'count' bytes of data from the current offset. + * + * Returns the number of bytes read, zero on EOF, or < 0 on error. + */ + AAsset_read :: proc(asset: ^AAsset, buf: rawptr, count: uint) -> i32 --- + + /** + * Seek to the specified offset within the asset data. 'whence' uses the + * same constants as lseek()/fseek(). + * + * Returns the new position on success, or (off_t) -1 on error. + */ + // TODO: should we just not bind these functions since their 64-bit counterparts are available? + // Because according to https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md + // and the __RENAME_IF_FILE_OFFSET64() macro these functions are replaced with the 64-bit versions at + // runtime anyway (at least for 32-bit Android). + // off_t is replaced with off64_t too. + // I think all Android API version <21 should explicitly be unsupported both by Odin and the bindings here since + // this opens a can of worms that I do not like. + AAsset_seek :: proc(asset: ^AAsset, offset: off_t, whence: Seek_Whence) -> off_t --- + + /** + * Seek to the specified offset within the asset data. 'whence' uses the + * same constants as lseek()/fseek(). + * + * Uses 64-bit data type for large files as opposed to the 32-bit type used + * by AAsset_seek. + * + * Returns the new position on success, or (off64_t) -1 on error. + */ + AAsset_seek64 :: proc(asset: ^AAsset, offset: off64_t, whence: Seek_Whence) -> off64_t --- + + /** + * Close the asset, freeing all associated resources. + */ + AAsset_close :: proc(asset: ^AAsset) --- + + /** + * Get a pointer to a buffer holding the entire contents of the assset. + * + * Returns NULL on failure. + */ + AAsset_getBuffer :: proc(asset: ^AAsset) -> rawptr --- + + /** + * Report the total size of the asset data. + */ + AAsset_getLength :: proc(asset: ^AAsset) -> off_t --- + + /** + * Report the total size of the asset data. Reports the size using a 64-bit + * number insted of 32-bit as AAsset_getLength. + */ + AAsset_getLength64 :: proc(asset: ^AAsset) -> off64_t --- + + /** + * Report the total amount of asset data that can be read from the current position. + */ + AAsset_getRemainingLength :: proc(asset: ^AAsset) -> off_t --- + + /** + * Report the total amount of asset data that can be read from the current position. + * + * Uses a 64-bit number instead of a 32-bit number as AAsset_getRemainingLength does. + */ + AAsset_getRemainingLength64 :: proc(asset: ^AAsset) -> off64_t --- + + /** + * Open a new file descriptor that can be used to read the asset data. If the + * start or length cannot be represented by a 32-bit number, it will be + * truncated. If the file is large, use AAsset_openFileDescriptor64 instead. + * + * Returns < 0 if direct fd access is not possible (for example, if the asset is + * compressed). + */ + AAsset_openFileDescriptor :: proc(asset: ^AAsset, outStart: ^off_t, outLength: ^off_t) -> i32 --- + + /** + * Open a new file descriptor that can be used to read the asset data. + * + * Uses a 64-bit number for the offset and length instead of 32-bit instead of + * as AAsset_openFileDescriptor does. + * + * Returns < 0 if direct fd access is not possible (for example, if the asset is + * compressed). + */ + AAsset_openFileDescriptor64 :: proc(asset: ^AAsset, outStart: ^off64_t, outLength: ^off64_t) -> i32 --- + + /** + * Returns whether this asset's internal buffer is allocated in ordinary RAM (i.e. not + * mmapped). + */ + AAsset_isAllocated :: proc(asset: ^AAsset) -> i32 --- +} diff --git a/asset_manager_jni.odin b/asset_manager_jni.odin new file mode 100644 index 0000000..cf3d111 --- /dev/null +++ b/asset_manager_jni.odin @@ -0,0 +1,14 @@ +//+build android +package android + +foreign import android "system:android" + +foreign android { + /** + * Given a Dalvik AssetManager object, obtain the corresponding native AAssetManager + * object. Note that the caller is responsible for obtaining and holding a VM reference + * to the jobject to prevent its being garbage collected while the native object is + * in use. + */ + AAssetManager_fromJava :: proc(env: ^JNIEnv, assetManager: jobject) -> ^AAssetManager --- +} diff --git a/bitmap.odin b/bitmap.odin new file mode 100644 index 0000000..83c5227 --- /dev/null +++ b/bitmap.odin @@ -0,0 +1,213 @@ +//+build android +package android + +foreign import android "system:android" + +/** AndroidBitmap functions result code. */ +ABitmapResult :: enum i32 { + SUCCESS = 0, + BAD_PARAMETER = -1, + JNI_EXCEPTION = -2, + ALLOCATION_FAILED = -3, +} + +/** Bitmap pixel format. */ +AndroidBitmapFormat :: enum i32 { + /** No format. */ + NONE = 0, + /** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/ + RGBA_8888 = 1, + /** Red: 5 bits, Green: 6 bits, Blue: 5 bits. **/ + RGB_565 = 4, + /** Deprecated in API level 13. Because of the poor quality of this configuration, it is advised to use ARGB_8888 instead. **/ + RGBA_4444 = 7, + /** Alpha: 8 bits. */ + A_8 = 8, + /** Each component is stored as a half float. **/ + RGBA_F16 = 9, + /** Red: 10 bits, Green: 10 bits, Blue: 10 bits, Alpha: 2 bits. **/ + RGBA_1010102 = 10, +} + +/** Bitmap alpha format */ +AndroidBitmapFlagsAlpha :: enum { + /** Pixel components are premultiplied by alpha. */ + PREMUL = 0, + /** Pixels are opaque. */ + OPAQUE = 1, + /** Pixel components are independent of alpha. */ + UNPREMUL = 2, + /** Bit mask for BitmapInfo.flags to isolate the alpha. */ + MASK = 0x3, + /** Shift for BitmapInfo.flags to isolate the alpha. */ + SHIFT = 0, +} + +AndroidBitmapFlags :: enum { + /** If this bit is set in BitmapInfo.flags, the Bitmap uses the + * HARDWARE Config, and its {@link AHardwareBuffer} can be retrieved via + * {@link AndroidBitmap_getHardwareBuffer}. + */ + IS_HARDWARE = 1 << 31, +} + +// Note: these values match android.graphics.Bitmap#compressFormat. + +/** + * Specifies the formats that can be compressed to with + * {@link AndroidBitmap_compress}. + */ +AndroidBitmapCompressFormat :: enum i32 { + /** + * Compress to the JPEG format. quality of 0 means + * compress for the smallest size. 100 means compress for max + * visual quality. + */ + JPEG = 0, + /** + * Compress to the PNG format. PNG is lossless, so quality is + * ignored. + */ + PNG = 1, + /** + * Compress to the WEBP lossy format. quality of 0 means + * compress for the smallest size. 100 means compress for max + * visual quality. + */ + WEBP_LOSSY = 3, + /** + * Compress to the WEBP lossless format. quality refers to how + * much effort to put into compression. A value of 0 means to + * compress quickly, resulting in a relatively large file size. + * 100 means to spend more time compressing, resulting in a + * smaller file. + */ + WEBP_LOSSLESS = 4, +} + +/** Bitmap info, see AndroidBitmap_getInfo(). */ +BitmapInfo :: struct { + /** The bitmap width in pixels. */ + width: u32, + /** The bitmap height in pixels. */ + height: u32, + /** The number of byte per row. */ + stride: u32, + /** The bitmap pixel format. See {@link AndroidBitmapFormat} */ + format: AndroidBitmapFormat, + /** Bitfield containing information about the bitmap. + * + *

Two bits are used to encode alpha. Use {@link AndroidBitmapFlagsAlpha.MASK} + * and {@link AndroidBitmapFlagsAlpha.SHIFT} to retrieve them.

+ * + *

One bit is used to encode whether the Bitmap uses the HARDWARE Config. Use + * {@link AndroidBitmapFlags.IS_HARDWARE} to know.

+ * + *

These flags were introduced in API level 30.

+ */ + flags: u32, +} + +/** + * User-defined function for writing the output of compression. + * + * Available since API level 30. + * + * @param userContext Pointer to user-defined data passed to + * {@link AndroidBitmap_compress}. + * @param data Compressed data of |size| bytes to write. + * @param size Length in bytes of data to write. + * @return Whether the operation succeeded. + */ +AndroidBitmap_CompressWriteFunc :: #type proc "c" (userContext: rawptr, data: rawptr, size: uint) -> bool + + +foreign android { + /** + * Given a java bitmap object, fill out the {@link BitmapInfo} struct for it. + * If the call fails, the info parameter will be ignored. + */ + AndroidBitmap_getInfo :: proc(env: ^JNIEnv, jbitmap: jobject, info: ^BitmapInfo) -> ABitmapResult --- + + /** + * Given a java bitmap object, return its {@link ADataSpace}. + * + * Note that {@link ADataSpace} only exposes a few values. This may return + * {@link ADATASPACE_UNKNOWN}, even for Named ColorSpaces, if they have no + * corresponding ADataSpace. + * + * Available since API level 30. + */ + AndroidBitmap_getDataSpace :: proc(env: ^JNIEnv, jbitmap: jobject) -> ADataSpace --- + + /** + * Given a java bitmap object, attempt to lock the pixel address. + * Locking will ensure that the memory for the pixels will not move + * until the unlockPixels call, and ensure that, if the pixels had been + * previously purged, they will have been restored. + * + * If this call succeeds, it must be balanced by a call to + * AndroidBitmap_unlockPixels, after which time the address of the pixels should + * no longer be used. + * + * If this succeeds, *addrPtr will be set to the pixel address. If the call + * fails, addrPtr will be ignored. + */ + AndroidBitmap_lockPixels :: proc(env: ^JNIEnv, jbitmap: jobject, addrPtr: ^rawptr) -> ABitmapResult --- + + /** + * Call this to balance a successful call to AndroidBitmap_lockPixels. + */ + AndroidBitmap_unlockPixels :: proc(env: ^JNIEnv, jbitmap: jobject) -> ABitmapResult --- + + /** + * Compress |pixels| as described by |info|. + * + * Available since API level 30. + * + * @param info Description of the pixels to compress. + * @param dataspace {@link ADataSpace} describing the color space of the + * pixels. + * @param pixels Pointer to pixels to compress. + * @param format {@link AndroidBitmapCompressFormat} to compress to. + * @param quality Hint to the compressor, 0-100. The value is interpreted + * differently depending on the + * {@link AndroidBitmapCompressFormat}. + * @param userContext User-defined data which will be passed to the supplied + * {@link AndroidBitmap_CompressWriteFunc} each time it is + * called. May be null. + * @param fn Function that writes the compressed data. Will be called each time + * the compressor has compressed more data that is ready to be + * written. May be called more than once for each call to this method. + * May not be null. + * @return AndroidBitmap functions result code. + */ + AndroidBitmap_compress :: proc( + info: ^BitmapInfo, + dataspace: ADataSpace, + pixels: rawptr, + format: AndroidBitmapCompressFormat, + quality: i32, + userContext: rawptr, + fn: AndroidBitmap_CompressWriteFunc) -> ABitmapResult --- + + /** + * Retrieve the native object associated with a HARDWARE Bitmap. + * + * Client must not modify it while a Bitmap is wrapping it. + * + * Available since API level 30. + * + * @param env Handle to the JNI environment pointer. + * @param bitmap Handle to an android.graphics.Bitmap. + * @param outBuffer On success, is set to a pointer to the + * {@link AHardwareBuffer} associated with bitmap. This acquires + * a reference on the buffer, and the client must call + * {@link AHardwareBuffer_release} when finished with it. + * @return AndroidBitmap functions result code. + * {@link ANDROID_BITMAP_RESULT_BAD_PARAMETER} if bitmap is not a + * HARDWARE Bitmap. + */ + AndroidBitmap_getHardwareBuffer :: proc(env: ^JNIEnv, bitmap: jobject, outBuffer: ^^AHardwareBuffer) -> ABitmapResult --- +} + diff --git a/choreographer.odin b/choreographer.odin new file mode 100644 index 0000000..ab7f268 --- /dev/null +++ b/choreographer.odin @@ -0,0 +1,201 @@ +//+build android +package android + +import "core:c" + +foreign import android "system:android" + +/** + * Opaque type that provides access to an AChoreographer object. + * + * A pointer can be obtained using {@link AChoreographer_getInstance()}. + */ +AChoreographer :: struct{} + +/** + * The identifier of a frame timeline. + */ +AVsyncId :: i64 + +/** + * Opaque type that provides access to an AChoreographerFrameCallbackData object, which contains + * various methods to extract frame information. + */ +AChoreographerFrameCallbackData :: struct{} + +/** + * Prototype of the function that is called when a new frame is being rendered. + * It's passed the time that the frame is being rendered as nanoseconds in the + * CLOCK_MONOTONIC time base, as well as the data pointer provided by the + * application that registered a callback. All callbacks that run as part of + * rendering a frame will observe the same frame time, so it should be used + * whenever events need to be synchronized (e.g. animations). + */ +AChoreographer_frameCallback :: #type proc "c" (frameTimeNanos: c.long, data: rawptr) + +/** + * Prototype of the function that is called when a new frame is being rendered. + * It's passed the time that the frame is being rendered as nanoseconds in the + * CLOCK_MONOTONIC time base, as well as the data pointer provided by the + * application that registered a callback. All callbacks that run as part of + * rendering a frame will observe the same frame time, so it should be used + * whenever events need to be synchronized (e.g. animations). + */ +AChoreographer_frameCallback64 :: #type proc "c" (frameTimeNanos: i64, data: rawptr) + +/** + * Prototype of the function that is called when a new frame is being rendered. + * It is called with \c callbackData describing multiple frame timelines, as well as the \c data + * pointer provided by the application that registered a callback. The \c callbackData does not + * outlive the callback. + */ +AChoreographer_vsyncCallback :: #type proc "c" (callbackData: ^AChoreographerFrameCallbackData, data: rawptr) + +/** + * Prototype of the function that is called when the display refresh rate + * changes. It's passed the new vsync period in nanoseconds, as well as the data + * pointer provided by the application that registered a callback. + */ +AChoreographer_refreshRateCallback :: #type proc "c" (vsyncPeriodNanos: i64, data: rawptr) + + +foreign android { + /** + * Get the AChoreographer instance for the current thread. This must be called + * on an ALooper thread. + * + * Available since API level 24. + */ + AChoreographer_getInstance :: proc() -> ^AChoreographer --- + + /** + * Deprecated: Use AChoreographer_postFrameCallback64 instead. + * Deprecated since API level 29 + */ + @(deprecated="Use AChoreographer_postFrameCallback64 instead") + AChoreographer_postFrameCallback :: proc(choreographer: ^AChoreographer, callback: AChoreographer_frameCallback, data: rawptr) --- + + /** + * Deprecated: Use AChoreographer_postFrameCallbackDelayed64 instead. + * Deprecated since API level 29 + */ + @(deprecated="Use AChoreographer_postFrameCallbackDelayed64 instead") + AChoreographer_postFrameCallbackDelayed :: proc(choreographer: ^AChoreographer, callback: AChoreographer_frameCallback, data: rawptr, delayMillis: c.long) --- + + /** + * Post a callback to be run on the next frame. The data pointer provided will + * be passed to the callback function when it's called. + * + * Available since API level 29. + */ + AChoreographer_postFrameCallback64 :: proc(choreographer: ^AChoreographer, callback: AChoreographer_frameCallback64, data: rawptr) --- + + /** + * Post a callback to be run on the frame following the specified delay. The + * data pointer provided will be passed to the callback function when it's + * called. + * + * Available since API level 29. + */ + AChoreographer_postFrameCallbackDelayed64 :: proc(choreographer: ^AChoreographer, callback: AChoreographer_frameCallback64, data: rawptr, delayMillis: u32) --- + + /** + * Posts a callback to be run on the next frame. The data pointer provided will + * be passed to the callback function when it's called. + * + * Available since API level 33. + */ + AChoreographer_postVsyncCallback :: proc(choreographer: ^AChoreographer, callback: AChoreographer_vsyncCallback, data: rawptr) --- + + /** + * Registers a callback to be run when the display refresh rate changes. The + * data pointer provided will be passed to the callback function when it's + * called. The same callback may be registered multiple times, provided that a + * different data pointer is provided each time. + * + * If an application registers a callback for this choreographer instance when + * no new callbacks were previously registered, that callback is guaranteed to + * be dispatched. However, if the callback and associated data pointer are + * unregistered prior to running the callback, then the callback may be silently + * dropped. + * + * This api is thread-safe. Any thread is allowed to register a new refresh + * rate callback for the choreographer instance. + * + * Note that in API level 30, this api is not guaranteed to be atomic with + * DisplayManager. That is, calling Display#getRefreshRate very soon after + * a refresh rate callback is invoked may return a stale refresh rate. If any + * Display properties would be required by this callback, then it is recommended + * to listen directly to DisplayManager.DisplayListener#onDisplayChanged events + * instead. + * + * As of API level 31, this api is guaranteed to have a consistent view with DisplayManager + * Display#getRefreshRate is guaranteed to not return a stale refresh rate when invoked from this + * callback. + * + * Available since API level 30. + */ + AChoreographer_registerRefreshRateCallback :: proc(choreographer: ^AChoreographer, callback: AChoreographer_refreshRateCallback, data: rawptr) --- + + /** + * Unregisters a callback to be run when the display refresh rate changes, along + * with the data pointer previously provided when registering the callback. The + * callback is only unregistered when the data pointer matches one that was + * previously registered. + * + * This api is thread-safe. Any thread is allowed to unregister an existing + * refresh rate callback for the choreographer instance. When a refresh rate + * callback and associated data pointer are unregistered, then there is a + * guarantee that when the unregistration completes that that callback will not + * be run with the data pointer passed. + * + * Available since API level 30. + */ + AChoreographer_unregisterRefreshRateCallback :: proc(choreographer: ^AChoreographer, callback: AChoreographer_refreshRateCallback, data: rawptr) --- + + /** + * The time in nanoseconds at which the frame started being rendered. + * + * Note that this time should \b not be used to advance animation clocks. + * Instead, see AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(). + */ + AChoreographerFrameCallbackData_getFrameTimeNanos :: proc(data: ^AChoreographerFrameCallbackData) -> i64 --- + + /** + * The number of possible frame timelines. + */ + AChoreographerFrameCallbackData_getFrameTimelinesLength :: proc(data: ^AChoreographerFrameCallbackData) -> uint --- + + /** + * Gets the index of the platform-preferred frame timeline. + * The preferred frame timeline is the default + * by which the platform scheduled the app, based on the device configuration. + */ + AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex :: proc(data: ^AChoreographerFrameCallbackData) -> uint --- + + /** + * Gets the token used by the platform to identify the frame timeline at the given \c index. + * + * \param index index of a frame timeline, in \f( [0, FrameTimelinesLength) \f). See + * AChoreographerFrameCallbackData_getFrameTimelinesLength() + */ + AChoreographerFrameCallbackData_getFrameTimelineVsyncId :: proc(data: ^AChoreographerFrameCallbackData, index: uint) -> AVsyncId --- + + /** + * Gets the time in nanoseconds at which the frame described at the given \c index is expected to + * be presented. This time should be used to advance any animation clocks. + * + * \param index index of a frame timeline, in \f( [0, FrameTimelinesLength) \f). See + * AChoreographerFrameCallbackData_getFrameTimelinesLength() + */ + AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos :: proc(data: ^AChoreographerFrameCallbackData, index: uint) -> i64 --- + + /** + * Gets the time in nanoseconds at which the frame described at the given \c index needs to be + * ready by in order to be presented on time. + * + * \param index index of a frame timeline, in \f( [0, FrameTimelinesLength) \f). See + * AChoreographerFrameCallbackData_getFrameTimelinesLength() + */ + AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos :: proc(data: ^AChoreographerFrameCallbackData, index: uint) -> i64 --- +} diff --git a/configuration.odin b/configuration.odin new file mode 100644 index 0000000..0f13ebd --- /dev/null +++ b/configuration.odin @@ -0,0 +1,713 @@ +//+build android +package android + +foreign import android "system:android" + +/** Orientation: not specified. */ +ORIENTATION_ANY :: 0x0000 +/** +* Orientation: value corresponding to the +* port +* resource qualifier. +*/ +ORIENTATION_PORT :: 0x0001 +/** +* Orientation: value corresponding to the +* land +* resource qualifier. +*/ +ORIENTATION_LAND :: 0x0002 +/** @deprecated Not currently supported or used. */ +ORIENTATION_SQUARE :: 0x0003 + +/** Touchscreen: not specified. */ +TOUCHSCREEN_ANY :: 0x0000 +/** +* Touchscreen: value corresponding to the +* notouch +* resource qualifier. +*/ +TOUCHSCREEN_NOTOUCH :: 0x0001 +/** @deprecated Not currently supported or used. */ +TOUCHSCREEN_STYLUS :: 0x0002 +/** +* Touchscreen: value corresponding to the +* finger +* resource qualifier. +*/ +TOUCHSCREEN_FINGER :: 0x0003 + +/** Density: default density. */ +DENSITY_DEFAULT :: 0 +/** +* Density: value corresponding to the +* ldpi +* resource qualifier. +*/ +DENSITY_LOW :: 120 +/** +* Density: value corresponding to the +* mdpi +* resource qualifier. +*/ +DENSITY_MEDIUM :: 160 +/** +* Density: value corresponding to the +* tvdpi +* resource qualifier. +*/ +DENSITY_TV :: 213 +/** +* Density: value corresponding to the +* hdpi +* resource qualifier. +*/ +DENSITY_HIGH :: 240 +/** +* Density: value corresponding to the +* xhdpi +* resource qualifier. +*/ +DENSITY_XHIGH :: 320 +/** +* Density: value corresponding to the +* xxhdpi +* resource qualifier. +*/ +DENSITY_XXHIGH :: 480 +/** +* Density: value corresponding to the +* xxxhdpi +* resource qualifier. +*/ +DENSITY_XXXHIGH :: 640 +/** Density: any density. */ +DENSITY_ANY :: 0xfffe +/** Density: no density specified. */ +DENSITY_NONE :: 0xffff + +/** Keyboard: not specified. */ +KEYBOARD_ANY :: 0x0000 +/** +* Keyboard: value corresponding to the +* nokeys +* resource qualifier. +*/ +KEYBOARD_NOKEYS :: 0x0001 +/** +* Keyboard: value corresponding to the +* qwerty +* resource qualifier. +*/ +KEYBOARD_QWERTY :: 0x0002 +/** +* Keyboard: value corresponding to the +* 12key +* resource qualifier. +*/ +KEYBOARD_12KEY :: 0x0003 + +/** Navigation: not specified. */ +NAVIGATION_ANY :: 0x0000 +/** +* Navigation: value corresponding to the +* nonav +* resource qualifier. +*/ +NAVIGATION_NONAV :: 0x0001 +/** +* Navigation: value corresponding to the +* dpad +* resource qualifier. +*/ +NAVIGATION_DPAD :: 0x0002 +/** +* Navigation: value corresponding to the +* trackball +* resource qualifier. +*/ +NAVIGATION_TRACKBALL :: 0x0003 +/** +* Navigation: value corresponding to the +* wheel +* resource qualifier. +*/ +NAVIGATION_WHEEL :: 0x0004 + +/** Keyboard availability: not specified. */ +KEYSHIDDEN_ANY :: 0x0000 +/** +* Keyboard availability: value corresponding to the +* keysexposed +* resource qualifier. +*/ +KEYSHIDDEN_NO :: 0x0001 +/** +* Keyboard availability: value corresponding to the +* keyshidden +* resource qualifier. +*/ +KEYSHIDDEN_YES :: 0x0002 +/** +* Keyboard availability: value corresponding to the +* keyssoft +* resource qualifier. +*/ +KEYSHIDDEN_SOFT :: 0x0003 + +/** Navigation availability: not specified. */ +NAVHIDDEN_ANY :: 0x0000 +/** +* Navigation availability: value corresponding to the +* navexposed +* resource qualifier. +*/ +NAVHIDDEN_NO :: 0x0001 +/** +* Navigation availability: value corresponding to the +* navhidden +* resource qualifier. +*/ +NAVHIDDEN_YES :: 0x0002 + +/** Screen size: not specified. */ +SCREENSIZE_ANY :: 0x00 +/** +* Screen size: value indicating the screen is at least +* approximately 320x426 dp units corresponding to the +* small +* resource qualifier. +*/ +SCREENSIZE_SMALL :: 0x01 +/** +* Screen size: value indicating the screen is at least +* approximately 320x470 dp units corresponding to the +* normal +* resource qualifier. +*/ +SCREENSIZE_NORMAL :: 0x02 +/** +* Screen size: value indicating the screen is at least +* approximately 480x640 dp units corresponding to the +* large +* resource qualifier. +*/ +SCREENSIZE_LARGE :: 0x03 +/** +* Screen size: value indicating the screen is at least +* approximately 720x960 dp units corresponding to the +* xlarge +* resource qualifier. +*/ +SCREENSIZE_XLARGE :: 0x04 + +/** Screen layout: not specified. */ +SCREENLONG_ANY :: 0x00 +/** +* Screen layout: value that corresponds to the +* notlong +* resource qualifier. +*/ +SCREENLONG_NO :: 0x1 +/** +* Screen layout: value that corresponds to the +* long +* resource qualifier. +*/ +SCREENLONG_YES :: 0x2 + +SCREENROUND_ANY :: 0x00 +SCREENROUND_NO :: 0x1 +SCREENROUND_YES :: 0x2 + +/** Wide color gamut: not specified. */ +WIDE_COLOR_GAMUT_ANY :: 0x00 +/** +* Wide color gamut: value that corresponds to +* no +* nowidecg resource qualifier specified. +*/ +WIDE_COLOR_GAMUT_NO :: 0x1 +/** +* Wide color gamut: value that corresponds to +* +* widecg resource qualifier specified. +*/ +WIDE_COLOR_GAMUT_YES :: 0x2 + +/** HDR: not specified. */ +HDR_ANY :: 0x00 +/** +* HDR: value that corresponds to +* +* lowdr resource qualifier specified. +*/ +HDR_NO :: 0x1 +/** +* HDR: value that corresponds to +* +* highdr resource qualifier specified. +*/ +HDR_YES :: 0x2 + +/** UI mode: not specified. */ +UI_MODE_TYPE_ANY :: 0x00 +/** +* UI mode: value that corresponds to +* no +* UI mode type resource qualifier specified. +*/ +UI_MODE_TYPE_NORMAL :: 0x01 +/** +* UI mode: value that corresponds to +* desk resource qualifier specified. +*/ +UI_MODE_TYPE_DESK :: 0x02 +/** +* UI mode: value that corresponds to +* car resource qualifier specified. +*/ +UI_MODE_TYPE_CAR :: 0x03 +/** +* UI mode: value that corresponds to +* television resource qualifier specified. +*/ +UI_MODE_TYPE_TELEVISION :: 0x04 +/** +* UI mode: value that corresponds to +* appliance resource qualifier specified. +*/ +UI_MODE_TYPE_APPLIANCE :: 0x05 +/** +* UI mode: value that corresponds to +* watch resource qualifier specified. +*/ +UI_MODE_TYPE_WATCH :: 0x06 +/** +* UI mode: value that corresponds to +* vr resource qualifier specified. +*/ +UI_MODE_TYPE_VR_HEADSET :: 0x07 + +/** UI night mode: not specified.*/ +UI_MODE_NIGHT_ANY :: 0x00 +/** +* UI night mode: value that corresponds to +* notnight resource qualifier specified. +*/ +UI_MODE_NIGHT_NO :: 0x1 +/** +* UI night mode: value that corresponds to +* night resource qualifier specified. +*/ +UI_MODE_NIGHT_YES :: 0x2 + +/** Screen width DPI: not specified. */ +SCREEN_WIDTH_DP_ANY :: 0x0000 + +/** Screen height DPI: not specified. */ +SCREEN_HEIGHT_DP_ANY :: 0x0000 + +/** Smallest screen width DPI: not specified.*/ +SMALLEST_SCREEN_WIDTH_DP_ANY :: 0x0000 + +/** Layout direction: not specified. */ +LAYOUTDIR_ANY :: 0x00 +/** +* Layout direction: value that corresponds to +* ldltr resource qualifier specified. +*/ +LAYOUTDIR_LTR :: 0x01 +/** +* Layout direction: value that corresponds to +* ldrtl resource qualifier specified. +*/ +LAYOUTDIR_RTL :: 0x02 + +/** +* Bit mask for +* mcc +* configuration. +*/ +MCC :: 0x0001 +/** +* Bit mask for +* mnc +* configuration. +*/ +MNC :: 0x0002 +/** +* Bit mask for +* locale +* configuration. +*/ +LOCALE :: 0x0004 +/** +* Bit mask for +* touchscreen +* configuration. +*/ +TOUCHSCREEN :: 0x0008 +/** +* Bit mask for +* keyboard +* configuration. +*/ +KEYBOARD :: 0x0010 +/** +* Bit mask for +* keyboardHidden +* configuration. +*/ +KEYBOARD_HIDDEN :: 0x0020 +/** +* Bit mask for +* navigation +* configuration. +*/ +NAVIGATION :: 0x0040 +/** +* Bit mask for +* orientation +* configuration. +*/ +ORIENTATION :: 0x0080 +/** +* Bit mask for +* density +* configuration. +*/ +DENSITY :: 0x0100 +/** +* Bit mask for +* screen size +* configuration. +*/ +SCREEN_SIZE :: 0x0200 +/** +* Bit mask for +* platform version +* configuration. +*/ +VERSION :: 0x0400 +/** +* Bit mask for screen layout configuration. +*/ +SCREEN_LAYOUT :: 0x0800 +/** +* Bit mask for +* ui mode +* configuration. +*/ +UI_MODE :: 0x1000 +/** +* Bit mask for +* smallest screen width +* configuration. +*/ +SMALLEST_SCREEN_SIZE :: 0x2000 +/** +* Bit mask for +* layout direction +* configuration. +*/ +LAYOUTDIR :: 0x4000 +SCREEN_ROUND :: 0x8000 +/** +* Bit mask for +* wide color gamut +* and HDR configurations. +*/ +COLOR_MODE :: 0x10000 +/** +* Constant used to to represent MNC (Mobile Network Code) zero. +* 0 cannot be used since it is used to represent an undefined MNC. +*/ +MNC_ZERO :: 0xffff + + +/** + * {@link AConfiguration} is an opaque type used to get and set + * various subsystem configurations. + * + * A {@link AConfiguration} pointer can be obtained using: + * - AConfiguration_new() + * - AConfiguration_fromAssetManager() + */ +AConfiguration :: struct{} + +foreign android { + /** + * Create a new AConfiguration, initialized with no values set. + */ + AConfiguration_new :: proc() -> ^AConfiguration --- + + /** + * Free an AConfiguration that was previously created with + * AConfiguration_new(). + */ + AConfiguration_delete :: proc(config: ^AConfiguration) --- + + /** + * Create and return a new AConfiguration based on the current configuration in + * use in the given {@link AAssetManager}. + */ + AConfiguration_fromAssetManager :: proc(out: ^AConfiguration, am: ^AAssetManager) --- + + /** + * Copy the contents of 'src' to 'dest'. + */ + AConfiguration_copy :: proc(dest: ^AConfiguration, src: ^AConfiguration) --- + + /** + * Return the current MCC set in the configuration. 0 if not set. + */ + AConfiguration_getMcc :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current MCC in the configuration. 0 to clear. + */ + AConfiguration_setMcc :: proc(config: ^AConfiguration, mcc: i32) --- + + /** + * Return the current MNC set in the configuration. 0 if not set. + */ + AConfiguration_getMnc :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current MNC in the configuration. 0 to clear. + */ + AConfiguration_setMnc :: proc(config: ^AConfiguration, mnc: i32) --- + + /** + * Return the current language code set in the configuration. The output will + * be filled with an array of two characters. They are not 0-terminated. If + * a language is not set, they will be 0. + */ + AConfiguration_getLanguage :: proc(config: ^AConfiguration, outLanguage: [^]byte) --- + + /** + * Set the current language code in the configuration, from the first two + * characters in the string. + */ + AConfiguration_setLanguage :: proc(config: ^AConfiguration, language: cstring) --- + + /** + * Return the current country code set in the configuration. The output will + * be filled with an array of two characters. They are not 0-terminated. If + * a country is not set, they will be 0. + */ + AConfiguration_getCountry :: proc(config: ^AConfiguration, outCountry: [^]byte) --- + + /** + * Set the current country code in the configuration, from the first two + * characters in the string. + */ + AConfiguration_setCountry :: proc(config: ^AConfiguration, country: cstring) --- + + /** + * Return the current ACONFIGURATION_ORIENTATION_* set in the configuration. + */ + AConfiguration_getOrientation :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current orientation in the configuration. + */ + AConfiguration_setOrientation :: proc(config: ^AConfiguration, orientation: i32) --- + + /** + * Return the current ACONFIGURATION_TOUCHSCREEN_* set in the configuration. + */ + AConfiguration_getTouchscreen :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current touchscreen in the configuration. + */ + AConfiguration_setTouchscreen :: proc(config: ^AConfiguration, touchscreen: i32) --- + + /** + * Return the current ACONFIGURATION_DENSITY_* set in the configuration. + */ + AConfiguration_getDensity :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current density in the configuration. + */ + AConfiguration_setDensity :: proc(config: ^AConfiguration, density: i32) --- + + /** + * Return the current ACONFIGURATION_KEYBOARD_* set in the configuration. + */ + AConfiguration_getKeyboard :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current keyboard in the configuration. + */ + AConfiguration_setKeyboard :: proc(config: ^AConfiguration, keyboard: i32) --- + + /** + * Return the current ACONFIGURATION_NAVIGATION_* set in the configuration. + */ + AConfiguration_getNavigation :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current navigation in the configuration. + */ + AConfiguration_setNavigation :: proc(config: ^AConfiguration, navigation: i32) --- + + /** + * Return the current ACONFIGURATION_KEYSHIDDEN_* set in the configuration. + */ + AConfiguration_getKeysHidden :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current keys hidden in the configuration. + */ + AConfiguration_setKeysHidden :: proc(config: ^AConfiguration, keysHidden: i32) --- + + /** + * Return the current ACONFIGURATION_NAVHIDDEN_* set in the configuration. + */ + AConfiguration_getNavHidden :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current nav hidden in the configuration. + */ + AConfiguration_setNavHidden :: proc(config: ^AConfiguration, navHidden: i32) --- + + /** + * Return the current SDK (API) version set in the configuration. + */ + AConfiguration_getSdkVersion :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current SDK version in the configuration. + */ + AConfiguration_setSdkVersion :: proc(config: ^AConfiguration, sdkVersion: i32) --- + + /** + * Return the current ACONFIGURATION_SCREENSIZE_* set in the configuration. + */ + AConfiguration_getScreenSize :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current screen size in the configuration. + */ + AConfiguration_setScreenSize :: proc(config: ^AConfiguration, screenSize: i32) --- + + /** + * Return the current ACONFIGURATION_SCREENLONG_* set in the configuration. + */ + AConfiguration_getScreenLong :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current screen long in the configuration. + */ + AConfiguration_setScreenLong :: proc(config: ^AConfiguration, screenLong: i32) --- + + /** + * Return the current ACONFIGURATION_SCREENROUND_* set in the configuration. + * + * Available since API level 30. + */ + AConfiguration_getScreenRound :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current screen round in the configuration. + */ + AConfiguration_setScreenRound :: proc(config: ^AConfiguration, screenRound: i32) --- + + /** + * Return the current ACONFIGURATION_UI_MODE_TYPE_* set in the configuration. + */ + AConfiguration_getUiModeType :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current UI mode type in the configuration. + */ + AConfiguration_setUiModeType :: proc(config: ^AConfiguration, uiModeType: i32) --- + + /** + * Return the current ACONFIGURATION_UI_MODE_NIGHT_* set in the configuration. + */ + AConfiguration_getUiModeNight :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the current UI mode night in the configuration. + */ + AConfiguration_setUiModeNight :: proc(config: ^AConfiguration, uiModeNight: i32) --- + + /** + * Return the current configuration screen width in dp units, or + * ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set. + */ + AConfiguration_getScreenWidthDp :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the configuration's current screen width in dp units. + */ + AConfiguration_setScreenWidthDp :: proc(config: ^AConfiguration, value: i32) --- + + /** + * Return the current configuration screen height in dp units, or + * ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set. + */ + AConfiguration_getScreenHeightDp :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the configuration's current screen width in dp units. + */ + AConfiguration_setScreenHeightDp :: proc(config: ^AConfiguration, value: i32) --- + + /** + * Return the configuration's smallest screen width in dp units, or + * ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set. + */ + AConfiguration_getSmallestScreenWidthDp :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the configuration's smallest screen width in dp units. + */ + AConfiguration_setSmallestScreenWidthDp :: proc(config: ^AConfiguration, value: i32) --- + + /** + * Return the configuration's layout direction, or + * ACONFIGURATION_LAYOUTDIR_ANY if not set. + * + * Available since API level 17. + */ + AConfiguration_getLayoutDirection :: proc(config: ^AConfiguration) -> i32 --- + + /** + * Set the configuration's layout direction. + * + * Available since API level 17. + */ + AConfiguration_setLayoutDirection :: proc(config: ^AConfiguration, value: i32) --- + + /** + * Perform a diff between two configurations. Returns a bit mask of + * ACONFIGURATION_* constants, each bit set meaning that configuration element + * is different between them. + */ + AConfiguration_diff :: proc(config1: ^AConfiguration, config2: ^AConfiguration) -> i32 --- + + /** + * Determine whether 'base' is a valid configuration for use within the + * environment 'requested'. Returns 0 if there are any values in 'base' + * that conflict with 'requested'. Returns 1 if it does not conflict. + */ + AConfiguration_match :: proc(base: ^AConfiguration, requested: ^AConfiguration) -> i32 --- + + /** + * Determine whether the configuration in 'test' is better than the existing + * configuration in 'base'. If 'requested' is non-NULL, this decision is based + * on the overall configuration given there. If it is NULL, this decision is + * simply based on which configuration is more specific. Returns non-0 if + * 'test' is better than 'base'. + * + * This assumes you have already filtered the configurations with + * AConfiguration_match(). + */ + AConfiguration_isBetterThan :: proc(base: ^AConfiguration, test: ^AConfiguration, requested: ^AConfiguration) -> i32 --- +} diff --git a/data_space.odin b/data_space.odin new file mode 100644 index 0000000..1e02bcc --- /dev/null +++ b/data_space.odin @@ -0,0 +1,527 @@ +//+build android +package android + +/** + * ADataSpace. + */ +ADataSpace :: enum i32 { + /** + * Default-assumption data space, when not explicitly specified. + * + * It is safest to assume the buffer is an image with sRGB primaries and + * encoding ranges, but the consumer and/or the producer of the data may + * simply be using defaults. No automatic gamma transform should be + * expected, except for a possible display gamma transform when drawn to a + * screen. + */ + UNKNOWN = 0, + + /** + * Color-description aspects + * + * The following aspects define various characteristics of the color + * specification. These represent bitfields, so that a data space value + * can specify each of them independently. + */ + + /** + * Standard aspect + * + * Defines the chromaticity coordinates of the source primaries in terms of + * the CIE 1931 definition of x and y specified in ISO 11664-1. + */ + STANDARD_MASK = 63 << 16, + + /** + * Chromacity coordinates are unknown or are determined by the application. + * Implementations shall use the following suggested standards: + * + * All YCbCr formats: BT709 if size is 720p or larger (since most video + * content is letterboxed this corresponds to width is + * 1280 or greater, or height is 720 or greater). + * BT601_625 if size is smaller than 720p or is JPEG. + * All RGB formats: BT709. + * + * For all other formats standard is undefined, and implementations should use + * an appropriate standard for the data represented. + */ + STANDARD_UNSPECIFIED = 0 << 16, + + /** + * Primaries: x y + * green 0.300 0.600 + * blue 0.150 0.060 + * red 0.640 0.330 + * white (D65) 0.3127 0.3290 + * + * Use the unadjusted KR = 0.2126, KB = 0.0722 luminance interpretation + * for RGB conversion. + */ + STANDARD_BT709 = 1 << 16, + + /** + * Primaries: x y + * green 0.290 0.600 + * blue 0.150 0.060 + * red 0.640 0.330 + * white (D65) 0.3127 0.3290 + * + * KR = 0.299, KB = 0.114. This adjusts the luminance interpretation + * for RGB conversion from the one purely determined by the primaries + * to minimize the color shift into RGB space that uses BT.709 + * primaries. + */ + STANDARD_BT601_625 = 2 << 16, + + /** + * Primaries: x y + * green 0.290 0.600 + * blue 0.150 0.060 + * red 0.640 0.330 + * white (D65) 0.3127 0.3290 + * + * Use the unadjusted KR = 0.222, KB = 0.071 luminance interpretation + * for RGB conversion. + */ + STANDARD_BT601_625_UNADJUSTED = 3 << 16, + + /** + * Primaries: x y + * green 0.310 0.595 + * blue 0.155 0.070 + * red 0.630 0.340 + * white (D65) 0.3127 0.3290 + * + * KR = 0.299, KB = 0.114. This adjusts the luminance interpretation + * for RGB conversion from the one purely determined by the primaries + * to minimize the color shift into RGB space that uses BT.709 + * primaries. + */ + STANDARD_BT601_525 = 4 << 16, + + /** + * Primaries: x y + * green 0.310 0.595 + * blue 0.155 0.070 + * red 0.630 0.340 + * white (D65) 0.3127 0.3290 + * + * Use the unadjusted KR = 0.212, KB = 0.087 luminance interpretation + * for RGB conversion (as in SMPTE 240M). + */ + STANDARD_BT601_525_UNADJUSTED = 5 << 16, + + /** + * Primaries: x y + * green 0.170 0.797 + * blue 0.131 0.046 + * red 0.708 0.292 + * white (D65) 0.3127 0.3290 + * + * Use the unadjusted KR = 0.2627, KB = 0.0593 luminance interpretation + * for RGB conversion. + */ + STANDARD_BT2020 = 6 << 16, + + /** + * Primaries: x y + * green 0.170 0.797 + * blue 0.131 0.046 + * red 0.708 0.292 + * white (D65) 0.3127 0.3290 + * + * Use the unadjusted KR = 0.2627, KB = 0.0593 luminance interpretation + * for RGB conversion using the linear domain. + */ + STANDARD_BT2020_CONSTANT_LUMINANCE = 7 << 16, + + /** + * Primaries: x y + * green 0.21 0.71 + * blue 0.14 0.08 + * red 0.67 0.33 + * white (C) 0.310 0.316 + * + * Use the unadjusted KR = 0.30, KB = 0.11 luminance interpretation + * for RGB conversion. + */ + STANDARD_BT470M = 8 << 16, + + /** + * Primaries: x y + * green 0.243 0.692 + * blue 0.145 0.049 + * red 0.681 0.319 + * white (C) 0.310 0.316 + * + * Use the unadjusted KR = 0.254, KB = 0.068 luminance interpretation + * for RGB conversion. + */ + STANDARD_FILM = 9 << 16, + + /** + * SMPTE EG 432-1 and SMPTE RP 431-2. (DCI-P3) + * Primaries: x y + * green 0.265 0.690 + * blue 0.150 0.060 + * red 0.680 0.320 + * white (D65) 0.3127 0.3290 + */ + STANDARD_DCI_P3 = 10 << 16, + + /** + * Adobe RGB + * Primaries: x y + * green 0.210 0.710 + * blue 0.150 0.060 + * red 0.640 0.330 + * white (D65) 0.3127 0.3290 + */ + STANDARD_ADOBE_RGB = 11 << 16, + + /** + * Transfer aspect + * + * Transfer characteristics are the opto-electronic transfer characteristic + * at the source as a function of linear optical intensity (luminance). + * + * For digital signals, E corresponds to the recorded value. Normally, the + * transfer function is applied in RGB space to each of the R, G and B + * components independently. This may result in color shift that can be + * minized by applying the transfer function in Lab space only for the L + * component. Implementation may apply the transfer function in RGB space + * for all pixel formats if desired. + */ + TRANSFER_MASK = 31 << 22, + + /** + * Transfer characteristics are unknown or are determined by the + * application. + * + * Implementations should use the following transfer functions: + * + * For YCbCr formats: use TRANSFER_SMPTE_170M + * For RGB formats: use TRANSFER_SRGB + * + * For all other formats transfer function is undefined, and implementations + * should use an appropriate standard for the data represented. + */ + TRANSFER_UNSPECIFIED = 0 << 22, + + /** + * Transfer characteristic curve: + * E = L + * L - luminance of image 0 <= L <= 1 for conventional colorimetry + * E - corresponding electrical signal + */ + TRANSFER_LINEAR = 1 << 22, + + /** + * Transfer characteristic curve: + * + * E = 1.055 * L^(1/2.4) - 0.055 for 0.0031308 <= L <= 1 + * = 12.92 * L for 0 <= L < 0.0031308 + * L - luminance of image 0 <= L <= 1 for conventional colorimetry + * E - corresponding electrical signal + */ + TRANSFER_SRGB = 2 << 22, + + /** + * BT.601 525, BT.601 625, BT.709, BT.2020 + * + * Transfer characteristic curve: + * E = 1.099 * L ^ 0.45 - 0.099 for 0.018 <= L <= 1 + * = 4.500 * L for 0 <= L < 0.018 + * L - luminance of image 0 <= L <= 1 for conventional colorimetry + * E - corresponding electrical signal + */ + TRANSFER_SMPTE_170M = 3 << 22, + + /** + * Assumed display gamma 2.2. + * + * Transfer characteristic curve: + * E = L ^ (1/2.2) + * L - luminance of image 0 <= L <= 1 for conventional colorimetry + * E - corresponding electrical signal + */ + TRANSFER_GAMMA2_2 = 4 << 22, + + /** + * display gamma 2.6. + * + * Transfer characteristic curve: + * E = L ^ (1/2.6) + * L - luminance of image 0 <= L <= 1 for conventional colorimetry + * E - corresponding electrical signal + */ + TRANSFER_GAMMA2_6 = 5 << 22, + + /** + * display gamma 2.8. + * + * Transfer characteristic curve: + * E = L ^ (1/2.8) + * L - luminance of image 0 <= L <= 1 for conventional colorimetry + * E - corresponding electrical signal + */ + TRANSFER_GAMMA2_8 = 6 << 22, + + /** + * SMPTE ST 2084 (Dolby Perceptual Quantizer) + * + * Transfer characteristic curve: + * E = ((c1 + c2 * L^n) / (1 + c3 * L^n)) ^ m + * c1 = c3 - c2 + 1 = 3424 / 4096 = 0.8359375 + * c2 = 32 * 2413 / 4096 = 18.8515625 + * c3 = 32 * 2392 / 4096 = 18.6875 + * m = 128 * 2523 / 4096 = 78.84375 + * n = 0.25 * 2610 / 4096 = 0.1593017578125 + * L - luminance of image 0 <= L <= 1 for HDR colorimetry. + * L = 1 corresponds to 10000 cd/m2 + * E - corresponding electrical signal + */ + TRANSFER_ST2084 = 7 << 22, + + /** + * ARIB STD-B67 Hybrid Log Gamma + * + * Transfer characteristic curve: + * E = r * L^0.5 for 0 <= L <= 1 + * = a * ln(L - b) + c for 1 < L + * a = 0.17883277 + * b = 0.28466892 + * c = 0.55991073 + * r = 0.5 + * L - luminance of image 0 <= L for HDR colorimetry. L = 1 corresponds + * to reference white level of 100 cd/m2 + * E - corresponding electrical signal + */ + TRANSFER_HLG = 8 << 22, + + /** + * Range aspect + * + * Defines the range of values corresponding to the unit range of 0-1. + * This is defined for YCbCr only, but can be expanded to RGB space. + */ + RANGE_MASK = 7 << 27, + + /** + * Range is unknown or are determined by the application. Implementations + * shall use the following suggested ranges: + * + * All YCbCr formats: limited range. + * All RGB or RGBA formats (including RAW and Bayer): full range. + * All Y formats: full range + * + * For all other formats range is undefined, and implementations should use + * an appropriate range for the data represented. + */ + RANGE_UNSPECIFIED = 0 << 27, + + /** + * Full range uses all values for Y, Cb and Cr from + * 0 to 2^b-1, where b is the bit depth of the color format. + */ + RANGE_FULL = 1 << 27, + + /** + * Limited range uses values 16/256*2^b to 235/256*2^b for Y, and + * 1/16*2^b to 15/16*2^b for Cb, Cr, R, G and B, where b is the bit depth of + * the color format. + * + * E.g. For 8-bit-depth formats: + * Luma (Y) samples should range from 16 to 235, inclusive + * Chroma (Cb, Cr) samples should range from 16 to 240, inclusive + * + * For 10-bit-depth formats: + * Luma (Y) samples should range from 64 to 940, inclusive + * Chroma (Cb, Cr) samples should range from 64 to 960, inclusive + */ + RANGE_LIMITED = 2 << 27, + + /** + * Extended range is used for scRGB. Intended for use with + * floating point pixel formats. [0.0 - 1.0] is the standard + * sRGB space. Values outside the range 0.0 - 1.0 can encode + * color outside the sRGB gamut. + * Used to blend / merge multiple dataspaces on a single display. + */ + RANGE_EXTENDED = 3 << 27, + + /** + * scRGB linear encoding: + * + * The red, green, and blue components are stored in extended sRGB space, + * but are linear, not gamma-encoded. + * The RGB primaries and the white point are the same as BT.709. + * + * The values are floating point. + * A pixel value of 1.0, 1.0, 1.0 corresponds to sRGB white (D65) at 80 nits. + * Values beyond the range [0.0 - 1.0] would correspond to other colors + * spaces and/or HDR content. + */ + SCRGB_LINEAR = 406913024, // STANDARD_BT709 | TRANSFER_LINEAR | RANGE_EXTENDED + + /** + * sRGB gamma encoding: + * + * The red, green and blue components are stored in sRGB space, and + * converted to linear space when read, using the SRGB transfer function + * for each of the R, G and B components. When written, the inverse + * transformation is performed. + * + * The alpha component, if present, is always stored in linear space and + * is left unmodified when read or written. + * + * Use full range and BT.709 standard. + */ + SRGB = 142671872, // STANDARD_BT709 | TRANSFER_SRGB | RANGE_FULL + + /** + * scRGB: + * + * The red, green, and blue components are stored in extended sRGB space, + * and gamma-encoded using the SRGB transfer function. + * The RGB primaries and the white point are the same as BT.709. + * + * The values are floating point. + * A pixel value of 1.0, 1.0, 1.0 corresponds to sRGB white (D65) at 80 nits. + * Values beyond the range [0.0 - 1.0] would correspond to other colors + * spaces and/or HDR content. + */ + SCRGB = 411107328, // STANDARD_BT709 | TRANSFER_SRGB | RANGE_EXTENDED + + /** + * Display P3 + * + * Use same primaries and white-point as DCI-P3 + * but sRGB transfer function. + */ + DISPLAY_P3 = 143261696, // STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_FULL + + /** + * ITU-R Recommendation 2020 (BT.2020) + * + * Ultra High-definition television + * + * Use full range, SMPTE 2084 (PQ) transfer and BT2020 standard + */ + BT2020_PQ = 163971072, // STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_FULL + + /** + * ITU-R Recommendation 2020 (BT.2020) + * + * Ultra High-definition television + * + * Use limited range, SMPTE 2084 (PQ) transfer and BT2020 standard + */ + BT2020_ITU_PQ = 298188800, // STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_LIMITED + + /** + * Adobe RGB + * + * Use full range, gamma 2.2 transfer and Adobe RGB primaries + * Note: Application is responsible for gamma encoding the data as + * a 2.2 gamma encoding is not supported in HW. + */ + ADOBE_RGB = 151715840, // STANDARD_ADOBE_RGB | TRANSFER_GAMMA2_2 | RANGE_FULL + + /** + * JPEG File Interchange Format (JFIF) + * + * Same model as BT.601-625, but all values (Y, Cb, Cr) range from 0 to 255 + * + * Use full range, SMPTE 170M transfer and BT.601_625 standard. + */ + JFIF = 146931712, // STANDARD_BT601_625 | TRANSFER_SMPTE_170M | RANGE_FULL + + /** + * ITU-R Recommendation 601 (BT.601) - 525-line + * + * Standard-definition television, 525 Lines (NTSC) + * + * Use limited range, SMPTE 170M transfer and BT.601_525 standard. + */ + BT601_625 = 281149440, // STANDARD_BT601_625 | TRANSFER_SMPTE_170M | RANGE_LIMITED + + /** + * ITU-R Recommendation 709 (BT.709) + * + * High-definition television + * + * Use limited range, SMPTE 170M transfer and BT.709 standard. + */ + BT601_525 = 281280512, // STANDARD_BT601_525 | TRANSFER_SMPTE_170M | RANGE_LIMITED + + /** + * ITU-R Recommendation 2020 (BT.2020) + * + * Ultra High-definition television + * + * Use full range, BT.709 transfer and BT2020 standard + */ + BT2020 = 147193856, // STANDARD_BT2020 | TRANSFER_SMPTE_170M | RANGE_FULL + + /** + * ITU-R Recommendation 709 (BT.709) + * + * High-definition television + * + * Use limited range, BT.709 transfer and BT.709 standard. + */ + BT709 = 281083904, // STANDARD_BT709 | TRANSFER_SMPTE_170M | RANGE_LIMITED + + /** + * SMPTE EG 432-1 and SMPTE RP 431-2. + * + * Digital Cinema DCI-P3 + * + * Use full range, gamma 2.6 transfer and D65 DCI-P3 standard + * Note: Application is responsible for gamma encoding the data as + * a 2.6 gamma encoding is not supported in HW. + */ + DCI_P3 = 155844608, // STANDARD_DCI_P3 | TRANSFER_GAMMA2_6 | RANGE_FULL + + /** + * sRGB linear encoding: + * + * The red, green, and blue components are stored in sRGB space, but + * are linear, not gamma-encoded. + * The RGB primaries and the white point are the same as BT.709. + * + * The values are encoded using the full range ([0,255] for 8-bit) for all + * components. + */ + SRGB_LINEAR = 138477568, // STANDARD_BT709 | TRANSFER_LINEAR | RANGE_FULL + + /** + * Hybrid Log Gamma encoding: + * + * Use full range, hybrid log gamma transfer and BT2020 standard. + */ + BT2020_HLG = 168165376, // STANDARD_BT2020 | TRANSFER_HLG | RANGE_FULL + + /** + * ITU Hybrid Log Gamma encoding: + * + * Use limited range, hybrid log gamma transfer and BT2020 standard. + */ + BT2020_ITU_HLG = 302383104, // STANDARD_BT2020 | TRANSFER_HLG | RANGE_LIMITED + + /** + * Depth: + * + * This value is valid with formats HAL_PIXEL_FORMAT_Y16 and HAL_PIXEL_FORMAT_BLOB. + */ + DEPTH = 4096, + + /** + * ISO 16684-1:2011(E) Dynamic Depth: + * + * Embedded depth metadata following the dynamic depth specification. + */ + DYNAMIC_DEPTH = 4098 +} + diff --git a/dlext.odin b/dlext.odin new file mode 100644 index 0000000..560a48b --- /dev/null +++ b/dlext.odin @@ -0,0 +1,161 @@ +//+build android +package android + +foreign import android "system:android" + +/** + * \file + * Advanced dynamic library opening support. Most users will want to use + * the standard [dlopen(3)](http://man7.org/linux/man-pages/man3/dlopen.3.html) + * functionality in `` instead. + */ + +/** Bitfield definitions for `android_dlextinfo::flags`. */ +DLextFlagsBits :: enum u64 { + /** + * When set, the `reserved_addr` and `reserved_size` fields must point to an + * already-reserved region of address space which will be used to load the + * library if it fits. + * + * If the reserved region is not large enough, loading will fail. + */ + RESERVED_ADDRESS = 0, + + /** + * Like `ANDROID_DLEXT_RESERVED_ADDRESS`, but if the reserved region is not large enough, + * the linker will choose an available address instead. + */ + RESERVED_ADDRESS_HINT = 1, + + /** + * When set, write the GNU RELRO section of the mapped library to `relro_fd` + * after relocation has been performed, to allow it to be reused by another + * process loading the same library at the same address. This implies + * `ANDROID_DLEXT_USE_RELRO`. + * + * This is mainly useful for the system WebView implementation. + */ + WRITE_RELRO = 2, + + /** + * When set, compare the GNU RELRO section of the mapped library to `relro_fd` + * after relocation has been performed, and replace any relocated pages that + * are identical with a version mapped from the file. + * + * This is mainly useful for the system WebView implementation. + */ + USE_RELRO = 3, + + /** + * Use `library_fd` instead of opening the file by name. + * The filename parameter is still used to identify the library. + */ + USE_LIBRARY_FD = 4, + + /** + * If opening a library using `library_fd` read it starting at `library_fd_offset`. + * This is mainly useful for loading a library stored within another file (such as uncompressed + * inside a ZIP archive). + * This flag is only valid when `ANDROID_DLEXT_USE_LIBRARY_FD` is set. + */ + USE_LIBRARY_FD_OFFSET = 5, + + /** + * When set, do not use `stat(2)` to check if the library has already been loaded. + * + * This flag allows forced loading of the library in the case when for some + * reason multiple ELF files share the same filename (because the already-loaded + * library has been removed and overwritten, for example). + * + * Note that if the library has the same `DT_SONAME` as an old one and some other + * library has the soname in its `DT_NEEDED` list, the first one will be used to resolve any + * dependencies. + */ + FORCE_LOAD = 6, + + // Historically we had two other options for ART. + // They were last available in Android P. + // Reuse these bits last! + // ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80 + // ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS = 0x100 + + /** + * This flag used to load library in a different namespace. The namespace is + * specified in `library_namespace`. + * + * This flag is for internal use only (since there is no NDK API for namespaces). + */ + USE_NAMESPACE = 9, + + /** + * Instructs dlopen to apply `ANDROID_DLEXT_RESERVED_ADDRESS`, + * `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`, `ANDROID_DLEXT_WRITE_RELRO` and + * `ANDROID_DLEXT_USE_RELRO` to any libraries loaded as dependencies of the + * main library as well. + * + * This means that if the main library depends on one or more not-already-loaded libraries, they + * will be loaded consecutively into the region starting at `reserved_addr`, and `reserved_size` + * must be large enough to contain all of the libraries. The libraries will be loaded in the + * deterministic order constructed from the DT_NEEDED entries, rather than the more secure random + * order used by default. + * + * Each library's GNU RELRO sections will be written out to `relro_fd` in the same order they were + * loaded. This will mean that the resulting file is dependent on which of the libraries were + * already loaded, as only the newly loaded libraries will be included, not any already-loaded + * dependencies. The caller should ensure that the set of libraries newly loaded is consistent + * for this to be effective. + * + * This is mainly useful for the system WebView implementation. + */ + RESERVED_ADDRESS_RECURSIVE = 10, +} + +DLextFlags :: bit_set[DLextFlagsBits; u64] + +AllDLextFlags :: DLextFlags{ + .RESERVED_ADDRESS, + .RESERVED_ADDRESS_HINT, + .WRITE_RELRO, + .USE_RELRO, + .USE_LIBRARY_FD, + .USE_LIBRARY_FD_OFFSET, + .FORCE_LOAD, + .USE_NAMESPACE, + .RESERVED_ADDRESS_RECURSIVE +} + +android_namespace_t :: struct{} + +/** Used to pass Android-specific arguments to `android_dlopen_ext`. */ +android_dlextinfo :: struct { + /** A bitmask of `ANDROID_DLEXT_` enum values. */ + flags: DLextFlags, + + /** Used by `ANDROID_DLEXT_RESERVED_ADDRESS` and `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`. */ + reserved_addr: rawptr, + /** Used by `ANDROID_DLEXT_RESERVED_ADDRESS` and `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`. */ + reserved_size: uint, + + /** Used by `ANDROID_DLEXT_WRITE_RELRO` and `ANDROID_DLEXT_USE_RELRO`. */ + relro_fd: i32, + + /** Used by `ANDROID_DLEXT_USE_LIBRARY_FD`. */ + library_fd: i32, + /** Used by `ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET` */ + library_fd_offset: off64_t, + + /** Used by `ANDROID_DLEXT_USE_NAMESPACE`. */ + library_namespace: ^android_namespace_t, +} + +foreign android { + /** + * Opens the given library. The `__filename` and `__flags` arguments are + * the same as for [dlopen(3)](http://man7.org/linux/man-pages/man3/dlopen.3.html), + * with the Android-specific flags supplied via the `flags` member of `__info`. + * + * Available since API level 21. + */ + android_dlopen_ext :: proc(__filename: cstring, __flags: i32, __info: ^android_dlextinfo) -> rawptr --- +} + diff --git a/doc.odin b/doc.odin new file mode 100644 index 0000000..7d2bf23 --- /dev/null +++ b/doc.odin @@ -0,0 +1,20 @@ +package android + +// Apparently the app still needs to have a manifest, it also MUST use the nativeactivity activity. +// Apparently the native code MUST be built as a shared library and then loaded by the JNI(?) +// Good ref: https://github.com/xlab/android-go/blob/master/examples/build-android.sh +// Even better ref: https://github.com/mmozeiko/android-native-example +// Hmm, what if the Odin compiler itself has support for an Android target, it would build the shared lib, link everything, +// package the app as an apk too. The minSdk level can be set using Odin's comptime defines, if any necessary define is missing +// the compiler refuses to build, or maybe the compiler just silently reads the build.gradle file and search for the minSdk define?? +// that would require that Odin Android apps MUST have the android file structure with some required files. +// Or maybe the Odin compiler will generate those files ??? so many possiblities and options. +// +// The above is a problem for later, let's just get a basic Odin Android app building and hopefully running. + +// TODO: We need some sort of way to guard against calling __INTRODUCED_IN(30) procs in older +// Android versions, preferably a way to have the compiler complain. +// Maybe some sort of #config that the user has to define and maybe we can @disabled these procs +// if the version isn't compatible. +// @disabled doesn't work on procs with a return value, a simple when ANDROID_API >= 30 {} works but it's still +// easily bypassable. diff --git a/fdsan.odin b/fdsan.odin new file mode 100644 index 0000000..9983869 --- /dev/null +++ b/fdsan.odin @@ -0,0 +1,204 @@ +//+build android +package android + +foreign import android "system:android" + +/* + * Error checking for close(2). + * + * Mishandling of file descriptor ownership is a common source of errors that + * can be extremely difficult to diagnose. Mistakes like the following can + * result in seemingly 'impossible' failures showing up on other threads that + * happened to try to open a file descriptor between the buggy code's close and + * fclose: + * + * int print(int fd) { + * int rc; + * char buf[128]; + * while ((rc = read(fd, buf, sizeof(buf))) > 0) { + * printf("%.*s", rc); + * } + * close(fd); + * } + * + * int bug() { + * FILE* f = fopen("foo", "r"); + * print(fileno(f)); + * fclose(f); + * } + * + * To make it easier to find this class of bugs, bionic provides a method to + * require that file descriptors are closed by their owners. File descriptors + * can be associated with tags with which they must be closed. This allows + * objects that conceptually own an fd (FILE*, unique_fd, etc.) to use their + * own address at the tag, to enforce that closure of the fd must come as a + * result of their own destruction (fclose, ~unique_fd, etc.) + * + * By default, a file descriptor's tag is 0, and close(fd) is equivalent to + * closing fd with the tag 0. + */ + +/* + * For improved diagnostics, the type of a file descriptors owner can be + * encoded in the most significant byte of the owner tag. Values of 0 and 0xff + * are ignored, which allows for raw pointers to be used as owner tags without + * modification. + */ +android_fdsan_owner_type :: enum { + /* + * Generic Java or native owners. + * + * Generic Java objects always use 255 as their type, using identityHashCode + * as the value of the tag, leaving bits 33-56 unset. Native pointers are sign + * extended from 48-bits of virtual address space, and so can have the MSB + * set to 255 as well. Use the value of bits 49-56 to distinguish between + * these cases. + */ + GENERIC_00 = 0, + GENERIC_FF = 255, + + /* FILE* */ + FILE = 1, + + /* DIR* */ + DIR = 2, + + /* android::base::unique_fd */ + UNIQUE_FD = 3, + + /* sqlite-owned file descriptors */ + SQLITE = 4, + + /* java.io.FileInputStream */ + FILEINPUTSTREAM = 5, + + /* java.io.FileOutputStream */ + FILEOUTPUTSTREAM = 6, + + /* java.io.RandomAccessFile */ + RANDOMACCESSFILE = 7, + + /* android.os.ParcelFileDescriptor */ + PARCELFILEDESCRIPTOR = 8, + + /* ART FdFile */ + ART_FDFILE = 9, + + /* java.net.DatagramSocketImpl */ + DATAGRAMSOCKETIMPL = 10, + + /* java.net.SocketImpl */ + SOCKETIMPL = 11, + + /* libziparchive's ZipArchive */ + ZIPARCHIVE = 12, + + /* native_handle_t */ + NATIVE_HANDLE = 13, +} + +android_fdsan_error_level :: enum { + // No errors. + DISABLED, + + // Warn once(ish) on error, and then downgrade to ANDROID_FDSAN_ERROR_LEVEL_DISABLED. + WARN_ONCE, + + // Warn always on error. + WARN_ALWAYS, + + // Abort on error. + FATAL, +} + +foreign android { + /* + * Create an owner tag with the specified type and least significant 56 bits of tag. + * + * Available since API level 29. + */ + @(linkage="weak") + android_fdsan_create_owner_tag :: proc(type: android_fdsan_owner_type, tag: u64) -> u64 --- + + /* + * Exchange a file descriptor's tag. + * + * Logs and aborts if the fd's tag does not match expected_tag. + * + * Available since API level 29. + */ + @(linkage="weak") + android_fdsan_exchange_owner_tag :: proc(fd: i32, expected_tag: u64, new_tag: u64) --- + + /* + * Close a file descriptor with a tag, and resets the tag to 0. + * + * Logs and aborts if the tag is incorrect. + * + * Available since API level 29. + */ + @(linkage="weak") + android_fdsan_close_with_tag :: proc(fd: i32, tag: u64) -> i32 --- + + /* + * Get a file descriptor's current owner tag. + * + * Returns 0 for untagged and invalid file descriptors. + * + * Available since API level 29. + */ + android_fdsan_get_owner_tag :: proc(fd: i32) -> u64 --- + + /* + * Get an owner tag's string representation. + * + * The return value points to memory with static lifetime, do not attempt to modify it. + * + * Available since API level 29. + */ + android_fdsan_get_tag_type :: proc(tag: u64) -> cstring --- + + /* + * Get an owner tag's value, with the type masked off. + * + * Available since API level 29. + */ + android_fdsan_get_tag_value :: proc(tag: u64) -> u64 --- + + /* + * Get the error level. + * + * Available since API level 29. + */ + @(linkage="weak") + android_fdsan_get_error_level :: proc() -> android_fdsan_error_level --- + + /* + * Set the error level and return the previous state. + * + * Error checking is automatically disabled in the child of a fork, to maintain + * compatibility with code that forks, closes all file descriptors, and then + * execs. + * + * In cases such as the zygote, where the child has no intention of calling + * exec, call this function to reenable fdsan checks. + * + * This function is not thread-safe and does not synchronize with checks of the + * value, and so should probably only be called in single-threaded contexts + * (e.g. postfork). + * + * Available since API level 29. + */ + @(linkage="weak") + android_fdsan_set_error_level :: proc(new_level: android_fdsan_error_level) -> android_fdsan_error_level --- + + + /* + * Set the error level to the global setting if available, or a default value. + * + * Available since API level 30. + */ + @(linkage="weak") + android_fdsan_set_error_level_from_property :: proc(default_level: android_fdsan_error_level) -> android_fdsan_error_level --- +} + diff --git a/file_descriptor_jni.odin b/file_descriptor_jni.odin new file mode 100644 index 0000000..fae2986 --- /dev/null +++ b/file_descriptor_jni.odin @@ -0,0 +1,54 @@ +//+build android +package android + +foreign import android "system:android" + +foreign android { + /** + * Returns a new java.io.FileDescriptor. + * + * The FileDescriptor created represents an invalid Unix file descriptor (represented by + * a file descriptor value of -1). + * + * Callers of this method should be aware that it can fail, returning NULL with a pending Java + * exception. + * + * Available since API level 31. + * + * \param env a pointer to the JNI Native Interface of the current thread. + * \return a java.io.FileDescriptor on success, nullptr if insufficient heap memory is available. + */ + AFileDescriptor_create :: proc(env: ^JNIEnv) -> jobject --- + + /** + * Returns the Unix file descriptor represented by the given java.io.FileDescriptor. + * + * A return value of -1 indicates that \a fileDescriptor represents an invalid file descriptor. + * + * Aborts the program if \a fileDescriptor is not a java.io.FileDescriptor instance. + * + * Available since API level 31. + * + * \param env a pointer to the JNI Native Interface of the current thread. + * \param fileDescriptor a java.io.FileDescriptor instance. + * \return the Unix file descriptor wrapped by \a fileDescriptor. + */ + AFileDescriptor_getFd :: proc(env: ^JNIEnv, fileDescriptor: jobject) -> i32 --- + + /** + * Sets the Unix file descriptor represented by the given java.io.FileDescriptor. + * + * This function performs no validation of the Unix file descriptor argument, \a fd. Android uses + * the value -1 to represent an invalid file descriptor, all other values are considered valid. + * The validity of a file descriptor can be checked with FileDescriptor#valid(). + * + * Aborts the program if \a fileDescriptor is not a java.io.FileDescriptor instance. + * + * Available since API level 31. + * + * \param env a pointer to the JNI Native Interface of the current thread. + * \param fileDescriptor a java.io.FileDescriptor instance. + * \param fd a Unix file descriptor that \a fileDescriptor will subsequently represent. + */ + AFileDescriptor_setFd :: proc(env: ^JNIEnv, fileDescriptor: jobject, fd: i32) --- +} diff --git a/font.odin b/font.odin new file mode 100644 index 0000000..93f47a5 --- /dev/null +++ b/font.odin @@ -0,0 +1,249 @@ +//+build android +package android + +foreign import android "system:android" + +FontWeight :: enum u16 { + /** The minimum value fot the font weight value. */ + MIN = 0, + + /** A font weight value for the thin weight. */ + THIN = 100, + + /** A font weight value for the extra-light weight. */ + EXTRA_LIGHT = 200, + + /** A font weight value for the light weight. */ + LIGHT = 300, + + /** A font weight value for the normal weight. */ + NORMAL = 400, + + /** A font weight value for the medium weight. */ + MEDIUM = 500, + + /** A font weight value for the semi-bold weight. */ + SEMI_BOLD = 600, + + /** A font weight value for the bold weight. */ + BOLD = 700, + + /** A font weight value for the extra-bold weight. */ + EXTRA_BOLD = 800, + + /** A font weight value for the black weight. */ + BLACK = 900, + + /** The maximum value for the font weight value. */ + MAX = 1000 +} + +/** + * AFont provides information of the single font configuration. + */ +AFont :: struct{} + + +foreign android { + /** + * Close an AFont. + * + * Available since API level 29. + * + * \param font a font returned by ASystemFontIterator_next or AFontMatchert_match. + * Do nothing if NULL is passed. + */ + AFont_close :: proc(font: ^AFont) --- + + /** + * Return an absolute path to the current font file. + * + * Here is a list of font formats returned by this method: + * + * The file extension could be one of *.otf, *.ttf, *.otc or *.ttc. + * + * The font file returned is guaranteed to be opend with O_RDONLY. + * Note that the returned pointer is valid until AFont_close() is called for the given font. + * + * Available since API level 29. + * + * \param font a font object. Passing NULL is not allowed. + * \return a string of the font file path. + */ + AFont_getFontFilePath :: proc(font: ^AFont) -> cstring --- + + /** + * Return a weight value associated with the current font. + * + * The weight values are positive and less than or equal to 1000. + * Here are pairs of the common names and their values. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ValueNameNDK Definition
100Thin{@link AFONT_WEIGHT_THIN}
200Extra Light (Ultra Light){@link AFONT_WEIGHT_EXTRA_LIGHT}
300Light{@link AFONT_WEIGHT_LIGHT}
400Normal (Regular){@link AFONT_WEIGHT_NORMAL}
500Medium{@link AFONT_WEIGHT_MEDIUM}
600Semi Bold (Demi Bold){@link AFONT_WEIGHT_SEMI_BOLD}
700Bold{@link AFONT_WEIGHT_BOLD}
800Extra Bold (Ultra Bold){@link AFONT_WEIGHT_EXTRA_BOLD}
900Black (Heavy){@link AFONT_WEIGHT_BLACK}
+ *

+ * Note that the weight value may fall in between above values, e.g. 250 weight. + * + * For more information about font weight, read [OpenType usWeightClass](https://docs.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass) + * + * Available since API level 29. + * + * \param font a font object. Passing NULL is not allowed. + * \return a positive integer less than or equal to {@link AFONT_WEIGHT_MAX} is returned. + */ + AFont_getWeight :: proc(font: ^AFont) -> FontWeight --- + + /** + * Return true if the current font is italic, otherwise returns false. + * + * Available since API level 29. + * + * \param font a font object. Passing NULL is not allowed. + * \return true if italic, otherwise false. + */ + AFont_isItalic :: proc(font: ^AFont) -> bool --- + + /** + * Return a IETF BCP47 compliant language tag associated with the current font. + * + * For information about IETF BCP47, read [Locale.forLanguageTag(java.lang.String)](https://developer.android.com/reference/java/util/Locale.html#forLanguageTag(java.lang.String)") + * + * Note that the returned pointer is valid until AFont_close() is called. + * + * Available since API level 29. + * + * \param font a font object. Passing NULL is not allowed. + * \return a IETF BCP47 compliant language tag or nullptr if not available. + */ + AFont_getLocale :: proc(font: ^AFont) -> cstring --- + + /** + * Return a font collection index value associated with the current font. + * + * In case the target font file is a font collection (e.g. .ttc or .otc), this + * returns a non-negative value as an font offset in the collection. This + * always returns 0 if the target font file is a regular font. + * + * Available since API level 29. + * + * \param font a font object. Passing NULL is not allowed. + * \return a font collection index. + */ + AFont_getCollectionIndex :: proc(font: ^AFont) -> uint --- + + /** + * Return a count of font variation settings associated with the current font + * + * The font variation settings are provided as multiple tag-values pairs. + * + * For example, bold italic font may have following font variation settings: + * 'wght' 700, 'slnt' -12 + * In this case, AFont_getAxisCount returns 2 and AFont_getAxisTag + * and AFont_getAxisValue will return following values. + * \code{.cpp} + * AFont* font = ASystemFontIterator_next(ite) + * + * // Returns the number of axes + * AFont_getAxisCount(font) // Returns 2 + * + * // Returns the tag-value pair for the first axis. + * AFont_getAxisTag(font, 0) // Returns 'wght'(0x77676874) + * AFont_getAxisValue(font, 0) // Returns 700.0 + * + * // Returns the tag-value pair for the second axis. + * AFont_getAxisTag(font, 1) // Returns 'slnt'(0x736c6e74) + * AFont_getAxisValue(font, 1) // Returns -12.0 + * \endcode + * + * For more information about font variation settings, read [Font Variations Table](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar) + * + * Available since API level 29. + * + * \param font a font object. Passing NULL is not allowed. + * \return a number of font variation settings. + */ + AFont_getAxisCount :: proc(font: ^AFont) -> uint --- + + + /** + * Return an OpenType axis tag associated with the current font. + * + * See AFont_getAxisCount for more details. + * + * Available since API level 29. + * + * \param font a font object. Passing NULL is not allowed. + * \param axisIndex an index to the font variation settings. Passing value larger than or + * equal to {@link AFont_getAxisCount} is not allowed. + * \return an OpenType axis tag value for the given font variation setting. + */ + AFont_getAxisTag :: proc(font: ^AFont, axisIndex: u32) -> u32 --- + + /** + * Return an OpenType axis value associated with the current font. + * + * See AFont_getAxisCount for more details. + * + * Available since API level 29. + * + * \param font a font object. Passing NULL is not allowed. + * \param axisIndex an index to the font variation settings. Passing value larger than or + * equal to {@link AFont_getAxisCount} is not allowed. + * \return a float value for the given font variation setting. + */ + AFont_getAxisValue :: proc(font: ^AFont, axisIndex: u32) -> f32 --- +} diff --git a/font_matcher.odin b/font_matcher.odin new file mode 100644 index 0000000..74b994b --- /dev/null +++ b/font_matcher.odin @@ -0,0 +1,159 @@ +//+build android +package android + +foreign import android "system:android" + +/** + * @file font_matcher.h + * @brief Provides the font matching logic with various inputs. + * + * You can use this class for deciding what font is to be used for drawing text. + * + * A matcher is created from text style, locales and UI compatibility. The match function for + * matcher object can be called multiple times until close function is called. + * + * Even if no font can render the given text, the match function will return a non-null result for + * drawing Tofu character. + * + * Examples: + * \code{.cpp} + * // Simple font query for the ASCII character. + * std::vector text = { 'A' }; + * AFontMatcher* matcher = AFontMatcher_create("sans-serif"); + * AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); + * // runLength will be 1 and the font will points a valid font file. + * AFontMatcher_destroy(matcher); + * + * // Querying font for CJK characters + * std::vector text = { 0x9AA8 }; + * AFontMatcher* matcher = AFontMatcher_create("sans-serif"); + * AFontMatcher_setLocales(matcher, "zh-CN,ja-JP"); + * AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); + * // runLength will be 1 and the font will points a Simplified Chinese font. + * AFontMatcher_setLocales(matcher, "ja-JP,zh-CN"); + * AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); + * // runLength will be 1 and the font will points a Japanese font. + * AFontMatcher_destroy(matcher); + * + * // Querying font for text/color emoji + * std::vector text = { 0xD83D, 0xDC68, 0x200D, 0x2764, 0xFE0F, 0x200D, 0xD83D, 0xDC68 }; + * AFontMatcher* matcher = AFontMatcher_create("sans-serif"); + * AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); + * // runLength will be 8 and the font will points a color emoji font. + * AFontMatcher_destroy(matcher); + * + * // Mixture of multiple script of characters. + * // 0x05D0 is a Hebrew character and 0x0E01 is a Thai character. + * std::vector text = { 0x05D0, 0x0E01 }; + * AFontMatcher* matcher = AFontMatcher_create("sans-serif"); + * AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); + * // runLength will be 1 and the font will points a Hebrew font. + * AFontMatcher_destroy(matcher); + * \endcode + * + * Available since API level 29. + */ + +FamilyVariant :: enum u32 { + /** A family variant value for the system default variant. */ + DEFAULT = 0, + + /** + * A family variant value for the compact font family variant. + * + * The compact font family has Latin-based vertical metrics. + */ + COMPACT = 1, + + /** + * A family variant value for the elegant font family variant. + * + * The elegant font family may have larger vertical metrics than Latin font. + */ + ELEGANT = 2, +}; + +/** + * AFontMatcher performs match operation on given parameters and available font files. + * This matcher is not a thread-safe object. Do not pass this matcher to other threads. + */ +AFontMatcher :: struct{} + + +foreign android { + /** + * Creates a new AFontMatcher object. + * + * Available since API level 29. + */ + AFontMatcher_create :: proc() -> ^AFontMatcher --- + + /** + * Destroy the matcher object. + * + * Available since API level 29. + * + * \param matcher a matcher object. Passing NULL is not allowed. + */ + AFontMatcher_destroy :: proc(matcher: ^AFontMatcher) --- + + /** + * Set font style to matcher. + * + * If this function is not called, the matcher performs with {@link AFONT_WEIGHT_NORMAL} + * with non-italic style. + * + * Available since API level 29. + * + * \param matcher a matcher object. Passing NULL is not allowed. + * \param weight a font weight value. Only from 0 to 1000 value is valid + * \param italic true if italic, otherwise false. + */ + AFontMatcher_setStyle :: proc(matcher: ^AFontMatcher, weight: FontWeight, italic: bool) --- + + /** + * Set font locales to matcher. + * + * If this function is not called, the matcher performs with empty locale list. + * + * Available since API level 29. + * + * \param matcher a matcher object. Passing NULL is not allowed. + * \param languageTags a null character terminated comma separated IETF BCP47 compliant language + * tags. + */ + AFontMatcher_setLocales :: proc(matcher: ^AFontMatcher, languageTags: cstring) --- + + /** + * Set family variant to matcher. + * + * If this function is not called, the matcher performs with {@link AFAMILY_VARIANT_DEFAULT}. + * + * Available since API level 29. + * + * \param matcher a matcher object. Passing NULL is not allowed. + * \param familyVariant Must be one of {@link AFAMILY_VARIANT_DEFAULT}, + * {@link AFAMILY_VARIANT_COMPACT} or {@link AFAMILY_VARIANT_ELEGANT} is valid. + */ + AFontMatcher_setFamilyVariant :: proc(matcher: ^AFontMatcher, familyVariant: FamilyVariant) --- + + /** + * Performs the matching from the generic font family for the text and select one font. + * + * For more information about generic font families, read [W3C spec](https://www.w3.org/TR/css-fonts-4/#generic-font-families) + * + * Even if no font can render the given text, this function will return a non-null result for + * drawing Tofu character. + * + * Available since API level 29. + * + * \param matcher a matcher object. Passing NULL is not allowed. + * \param familyName a null character terminated font family name + * \param text a UTF-16 encoded text buffer to be rendered. Do not pass empty string. + * \param textLength a length of the given text buffer. This must not be zero. + * \param runLengthOut if not null, the font run length will be filled. + * \return a font to be used for given text and params. You need to release the returned font by + * AFont_close when it is no longer needed. + */ + AFontMatcher_match :: proc(matcher: ^AFontMatcher, familyName: cstring, text: [^]u16, textLength: u32, runLengthOut: ^u32) -> ^AFont --- +} diff --git a/hardware_buffer.odin b/hardware_buffer.odin new file mode 100644 index 0000000..f061590 --- /dev/null +++ b/hardware_buffer.odin @@ -0,0 +1,578 @@ +//+build android +package android + +foreign import android "system:android" + +/** + * @file hardware_buffer.h + * @brief API for native hardware buffers. + */ +/** + * @defgroup AHardwareBuffer Native Hardware Buffer + * + * AHardwareBuffer objects represent chunks of memory that can be + * accessed by various hardware components in the system. It can be + * easily converted to the Java counterpart + * android.hardware.HardwareBuffer and passed between processes using + * Binder. All operations involving AHardwareBuffer and HardwareBuffer + * are zero-copy, i.e., passing AHardwareBuffer to another process + * creates a shared view of the same region of memory. + * + * AHardwareBuffers can be bound to EGL/OpenGL and Vulkan primitives. + * For EGL, use the extension function eglGetNativeClientBufferANDROID + * to obtain an EGLClientBuffer and pass it directly to + * eglCreateImageKHR. Refer to the EGL extensions + * EGL_ANDROID_get_native_client_buffer and + * EGL_ANDROID_image_native_buffer for more information. In Vulkan, + * the contents of the AHardwareBuffer can be accessed as external + * memory. See the VK_ANDROID_external_memory_android_hardware_buffer + * extension for details. + * + * @{ + */ + +/** + * Buffer pixel formats. + */ +AHardwareBuffer_Format :: enum u32 { + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_R8G8B8A8_UNORM + * OpenGL ES: GL_RGBA8 + */ + R8G8B8A8_UNORM = 1, + + /** + * 32 bits per pixel, 8 bits per channel format where alpha values are + * ignored (always opaque). + * Corresponding formats: + * Vulkan: VK_FORMAT_R8G8B8A8_UNORM + * OpenGL ES: GL_RGB8 + */ + R8G8B8X8_UNORM = 2, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_R8G8B8_UNORM + * OpenGL ES: GL_RGB8 + */ + R8G8B8_UNORM = 3, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_R5G6B5_UNORM_PACK16 + * OpenGL ES: GL_RGB565 + */ + R5G6B5_UNORM = 4, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_R16G16B16A16_SFLOAT + * OpenGL ES: GL_RGBA16F + */ + R16G16B16A16_FLOAT = 0x16, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_A2B10G10R10_UNORM_PACK32 + * OpenGL ES: GL_RGB10_A2 + */ + R10G10B10A2_UNORM = 0x2b, + + /** + * Opaque binary blob format. + * Must have height 1 and one layer, with width equal to the buffer + * size in bytes. Corresponds to Vulkan buffers and OpenGL buffer + * objects. Can be bound to the latter using GL_EXT_external_buffer. + */ + BLOB = 0x21, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_D16_UNORM + * OpenGL ES: GL_DEPTH_COMPONENT16 + */ + D16_UNORM = 0x30, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_X8_D24_UNORM_PACK32 + * OpenGL ES: GL_DEPTH_COMPONENT24 + */ + D24_UNORM = 0x31, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_D24_UNORM_S8_UINT + * OpenGL ES: GL_DEPTH24_STENCIL8 + */ + D24_UNORM_S8_UINT = 0x32, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_D32_SFLOAT + * OpenGL ES: GL_DEPTH_COMPONENT32F + */ + D32_FLOAT = 0x33, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_D32_SFLOAT_S8_UINT + * OpenGL ES: GL_DEPTH32F_STENCIL8 + */ + D32_FLOAT_S8_UINT = 0x34, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_S8_UINT + * OpenGL ES: GL_STENCIL_INDEX8 + */ + S8_UINT = 0x35, + + /** + * YUV 420 888 format. + * Must have an even width and height. Can be accessed in OpenGL + * shaders through an external sampler. Does not support mip-maps + * cube-maps or multi-layered textures. + */ + Y8Cb8Cr8_420 = 0x23, + + /** + * YUV P010 format. + * Must have an even width and height. Can be accessed in OpenGL + * shaders through an external sampler. Does not support mip-maps + * cube-maps or multi-layered textures. + */ + YCbCr_P010 = 0x36, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_R8_UNORM + * OpenGL ES: GR_GL_R8 + */ + R8_UNORM = 0x38, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_R16_UINT + * OpenGL ES: GL_R16UI + */ + R16_UINT = 0x39, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_R16G16_UINT + * OpenGL ES: GL_RG16UI + */ + R16G16_UINT = 0x3a, + + /** + * Corresponding formats: + * Vulkan: VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 + * OpenGL ES: N/A + */ + R10G10B10A10_UNORM = 0x3b, +} + +/** + * Buffer usage flags, specifying how the buffer will be accessed. + */ +AHardwareBuffer_UsageFlags :: enum u64 { + /** + * The buffer will never be locked for direct CPU reads using the + * AHardwareBuffer_lock() function. Note that reading the buffer + * using OpenGL or Vulkan functions or memory mappings is still + * allowed. + */ + CPU_READ_NEVER = 0, + /** + * The buffer will sometimes be locked for direct CPU reads using + * the AHardwareBuffer_lock() function. Note that reading the + * buffer using OpenGL or Vulkan functions or memory mappings + * does not require the presence of this flag. + */ + CPU_READ_RARELY = 2, + /** + * The buffer will often be locked for direct CPU reads using + * the AHardwareBuffer_lock() function. Note that reading the + * buffer using OpenGL or Vulkan functions or memory mappings + * does not require the presence of this flag. + */ + CPU_READ_OFTEN = 3, + + /** CPU read value mask. */ + CPU_READ_MASK = 0xF, + /** + * The buffer will never be locked for direct CPU writes using the + * AHardwareBuffer_lock() function. Note that writing the buffer + * using OpenGL or Vulkan functions or memory mappings is still + * allowed. + */ + CPU_WRITE_NEVER = 0 << 4, + /** + * The buffer will sometimes be locked for direct CPU writes using + * the AHardwareBuffer_lock() function. Note that writing the + * buffer using OpenGL or Vulkan functions or memory mappings + * does not require the presence of this flag. + */ + CPU_WRITE_RARELY = 2 << 4, + /** + * The buffer will often be locked for direct CPU writes using + * the AHardwareBuffer_lock() function. Note that writing the + * buffer using OpenGL or Vulkan functions or memory mappings + * does not require the presence of this flag. + */ + CPU_WRITE_OFTEN = 3 << 4, + /** CPU write value mask. */ + CPU_WRITE_MASK = 0xF << 4, + /** The buffer will be read from by the GPU as a texture. */ + GPU_SAMPLED_IMAGE = 1 << 8, + /** The buffer will be written to by the GPU as a framebuffer attachment.*/ + GPU_FRAMEBUFFER = 1 << 9, + /** + * The buffer will be written to by the GPU as a framebuffer + * attachment. + * + * Note that the name of this flag is somewhat misleading: it does + * not imply that the buffer contains a color format. A buffer with + * depth or stencil format that will be used as a framebuffer + * attachment should also have this flag. Use the equivalent flag + * AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER to avoid this confusion. + */ + GPU_COLOR_OUTPUT = GPU_FRAMEBUFFER, + /** + * The buffer will be used as a composer HAL overlay layer. + * + * This flag is currently only needed when using ASurfaceTransaction_setBuffer + * to set a buffer. In all other cases, the framework adds this flag + * internally to buffers that could be presented in a composer overlay. + * ASurfaceTransaction_setBuffer is special because it uses buffers allocated + * directly through AHardwareBuffer_allocate instead of buffers allocated + * by the framework. + */ + COMPOSER_OVERLAY = 1 << 11, + /** + * The buffer is protected from direct CPU access or being read by + * non-secure hardware, such as video encoders. + * + * This flag is incompatible with CPU read and write flags. It is + * mainly used when handling DRM video. Refer to the EGL extension + * EGL_EXT_protected_content and GL extension + * GL_EXT_protected_textures for more information on how these + * buffers are expected to behave. + */ + PROTECTED_CONTENT = 1 << 14, + /** The buffer will be read by a hardware video encoder. */ + VIDEO_ENCODE = 1 << 16, + /** + * The buffer will be used for direct writes from sensors. + * When this flag is present, the format must be AHARDWAREBUFFER_FORMAT_BLOB. + */ + SENSOR_DIRECT_DATA = 1 << 23, + /** + * The buffer will be used as a shader storage or uniform buffer object. + * When this flag is present, the format must be AHARDWAREBUFFER_FORMAT_BLOB. + */ + GPU_DATA_BUFFER = 1 << 24, + /** + * The buffer will be used as a cube map texture. + * When this flag is present, the buffer must have a layer count + * that is a multiple of 6. Note that buffers with this flag must be + * bound to OpenGL textures using the extension + * GL_EXT_EGL_image_storage instead of GL_KHR_EGL_image. + */ + GPU_CUBE_MAP = 1 << 25, + /** + * The buffer contains a complete mipmap hierarchy. + * Note that buffers with this flag must be bound to OpenGL textures using + * the extension GL_EXT_EGL_image_storage instead of GL_KHR_EGL_image. + */ + GPU_MIPMAP_COMPLETE = 1 << 26, + + /** + * Usage: The buffer is used for front-buffer rendering. When + * front-buffering rendering is specified, different usages may adjust their + * behavior as a result. For example, when used as GPU_COLOR_OUTPUT the buffer + * will behave similar to a single-buffered window. When used with + * COMPOSER_OVERLAY, the system will try to prioritize the buffer receiving + * an overlay plane & avoid caching it in intermediate composition buffers. + */ + FRONT_BUFFER = 1 << 32, + + VENDOR_0 = 1 << 28, + VENDOR_1 = 1 << 29, + VENDOR_2 = 1 << 30, + VENDOR_3 = 1 << 31, + VENDOR_4 = 1 << 48, + VENDOR_5 = 1 << 49, + VENDOR_6 = 1 << 50, + VENDOR_7 = 1 << 51, + VENDOR_8 = 1 << 52, + VENDOR_9 = 1 << 53, + VENDOR_10 = 1 << 54, + VENDOR_11 = 1 << 55, + VENDOR_12 = 1 << 56, + VENDOR_13 = 1 << 57, + VENDOR_14 = 1 << 58, + VENDOR_15 = 1 << 59, + VENDOR_16 = 1 << 60, + VENDOR_17 = 1 << 61, + VENDOR_18 = 1 << 62, + VENDOR_19 = 1 << 63, +} + +/** + * Buffer description. Used for allocating new buffers and querying + * parameters of existing ones. + */ +AHardwareBuffer_Desc :: struct { + width: u32, ///< Width in pixels. + height: u32, ///< Height in pixels. + /** + * Number of images in an image array. AHardwareBuffers with one + * layer correspond to regular 2D textures. AHardwareBuffers with + * more than layer correspond to texture arrays. If the layer count + * is a multiple of 6 and the usage flag + * AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP is present, the buffer is + * a cube map or a cube map array. + */ + layers: u32, + format: AHardwareBuffer_Format, ///< One of AHardwareBuffer_Format. + usage: AHardwareBuffer_UsageFlags, ///< Combination of AHardwareBuffer_UsageFlags. + stride: u32, ///< Row stride in pixels, ignored for AHardwareBuffer_allocate() + rfu0: u32, ///< Initialize to zero, reserved for future use. + rfu1: u64, ///< Initialize to zero, reserved for future use. +} + +/** + * Holds data for a single image plane. + */ +AHardwareBuffer_Plane :: struct { + data: rawptr, ///< Points to first byte in plane + pixelStride: u32, ///< Distance in bytes from the color channel of one pixel to the next + rowStride: u32, ///< Distance in bytes from the first value of one row of the image to + /// the first value of the next row. +} + +/** + * Holds all image planes that contain the pixel data. + */ +AHardwareBuffer_Planes :: struct { + planeCount: u32, ///< Number of distinct planes + planes: [4]AHardwareBuffer_Plane, ///< Array of image planes +} + +/** + * Opaque handle for a native hardware buffer. + */ +AHardwareBuffer :: struct{} + +foreign android { + /** + * Allocates a buffer that matches the passed AHardwareBuffer_Desc. + * + * If allocation succeeds, the buffer can be used according to the + * usage flags specified in its description. If a buffer is used in ways + * not compatible with its usage flags, the results are undefined and + * may include program termination. + * + * Available since API level 26. + * + * \return 0 on success, or an error number of the allocation fails for + * any reason. The returned buffer has a reference count of 1. + */ + AHardwareBuffer_allocate :: proc(desc: ^AHardwareBuffer_Desc, outBuffer: ^^AHardwareBuffer) -> i32 --- + /** + * Acquire a reference on the given AHardwareBuffer object. + * + * This prevents the object from being deleted until the last reference + * is removed. + * + * Available since API level 26. + */ + AHardwareBuffer_acquire :: proc(buffer: ^AHardwareBuffer) --- + + /** + * Remove a reference that was previously acquired with + * AHardwareBuffer_acquire() or AHardwareBuffer_allocate(). + * + * Available since API level 26. + */ + AHardwareBuffer_release :: proc(buffer: ^AHardwareBuffer) --- + + /** + * Return a description of the AHardwareBuffer in the passed + * AHardwareBuffer_Desc struct. + * + * Available since API level 26. + */ + AHardwareBuffer_describe :: proc(buffer: ^AHardwareBuffer, outDesc: ^AHardwareBuffer_Desc) --- + + /** + * Lock the AHardwareBuffer for direct CPU access. + * + * This function can lock the buffer for either reading or writing. + * It may block if the hardware needs to finish rendering, if CPU caches + * need to be synchronized, or possibly for other implementation- + * specific reasons. + * + * The passed AHardwareBuffer must have one layer, otherwise the call + * will fail. + * + * If \a fence is not negative, it specifies a fence file descriptor on + * which to wait before locking the buffer. If it's negative, the caller + * is responsible for ensuring that writes to the buffer have completed + * before calling this function. Using this parameter is more efficient + * than waiting on the fence and then calling this function. + * + * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*. + * If set, then outVirtualAddress is filled with the address of the + * buffer in virtual memory. The flags must also be compatible with + * usage flags specified at buffer creation: if a read flag is passed, + * the buffer must have been created with + * AHARDWAREBUFFER_USAGE_CPU_READ_RARELY or + * AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN. If a write flag is passed, it + * must have been created with AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY or + * AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN. + * + * If \a rect is not NULL, the caller promises to modify only data in + * the area specified by rect. If rect is NULL, the caller may modify + * the contents of the entire buffer. The content of the buffer outside + * of the specified rect is NOT modified by this call. + * + * It is legal for several different threads to lock a buffer for read + * access none of the threads are blocked. + * + * Locking a buffer simultaneously for write or read/write is undefined, + * but will neither terminate the process nor block the caller. + * AHardwareBuffer_lock may return an error or leave the buffer's + * content in an indeterminate state. + * + * If the buffer has AHARDWAREBUFFER_FORMAT_BLOB, it is legal lock it + * for reading and writing in multiple threads and/or processes + * simultaneously, and the contents of the buffer behave like shared + * memory. + * + * Available since API level 26. + * + * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags + * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer + * has more than one layer. Error number if the lock fails for any other + * reason. + */ + AHardwareBuffer_lock :: proc(buffer: ^AHardwareBuffer, usage: AHardwareBuffer_UsageFlags, fence: i32, rect: ^ARect, outVirtualAddress: ^rawptr) -> i32 --- + + /** + * Unlock the AHardwareBuffer from direct CPU access. + * + * Must be called after all changes to the buffer are completed by the + * caller. If \a fence is NULL, the function will block until all work + * is completed. Otherwise, \a fence will be set either to a valid file + * descriptor or to -1. The file descriptor will become signaled once + * the unlocking is complete and buffer contents are updated. + * The caller is responsible for closing the file descriptor once it's + * no longer needed. The value -1 indicates that unlocking has already + * completed before the function returned and no further operations are + * necessary. + * + * Available since API level 26. + * + * \return 0 on success. -EINVAL if \a buffer is NULL. Error number if + * the unlock fails for any reason. + */ + AHardwareBuffer_unlock :: proc(buffer: ^AHardwareBuffer, fence: ^i32) -> i32 --- + + /** + * Send the AHardwareBuffer to an AF_UNIX socket. + * + * Available since API level 26. + * + * \return 0 on success, -EINVAL if \a buffer is NULL, or an error + * number if the operation fails for any reason. + */ + AHardwareBuffer_sendHandleToUnixSocket :: proc(buffer: ^AHardwareBuffer, socketFd: i32) -> i32 --- + + /** + * Receive an AHardwareBuffer from an AF_UNIX socket. + * + * Available since API level 26. + * + * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error + * number if the operation fails for any reason. + */ + AHardwareBuffer_recvHandleFromUnixSocket :: proc(socketFd: i32, outBuffer: ^^AHardwareBuffer) -> i32 --- + + /** + * Lock a potentially multi-planar AHardwareBuffer for direct CPU access. + * + * This function is similar to AHardwareBuffer_lock, but can lock multi-planar + * formats. The locked planes are returned in the \a outPlanes argument. Note, + * that multi-planar should not be confused with multi-layer images, which this + * locking function does not support. + * + * YUV formats are always represented by three separate planes of data, one for + * each color plane. The order of planes in the array is guaranteed such that + * plane #0 is always Y, plane #1 is always U (Cb), and plane #2 is always V + * (Cr). All other formats are represented by a single plane. + * + * Additional information always accompanies the buffers, describing the row + * stride and the pixel stride for each plane. + * + * In case the buffer cannot be locked, \a outPlanes will contain zero planes. + * + * See the AHardwareBuffer_lock documentation for all other locking semantics. + * + * Available since API level 29. + * + * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags + * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer + * has more than one layer. Error number if the lock fails for any other + * reason. + */ + AHardwareBuffer_lockPlanes :: proc(buffer: ^AHardwareBuffer, usage: AHardwareBuffer_UsageFlags, fence: i32, rect: ^ARect, outPlanes: ^AHardwareBuffer_Planes) -> i32 --- + + /** + * Test whether the given format and usage flag combination is + * allocatable. + * + * If this function returns true, it means that a buffer with the given + * description can be allocated on this implementation, unless resource + * exhaustion occurs. If this function returns false, it means that the + * allocation of the given description will never succeed. + * + * The return value of this function may depend on all fields in the + * description, except stride, which is always ignored. For example, + * some implementations have implementation-defined limits on texture + * size and layer count. + * + * Available since API level 29. + * + * \return 1 if the format and usage flag combination is allocatable, + * 0 otherwise. + */ + AHardwareBuffer_isSupported :: proc(desc: ^AHardwareBuffer_Desc) -> i32 --- + + /** + * Lock an AHardwareBuffer for direct CPU access. + * + * This function is the same as the above lock function, but passes back + * additional information about the bytes per pixel and the bytes per stride + * of the locked buffer. If the bytes per pixel or bytes per stride are unknown + * or variable, or if the underlying mapper implementation does not support returning + * additional information, then this call will fail with INVALID_OPERATION + * + * Available since API level 29. + */ + AHardwareBuffer_lockAndGetInfo :: proc(buffer: ^AHardwareBuffer, usage: AHardwareBuffer_UsageFlags, fence: i32, rect: ^ARect, outVirtualAddress: ^rawptr, outBytesPerPixel: ^i32, outBytesPerStride: ^i32) -> i32 --- + + + /** + * Get the system wide unique id for an AHardwareBuffer. + * + * Available since API level 31. + * + * \return 0 on success, -EINVAL if \a buffer or \a outId is NULL, or an error number if the + * operation fails for any reason. + */ + AHardwareBuffer_getId :: proc(buffer: ^AHardwareBuffer, outId: ^u64) -> i32 --- +} diff --git a/hardware_buffer_jni.odin b/hardware_buffer_jni.odin new file mode 100644 index 0000000..763f50e --- /dev/null +++ b/hardware_buffer_jni.odin @@ -0,0 +1,37 @@ +//+build android +package android + +foreign import android "system:android" + +foreign android { + /** + * Return the AHardwareBuffer wrapped by a Java HardwareBuffer object. + * + * This method does not acquire any additional reference to the AHardwareBuffer + * that is returned. To keep the AHardwareBuffer alive after the Java + * HardwareBuffer object is closed, explicitly or by the garbage collector, be + * sure to use AHardwareBuffer_acquire() to acquire an additional reference. + * + * Available since API level 26. + */ + AHardwareBuffer_fromHardwareBuffer :: proc(env: ^JNIEnv, hardwareBufferObj: jobject) -> ^AHardwareBuffer --- + + /** + * Return a new Java HardwareBuffer object that wraps the passed native + * AHardwareBuffer object. The Java HardwareBuffer will acquire a reference to + * the internal buffer and manage its lifetime. For example: + * + *

+	* AHardwareBuffer* buffer
+	* AHardwareBuffer_allocate(..., &buffer)  // `buffer` has reference count 1
+	* jobject java_result = AHardwareBuffer_toHardwareBuffer(buffer)  // `buffer` has reference count 2.
+	* AHardwareBuffer_release(buffer) // `buffer` has reference count 1
+	* return result  // The underlying buffer is kept alive by `java_result` and
+	*                 // will be set to 0 when it is closed on the Java side with
+	*                 // HardwareBuffer::close().
+	* 
+ * + * Available since API level 26. + */ + AHardwareBuffer_toHardwareBuffer :: proc(env: ^JNIEnv, hardwareBuffer: ^AHardwareBuffer) -> jobject --- +} diff --git a/hdr_metadata.odin b/hdr_metadata.odin new file mode 100644 index 0000000..6f18f27 --- /dev/null +++ b/hdr_metadata.odin @@ -0,0 +1,45 @@ +//+build android +package android + +/** + * These structures are used to define the display's capabilities for HDR content. + * They can be used to better tone map content to user's display. + */ + +/** + * HDR metadata standards that are supported by Android. + */ +AHdrMetadataType :: enum u32 { + HDR10_SMPTE2086 = 1, + HDR10_CTA861_3 = 2, + HDR10PLUS_SEI = 3, +} + +/** + * Color is defined in CIE XYZ coordinates. + */ +AColor_xy :: struct { + x: f32, + y: f32, +} + +/** + * SMPTE ST 2086 "Mastering Display Color Volume" static metadata + */ +AHdrMetadata_smpte2086 :: struct { + displayPrimaryRed: AColor_xy, + displayPrimaryGreen: AColor_xy, + displayPrimaryBlue: AColor_xy, + whitePoint: AColor_xy, + maxLuminance: f32, + minLuminance: f32, +} + +/** + * CTA 861.3 "HDR Static Metadata Extension" static metadata + */ +AHdrMetadata_cta861_3 :: struct { + maxContentLightLevel: f32, + maxFrameAverageLightLevel: f32, +} + diff --git a/imagedecoder.odin b/imagedecoder.odin new file mode 100644 index 0000000..7c8bca4 --- /dev/null +++ b/imagedecoder.odin @@ -0,0 +1,992 @@ +//+build android +package android + +foreign import android "system:android" + +/** + * @defgroup ImageDecoder Android Image Decoder + * + * Functions for converting encoded images into RGBA pixels. + * + * Similar to the Java counterpart android.graphics.ImageDecoder, it can be used + * to decode images in the following formats: + * - JPEG + * - PNG + * - GIF + * - WebP + * - BMP + * - ICO + * - WBMP + * - HEIF + * - Digital negatives (via the DNG SDK) + *

It has similar options for scaling, cropping, and choosing the output format. + * Unlike the Java API, which can create an android.graphics.Bitmap or + * android.graphics.drawable.Drawable object, AImageDecoder decodes directly + * into memory provided by the client. For more information, see the + * Image decoder + * developer guide. + * @{ + */ + +/** + * {@link AImageDecoder} functions result code. + * + * Introduced in API 30. + * + * Many functions will return this to indicate success + * ({@link ANDROID_IMAGE_DECODER_SUCCESS}) or the reason for the failure. On + * failure, any out-parameters should be considered uninitialized, except where + * specified. Use {@link AImageDecoder_resultToString} for a readable + * version of the result code. + */ +AImageDecoderResult :: enum i32 { + /** + * Decoding was successful and complete. + */ + SUCCESS = 0, + /** + * The input is incomplete. + */ + INCOMPLETE = -1, + /** + * The input contained an error after decoding some lines. + */ + ERROR = -2, + /** + * Could not convert. For example, attempting to decode an image with + * alpha to an opaque format. + */ + INVALID_CONVERSION = -3, + /** + * The scale is invalid. It may have overflowed, or it may be incompatible + * with the current alpha setting. + */ + INVALID_SCALE = -4, + /** + * Some other parameter is invalid. + */ + BAD_PARAMETER = -5, + /** + * Input was invalid before decoding any pixels. + */ + INVALID_INPUT = -6, + /** + * A seek was required and it failed. + */ + SEEK_ERROR = -7, + /** + * Some other error. For example, an internal allocation failed. + */ + INTERNAL_ERROR = -8, + /** + * AImageDecoder did not recognize the format. + */ + UNSUPPORTED_FORMAT = -9, + /** + * The animation has reached the end. + */ + FINISHED = -10, + /** + * This method cannot be called while the AImageDecoder is in its current + * state. For example, various setters (like {@link AImageDecoder_setTargetSize}) + * can only be called while the AImageDecoder is set to decode the first + * frame of an animation. This ensures that any blending and/or restoring + * prior frames works correctly. + */ + INVALID_STATE = -11, +} + +AImageDecoderRepeatCount :: enum i32 { + /** + * Reported by {@link AImageDecoder_getRepeatCount} if the + * animation should repeat forever. + * + * Introduced in API 31 + */ + INFINITE = max(i32), +} + +/** +* How a frame is “disposed” before showing the next one. +* +* Introduced in API 31. +* +* This, along with other information in AImageDecoderFrameInfo, +* can be useful for determining whether a frame is independent, but +* the decoder handles disposing of frames, so a simple +* sequential client does not need this. +*/ +AImageDecoderFrameDisposalOp :: enum i32 { + /// No disposal. The following frame will be drawn directly + /// on top of this one. + NONE = 1, + /// The frame’s rectangle is cleared to transparent (by AImageDecoder) + /// before decoding the next frame. + BACKGROUND = 2, + /// The frame’s rectangle is reverted to the prior frame before decoding + /// the next frame. This is handled by AImageDecoder, unless + /// {@link AImageDecoder_setInternallyHandleDisposePrevious} is set to false. + PREVIOUS = 3, +} + +/** +* How a frame is blended with the previous frame. +* +* Introduced in API 31. +* +* This, along with other information in AImageDecoderFrameInfo, +* can be useful for determining whether a frame is independent, but +* the decoder handles blending frames, so a simple +* sequential client does not need this. +*/ +AImageDecoderBlendOp :: enum i32 { + /// This frame replaces existing content. This corresponds + /// to webp’s “do not blend”. + SRC = 1, + /// This frame blends with the previous frame. + SRC_OVER = 2, +} + +ResultOrRepeatCount :: union { + AImageDecoderResult, + AImageDecoderRepeatCount, + i32, +} + +ResultOrFrameDuration :: union { + AImageDecoderResult, + i64, +} + +ResultOrFrameDisposalOp :: union { + AImageDecoderResult, + AImageDecoderFrameDisposalOp, +} + +ResultOrBlendOp :: union { + AImageDecoderResult, + AImageDecoderBlendOp, +} + +/** + * Opaque handle for decoding images. + * + * Introduced in API 30 + * + * Create using one of the following: + * - {@link AImageDecoder_createFromAAsset} + * - {@link AImageDecoder_createFromFd} + * - {@link AImageDecoder_createFromBuffer} + * + * After creation, {@link AImageDecoder_getHeaderInfo} can be used to retrieve + * information about the encoded image. Other functions, like + * {@link AImageDecoder_setTargetSize}, can be used to specify how to decode, and + * {@link AImageDecoder_decodeImage} will decode into client provided memory. + * + * {@link AImageDecoder} objects are NOT thread-safe, and should not be shared across + * threads. + */ +AImageDecoder :: struct{} + +/** +* Opaque handle for representing information about the encoded image. +* +* Introduced in API 30 +* +* Retrieved using {@link AImageDecoder_getHeaderInfo} and passed to methods +* like {@link AImageDecoderHeaderInfo_getWidth} and +* {@link AImageDecoderHeaderInfo_getHeight}. +*/ +AImageDecoderHeaderInfo :: struct{} + +/** +* Opaque handle to animation information about a single frame. +* +* Introduced in API 31 +* +* The duration (retrieved with {@link AImageDecoderFrameInfo_getDuration}) is +* necessary for clients to display the animation at the proper speed. The other +* information is helpful for a client that wants to determine what frames are +* independent (or what frames they depend on), but is unnecessary for +* a simple client that wants to sequentially display all frames. +*/ +AImageDecoderFrameInfo :: struct{} + +foreign android { + /** + * Return a constant string value representing the error code. + * + * Introduced in API 31. + * + * Pass the return value from an {@link AImageDecoder} method (e.g. + * {@link AImageDecoder_decodeImage}) for a text string representing the error + * code. + * + * Errors: + * - Returns null for a value out of range. + */ + AImageDecoder_resultToString :: proc(result: AImageDecoderResult) -> cstring --- + + /** + * Create a new {@link AImageDecoder} from an {@link AAsset}. + * + * Available since API level 30. + * + * @param asset {@link AAsset} containing encoded image data. Client is still + * responsible for calling {@link AAsset_close} on it, which may be + * done after deleting the returned {@link AImageDecoder}. + * @param outDecoder On success (i.e. return value is + * {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to + * a newly created {@link AImageDecoder}. Caller is + * responsible for calling {@link AImageDecoder_delete} on it. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The asset was truncated before + * reading the image header. + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: One of the parameters is + * null. + * - {@link ANDROID_IMAGE_DECODER_INVALID_INPUT}: There is an error in the + * header. + * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The asset failed to seek. + * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a + * failure to allocate memory. + * - {@link ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT}: The format is not + * supported. + */ + AImageDecoder_createFromAAsset :: proc(asset: ^AAsset, outDecoder: ^^AImageDecoder) -> AImageDecoderResult --- + + /** + * Create a new {@link AImageDecoder} from a file descriptor. + * + * Available since API level 30. + * + * @param fd Seekable, readable, open file descriptor for encoded data. + * Client is still responsible for closing it, which may be done + * after deleting the returned {@link AImageDecoder}. + * @param outDecoder On success (i.e. return value is + * {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to + * a newly created {@link AImageDecoder}. Caller is + * responsible for calling {@link AImageDecoder_delete} on it. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The file was truncated before + * reading the image header. + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The {@link AImageDecoder} is + * null, or |fd| does not represent a valid, seekable file descriptor. + * - {@link ANDROID_IMAGE_DECODER_INVALID_INPUT}: There is an error in the + * header. + * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The descriptor failed to seek. + * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a + * failure to allocate memory. + * - {@link ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT}: The format is not + * supported. + */ + AImageDecoder_createFromFd :: proc(fd: i32, outDecoder: ^^AImageDecoder) -> AImageDecoderResult --- + + /** + * Create a new AImageDecoder from a buffer. + * + * Available since API level 30. + * + * @param buffer Pointer to encoded data. Must be valid for the entire time + * the {@link AImageDecoder} is used. + * @param length Byte length of buffer. + * @param outDecoder On success (i.e. return value is + * {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to + * a newly created {@link AImageDecoder}. Caller is + * responsible for calling {@link AImageDecoder_delete} on it. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The encoded image was truncated before + * reading the image header. + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: One of the parameters is + * invalid. + * - {@link ANDROID_IMAGE_DECODER_INVALID_INPUT}: There is an error in the + * header. + * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a + * failure to allocate memory. + * - {@link ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT}: The format is not + * supported. + */ + AImageDecoder_createFromBuffer :: proc(buffer: rawptr, length: uint, outDecoder: ^^AImageDecoder) -> AImageDecoderResult --- + + /** + * Delete the AImageDecoder. + * @param decoder {@link AImageDecoder} object created with one of AImageDecoder_createFrom... + * functions. + * Available since API level 30. + */ + AImageDecoder_delete :: proc(decoder: ^AImageDecoder) --- + + /** + * Choose the desired output format. + * + * If the encoded image represents an animation, this must be called while on + * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or + * after calling {@link AImageDecoder_rewind}). + * + * Available since API level 30. + * + * @param format {@link AndroidBitmapFormat} to use for the output. + * @param decoder an {@link AImageDecoder} object. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. On failure, the + * {@link AImageDecoder} uses the format it was already planning + * to use (either its default or a previously successful setting + * from this function). + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder} is null or |format| does not correspond to an + * {@link AndroidBitmapFormat}. + * - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION}: The + * {@link AndroidBitmapFormat} is incompatible with the image. + * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on + * the first frame. + */ + AImageDecoder_setAndroidBitmapFormat :: proc(decoder: ^AImageDecoder, format: AndroidBitmapFormat) -> AImageDecoderResult --- + + /** + * Specify whether the output's pixels should be unpremultiplied. + * + * By default, {@link AImageDecoder_decodeImage} will premultiply the pixels, if they have alpha. + * Pass true to this method to leave them unpremultiplied. This has no effect on an + * opaque image. + * + * If the encoded image represents an animation, this must be called while on + * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or + * after calling {@link AImageDecoder_rewind}). + * + * Available since API level 30. + * + * @param decoder an {@link AImageDecoder} object. + * @param unpremultipliedRequired Pass true to leave the pixels unpremultiplied. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION}: Unpremultiplied is not + * possible due to an existing scale set by + * {@link AImageDecoder_setTargetSize}. + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder} is null. + * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on + * the first frame. + */ + AImageDecoder_setUnpremultipliedRequired :: proc(decoder: ^AImageDecoder, unpremultipliedRequired: bool) -> AImageDecoderResult --- + + /** + * Choose the dataspace for the output. + * + * Ignored by {@link ANDROID_BITMAP_FORMAT_A_8}, which does not support + * an {@link ADataSpace}. + * + * If the encoded image represents an animation, this must be called while on + * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or + * after calling {@link AImageDecoder_rewind}). + * + * Available since API level 30. + * + * @param decoder an {@link AImageDecoder} object. + * @param dataspace The {@link ADataSpace} to decode into. An ADataSpace + * specifies how to interpret the colors. By default, + * AImageDecoder will decode into the ADataSpace specified by + * {@link AImageDecoderHeaderInfo_getDataSpace}. If this + * parameter is set to a different ADataSpace, AImageDecoder + * will transform the output into the specified ADataSpace. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder} is null or |dataspace| does not correspond to an + * {@link ADataSpace} value. + * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on + * the first frame. + */ + AImageDecoder_setDataSpace :: proc(decoder: ^AImageDecoder, dataspace: ADataSpace) -> AImageDecoderResult --- + + /** + * Specify the output size for a decoded image. + * + * Future calls to {@link AImageDecoder_decodeImage} will sample or scale the + * encoded image to reach the desired size. If a crop rect is set (via + * {@link AImageDecoder_setCrop}), it must be contained within the dimensions + * specified by width and height, and the output image will be the size of the + * crop rect. + * + * If the encoded image represents an animation, this must be called while on + * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or + * after calling {@link AImageDecoder_rewind}). + * + * It is strongly recommended to use setTargetSize only for downscaling, as it + * is often more efficient to scale-up when rendering than up-front due to + * reduced overall memory. + * + * Available since API level 30. + * + * @param decoder an {@link AImageDecoder} object. + * @param width Width of the output (prior to cropping). + * This will affect future calls to + * {@link AImageDecoder_getMinimumStride}, which will now return + * a value based on this width. + * @param height Height of the output (prior to cropping). + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder} is null. + * - {@link ANDROID_IMAGE_DECODER_INVALID_SCALE}: |width| or |height| is <= 0, + * the size is too big, any existing crop is not contained by the new image + * dimensions, or the scale is incompatible with a previous call to + * {@link AImageDecoder_setUnpremultipliedRequired}(true). + * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on + * the first frame. + */ + AImageDecoder_setTargetSize :: proc(decoder: ^AImageDecoder, width: i32, height: i32) -> AImageDecoderResult --- + + /** + * Compute the dimensions to use for a given sampleSize. + * + * Although AImageDecoder can scale to an arbitrary target size (see + * {@link AImageDecoder_setTargetSize}), some sizes may be more efficient than + * others. This computes the most efficient target size to use to reach a + * particular sampleSize. + * + * Available since API level 30. + * + * @param decoder an {@link AImageDecoder} object. + * @param sampleSize A subsampling rate of the original image. Must be greater + * than or equal to 1. A sampleSize of 2 means to skip every + * other pixel/line, resulting in a width and height that are + * 1/2 of the original dimensions, with 1/4 the number of + * pixels. + * @param width Out parameter for the width sampled by sampleSize, and rounded + * in the direction that the decoder can do most efficiently. + * @param height Out parameter for the height sampled by sampleSize, and rounded + * in the direction that the decoder can do most efficiently. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder}, |width| or |height| is null or |sampleSize| is < 1. + */ + AImageDecoder_computeSampledSize :: proc(decoder: ^AImageDecoder, sampleSize: i32, width: ^i32, height: ^i32) -> AImageDecoderResult --- + + /** + * Specify how to crop the output after scaling (if any). + * + * Future calls to {@link AImageDecoder_decodeImage} will crop their output to + * the specified {@link ARect}. Clients will only need to allocate enough memory + * for the cropped ARect. + * + * If the encoded image represents an animation, this must be called while on + * the first frame (e.g. before calling {@link AImageDecoder_advanceFrame} or + * after calling {@link AImageDecoder_rewind}). + * + * Available since API level 30. + * + * @param decoder an {@link AImageDecoder} object. + * @param crop Rectangle describing a crop of the decode. It must be contained inside of + * the (possibly scaled, by {@link AImageDecoder_setTargetSize}) + * image dimensions. This will affect future calls to + * {@link AImageDecoder_getMinimumStride}, which will now return a + * value based on the width of the crop. An empty ARect - + * specifically { 0, 0, 0, 0 } - may be used to remove the cropping + * behavior. Any other empty or unsorted ARects will result in + * returning {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder} is null, or the crop is not contained by the + * (possibly scaled) image dimensions. + * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE}: The animation is not on + * the first frame. + */ + AImageDecoder_setCrop :: proc(decoder: ^AImageDecoder, crop: ARect) -> AImageDecoderResult --- + + /** + * Return an opaque handle for reading header info. + * + * This is owned by the {@link AImageDecoder} and will be destroyed when the + * AImageDecoder is destroyed via {@link AImageDecoder_delete}. + * + * @param decoder an {@link AImageDecoder} object. + * + * Available since API level 30. + */ + AImageDecoder_getHeaderInfo :: proc(decoder: ^AImageDecoder) -> ^AImageDecoderHeaderInfo --- + + /** + * Report the native width of the encoded image. This is also the logical + * pixel width of the output, unless {@link AImageDecoder_setTargetSize} is + * used to choose a different size or {@link AImageDecoder_setCrop} is used to + * set a crop rect. + * + * Available since API level 30. + */ + AImageDecoderHeaderInfo_getWidth :: proc(header_info: ^AImageDecoderHeaderInfo) -> i32 --- + + /** + * Report the native height of the encoded image. This is also the logical + * pixel height of the output, unless {@link AImageDecoder_setTargetSize} is + * used to choose a different size or {@link AImageDecoder_setCrop} is used to + * set a crop rect. + * + * Available since API level 30. + */ + AImageDecoderHeaderInfo_getHeight :: proc(header_info: ^AImageDecoderHeaderInfo) -> i32 --- + + /** + * Report the mimeType of the encoded image. + * + * Available since API level 30. + * + * @return a string literal describing the mime type. + */ + AImageDecoderHeaderInfo_getMimeType :: proc(header_info: ^AImageDecoderHeaderInfo) -> cstring --- + + /** + * Report the {@link AndroidBitmapFormat} the AImageDecoder will decode to + * by default. {@link AImageDecoder} will try to choose one that is sensible + * for the image and the system. Note that this does not indicate the + * encoded format of the image. + * + * Available since API level 30. + */ + AImageDecoderHeaderInfo_getAndroidBitmapFormat :: proc(header_info: ^AImageDecoderHeaderInfo) -> AndroidBitmapFormat --- + + /** + * Report how the {@link AImageDecoder} will handle alpha by default. If the image + * contains no alpha (according to its header), this will return + * {@link ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE}. If the image may contain alpha, + * this returns {@link ANDROID_BITMAP_FLAGS_ALPHA_PREMUL}, because + * {@link AImageDecoder_decodeImage} will premultiply pixels by default. + * + * Available since API level 30. + * + * Starting in API level 31, an AImageDecoder may contain multiple frames of an + * animation, but this method still only reports whether the first frame has + * alpha. + */ + AImageDecoderHeaderInfo_getAlphaFlags :: proc(header_info: ^AImageDecoderHeaderInfo) -> AndroidBitmapFlagsAlpha --- + + /** + * Report the dataspace the AImageDecoder will decode to by default. + * + * By default, {@link AImageDecoder_decodeImage} will not do any color + * conversion. + * + * Available since API level 30. + * + * @return The {@link ADataSpace} representing the way the colors + * are encoded (or {@link ADATASPACE_UNKNOWN} if there is not a + * corresponding ADataSpace). This specifies how to interpret the colors + * in the decoded image, unless {@link AImageDecoder_setDataSpace} is + * called to decode to a different ADataSpace. + * + * Note that ADataSpace only exposes a few values. This may return + * {@link ADATASPACE_UNKNOWN}, even for Named ColorSpaces, if they have + * no corresponding {@link ADataSpace}. + */ + AImageDecoderHeaderInfo_getDataSpace :: proc(header_info: ^AImageDecoderHeaderInfo) -> ADataSpace --- + + /** + * Return the minimum stride that can be used in + * {@link AImageDecoder_decodeImage}. + * + * This stride provides no padding, meaning it will be exactly equal to the + * width times the number of bytes per pixel for the {@link AndroidBitmapFormat} + * being used. + * + * If the output is scaled (via {@link AImageDecoder_setTargetSize}) and/or + * cropped (via {@link AImageDecoder_setCrop}), this takes those into account. + * + * @param decoder an {@link AImageDecoder} object. + * + * Available since API level 30. + */ + AImageDecoder_getMinimumStride :: proc(decoder: ^AImageDecoder) -> uint --- + + /** + * Decode the image into pixels, using the settings of the {@link AImageDecoder}. + * + * Available since API level 30. + * + * Starting in API level 31, it can be used to decode all of the frames of an + * animated image (i.e. GIF, WebP) using new APIs. Internally, + * AImageDecoder keeps track of its "current frame" - that is, the frame that + * will be decoded by a call to AImageDecoder_decodeImage. At creation time, the + * current frame is always the first frame, and multiple calls to this method + * will each decode the first frame. {@link AImageDecoder_advanceFrame} advances + * the current frame to the following frame, so that future calls to this method + * will decode that frame. Some frames may update only part of the image. They + * may only update a sub-rectangle (see {@link + * AImageDecoderFrameInfo_getFrameRect}), or they may have alpha (see + * {@link AImageDecoderFrameInfo_hasAlphaWithinBounds}). In these cases, this + * method assumes that the prior frame is still residing in the |pixels| buffer, + * decodes only the new portion, and blends it with the buffer. Frames that change + * the entire |pixels| buffer are "independent", and do not require the prior + * frame to remain in the buffer. The first frame is always independent. A + * sophisticated client can use information from the {@link AImageDecoderFrameInfo} + * to determine whether other frames are independent, or what frames they rely on. + * + * If the current frame is marked {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS}, + * AImageDecoder_decodeImage will store the |pixels| buffer prior to decoding + * (note: this only happens for the first in a string of consecutive + * ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS frames). After advancing to the + * following frame, AImageDecoder_decodeImage will restore that buffer prior to + * decoding that frame. This is the default behavior, but it can be disabled + * by passing false to {@link AImageDecoder_setInternallyHandleDisposePrevious}. + * + * Ignoring timing information, display, etc, a client wishing to decode all + * frames of an animated image may conceptually use code like the following: + * + * while (true) { + * int result = AImageDecoder_decodeImage(decoder, pixels, stride, size); + * if (result != ANDROID_IMAGE_DECODER_SUCCESS) break; + * + * // Display or save the image in |pixels|, keeping the buffer intact for + * // AImageDecoder to decode the next frame correctly. + * Application_viewImage(pixels); + * + * result = AImageDecoder_advanceFrame(decoder); + * if (result != ANDROID_IMAGE_DECODER_SUCCESS) break; + * } + * + * @param decoder Opaque object representing the decoder. + * @param pixels On success, will be filled with the result + * of the decode. Must be large enough to hold |size| bytes. + * @param stride Width in bytes of a single row. Must be at least + * {@link AImageDecoder_getMinimumStride} and a multiple of the + * bytes per pixel of the {@link AndroidBitmapFormat}. + * @param size Size of the pixel buffer in bytes. Must be at least + * stride * (height - 1) + + * {@link AImageDecoder_getMinimumStride}. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The image was truncated. A + * partial image was decoded, and undecoded lines have been initialized to all + * zeroes. + * - {@link ANDROID_IMAGE_DECODER_ERROR}: The image contained an error. A + * partial image was decoded, and undecoded lines have been initialized to all + * zeroes. + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The {@link AImageDecoder} or + * |pixels| is null, the stride is not large enough or not pixel aligned, or + * |size| is not large enough. + * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The asset or file descriptor + * failed to seek. + * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a + * failure to allocate memory. + * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no + * more frames. No decoding occurred. The client must call + * {@link AImageDecoder_rewind} before calling + * {@link AImageDecoder_decodeImage} again. + */ + AImageDecoder_decodeImage :: proc(decoder: ^AImageDecoder, pixels: rawptr, stride: uint, size: uint) -> AImageDecoderResult --- + + /** + * Return true iff the image is animated - i.e. has multiple frames. + * + * Introduced in API 31. + * + * A single frame GIF is considered to *not* be animated. This may require + * seeking past the first frame to verify whether there is a following frame. + * + * @param decoder an {@link AImageDecoder} object. + * + * Errors: + * - returns false if |decoder| is null. + */ + AImageDecoder_isAnimated :: proc(decoder: ^AImageDecoder) -> bool --- + + + /** + * Report how many times the animation should repeat. + * + * Introduced in API 31. + * + * This does not include the first play through. e.g. a repeat + * count of 4 means that each frame is played 5 times. + * + * {@link ANDROID_IMAGE_DECODER_INFINITE} means to repeat forever. + * + * This may require seeking. + * + * For non-animated formats, this returns 0. It may return non-zero for + * an image with only one frame (i.e. {@link AImageDecoder_isAnimated} returns + * false) if the encoded image contains a repeat count. + * + * @param decoder an {@link AImageDecoder} object. + * @return Number of times to repeat on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The AImageDecoder + * is null. + */ + AImageDecoder_getRepeatCount :: proc(decoder: ^AImageDecoder) -> ResultOrRepeatCount --- + + /** + * Advance to the next frame in the animation. + * + * Introduced in API 31. + * + * The AImageDecoder keeps track internally which frame it is ready to decode + * (the "current frame"). Initially it is set to decode the first frame, and + * each call to {@link AImageDecoder_decodeImage} will continue to decode + * the same frame until this method (or {@link AImageDecoder_rewind}) + * is called. + * + * Note that this can be used to skip a frame without decoding it. But + * some frames depend on (i.e. blend with) prior frames, and + * AImageDecoder_decodeImage assumes that the prior frame is in the + * |pixels| buffer. In addition, AImageDecoder_decodeImage handles caching and + * restoring frames (see {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS}), so + * skipping frames in an image with such frames may not produce the correct + * results. + * + * Only supported by {@link ANDROID_BITMAP_FORMAT_RGBA_8888} and + * {@link ANDROID_BITMAP_FORMAT_RGBA_F16}. + * + * @param decoder an {@link AImageDecoder} object. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The AImageDecoder + * represents an image that is not animated (see + * {@link AImageDecoder_isAnimated}) or the AImageDecoder is null. + * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE): The requested + * {@link AndroidBitmapFormat} does not support animation. + * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The input appears + * to be truncated. The client must call {@link AImageDecoder_rewind} + * before calling {@link AImageDecoder_decodeImage} again. + * - {@link ANDROID_IMAGE_DECODER_ERROR}: The input contains an error. + * The client must call {@link AImageDecoder_rewind} before + * calling {@link AImageDecoder_decodeImage} again. + * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no + * more frames. The client must call {@link AImageDecoder_rewind} + * before calling {@link AImageDecoder_decodeImage} again. + */ + AImageDecoder_advanceFrame :: proc(decoder: ^AImageDecoder) -> AImageDecoderResult --- + + /** + * Return to the beginning of the animation. + * + * Introduced in API 31. + * + * After this call, the AImageDecoder will be ready to decode the + * first frame of the animation. This can be called after reaching + * the end of the animation or an error or in the middle of the + * animation. + * + * @param decoder an {@link AImageDecoder} object. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The AImageDecoder + * represents an image that is not animated (see + * {@link AImageDecoder_isAnimated}) or the AImageDecoder is + * null. + * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The asset or file + * descriptor failed to seek. + */ + AImageDecoder_rewind :: proc(decoder: ^AImageDecoder) -> AImageDecoderResult --- + + /** + * Create an uninitialized AImageDecoderFrameInfo. + * + * Introduced in API 31. + * + * This can be passed to {@link AImageDecoder_getFrameInfo} to fill + * in information about the current frame. It may be reused. + * + * Must be deleted with {@link AImageDecoderFrameInfo_delete}. + */ + AImageDecoderFrameInfo_create :: proc() -> ^AImageDecoderFrameInfo --- + + /** + * Delete an AImageDecoderFrameInfo. + * + * Introduced in API 31. + */ + AImageDecoderFrameInfo_delete :: proc(info: ^AImageDecoderFrameInfo) --- + + /** + * Fill |info| with information about the current frame. + * + * Introduced in API 31. + * + * Initially, this will return information about the first frame. + * {@link AImageDecoder_advanceFrame} and + * {@link AImageDecoder_rewind} can be used to change which frame + * is the current frame. + * + * If the image only has one frame, this will fill the {@link + * AImageDecoderFrameInfo} with the encoded info and reasonable + * defaults. + * + * If {@link AImageDecoder_advanceFrame} succeeded, this will succeed as well. + * + * @param decoder Opaque object representing the decoder. + * @param info Opaque object to hold frame information. On success, will be + * filled with information regarding the current frame. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: One of the parameters is null. + * - {@link ANDROID_IMAGE_DECODER_FINISHED}: The input contains no + * more frames. The client must call {@link AImageDecoder_rewind} to reset the + * current frame to a valid frame (0). + */ + AImageDecoder_getFrameInfo :: proc(decoder: ^AImageDecoder, info: ^AImageDecoderFrameInfo) -> AImageDecoderResult --- + + /** + * Report the number of nanoseconds to show the current frame. + * + * Introduced in API 31. + * + * Errors: + * - returns {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if |info| is null. + */ + AImageDecoderFrameInfo_getDuration :: proc(info: ^AImageDecoderFrameInfo) -> ResultOrFrameDuration --- + + /** + * The rectangle of the image (within 0, 0, + * {@link AImageDecoderHeaderInfo_getWidth}, {@link AImageDecoderHeaderInfo_getHeight}) + * updated by this frame. + * + * Introduced in API 31. + * + * Note that this is unaffected by calls to + * {@link AImageDecoder_setTargetSize} or + * {@link AImageDecoder_setCrop}. + * + * A frame may update only part of the image. This will always be + * contained by the image’s dimensions. + * + * This, along with other information in AImageDecoderFrameInfo, + * can be useful for determining whether a frame is independent, but + * the decoder handles blending frames, so a simple + * sequential client does not need this. + * + * Errors: + * - returns an empty ARect if |info| is null. + */ + AImageDecoderFrameInfo_getFrameRect :: proc(info: ^AImageDecoderFrameInfo) -> ARect --- + + /** + * Whether the new portion of this frame may contain alpha. + * + * Introduced in API 31. + * + * Unless this frame is independent (see {@link AImageDecoder_decodeImage}), + * a single call to {@link AImageDecoder_decodeImage} will decode an updated + * rectangle of pixels and then blend it with the existing pixels in the + * |pixels| buffer according to {@link AImageDecoderFrameInfo_getBlendOp}. This + * method returns whether the updated rectangle has alpha, prior to blending. + * The return value is conservative for example, if a color-index-based frame + * has a color with alpha but does not use it, this will still return true. + * + * This, along with other information in AImageDecoderFrameInfo, + * can be useful for determining whether a frame is independent, but + * the decoder handles blending frames, so a simple + * sequential client does not need this. + * + * Note that this may differ from whether the composed frame (that is, the + * resulting image after blending) has alpha. If this frame does not fill the + * entire image dimensions (see {@link AImageDecoderFrameInfo_getFrameRect}) + * or it blends with an opaque frame, for example, the composed frame’s alpha + * may not match. + * + * Errors: + * - returns false if |info| is null. + */ + AImageDecoderFrameInfo_hasAlphaWithinBounds :: proc(info: ^AImageDecoderFrameInfo) -> bool --- + + /** + * Return how this frame is “disposed” before showing the next one. + * + * Introduced in API 31. + * + * This, along with other information in AImageDecoderFrameInfo, + * can be useful for determining whether a frame is independent, but + * the decoder handles disposing of frames, so a simple + * sequential client does not need this. + * + * @return one of: + * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE} + * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND} + * - {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS} + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if |info| is null. + */ + AImageDecoderFrameInfo_getDisposeOp :: proc(info: ^AImageDecoderFrameInfo) -> ResultOrFrameDisposalOp --- + + /** + * Return how this frame is blended with the previous frame. + * + * Introduced in API 31. + * + * This, along with other information in AImageDecoderFrameInfo, + * can be useful for determining whether a frame is independent, but + * the decoder handles blending frames, so a simple + * sequential client does not need this. + * + * @return one of: + * - {@link ANDROID_IMAGE_DECODER_BLEND_OP_SRC} + * - {@link ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER} + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if |info| is null. + */ + AImageDecoderFrameInfo_getBlendOp :: proc(info: ^AImageDecoderFrameInfo) -> ResultOrBlendOp --- + + /** + * Whether to have AImageDecoder store the frame prior to a + * frame marked {@link ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS}. + * + * Introduced in API 31. + * + * The default is true. Many images will not have such a frame (it + * is not supported by WebP, and only some GIFs use it). But + * if frame i is ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS, then i+1 + * may depend on i-1. When this setting is true, AImageDecoder will + * defensively copy frame i-1 (i.e. the contents of |pixels| in + * {@link AImageDecoder_decodeImage}) into an internal buffer so that + * it can be used to decode i+1. + * + * AImageDecoder will only store a single frame, at the size specified + * by {@link AImageDecoder_setTargetSize} (or the original dimensions + * if that method has not been called), and will discard it when it is + * no longer necessary. + * + * A client that desires to manually store such frames may set this to + * false, so that AImageDecoder does not need to store this extra + * frame. Instead, when decoding the same + * ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS frame i, AImageDecoder + * will decode directly into |pixels|, assuming the client stored i-1. + * When asked to decode frame i+1, AImageDecoder will now assume that + * the client provided i-1 in |pixels|. + * + * @param decoder an {@link AImageDecoder} object. + * @param handleInternally Whether AImageDecoder will internally + * handle ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS + * frames. + */ + AImageDecoder_setInternallyHandleDisposePrevious :: proc(decoder: ^AImageDecoder, handleInternally: bool) --- +} diff --git a/input.odin b/input.odin new file mode 100644 index 0000000..0bf3040 --- /dev/null +++ b/input.odin @@ -0,0 +1,1289 @@ +//+build android +package android + +foreign import android "system:android" + +/** + * Key states (may be returned by queries about the current state of a + * particular key code, scan code or switch). + */ +KeyState :: enum { + /** The key state is unknown or the requested key itself is not supported. */ + UNKNOWN = -1, + + /** The key is up. */ + UP = 0, + + /** The key is down. */ + DOWN = 1, + + /** The key is down but is a virtual key press that is being emulated by the system. */ + VIRTUAL = 2 +} + +/** + * Meta key / modifier state. + */ +MetaKeyStateBits :: enum i32 { + ALT_ON = 1, + ALT_LEFT_ON = 4, + ALT_RIGHT_ON = 5, + + SHIFT_ON = 0, + SHIFT_LEFT_ON = 6, + SHIFT_RIGHT_ON = 7, + + SYM_ON = 2, + FUNCTION_ON = 3, + + CTRL_ON = 12, + CTRL_LEFT_ON = 13, + CTRL_RIGHT_ON = 14, + + META_ON = 16, + META_LEFT_ON = 17, + META_RIGHT_ON = 18, + + CAPS_LOCK_ON = 20, + NUM_LOCK_ON = 21, + SCROLL_LOCK_ON = 22, +} + +MetaKeyState :: bit_set[MetaKeyStateBits; i32] + +/** + * Input event types. + */ +InputEventType :: enum i32 { + /** Indicates that the input event is a key event. */ + KEY = 1, + + /** Indicates that the input event is a motion event. */ + MOTION = 2, + + /** Focus event */ + FOCUS = 3, + + /** Capture event */ + CAPTURE = 4, + + /** Drag event */ + DRAG = 5, + + /** TouchMode event */ + TOUCH_MODE = 6, +} + +/** + * Key event actions. + */ +KeyEventAction :: enum i32 { + /** The key has been pressed down. */ + DOWN = 0, + + /** The key has been released. */ + UP = 1, + + /** + * Multiple duplicate key events have occurred in a row, or a + * complex string is being delivered. The repeat_count property + * of the key event contains the number of times the given key + * code should be executed. + */ + MULTIPLE = 2 +} + +/** + * Key event flags. + */ +KeyEventFlagsBits :: enum { + /** This mask is set if the device woke because of this key event. */ + WOKE_HERE = 0, + + /** This mask is set if the key event was generated by a software keyboard. */ + SOFT_KEYBOARD = 1, + + /** This mask is set if we don't want the key event to cause us to leave touch mode. */ + KEEP_TOUCH_MODE = 2, + + /** + * This mask is set if an event was known to come from a trusted + * part of the system. That is, the event is known to come from + * the user, and could not have been spoofed by a third party + * component. + */ + FROM_SYSTEM = 3, + + /** + * This mask is used for compatibility, to identify enter keys that are + * coming from an IME whose enter key has been auto-labelled "next" or + * "done". This allows TextView to dispatch these as normal enter keys + * for old applications, but still do the appropriate action when + * receiving them. + */ + EDITOR_ACTION = 4, + + /** + * When associated with up key events, this indicates that the key press + * has been canceled. Typically this is used with virtual touch screen + * keys, where the user can slide from the virtual key area on to the + * display: in that case, the application will receive a canceled up + * event and should not perform the action normally associated with the + * key. Note that for this to work, the application can not perform an + * action for a key until it receives an up or the long press timeout has + * expired. + */ + CANCELED = 5, + + /** + * This key event was generated by a virtual (on-screen) hard key area. + * Typically this is an area of the touchscreen, outside of the regular + * display, dedicated to "hardware" buttons. + */ + VIRTUAL_HARD_KEY = 6, + + /** + * This flag is set for the first key repeat that occurs after the + * long press timeout. + */ + LONG_PRESS = 7, + + /** + * Set when a key event has #AKEY_EVENT_FLAG_CANCELED set because a long + * press action was executed while it was down. + */ + CANCELED_LONG_PRESS = 8, + + /** + * Set for #AKEY_EVENT_ACTION_UP when this event's key code is still being + * tracked from its initial down. That is, somebody requested that tracking + * started on the key down and a long press has not caused + * the tracking to be canceled. + */ + FLAG_TRACKING = 9, + + /** + * Set when a key event has been synthesized to implement default behavior + * for an event that the application did not handle. + * Fallback key events are generated by unhandled trackball motions + * (to emulate a directional keypad) and by certain unhandled key presses + * that are declared in the key map (such as special function numeric keypad + * keys when numlock is off). + */ + FLAG_FALLBACK = 10, +} + +KeyEventFlags :: bit_set[KeyEventFlagsBits] + +/** + * Bit shift for the action bits holding the pointer index as + * defined by #AMOTION_EVENT_ACTION_POINTER_INDEX_MASK. + */ +AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT :: 8 + +MotionEventAction :: enum i32 { + /** Bit mask of the parts of the action code that are the action itself. */ + MASK = 0xff, + + /** + * Bits in the action code that represent a pointer index, used with + * #AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting + * down by #AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer + * index where the data for the pointer going up or down can be found. + */ + INDEX_MASK = 0xff00, + + /** A pressed gesture has started, the motion contains the initial starting location. */ + DOWN = 0, + + /** + * A pressed gesture has finished, the motion contains the final release location + * as well as any intermediate points since the last down or move event. + */ + UP = 1, + + /** + * A change has happened during a press gesture (between #AMOTION_EVENT_ACTION_DOWN and + * #AMOTION_EVENT_ACTION_UP). The motion contains the most recent point, as well as + * any intermediate points since the last down or move event. + */ + MOVE = 2, + + /** + * The current gesture has been aborted. + * You will not receive any more points in it. You should treat this as + * an up event, but not perform any action that you normally would. + */ + CANCEL = 3, + + /** + * A movement has happened outside of the normal bounds of the UI element. + * This does not provide a full gesture, but only the initial location of the movement/touch. + */ + OUTSIDE = 4, + + /** + * A non-primary pointer has gone down. + * The bits in #AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed. + */ + POINTER_DOWN = 5, + + /** + * A non-primary pointer has gone up. + * The bits in #AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed. + */ + POINTER_UP = 6, + + /** + * A change happened but the pointer is not down (unlike #AMOTION_EVENT_ACTION_MOVE). + * The motion contains the most recent point, as well as any intermediate points since + * the last hover move event. + */ + HOVER_MOVE = 7, + + /** + * The motion event contains relative vertical and/or horizontal scroll offsets. + * Use {@link AMotionEvent_getAxisValue} to retrieve the information from + * #AMOTION_EVENT_AXIS_VSCROLL and #AMOTION_EVENT_AXIS_HSCROLL. + * The pointer may or may not be down when this event is dispatched. + * This action is always delivered to the winder under the pointer, which + * may not be the window currently touched. + */ + SCROLL = 8, + + /** The pointer is not down but has entered the boundaries of a window or view. */ + HOVER_ENTER = 9, + + /** The pointer is not down but has exited the boundaries of a window or view. */ + HOVER_EXIT = 10, + + /* One or more buttons have been pressed. */ + BUTTON_PRESS = 11, + + /* One or more buttons have been released. */ + BUTTON_RELEASE = 12, +} + +/** + * Motion event flags. + */ +MotionEventFlagsBits :: enum i32 { + /** + * This flag indicates that the window that received this motion event is partly + * or wholly obscured by another visible window above it. This flag is set to true + * even if the event did not directly pass through the obscured area. + * A security sensitive application can check this flag to identify situations in which + * a malicious application may have covered up part of its content for the purpose + * of misleading the user or hijacking touches. An appropriate response might be + * to drop the suspect touches or to take additional precautions to confirm the user's + * actual intent. + */ + WINDOW_IS_OBSCURED = 0, +} + +MotionEventFlags :: bit_set[MotionEventFlagsBits; i32] + +/** + * Motion event edge touch flags. + */ +MotionEventEdgeFlagsBits :: enum i32 { + /** Flag indicating the motion event intersected the top edge of the screen. */ + TOP = 0, + /** Flag indicating the motion event intersected the bottom edge of the screen. */ + BOTTOM = 1, + /** Flag indicating the motion event intersected the left edge of the screen. */ + LEFT = 2, + /** Flag indicating the motion event intersected the right edge of the screen. */ + RIGHT = 3, +} + +MotionEventEdgeFlags :: bit_set[MotionEventEdgeFlagsBits; i32] + +/** + * Constants that identify each individual axis of a motion event. + * @anchor AMOTION_EVENT_AXIS + */ +MotionEventAxis :: enum i32 { + /** + * Axis constant: X axis of a motion event. + * + * - For a touch screen, reports the absolute X screen position of the center of + * the touch contact area. The units are display pixels. + * - For a touch pad, reports the absolute X surface position of the center of the touch + * contact area. The units are device-dependent. + * - For a mouse, reports the absolute X screen position of the mouse pointer. + * The units are display pixels. + * - For a trackball, reports the relative horizontal displacement of the trackball. + * The value is normalized to a range from -1.0 (left) to 1.0 (right). + * - For a joystick, reports the absolute X position of the joystick. + * The value is normalized to a range from -1.0 (left) to 1.0 (right). + */ + X = 0, + /** + * Axis constant: Y axis of a motion event. + * + * - For a touch screen, reports the absolute Y screen position of the center of + * the touch contact area. The units are display pixels. + * - For a touch pad, reports the absolute Y surface position of the center of the touch + * contact area. The units are device-dependent. + * - For a mouse, reports the absolute Y screen position of the mouse pointer. + * The units are display pixels. + * - For a trackball, reports the relative vertical displacement of the trackball. + * The value is normalized to a range from -1.0 (up) to 1.0 (down). + * - For a joystick, reports the absolute Y position of the joystick. + * The value is normalized to a range from -1.0 (up or far) to 1.0 (down or near). + */ + Y = 1, + /** + * Axis constant: Pressure axis of a motion event. + * + * - For a touch screen or touch pad, reports the approximate pressure applied to the surface + * by a finger or other tool. The value is normalized to a range from + * 0 (no pressure at all) to 1 (normal pressure), although values higher than 1 + * may be generated depending on the calibration of the input device. + * - For a trackball, the value is set to 1 if the trackball button is pressed + * or 0 otherwise. + * - For a mouse, the value is set to 1 if the primary mouse button is pressed + * or 0 otherwise. + */ + PRESSURE = 2, + /** + * Axis constant: Size axis of a motion event. + * + * - For a touch screen or touch pad, reports the approximate size of the contact area in + * relation to the maximum detectable size for the device. The value is normalized + * to a range from 0 (smallest detectable size) to 1 (largest detectable size), + * although it is not a linear scale. This value is of limited use. + * To obtain calibrated size information, see + * {@link AMOTION_EVENT_AXIS_TOUCH_MAJOR} or {@link AMOTION_EVENT_AXIS_TOOL_MAJOR}. + */ + SIZE = 3, + /** + * Axis constant: TouchMajor axis of a motion event. + * + * - For a touch screen, reports the length of the major axis of an ellipse that + * represents the touch area at the point of contact. + * The units are display pixels. + * - For a touch pad, reports the length of the major axis of an ellipse that + * represents the touch area at the point of contact. + * The units are device-dependent. + */ + TOUCH_MAJOR = 4, + /** + * Axis constant: TouchMinor axis of a motion event. + * + * - For a touch screen, reports the length of the minor axis of an ellipse that + * represents the touch area at the point of contact. + * The units are display pixels. + * - For a touch pad, reports the length of the minor axis of an ellipse that + * represents the touch area at the point of contact. + * The units are device-dependent. + * + * When the touch is circular, the major and minor axis lengths will be equal to one another. + */ + TOUCH_MINOR = 5, + /** + * Axis constant: ToolMajor axis of a motion event. + * + * - For a touch screen, reports the length of the major axis of an ellipse that + * represents the size of the approaching finger or tool used to make contact. + * - For a touch pad, reports the length of the major axis of an ellipse that + * represents the size of the approaching finger or tool used to make contact. + * The units are device-dependent. + * + * When the touch is circular, the major and minor axis lengths will be equal to one another. + * + * The tool size may be larger than the touch size since the tool may not be fully + * in contact with the touch sensor. + */ + TOOL_MAJOR = 6, + /** + * Axis constant: ToolMinor axis of a motion event. + * + * - For a touch screen, reports the length of the minor axis of an ellipse that + * represents the size of the approaching finger or tool used to make contact. + * - For a touch pad, reports the length of the minor axis of an ellipse that + * represents the size of the approaching finger or tool used to make contact. + * The units are device-dependent. + * + * When the touch is circular, the major and minor axis lengths will be equal to one another. + * + * The tool size may be larger than the touch size since the tool may not be fully + * in contact with the touch sensor. + */ + TOOL_MINOR = 7, + /** + * Axis constant: Orientation axis of a motion event. + * + * - For a touch screen or touch pad, reports the orientation of the finger + * or tool in radians relative to the vertical plane of the device. + * An angle of 0 radians indicates that the major axis of contact is oriented + * upwards, is perfectly circular or is of unknown orientation. A positive angle + * indicates that the major axis of contact is oriented to the right. A negative angle + * indicates that the major axis of contact is oriented to the left. + * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians + * (finger pointing fully right). + * - For a stylus, the orientation indicates the direction in which the stylus + * is pointing in relation to the vertical axis of the current orientation of the screen. + * The range is from -PI radians to PI radians, where 0 is pointing up, + * -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians + * is pointing right. See also #AMOTION_EVENT_AXIS_TILT. + */ + ORIENTATION = 8, + /** + * Axis constant: Vertical Scroll axis of a motion event. + * + * - For a mouse, reports the relative movement of the vertical scroll wheel. + * The value is normalized to a range from -1.0 (down) to 1.0 (up). + * + * This axis should be used to scroll views vertically. + */ + VSCROLL = 9, + /** + * Axis constant: Horizontal Scroll axis of a motion event. + * + * - For a mouse, reports the relative movement of the horizontal scroll wheel. + * The value is normalized to a range from -1.0 (left) to 1.0 (right). + * + * This axis should be used to scroll views horizontally. + */ + HSCROLL = 10, + /** + * Axis constant: Z axis of a motion event. + * + * - For a joystick, reports the absolute Z position of the joystick. + * The value is normalized to a range from -1.0 (high) to 1.0 (low). + * On game pads with two analog joysticks, this axis is often reinterpreted + * to report the absolute X position of the second joystick instead. + */ + Z = 11, + /** + * Axis constant: X Rotation axis of a motion event. + * + * - For a joystick, reports the absolute rotation angle about the X axis. + * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise). + */ + RX = 12, + /** + * Axis constant: Y Rotation axis of a motion event. + * + * - For a joystick, reports the absolute rotation angle about the Y axis. + * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise). + */ + RY = 13, + /** + * Axis constant: Z Rotation axis of a motion event. + * + * - For a joystick, reports the absolute rotation angle about the Z axis. + * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise). + * On game pads with two analog joysticks, this axis is often reinterpreted + * to report the absolute Y position of the second joystick instead. + */ + RZ = 14, + /** + * Axis constant: Hat X axis of a motion event. + * + * - For a joystick, reports the absolute X position of the directional hat control. + * The value is normalized to a range from -1.0 (left) to 1.0 (right). + */ + HAT_X = 15, + /** + * Axis constant: Hat Y axis of a motion event. + * + * - For a joystick, reports the absolute Y position of the directional hat control. + * The value is normalized to a range from -1.0 (up) to 1.0 (down). + */ + HAT_Y = 16, + /** + * Axis constant: Left Trigger axis of a motion event. + * + * - For a joystick, reports the absolute position of the left trigger control. + * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed). + */ + LTRIGGER = 17, + /** + * Axis constant: Right Trigger axis of a motion event. + * + * - For a joystick, reports the absolute position of the right trigger control. + * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed). + */ + RTRIGGER = 18, + /** + * Axis constant: Throttle axis of a motion event. + * + * - For a joystick, reports the absolute position of the throttle control. + * The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed). + */ + THROTTLE = 19, + /** + * Axis constant: Rudder axis of a motion event. + * + * - For a joystick, reports the absolute position of the rudder control. + * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right). + */ + RUDDER = 20, + /** + * Axis constant: Wheel axis of a motion event. + * + * - For a joystick, reports the absolute position of the steering wheel control. + * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right). + */ + WHEEL = 21, + /** + * Axis constant: Gas axis of a motion event. + * + * - For a joystick, reports the absolute position of the gas (accelerator) control. + * The value is normalized to a range from 0.0 (no acceleration) + * to 1.0 (maximum acceleration). + */ + GAS = 22, + /** + * Axis constant: Brake axis of a motion event. + * + * - For a joystick, reports the absolute position of the brake control. + * The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking). + */ + BRAKE = 23, + /** + * Axis constant: Distance axis of a motion event. + * + * - For a stylus, reports the distance of the stylus from the screen. + * A value of 0.0 indicates direct contact and larger values indicate increasing + * distance from the surface. + */ + DISTANCE = 24, + /** + * Axis constant: Tilt axis of a motion event. + * + * - For a stylus, reports the tilt angle of the stylus in radians where + * 0 radians indicates that the stylus is being held perpendicular to the + * surface, and PI/2 radians indicates that the stylus is being held flat + * against the surface. + */ + TILT = 25, + /** + * Axis constant: Generic scroll axis of a motion event. + * + * - This is used for scroll axis motion events that can't be classified as strictly + * vertical or horizontal. The movement of a rotating scroller is an example of this. + */ + SCROLL = 26, + /** + * Axis constant: The movement of x position of a motion event. + * + * - For a mouse, reports a difference of x position between the previous position. + * This is useful when pointer is captured, in that case the mouse pointer doesn't + * change the location but this axis reports the difference which allows the app + * to see how the mouse is moved. + */ + RELATIVE_X = 27, + /** + * Axis constant: The movement of y position of a motion event. + * + * Same as #AMOTION_EVENT_AXIS_RELATIVE_X, but for y position. + */ + RELATIVE_Y = 28, + /** + * Axis constant: Generic 1 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_1 = 32, + /** + * Axis constant: Generic 2 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_2 = 33, + /** + * Axis constant: Generic 3 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_3 = 34, + /** + * Axis constant: Generic 4 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_4 = 35, + /** + * Axis constant: Generic 5 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_5 = 36, + /** + * Axis constant: Generic 6 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_6 = 37, + /** + * Axis constant: Generic 7 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_7 = 38, + /** + * Axis constant: Generic 8 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_8 = 39, + /** + * Axis constant: Generic 9 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_9 = 40, + /** + * Axis constant: Generic 10 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_10 = 41, + /** + * Axis constant: Generic 11 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_11 = 42, + /** + * Axis constant: Generic 12 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_12 = 43, + /** + * Axis constant: Generic 13 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_13 = 44, + /** + * Axis constant: Generic 14 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_14 = 45, + /** + * Axis constant: Generic 15 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_15 = 46, + /** + * Axis constant: Generic 16 axis of a motion event. + * The interpretation of a generic axis is device-specific. + */ + GENERIC_16 = 47, +} + +/** + * Constants that identify buttons that are associated with motion events. + * Refer to the documentation on the MotionEvent class for descriptions of each button. + */ +// TODO: bit_set this? +MotionEventButton :: enum { + PRIMARY = 1 << 0, + SECONDARY = 1 << 1, + TERTIARY = 1 << 2, + BACK = 1 << 3, + FORWARD = 1 << 4, + STYLUS_PRIMARY = 1 << 5, + STYLUS_SECONDARY = 1 << 6, +} + +/** + * Constants that identify tool types. + * Refer to the documentation on the MotionEvent class for descriptions of each tool type. + */ +ToolType :: enum i32 { + UNKNOWN = 0, + FINGER = 1, + STYLUS = 2, + MOUSE = 3, + ERASER = 4, + PALM = 5, +} + +/** + * Constants that identify different gesture classification types. + */ +AMotionClassification :: enum i32 { + /** + * Classification constant: None. + * + * No additional information is available about the current motion event stream. + */ + NONE = 0, + /** + * Classification constant: Ambiguous gesture. + * + * The user's intent with respect to the current event stream is not yet determined. Events + * starting in #AMOTION_EVENT_CLASSIFICATION_AMBIGUOUS_GESTURE will eventually resolve into + * either #AMOTION_EVENT_CLASSIFICATION_DEEP_PRESS or #AMOTION_EVENT_CLASSIFICATION_NONE. + * Gestural actions, such as scrolling, should be inhibited until the classification resolves + * to another value or the event stream ends. + */ + AMBIGUOUS_GESTURE = 1, + /** + * Classification constant: Deep press. + * + * The current event stream represents the user intentionally pressing harder on the screen. + * This classification type should be used to accelerate the long press behaviour. + */ + DEEP_PRESS = 2, +} + +/** + * Input source masks. + * + * Refer to the documentation on android.view.InputDevice for more details about input sources + * and their correct interpretation. + */ +InputSourceClass :: enum i32 { + NONE = 0x00000000, + BUTTON = 0x00000001, + POINTER = 0x00000002, + NAVIGATION = 0x00000004, + POSITION = 0x00000008, + JOYSTICK = 0x00000010, + MASK = 0x000000ff, +} + +/** + * Input sources. + */ +InputSource :: enum i32 { + UNKNOWN = 0x00000000, + + KEYBOARD = 0x00000100 | i32(InputSourceClass.BUTTON), + DPAD = 0x00000200 | i32(InputSourceClass.BUTTON), + GAMEPAD = 0x00000400 | i32(InputSourceClass.BUTTON), + TOUCHSCREEN = 0x00001000 | i32(InputSourceClass.POINTER), + MOUSE = 0x00002000 | i32(InputSourceClass.POINTER), + STYLUS = 0x00004000 | i32(InputSourceClass.POINTER), + BLUETOOTH_STYLUS = 0x00008000 | STYLUS, + TRACKBALL = 0x00010000 | i32(InputSourceClass.NAVIGATION), + MOUSE_RELATIVE = 0x00020000 | i32(InputSourceClass.NAVIGATION), + TOUCHPAD = 0x00100000 | i32(InputSourceClass.POSITION), + TOUCH_NAVIGATION = 0x00200000 | i32(InputSourceClass.NONE), + JOYSTICK = 0x01000000 | i32(InputSourceClass.JOYSTICK), + HDMI = 0x02000000 | i32(InputSourceClass.BUTTON), + SENSOR = 0x04000000 | i32(InputSourceClass.NONE), + ROTARY_ENCODER = 0x00400000 | i32(InputSourceClass.NONE), + + ANY = -256, // 0xffffff00 +} + +/** + * Keyboard types. + * + * Refer to the documentation on android.view.InputDevice for more details. + * Note: When adding a new keyboard type here InputDeviceInfo::setKeyboardType needs to be updated. + */ +KeyBoardType :: enum { + NONE = 0, + NON_ALPHABETIC = 1, + TYPE_ALPHABETIC = 2, +} + +/** + * Constants used to retrieve information about the range of motion for a particular + * coordinate of a motion event. + * + * Refer to the documentation on android.view.InputDevice for more details about input sources + * and their correct interpretation. + * + * @deprecated These constants are deprecated. Use {@link AMOTION_EVENT_AXIS AMOTION_EVENT_AXIS_*} + * constants instead. + */ +// TODO: should I just delete this ?? +MotionRange :: enum { + X = 0, + Y = 1, + PRESSURE = 2, + SIZE = 3, + TOUCH_MAJOR = 4, + TOUCH_MINOR = 5, + TOOL_MAJOR = 6, + TOOL_MINOR = 7, + ORIENTATION = 8, +} + +/** + * Input events. + * + * Input events are opaque structures. Use the provided accessors functions to + * read their properties. + */ +AInputEvent :: struct{} +/** + * Input queue + * + * An input queue is the facility through which you retrieve input + * events. + */ +AInputQueue :: struct{} + +foreign android { + /** Get the input event type. */ + AInputEvent_getType :: proc(event: ^AInputEvent) -> InputEventType --- + + /** Get the id for the device that an input event came from. + * + * Input events can be generated by multiple different input devices. + * Use the input device id to obtain information about the input + * device that was responsible for generating a particular event. + * + * An input device id of 0 indicates that the event didn't come from a physical device + * other numbers are arbitrary and you shouldn't depend on the values. + * Use the provided input device query API to obtain information about input devices. + */ + AInputEvent_getDeviceId :: proc(event: ^AInputEvent) -> i32 --- + + /** Get the input event source. */ + AInputEvent_getSource :: proc(event: ^AInputEvent) -> InputSource --- + + /** + * Releases interface objects created by {@link AKeyEvent_fromJava()} + * and {@link AMotionEvent_fromJava()}. + * After returning, the specified {@link AInputEvent}* object becomes invalid and should no longer + * be used. The underlying Java object remains valid and does not change its state. + * + * Available since API level 31. + */ + AInputEvent_release :: proc(event: ^AInputEvent) --- + + /** Get the key event action. */ + AKeyEvent_getAction :: proc(key_event: ^AInputEvent) -> KeyEventAction --- + + /** Get the key event flags. */ + AKeyEvent_getFlags :: proc(key_event: ^AInputEvent) -> KeyEventFlags --- + + /** + * Get the key code of the key event. + * This is the physical key that was pressed, not the Unicode character. + */ + AKeyEvent_getKeyCode :: proc(key_event: ^AInputEvent) -> i32 --- + + /** + * Get the hardware key id of this key event. + * These values are not reliable and vary from device to device. + */ + AKeyEvent_getScanCode :: proc(key_event: ^AInputEvent) -> i32 --- + + /** Get the meta key state. */ + AKeyEvent_getMetaState :: proc(key_event: ^AInputEvent) -> MetaKeyState --- + + /** + * Get the repeat count of the event. + * For both key up an key down events, this is the number of times the key has + * repeated with the first down starting at 0 and counting up from there. For + * multiple key events, this is the number of down/up pairs that have occurred. + */ + AKeyEvent_getRepeatCount :: proc(key_event: ^AInputEvent) -> i32 --- + + /** + * Get the time of the most recent key down event, in the + * java.lang.System.nanoTime() time base. If this is a down event, + * this will be the same as eventTime. + * Note that when chording keys, this value is the down time of the most recently + * pressed key, which may not be the same physical key of this event. + */ + AKeyEvent_getDownTime :: proc(key_event: ^AInputEvent) -> i64 --- + + /** + * Get the time this event occurred, in the + * java.lang.System.nanoTime() time base. + */ + AKeyEvent_getEventTime :: proc(key_event: ^AInputEvent) -> i64 --- + + /** + * Creates a native {@link AInputEvent}* object that is a copy of the specified Java + * android.view.KeyEvent. The result may be used with generic and KeyEvent-specific AInputEvent_* + * functions. The object returned by this function must be disposed using + * {@link AInputEvent_release()}. + * + * Available since API level 31. + */ + AKeyEvent_fromJava :: proc(env: ^JNIEnv, keyEvent: jobject) -> ^AInputEvent --- + + /** Get the combined motion event action code and pointer index. */ + AMotionEvent_getAction :: proc(motion_event: ^AInputEvent) -> MotionEventAction --- + + /** Get the motion event flags. */ + AMotionEvent_getFlags :: proc(motion_event: ^AInputEvent) -> MotionEventFlags --- + + /** + * Get the state of any meta / modifier keys that were in effect when the + * event was generated. + */ + AMotionEvent_getMetaState :: proc(motion_event: ^AInputEvent) -> MetaKeyState --- + + /** Get the button state of all buttons that are pressed. */ + // TODO: Do we have an enum or bit_set for this ??? this might be MotionEventButton but we'll double check by + // writing some code and printing values. + AMotionEvent_getButtonState :: proc(motion_event: ^AInputEvent) -> i32 --- + + /** + * Get a bitfield indicating which edges, if any, were touched by this motion event. + * For touch events, clients can use this to determine if the user's finger was + * touching the edge of the display. + */ + AMotionEvent_getEdgeFlags :: proc(motion_event: ^AInputEvent) -> MotionEventEdgeFlags --- + + /** + * Get the time when the user originally pressed down to start a stream of + * position events, in the java.lang.System.nanoTime() time base. + */ + AMotionEvent_getDownTime :: proc(motion_event: ^AInputEvent) -> i64 --- + + /** + * Get the time when this specific event was generated, + * in the java.lang.System.nanoTime() time base. + */ + AMotionEvent_getEventTime :: proc(motion_event: ^AInputEvent) -> i64 --- + + /** + * Get the X coordinate offset. + * For touch events on the screen, this is the delta that was added to the raw + * screen coordinates to adjust for the absolute position of the containing windows + * and views. + */ + AMotionEvent_getXOffset :: proc(motion_event: ^AInputEvent) -> f32 --- + + /** + * Get the Y coordinate offset. + * For touch events on the screen, this is the delta that was added to the raw + * screen coordinates to adjust for the absolute position of the containing windows + * and views. + */ + AMotionEvent_getYOffset :: proc(motion_event: ^AInputEvent) -> f32 --- + + /** + * Get the precision of the X coordinates being reported. + * You can multiply this number with an X coordinate sample to find the + * actual hardware value of the X coordinate. + */ + AMotionEvent_getXPrecision :: proc(#by_ptr motion_event: AInputEvent) -> f32 --- + + /** + * Get the precision of the Y coordinates being reported. + * You can multiply this number with a Y coordinate sample to find the + * actual hardware value of the Y coordinate. + */ + AMotionEvent_getYPrecision :: proc(#by_ptr motion_event: AInputEvent) -> f32 --- + + /** + * Get the number of pointers of data contained in this event. + * Always >= 1. + */ + AMotionEvent_getPointerCount :: proc(motion_event: ^AInputEvent) -> uint --- + + /** + * Get the pointer identifier associated with a particular pointer + * data index in this event. The identifier tells you the actual pointer + * number associated with the data, accounting for individual pointers + * going up and down since the start of the current gesture. + */ + AMotionEvent_getPointerId :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> i32 --- + + /** + * Get the tool type of a pointer for the given pointer index. + * The tool type indicates the type of tool used to make contact such as a + * finger or stylus, if known. + */ + AMotionEvent_getToolType :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> ToolType --- + + /** + * Get the original raw X coordinate of this event. + * For touch events on the screen, this is the original location of the event + * on the screen, before it had been adjusted for the containing window + * and views. + */ + AMotionEvent_getRawX :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** + * Get the original raw X coordinate of this event. + * For touch events on the screen, this is the original location of the event + * on the screen, before it had been adjusted for the containing window + * and views. + */ + AMotionEvent_getRawY :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** + * Get the current X coordinate of this event for the given pointer index. + * Whole numbers are pixels the value may have a fraction for input devices + * that are sub-pixel precise. + */ + AMotionEvent_getX :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** + * Get the current Y coordinate of this event for the given pointer index. + * Whole numbers are pixels the value may have a fraction for input devices + * that are sub-pixel precise. + */ + AMotionEvent_getY :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** + * Get the current pressure of this event for the given pointer index. + * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure), + * although values higher than 1 may be generated depending on the calibration of + * the input device. + */ + AMotionEvent_getPressure :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** + * Get the current scaled value of the approximate size for the given pointer index. + * This represents some approximation of the area of the screen being + * pressed the actual value in pixels corresponding to the + * touch is normalized with the device specific range of values + * and scaled to a value between 0 and 1. The value of size can be used to + * determine fat touch events. + */ + AMotionEvent_getSize :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** + * Get the current length of the major axis of an ellipse that describes the touch area + * at the point of contact for the given pointer index. + */ + AMotionEvent_getTouchMajor :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** + * Get the current length of the minor axis of an ellipse that describes the touch area + * at the point of contact for the given pointer index. + */ + AMotionEvent_getTouchMinor :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** + * Get the current length of the major axis of an ellipse that describes the size + * of the approaching tool for the given pointer index. + * The tool area represents the estimated size of the finger or pen that is + * touching the device independent of its actual touch area at the point of contact. + */ + AMotionEvent_getToolMajor :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** + * Get the current length of the minor axis of an ellipse that describes the size + * of the approaching tool for the given pointer index. + * The tool area represents the estimated size of the finger or pen that is + * touching the device independent of its actual touch area at the point of contact. + */ + AMotionEvent_getToolMinor :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** + * Get the current orientation of the touch area and tool area in radians clockwise from + * vertical for the given pointer index. + * An angle of 0 degrees indicates that the major axis of contact is oriented + * upwards, is perfectly circular or is of unknown orientation. A positive angle + * indicates that the major axis of contact is oriented to the right. A negative angle + * indicates that the major axis of contact is oriented to the left. + * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians + * (finger pointing fully right). + */ + AMotionEvent_getOrientation :: proc(motion_event: ^AInputEvent, pointer_index: uint) -> f32 --- + + /** Get the value of the request axis for the given pointer index. */ + AMotionEvent_getAxisValue :: proc(motion_event: ^AInputEvent, axis: MotionEventAxis, pointer_index: uint) -> f32 --- + + /** + * Get the number of historical points in this event. These are movements that + * have occurred between this event and the previous event. This only applies + * to #AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0. + * Historical samples are indexed from oldest to newest. + */ + AMotionEvent_getHistorySize :: proc(motion_event: ^AInputEvent) -> uint --- + + /** + * Get the time that a historical movement occurred between this event and + * the previous event, in the java.lang.System.nanoTime() time base. + */ + AMotionEvent_getHistoricalEventTime :: proc(motion_event: ^AInputEvent, history_index: uint) -> i64 --- + + /** + * Get the historical raw X coordinate of this event for the given pointer index that + * occurred between this event and the previous motion event. + * For touch events on the screen, this is the original location of the event + * on the screen, before it had been adjusted for the containing window + * and views. + * Whole numbers are pixels the value may have a fraction for input devices + * that are sub-pixel precise. + */ + AMotionEvent_getHistoricalRawX :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the historical raw Y coordinate of this event for the given pointer index that + * occurred between this event and the previous motion event. + * For touch events on the screen, this is the original location of the event + * on the screen, before it had been adjusted for the containing window + * and views. + * Whole numbers are pixels the value may have a fraction for input devices + * that are sub-pixel precise. + */ + AMotionEvent_getHistoricalRawY :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the historical X coordinate of this event for the given pointer index that + * occurred between this event and the previous motion event. + * Whole numbers are pixels the value may have a fraction for input devices + * that are sub-pixel precise. + */ + AMotionEvent_getHistoricalX :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the historical Y coordinate of this event for the given pointer index that + * occurred between this event and the previous motion event. + * Whole numbers are pixels the value may have a fraction for input devices + * that are sub-pixel precise. + */ + AMotionEvent_getHistoricalY :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the historical pressure of this event for the given pointer index that + * occurred between this event and the previous motion event. + * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure), + * although values higher than 1 may be generated depending on the calibration of + * the input device. + */ + AMotionEvent_getHistoricalPressure :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the current scaled value of the approximate size for the given pointer index that + * occurred between this event and the previous motion event. + * This represents some approximation of the area of the screen being + * pressed the actual value in pixels corresponding to the + * touch is normalized with the device specific range of values + * and scaled to a value between 0 and 1. The value of size can be used to + * determine fat touch events. + */ + AMotionEvent_getHistoricalSize :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the historical length of the major axis of an ellipse that describes the touch area + * at the point of contact for the given pointer index that + * occurred between this event and the previous motion event. + */ + AMotionEvent_getHistoricalTouchMajor :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the historical length of the minor axis of an ellipse that describes the touch area + * at the point of contact for the given pointer index that + * occurred between this event and the previous motion event. + */ + AMotionEvent_getHistoricalTouchMinor :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the historical length of the major axis of an ellipse that describes the size + * of the approaching tool for the given pointer index that + * occurred between this event and the previous motion event. + * The tool area represents the estimated size of the finger or pen that is + * touching the device independent of its actual touch area at the point of contact. + */ + AMotionEvent_getHistoricalToolMajor :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the historical length of the minor axis of an ellipse that describes the size + * of the approaching tool for the given pointer index that + * occurred between this event and the previous motion event. + * The tool area represents the estimated size of the finger or pen that is + * touching the device independent of its actual touch area at the point of contact. + */ + AMotionEvent_getHistoricalToolMinor :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the historical orientation of the touch area and tool area in radians clockwise from + * vertical for the given pointer index that + * occurred between this event and the previous motion event. + * An angle of 0 degrees indicates that the major axis of contact is oriented + * upwards, is perfectly circular or is of unknown orientation. A positive angle + * indicates that the major axis of contact is oriented to the right. A negative angle + * indicates that the major axis of contact is oriented to the left. + * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians + * (finger pointing fully right). + */ + AMotionEvent_getHistoricalOrientation :: proc(motion_event: ^AInputEvent, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the historical value of the request axis for the given pointer index + * that occurred between this event and the previous motion event. + */ + AMotionEvent_getHistoricalAxisValue :: proc(motion_event: ^AInputEvent, axis: MotionEventAxis, pointer_index: uint, history_index: uint) -> f32 --- + + /** + * Get the action button for the motion event. Returns a valid action button when the + * event is associated with a button press or button release action. For other actions + * the return value is undefined. + * + * Available since API level 33. + * + * @see #AMOTION_EVENT_BUTTON_PRIMARY + * @see #AMOTION_EVENT_BUTTON_SECONDARY + * @see #AMOTION_EVENT_BUTTON_TERTIARY + * @see #AMOTION_EVENT_BUTTON_BACK + * @see #AMOTION_EVENT_BUTTON_FORWARD + * @see #AMOTION_EVENT_BUTTON_STYLUS_PRIMARY + * @see #AMOTION_EVENT_BUTTON_STYLUS_SECONDARY + */ + AMotionEvent_getActionButton :: proc(motion_event: ^AInputEvent) -> MotionEventButton --- + + /** + * Returns the classification for the current gesture. + * The classification may change as more events become available for the same gesture. + * + * Available since API level 33. + * + * @see #AMOTION_EVENT_CLASSIFICATION_NONE + * @see #AMOTION_EVENT_CLASSIFICATION_AMBIGUOUS_GESTURE + * @see #AMOTION_EVENT_CLASSIFICATION_DEEP_PRESS + */ + AMotionEvent_getClassification :: proc(motion_event: ^AInputEvent) -> AMotionClassification --- + + /** + * Creates a native {@link AInputEvent}* object that is a copy of the specified Java + * android.view.MotionEvent. The result may be used with generic and MotionEvent-specific + * AInputEvent_* functions. The object returned by this function must be disposed using + * {@link AInputEvent_release()}. + * + * Available since API level 31. + */ + AMotionEvent_fromJava :: proc(env: ^JNIEnv, motionEvent: jobject) -> ^AInputEvent --- + + /** + * Add this input queue to a looper for processing. See + * {@link ALooper_addFd()} for information on the ident, callback, and data params. + */ + AInputQueue_attachLooper :: proc(queue: ^AInputQueue, looper: ^ALooper, ident: i32, callback: ALooper_callbackFunc, data: rawptr) --- + + /** + * Remove the input queue from the looper it is currently attached to. + */ + AInputQueue_detachLooper :: proc(queue: ^AInputQueue) --- + + /** + * Returns true if there are one or more events available in the + * input queue. Returns 1 if the queue has events 0 if + * it does not have events and a negative value if there is an error. + */ + AInputQueue_hasEvents :: proc(queue: ^AInputQueue) -> i32 --- + + /** + * Returns the next available event from the queue. Returns a negative + * value if no events are available or an error has occurred. + */ + AInputQueue_getEvent :: proc(queue: ^AInputQueue, outEvent: ^^AInputEvent) -> i32 --- + + /** + * Sends the key for standard pre-dispatching -- that is, possibly deliver + * it to the current IME to be consumed before the app. Returns 0 if it + * was not pre-dispatched, meaning you can process it right now. If non-zero + * is returned, you must abandon the current event processing and allow the + * event to appear again in the event queue (if it does not get consumed during + * pre-dispatching). + */ + AInputQueue_preDispatchEvent :: proc(queue: ^AInputQueue, event: ^AInputEvent) -> i32 --- + + /** + * Report that dispatching has finished with the given event. + * This must be called after receiving an event with {@link AInputQueue_getEvent()}. + */ + AInputQueue_finishEvent :: proc(queue: ^AInputQueue, event: ^AInputEvent, handled: i32) --- + + /** + * Returns the {@link AInputQueue}* object associated with the supplied Java InputQueue + * object. The returned native object holds a weak reference to the Java object, + * and is only valid as long as the Java object has not yet been disposed. You + * should ensure that there is a strong reference to the Java object and that it + * has not been disposed before using the returned object. + * + * Available since API level 33. + */ + AInputQueue_fromJava :: proc(env: ^JNIEnv, inputQueue: jobject) -> ^AInputQueue --- +} diff --git a/jni.odin b/jni.odin new file mode 100644 index 0000000..a013a84 --- /dev/null +++ b/jni.odin @@ -0,0 +1,367 @@ +//+build android +package android + +import "core:c" + +/* Primitive types that match up with Java equivalents. */ +jboolean :: c.uint8_t /* unsigned 8 bits */ +jbyte :: c.int8_t /* signed 8 bits */ +jchar :: c.uint16_t /* unsigned 16 bits */ +jshort :: c.int16_t /* signed 16 bits */ +jint :: c.int32_t /* signed 32 bits */ +jlong :: c.int64_t /* signed 64 bits */ +jfloat :: c.float /* 32-bit IEEE 754 */ +jdouble :: c.double /* 64-bit IEEE 754 */ + +/* "cardinal indices and sizes" */ +jsize :: jint + +/* + * Reference types, in C. + */ +jobject :: distinct rawptr +jclass :: distinct jobject +jstring :: distinct jobject +jarray :: distinct jobject +jobjectArray :: distinct jarray +jbooleanArray :: distinct jarray +jbyteArray :: distinct jarray +jcharArray :: distinct jarray +jshortArray :: distinct jarray +jintArray :: distinct jarray +jlongArray :: distinct jarray +jfloatArray :: distinct jarray +jdoubleArray :: distinct jarray +jthrowable :: distinct jobject +jweak :: distinct jobject + +// Opaque +jfieldID :: rawptr +jmethodID :: rawptr + +jvalue :: struct #raw_union { + z: jboolean, + b: jbyte, + c: jchar, + s: jshort, + i: jint, + j: jlong, + f: jfloat, + d: jdouble, + l: jobject, +} + +jobjectRefType :: enum c.int { + JNIInvalidRefType = 0, + JNILocalRefType = 1, + JNIGlobalRefType = 2, + JNIWeakGlobalRefType = 3 +} + +JNINativeMethod :: struct { + name: cstring, + signature: cstring, + fnPtr: rawptr, +} + +JavaVM :: ^JNIInvokeInterface +JNIEnv :: ^JNINativeInterface + +// NOTE: JNINativeInterface and JNIInvokeInterface don't use the aliased pointer types because of they're considered +// not defined when used inside the structs so we just refer to the struct itself and add an extra pointer hat ^ + +/* + * Table of interface function pointers. + */ +JNINativeInterface :: struct { + reserved0: rawptr, + reserved1: rawptr, + reserved2: rawptr, + reserved3: rawptr, + + GetVersion: #type proc "c" (jni: ^^JNINativeInterface) -> jint, + + DefineClass: #type proc "c" (jni: ^^JNINativeInterface, name: cstring, loader: jobject, #by_ptr buf: jbyte, bufLen: jsize) -> jclass, + FindClass: #type proc "c" (jni: ^^JNINativeInterface, name: cstring) -> jclass, + + FromReflectedMethod: #type proc "c" (jni: ^^JNINativeInterface, method: jobject) -> jmethodID, + FromReflectedField: #type proc "c" (jni: ^^JNINativeInterface, field: jobject) -> jfieldID, + /* spec doesn't show jboolean parameter */ + ToReflectedMethod: #type proc "c" (jni: ^^JNINativeInterface, cls: jclass, methodID: jmethodID, isStatic: jboolean) -> jobject, + + GetSuperclass: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass) -> jclass, + IsAssignableFrom: #type proc "c" (jni: ^^JNINativeInterface, clazz1: jclass, clazz2: jclass) -> jboolean, + + /* spec doesn't show jboolean parameter */ + ToReflectedField: #type proc "c" (jni: ^^JNINativeInterface, cls: jclass, fieldID: jfieldID, isStatic: jboolean) -> jobject, + + Throw: #type proc "c" (jni: ^^JNINativeInterface, obj: jthrowable) -> jint, + ThrowNew: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, message: cstring) -> jint, + ExceptionOccurred: #type proc "c" (jni: ^^JNINativeInterface), + ExceptionDescribe: #type proc "c" (jni: ^^JNINativeInterface), + ExceptionClear: #type proc "c" (jni: ^^JNINativeInterface), + FatalError: #type proc "c" (jni: ^^JNINativeInterface, msg: cstring), + + PushLocalFrame: #type proc "c" (jni: ^^JNINativeInterface, capacity: jint) -> jint, + PopLocalFrame: #type proc "c" (jni: ^^JNINativeInterface, result: jobject) -> jobject, + + NewGlobalRef: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject) -> jobject, + DeleteGlobalRef: #type proc "c" (jni: ^^JNINativeInterface, globalRef: jobject), + DeleteLocalRef: #type proc "c" (jni: ^^JNINativeInterface, localRef: jobject), + IsSameObject: #type proc "c" (jni: ^^JNINativeInterface, ref1: jobject, ref2: jobject) -> jboolean, + + NewLocalRef: #type proc "c" (jni: ^^JNINativeInterface, ref: jobject) -> jobject, + EnsureLocalCapacity: #type proc "c" (jni: ^^JNINativeInterface, capacity: jint) -> jint, + + AllocObject: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass) -> jobject, + NewObject: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jobject, + NewObjectV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jobject, + NewObjectA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jobject, + + GetObjectClass: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject) -> jclass, + IsInstanceOf: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass) -> jboolean, + GetMethodID: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, name: cstring, sig: cstring) -> jmethodID, + + // TODO: should va_list args be pointers? + CallObjectMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #c_vararg args: ..any) -> jobject, + CallObjectMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, args: ^c.va_list) -> jobject, + CallObjectMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #by_ptr args: jvalue) -> jobject, + CallBooleanMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #c_vararg args: ..any) -> jboolean, + CallBooleanMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, args: ^c.va_list) -> jboolean, + CallBooleanMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #by_ptr args: jvalue) -> jboolean, + CallByteMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #c_vararg args: ..any) -> jbyte, + CallByteMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, args: ^c.va_list) -> jbyte, + CallByteMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #by_ptr args: jvalue) -> jbyte, + CallCharMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #c_vararg args: ..any) -> jchar, + CallCharMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, args: ^c.va_list) -> jchar, + CallCharMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #by_ptr args: jvalue) -> jchar, + CallShortMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #c_vararg args: ..any) -> jshort, + CallShortMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, args: ^c.va_list) -> jshort, + CallShortMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #by_ptr args: jvalue) -> jshort, + CallIntMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #c_vararg args: ..any) -> jint, + CallIntMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, args: ^c.va_list) -> jint, + CallIntMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #by_ptr args: jvalue) -> jint, + CallLongMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #c_vararg args: ..any) -> jlong, + CallLongMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, args: ^c.va_list) -> jlong, + CallLongMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #by_ptr args: jvalue) -> jlong, + CallFloatMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #c_vararg args: ..any) -> jfloat, + CallFloatMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, args: ^c.va_list) -> jfloat, + CallFloatMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #by_ptr args: jvalue) -> jfloat, + CallDoubleMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #c_vararg args: ..any) -> jdouble, + CallDoubleMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, args: ^c.va_list) -> jdouble, + CallDoubleMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #by_ptr args: jvalue) -> jdouble, + CallVoidMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #c_vararg args: ..any), + CallVoidMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, args: ^c.va_list), + CallVoidMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, methodID: jmethodID, #by_ptr args: jvalue), + + CallNonvirtualObjectMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jobject, + CallNonvirtualObjectMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jobject, + CallNonvirtualObjectMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jobject, + CallNonvirtualBooleanMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jboolean, + CallNonvirtualBooleanMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jboolean, + CallNonvirtualBooleanMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jboolean, + CallNonvirtualByteMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jbyte, + CallNonvirtualByteMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jbyte, + CallNonvirtualByteMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jbyte, + CallNonvirtualCharMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jchar, + CallNonvirtualCharMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jchar, + CallNonvirtualCharMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jchar, + CallNonvirtualShortMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jshort, + CallNonvirtualShortMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jshort, + CallNonvirtualShortMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jshort, + CallNonvirtualIntMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jint, + CallNonvirtualIntMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jint, + CallNonvirtualIntMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jint, + CallNonvirtualLongMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jlong, + CallNonvirtualLongMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jlong, + CallNonvirtualLongMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jlong, + CallNonvirtualFloatMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jfloat, + CallNonvirtualFloatMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jfloat, + CallNonvirtualFloatMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jfloat, + CallNonvirtualDoubleMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jdouble, + CallNonvirtualDoubleMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jdouble, + CallNonvirtualDoubleMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jdouble, + CallNonvirtualVoidMethod: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any), + CallNonvirtualVoidMethodV: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, args: ^c.va_list), + CallNonvirtualVoidMethodA: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue), + + GetFieldID: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, name: cstring, sig: cstring) -> jfieldID, + + GetObjectField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID) -> jobject, + GetBooleanField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID) -> jboolean, + GetByteField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID) -> jbyte, + GetCharField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID) -> jchar, + GetShortField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID) -> jshort, + GetIntField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID) -> jint, + GetLongField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID) -> jlong, + GetFloatField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID) -> jfloat, + GetDoubleField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID) -> jdouble, + + SetObjectField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID, value: jobject), + SetBooleanField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID, value: jboolean), + SetByteField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID, value: jbyte), + SetCharField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID, value: jchar), + SetShortField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID, value: jshort), + SetIntField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID, value: jint), + SetLongField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID, value: jlong), + SetFloatField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID, value: jfloat), + SetDoubleField: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject, fieldID: jfieldID, value: jdouble), + + GetStaticMethodID: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, name: cstring, sig: cstring) -> jmethodID, + + CallStaticObjectMethod: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jobject, + CallStaticObjectMethodV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jobject, + CallStaticObjectMethodA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jobject, + CallStaticBooleanMethod: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jboolean, + CallStaticBooleanMethodV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jboolean, + CallStaticBooleanMethodA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jboolean, + CallStaticByteMethod: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jbyte, + CallStaticByteMethodV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jbyte, + CallStaticByteMethodA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jbyte, + CallStaticCharMethod: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jchar, + CallStaticCharMethodV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jchar, + CallStaticCharMethodA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jchar, + CallStaticShortMethod: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jshort, + CallStaticShortMethodV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jshort, + CallStaticShortMethodA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jshort, + CallStaticIntMethod: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jint, + CallStaticIntMethodV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jint, + CallStaticIntMethodA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jint, + CallStaticLongMethod: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jlong, + CallStaticLongMethodV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jlong, + CallStaticLongMethodA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jlong, + CallStaticFloatMethod: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jfloat, + CallStaticFloatMethodV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jfloat, + CallStaticFloatMethodA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jfloat, + CallStaticDoubleMethod: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any) -> jdouble, + CallStaticDoubleMethodV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list) -> jdouble, + CallStaticDoubleMethodA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue) -> jdouble, + CallStaticVoidMethod: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #c_vararg args: ..any), + CallStaticVoidMethodV: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, args: ^c.va_list), + CallStaticVoidMethodA: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methodID: jmethodID, #by_ptr args: jvalue), + + GetStaticFieldID: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, name: cstring, sig: cstring) -> jfieldID, + + GetStaticObjectField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID) -> jobject, + GetStaticBooleanField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID) -> jboolean, + GetStaticByteField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID) -> jbyte, + GetStaticCharField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID) -> jchar, + GetStaticShortField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID) -> jshort, + GetStaticIntField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID) -> jint, + GetStaticLongField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID) -> jlong, + GetStaticFloatField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID) -> jfloat, + GetStaticDoubleField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID) -> jdouble, + + SetStaticObjectField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID, value: jobject), + SetStaticBooleanField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID, value: jboolean), + SetStaticByteField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID, value: jbyte), + SetStaticCharField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID, value: jchar), + SetStaticShortField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID, value: jshort), + SetStaticIntField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID, value: jint), + SetStaticLongField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID, value: jlong), + SetStaticFloatField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID, value: jfloat), + SetStaticDoubleField: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, fieldID: jfieldID, value: jdouble), + + NewString: #type proc "c" (jni: ^^JNINativeInterface, unicodeChars: [^]jchar, len: jsize) -> jstring, + GetStringLength: #type proc "c" (jni: ^^JNINativeInterface, str: jstring) -> jsize, + GetStringChars: #type proc "c" (jni: ^^JNINativeInterface, str: jstring, isCopy: ^jboolean) -> [^]jchar, + ReleaseStringChars: #type proc "c" (jni: ^^JNINativeInterface, str: jstring, chars: [^]jchar), + NewStringUTF: #type proc "c" (jni: ^^JNINativeInterface, bytes: [^]c.char) -> jstring, + GetStringUTFLength: #type proc "c" (jni: ^^JNINativeInterface, str: jstring) -> jsize, + /* JNI spec says this returns const jbyte*, but that's inconsistent */ + GetStringUTFChars: #type proc "c" (jni: ^^JNINativeInterface, str: jstring, isCopy: ^jboolean) -> cstring, + ReleaseStringUTFChars: #type proc "c" (jni: ^^JNINativeInterface, str: jstring, utf: cstring), + GetArrayLength: #type proc "c" (jni: ^^JNINativeInterface, array: jarray) -> jsize, + NewObjectArray: #type proc "c" (jni: ^^JNINativeInterface, length: jsize, elementClass: jclass, initialElement: jobject) -> jobjectArray, + GetObjectArrayElement: #type proc "c" (jni: ^^JNINativeInterface, array: jobjectArray, index: jsize) -> jobject, + SetObjectArrayElement: #type proc "c" (jni: ^^JNINativeInterface, array: jobjectArray, index: jsize, value: jobject), + + NewBooleanArray: #type proc "c" (jni: ^^JNINativeInterface, length: jsize) -> jbooleanArray, + NewByteArray: #type proc "c" (jni: ^^JNINativeInterface, length: jsize) -> jbyteArray, + NewCharArray: #type proc "c" (jni: ^^JNINativeInterface, length: jsize) -> jcharArray, + NewShortArray: #type proc "c" (jni: ^^JNINativeInterface, length: jsize) -> jshortArray, + NewIntArray: #type proc "c" (jni: ^^JNINativeInterface, length: jsize) -> jintArray, + NewLongArray: #type proc "c" (jni: ^^JNINativeInterface, length: jsize) -> jlongArray, + NewFloatArray: #type proc "c" (jni: ^^JNINativeInterface, length: jsize) -> jfloatArray, + NewDoubleArray: #type proc "c" (jni: ^^JNINativeInterface, length: jsize) -> jdoubleArray, + + GetBooleanArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jbooleanArray, isCopy: ^jboolean) -> [^]jboolean, + GetByteArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jbyteArray, isCopy: ^jboolean) -> [^]jbyte, + GetCharArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jcharArray, isCopy: ^jboolean) -> [^]jchar, + GetShortArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jshortArray, isCopy: ^jboolean) -> [^]jshort, + GetIntArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jintArray, isCopy: ^jboolean) -> [^]jint, + GetLongArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jlongArray, isCopy: ^jboolean) -> [^]jlong, + GetFloatArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jfloatArray, isCopy: ^jboolean) -> [^]jfloat, + GetDoubleArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jdoubleArray, isCopy: ^jboolean) -> [^]jdouble, + + ReleaseBooleanArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jbooleanArray, elems: [^]jboolean, mode: jint), + ReleaseByteArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jbyteArray, elems: [^]jbyte, mode: jint), + ReleaseCharArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jcharArray, elems: [^]jchar, mode: jint), + ReleaseShortArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jshortArray, elems: [^]jshort, mode: jint), + ReleaseIntArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jintArray, elems: [^]jint, mode: jint), + ReleaseLongArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jlongArray, elems: [^]jlong, mode: jint), + ReleaseFloatArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jfloatArray, elems: [^]jfloat, mode: jint), + ReleaseDoubleArrayElements: #type proc "c" (jni: ^^JNINativeInterface, array: jdoubleArray, elems: [^]jdouble, mode: jint), + + GetBooleanArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jbooleanArray, start: jsize, len: jsize, buf: [^]jboolean), + GetByteArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jbyteArray, start: jsize, len: jsize, buf: [^]jbyte), + GetCharArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jcharArray, start: jsize, len: jsize, buf: [^]jchar), + GetShortArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jshortArray, start: jsize, len: jsize, buf: [^]jshort), + GetIntArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jintArray, start: jsize, len: jsize, buf: [^]jint), + GetLongArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jlongArray, start: jsize, len: jsize, buf: [^]jlong), + GetFloatArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jfloatArray, start: jsize, len: jsize, buf: [^]jfloat), + GetDoubleArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jdoubleArray, start: jsize, len: jsize, buf: [^]jdouble), + + /* spec shows these without const, some jni.h do, some don't */ + SetBooleanArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jbooleanArray, start: jsize, len: jsize, buf: [^]jboolean), + SetByteArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jbyteArray, start: jsize, len: jsize, buf: [^]jbyte), + SetCharArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jcharArray, start: jsize, len: jsize, buf: [^]jchar), + SetShortArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jshortArray, start: jsize, len: jsize, buf: [^]jshort), + SetIntArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jintArray, start: jsize, len: jsize, buf: [^]jint), + SetLongArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jlongArray, start: jsize, len: jsize, buf: [^]jlong), + SetFloatArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jfloatArray, start: jsize, len: jsize, buf: [^]jfloat), + SetDoubleArrayRegion: #type proc "c" (jni: ^^JNINativeInterface, array: jdoubleArray, start: jsize, len: jsize, buf: [^]jdouble), + + RegisterNatives: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass, methods: [^]JNINativeMethod, nMethods: jint) -> jint, + UnregisterNatives: #type proc "c" (jni: ^^JNINativeInterface, clazz: jclass) -> jint, + MonitorEnter: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject) -> jint, + MonitorExit: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject) -> jint, + GetJavaVM: #type proc "c" (jni: ^^JNINativeInterface, vm: ^^^JNIInvokeInterface) -> jint, + + GetStringRegion: #type proc "c" (jni: ^^JNINativeInterface, str: jstring, start: jsize, len: jsize, buf: [^]jchar), + GetStringUTFRegion: #type proc "c" (jni: ^^JNINativeInterface, str: jstring, start: jsize, len: jsize, buf: [^]c.char), + + GetPrimitiveArrayCritical: #type proc "c" (jni: ^^JNINativeInterface, array: jarray, isCopy: ^jboolean) -> rawptr, + ReleasePrimitiveArrayCritical: #type proc "c" (jni: ^^JNINativeInterface, array: jarray, carray: rawptr, mode: jint), + + GetStringCritical: #type proc "c" (jni: ^^JNINativeInterface, str: jstring, isCopy: ^jboolean) -> [^]jchar, + ReleaseStringCritical: #type proc "c" (jni: ^^JNINativeInterface, str: jstring, carray: [^]jchar), + + NewWeakGlobalRef: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject) -> jweak, + DeleteWeakGlobalRef: #type proc "c" (jni: ^^JNINativeInterface, obj: jweak), + + ExceptionCheck: #type proc "c" (jni: ^^JNINativeInterface), + + NewDirectByteBuffer: #type proc "c" (jni: ^^JNINativeInterface, address: rawptr, capacity: jlong) -> jobject, + GetDirectBufferAddress: #type proc "c" (jni: ^^JNINativeInterface, buf: jobject) -> rawptr, + GetDirectBufferCapacity: #type proc "c" (jni: ^^JNINativeInterface, buf: jobject) -> jlong, + + /* added in JNI 1.6 */ + GetObjectRefType: #type proc "c" (jni: ^^JNINativeInterface, obj: jobject) -> jobjectRefType, +} + + +/* + * JNI invocation interface. + */ +JNIInvokeInterface :: struct { + reserved0: rawptr, + reserved1: rawptr, + reserved2: rawptr, + + DestroyJavaVM: #type proc "c" (vm: ^^JNIInvokeInterface) -> jint, + AttachCurrentThread: #type proc "c" (vm: ^^JNIInvokeInterface, p_env: ^^JNIEnv, thr_args: rawptr) -> jint, + DetachCurrentThread: #type proc "c" (vm: ^^JNIInvokeInterface) -> jint, + GetEnv: #type proc "c" (vm: ^^JNIInvokeInterface, env: ^rawptr, version: jint) -> jint, + AttachCurrentThreadAsDaemon: #type proc "c" (vm: ^^JNIInvokeInterface, p_env: ^^JNIEnv, thr_args: ^rawptr) -> jint, +} diff --git a/log.odin b/log.odin new file mode 100644 index 0000000..26e499d --- /dev/null +++ b/log.odin @@ -0,0 +1,340 @@ +//+build android +package android + +import "core:c" + +foreign import log "system:log" + +/** + * \file + * + * Support routines to send messages to the Android log buffer, + * which can later be accessed through the `logcat` utility. + * + * Each log message must have + * - a priority + * - a log tag + * - some text + * + * The tag normally corresponds to the component that emits the log message, + * and should be reasonably small. + * + * Log message text may be truncated to less than an implementation-specific + * limit (1023 bytes). + * + * Note that a newline character ("\n") will be appended automatically to your + * log message, if not already there. It is not possible to send several + * messages and have them appear on a single line in logcat. + * + * Please use logging in moderation: + * + * - Sending log messages eats CPU and slow down your application and the + * system. + * + * - The circular log buffer is pretty small, so sending many messages + * will hide other important log messages. + * + * - In release builds, only send log messages to account for exceptional + * conditions. + */ + + +/** + * Android log priority values, in increasing order of priority. + */ +LogPriority :: enum i32 { + /** For internal use only. */ + UNKNOWN = 0, + /** The default priority, for internal use only. */ + DEFAULT, /* only for SetMinPriority() */ + /** Verbose logging. Should typically be disabled for a release apk. */ + VERBOSE, + /** Debug logging. Should typically be disabled for a release apk. */ + DEBUG, + /** Informational logging. Should typically be disabled for a release apk. */ + INFO, + /** Warning logging. For use with recoverable failures. */ + WARN, + /** Error logging. For use with unrecoverable failures. */ + ERROR, + /** Fatal logging. For use when aborting. */ + FATAL, + /** For internal use only. */ + SILENT, /* only for SetMinPriority(); must be last */ +} + +/** + * Identifies a specific log buffer for __android_log_buf_write() + * and __android_log_buf_print(). + */ +LogId :: enum i32 { + MIN = 0, + + /** The main log buffer. This is the only log buffer available to apps. */ + MAIN = 0, + /** The radio log buffer. */ + RADIO = 1, + /** The event log buffer. */ + EVENTS = 2, + /** The system log buffer. */ + SYSTEM = 3, + /** The crash log buffer. */ + CRASH = 4, + /** The statistics log buffer. */ + STATS = 5, + /** The security log buffer. */ + SECURITY = 6, + /** The kernel log buffer. */ + KERNEL = 7, + + MAX, + + /** Let the logging function choose the best log target. */ + DEFAULT = 0x7FFFFFFF +} + +/** + * Logger data struct used for writing log messages to liblog via __android_log_write_logger_data() + * and sending log messages to user defined loggers specified in __android_log_set_logger(). + */ +LogMessage :: struct { + /** Must be set to sizeof(LogMessage) and is used for versioning. */ + struct_size: uint, + + /** {@link log_id_t} values. */ + buffer_id: i32, + + /** {@link android_LogPriority} values. */ + priority: i32, + + /** The tag for the log message. */ + tag: cstring, + + /** Optional file name, may be set to nullptr. */ + file: cstring, + + /** Optional line number, ignore if file is nullptr. */ + line: u32, + + /** The log message itself. */ + message: cstring, +} + +/** + * Prototype for the 'logger' function that is called for every log message. + */ +__android_logger_function :: #type proc "c" (log_message: ^LogMessage) +/** + * Prototype for the 'abort' function that is called when liblog will abort due to + * __android_log_assert() failures. + */ +__android_aborter_function :: #type proc "c" (abort_message: cstring) + +foreign log { + /** + * Writes the constant string `text` to the log, with priority `prio` and tag + * `tag`. + */ + __android_log_write :: proc(prio: LogPriority, tag: cstring, text: cstring) -> i32 --- + + /** + * Writes a formatted string to the log, with priority `prio` and tag `tag`. + * The details of formatting are the same as for + * [printf(3)](http://man7.org/linux/man-pages/man3/printf.3.html). + */ + __android_log_print :: proc(prio: LogPriority, tag: cstring, fmt: cstring, #c_vararg args: ..any) -> i32 --- + + /** + * Equivalent to `__android_log_print`, but taking a `va_list`. + * (If `__android_log_print` is like `printf`, this is like `vprintf`.) + */ + __android_log_vprint :: proc(prio: LogPriority, tag: cstring, fmt: cstring, ap: c.va_list) -> i32 --- + + /** + * Writes an assertion failure to the log (as `ANDROID_LOG_FATAL`) and to + * stderr, before calling + * [abort(3)](http://man7.org/linux/man-pages/man3/abort.3.html). + * + * If `fmt` is non-null, `cond` is unused. If `fmt` is null, the string + * `Assertion failed: %s` is used with `cond` as the string argument. + * If both `fmt` and `cond` are null, a default string is provided. + * + * Most callers should use + * [assert(3)](http://man7.org/linux/man-pages/man3/assert.3.html) from + * `<assert.h>` instead, or the `__assert` and `__assert2` functions + * provided by bionic if more control is needed. They support automatically + * including the source filename and line number more conveniently than this + * function. + */ + __android_log_assert :: proc(cond: cstring, tag: cstring, fmt: cstring, #c_vararg args: ..any) --- + + /** + * Writes the constant string `text` to the log buffer `id`, + * with priority `prio` and tag `tag`. + * + * Apps should use __android_log_write() instead. + */ + __android_log_buf_write :: proc(bufID: LogId, prio: LogPriority, tag: cstring, text: cstring) -> i32 --- + + /** + * Writes a formatted string to log buffer `id`, + * with priority `prio` and tag `tag`. + * The details of formatting are the same as for + * [printf(3)](http://man7.org/linux/man-pages/man3/printf.3.html). + * + * Apps should use __android_log_print() instead. + */ + __android_log_buf_print :: proc(bufID: LogId, prio: LogPriority, tag: cstring, fmt: cstring, #c_vararg args: ..any) -> i32 --- + + /** + * Writes the log message specified by log_message. log_message includes additional file name and + * line number information that a logger may use. log_message is versioned for backwards + * compatibility. + * This assumes that loggability has already been checked through __android_log_is_loggable(). + * Higher level logging libraries, such as libbase, first check loggability, then format their + * buffers, then pass the message to liblog via this function, and therefore we do not want to + * duplicate the loggability check here. + * + * @param log_message the log message itself, see __android_log_message. + * + * Available since API level 30. + */ + __android_log_write_log_message :: proc(log_message: ^LogMessage) --- + + /** + * Sets a user defined logger function. All log messages sent to liblog will be set to the + * function pointer specified by logger for processing. It is not expected that log messages are + * already terminated with a new line. This function should add new lines if required for line + * separation. + * + * @param logger the new function that will handle log messages. + * + * Available since API level 30. + */ + __android_log_set_logger :: proc(logger: __android_logger_function) --- + + /** + * Writes the log message to logd. This is an __android_logger_function and can be provided to + * __android_log_set_logger(). It is the default logger when running liblog on a device. + * + * @param log_message the log message to write, see __android_log_message. + * + * Available since API level 30. + */ + __android_log_logd_logger :: proc(log_message: ^LogMessage) --- + + /** + * Writes the log message to stderr. This is an __android_logger_function and can be provided to + * __android_log_set_logger(). It is the default logger when running liblog on host. + * + * @param log_message the log message to write, see __android_log_message. + * + * Available since API level 30. + */ + __android_log_stderr_logger :: proc(log_message: ^LogMessage) --- + + /** + * Sets a user defined aborter function that is called for __android_log_assert() failures. This + * user defined aborter function is highly recommended to abort and be noreturn, but is not strictly + * required to. + * + * @param aborter the new aborter function, see __android_aborter_function. + * + * Available since API level 30. + */ + __android_log_set_aborter :: proc(aborter: __android_aborter_function) --- + + /** + * Calls the stored aborter function. This allows for other logging libraries to use the same + * aborter function by calling this function in liblog. + * + * @param abort_message an additional message supplied when aborting, for example this is used to + * call android_set_abort_message() in __android_log_default_aborter(). + * + * Available since API level 30. + */ + __android_log_call_aborter :: proc(abort_message: cstring) --- + + /** + * Sets android_set_abort_message() on device then aborts(). This is the default aborter. + * + * @param abort_message an additional message supplied when aborting. This functions calls + * android_set_abort_message() with its contents. + * + * Available since API level 30. + */ + __android_log_default_aborter :: proc(abort_message: cstring) --- + + /** + * Use the per-tag properties "log.tag." along with the minimum priority from + * __android_log_set_minimum_priority() to determine if a log message with a given prio and tag will + * be printed. A non-zero result indicates yes, zero indicates false. + * + * If both a priority for a tag and a minimum priority are set by + * __android_log_set_minimum_priority(), then the lowest of the two values are to determine the + * minimum priority needed to log. If only one is set, then that value is used to determine the + * minimum priority needed. If none are set, then default_priority is used. + * + * @param prio the priority to test, takes android_LogPriority values. + * @param tag the tag to test. + * @param default_prio the default priority to use if no properties or minimum priority are set. + * @return an integer where 1 indicates that the message is loggable and 0 indicates that it is not. + * + * Available since API level 30. + */ + __android_log_is_loggable :: proc(prio: LogPriority, tag: cstring, default_prio: LogPriority) -> i32 --- + + /** + * Use the per-tag properties "log.tag." along with the minimum priority from + * __android_log_set_minimum_priority() to determine if a log message with a given prio and tag will + * be printed. A non-zero result indicates yes, zero indicates false. + * + * If both a priority for a tag and a minimum priority are set by + * __android_log_set_minimum_priority(), then the lowest of the two values are to determine the + * minimum priority needed to log. If only one is set, then that value is used to determine the + * minimum priority needed. If none are set, then default_priority is used. + * + * @param prio the priority to test, takes android_LogPriority values. + * @param tag the tag to test. + * @param len the length of the tag. + * @param default_prio the default priority to use if no properties or minimum priority are set. + * @return an integer where 1 indicates that the message is loggable and 0 indicates that it is not. + * + * Available since API level 30. + */ + __android_log_is_loggable_len :: proc(prio: LogPriority, tag: cstring, len: uint, default_prio: LogPriority) -> i32 --- + + /** + * Sets the minimum priority that will be logged for this process. + * + * @param priority the new minimum priority to set, takes android_LogPriority values. + * @return the previous set minimum priority as android_LogPriority values, or + * ANDROID_LOG_DEFAULT if none was set. + * + * Available since API level 30. + */ + __android_log_set_minimum_priority :: proc(priority: LogPriority) -> LogPriority --- + + /** + * Gets the minimum priority that will be logged for this process. If none has been set by a + * previous __android_log_set_minimum_priority() call, this returns ANDROID_LOG_DEFAULT. + * + * @return the current minimum priority as android_LogPriority values, or + * ANDROID_LOG_DEFAULT if none is set. + * + * Available since API level 30. + */ + __android_log_get_minimum_priority :: proc() -> LogPriority --- + + /** + * Sets the default tag if no tag is provided when writing a log message. Defaults to + * getprogname(). This truncates tag to the maximum log message size, though appropriate tags + * should be much smaller. + * + * @param tag the new log tag. + * + * Available since API level 30. + */ + __android_log_set_default_tag :: proc(tag: cstring) --- +} + diff --git a/looper.odin b/looper.odin new file mode 100644 index 0000000..4c1799b --- /dev/null +++ b/looper.odin @@ -0,0 +1,30 @@ +//+build android +package android + +import "core:c" + +foreign import android "system:android" + +/** + * ALooper + * + * A looper is the state tracking an event loop for a thread. + * Loopers do not define event structures or other such things; rather + * they are a lower-level facility to attach one or more discrete objects + * listening for an event. An "event" here is simply data available on + * a file descriptor: each attached object has an associated file descriptor, + * and waiting for "events" means (internally) polling on all of these file + * descriptors until one or more of them have data available. + * + * A thread can have only one ALooper associated with it. + */ +ALooper :: struct{} + +foreign android { + /** + * Like ALooper_pollOnce(), but performs all pending callbacks until all + * data has been consumed or a file descriptor is available with no callback. + * This function will never return ALOOPER_POLL_CALLBACK. + */ + ALooper_pollAll :: proc(timeoutMillis: c.int, outFd: ^c.int, outEvents: ^c.int, outData: ^rawptr) -> c.int --- +} diff --git a/native_acitivty.odin b/native_acitivty.odin new file mode 100644 index 0000000..a5e00f5 --- /dev/null +++ b/native_acitivty.odin @@ -0,0 +1,196 @@ +//+build android +package android + +import "core:c" + +/** + * This structure defines the native side of an android.app.NativeActivity. + * It is created by the framework, and handed to the application's native + * code as it is being launched. + */ +ANativeActivity :: struct { + /** + * Pointer to the callback function table of the native application. + * You can set the functions here to your own callbacks. The callbacks + * pointer itself here should not be changed, it is allocated and managed + * for you by the framework. + */ + callbacks: ^ANativeActivityCallbacks, + + /** + * The global handle on the process's Java VM. + */ + vm: ^JavaVM, + + /** + * JNI context for the main thread of the app. Note that this field + * can ONLY be used from the main thread of the process, that is, the + * thread that calls into the ANativeActivityCallbacks. + */ + env: ^JNIEnv, + + /** + * The NativeActivity object handle. + * + * IMPORTANT NOTE: This member is mis-named. It should really be named + * 'activity' instead of 'clazz', since it's a reference to the + * NativeActivity instance created by the system for you. + * + * We unfortunately cannot change this without breaking NDK + * source-compatibility. + */ + clazz: jobject, + + /** + * Path to this application's internal data directory. + */ + internalDataPath: cstring, + + /** + * Path to this application's external (removable/mountable) data directory. + */ + externalDataPath: cstring, + + /** + * The platform's SDK version code. + */ + sdkVersion: c.int32_t, + + /** + * This is the native instance of the application. It is not used by + * the framework, but can be set by the application to its own instance + * state. + */ + instance: rawptr, + + /** + * Pointer to the Asset Manager instance for the application. The application + * uses this to access binary assets bundled inside its own .apk file. + */ + assetManager: ^AAssetManager, + + /** + * Available starting with Honeycomb: path to the directory containing + * the application's OBB files (if any). If the app doesn't have any + * OBB files, this directory may not exist. + */ + obbPath: cstring, +} + +/** + * These are the callbacks the framework makes into a native application. + * All of these callbacks happen on the main thread of the application. + * By default, all callbacks are NULL; set to a pointer to your own function + * to have it called. + */ +ANativeActivityCallbacks :: struct { + /** + * NativeActivity has started. See Java documentation for Activity.onStart() + * for more information. + */ + onStart: #type proc "c" (activity: ^ANativeActivity), + + /** + * NativeActivity has resumed. See Java documentation for Activity.onResume() + * for more information. + */ + onResume: #type proc "c" (activity: ^ANativeActivity), + + /** + * Framework is asking NativeActivity to save its current instance state. + * See Java documentation for Activity.onSaveInstanceState() for more + * information. The returned pointer needs to be created with malloc(), + * the framework will call free() on it for you. You also must fill in + * outSize with the number of bytes in the allocation. Note that the + * saved state will be persisted, so it can not contain any active + * entities (pointers to memory, file descriptors, etc). + */ + onSaveInstanceState: #type proc "c" (activity: ^ANativeActivity, outSize: ^c.size_t) -> rawptr, + + /** + * NativeActivity has paused. See Java documentation for Activity.onPause() + * for more information. + */ + onPause: #type proc "c" (activity: ^ANativeActivity), + + /** + * NativeActivity has stopped. See Java documentation for Activity.onStop() + * for more information. + */ + onStop: #type proc "c" (activity: ^ANativeActivity), + + /** + * NativeActivity is being destroyed. See Java documentation for Activity.onDestroy() + * for more information. + */ + onDestroy: #type proc "c" (activity: ^ANativeActivity), + + /** + * Focus has changed in this NativeActivity's window. This is often used, + * for example, to pause a game when it loses input focus. + */ + onWindowFocusChanged: #type proc "c" (activity: ^ANativeActivity, hasFocus: c.int), + + /** + * The drawing window for this native activity has been created. You + * can use the given native window object to start drawing. + */ + onNativeWindowCreated: #type proc "c" (activity: ^ANativeActivity, window: ^ANativeWindow), + + /** + * The drawing window for this native activity has been resized. You should + * retrieve the new size from the window and ensure that your rendering in + * it now matches. + */ + onNativeWindowResized: #type proc "c" (activity: ^ANativeActivity, window: ^ANativeWindow), + + /** + * The drawing window for this native activity needs to be redrawn. To avoid + * transient artifacts during screen changes (such resizing after rotation), + * applications should not return from this function until they have finished + * drawing their window in its current state. + */ + onNativeWindowRedrawNeeded: #type proc "c" (activity: ^ANativeActivity, window: ^ANativeWindow), + + /** + * The drawing window for this native activity is going to be destroyed. + * You MUST ensure that you do not touch the window object after returning + * from this function: in the common case of drawing to the window from + * another thread, that means the implementation of this callback must + * properly synchronize with the other thread to stop its drawing before + * returning from here. + */ + onNativeWindowDestroyed: #type proc "c" (activity: ^ANativeActivity, window: ^ANativeWindow), + + /** + * The input queue for this native activity's window has been created. + * You can use the given input queue to start retrieving input events. + */ + onInputQueueCreated: #type proc "c" (activity: ^ANativeActivity, queue: ^AInputQueue), + + /** + * The input queue for this native activity's window is being destroyed. + * You should no longer try to reference this object upon returning from this + * function. + */ + onInputQueueDestroyed: #type proc "c" (activity: ^ANativeActivity, queue: ^AInputQueue), + + /** + * The rectangle in the window in which content should be placed has changed. + */ + onContentRectChanged: #type proc "c" (activity: ^ANativeActivity, #by_ptr rect: ARect), + + /** + * The current device AConfiguration has changed. The new configuration can + * be retrieved from assetManager. + */ + onConfigurationChanged: #type proc "c" (activity: ^ANativeActivity), + + /** + * The system is running low on memory. Use this callback to release + * resources you do not need, to help the system avoid killing more + * important processes. + */ + onLowMemory: #type proc "c" (activity: ^ANativeActivity), +} + diff --git a/native_window.odin b/native_window.odin new file mode 100644 index 0000000..68cf3ee --- /dev/null +++ b/native_window.odin @@ -0,0 +1,47 @@ +//+build android +package android + +/** + * Opaque type that provides access to a native window. + * + * A pointer can be obtained using {@link ANativeWindow_fromSurface()}. + */ +ANativeWindow :: struct{} + +foreign import android "system:android" + +foreign android { + /** + * Change the format and size of the window buffers. + * + * The width and height control the number of pixels in the buffers, not the + * dimensions of the window on screen. If these are different than the + * window's physical size, then its buffer will be scaled to match that size + * when compositing it to the screen. The width and height must be either both zero + * or both non-zero. + * + * For all of these parameters, if 0 is supplied then the window's base + * value will come back in force. + * + * \param window pointer to an ANativeWindow object. + * \param width width of the buffers in pixels. + * \param height height of the buffers in pixels. + * \param format one of the AHardwareBuffer_Format constants. + * \return 0 for success, or a negative value on error. + */ + ANativeWindow_setBuffersGeometry :: proc(window: ^ANativeWindow, width: i32, height: i32, format: i32) -> i32 --- + + /** + * Return the current width in pixels of the window surface. + * + * \return negative value on error. + */ + ANativeWindow_getWidth :: proc(window: ^ANativeWindow) -> i32 --- + + /** + * Return the current height in pixels of the window surface. + * + * \return a negative value on error. + */ + ANativeWindow_getHeight :: proc(window: ^ANativeWindow) -> i32 --- +} diff --git a/rect.odin b/rect.odin new file mode 100644 index 0000000..072d987 --- /dev/null +++ b/rect.odin @@ -0,0 +1,26 @@ +//+build android +package android + +import "core:c" + +/** + * Rectangular window area. + * + * This is the NDK equivalent of the android.graphics.Rect class in Java. It is + * used with {@link ANativeActivityCallbacks::onContentRectChanged} event + * callback and the ANativeWindow_lock() function. + * + * In a valid ARect, left <= right and top <= bottom. ARect with left=0, top=10, + * right=1, bottom=11 contains only one pixel at x=0, y=10. + */ +ARect :: struct { + /// Minimum X coordinate of the rectangle. + left: c.int32_t, + /// Minimum Y coordinate of the rectangle. + top: c.int32_t, + /// Maximum X coordinate of the rectangle. + right: c.int32_t, + /// Maximum Y coordinate of the rectangle. + bottom: c.int32_t, +} + diff --git a/types.odin b/types.odin new file mode 100644 index 0000000..b5c6488 --- /dev/null +++ b/types.odin @@ -0,0 +1,4 @@ +package android + +off_t :: i64 +off64_t :: i64