2018-09-26 17:39:17 +00:00
|
|
|
#include <stdarg.h>
|
2019-06-02 07:20:10 +00:00
|
|
|
#include <stddef.h>
|
2020-05-19 19:49:40 +00:00
|
|
|
#include <stdint.h>
|
2016-09-30 06:18:51 +00:00
|
|
|
|
2017-01-26 10:20:30 +00:00
|
|
|
#pragma once
|
2016-10-04 22:05:34 +00:00
|
|
|
|
2019-05-20 09:47:33 +00:00
|
|
|
#define LOVR_VERSION_MAJOR 0
|
2023-10-15 02:36:19 +00:00
|
|
|
#define LOVR_VERSION_MINOR 17
|
2024-03-12 18:56:30 +00:00
|
|
|
#define LOVR_VERSION_PATCH 1
|
2023-10-15 02:36:19 +00:00
|
|
|
#define LOVR_VERSION_ALIAS "Tritium Gourmet"
|
2019-05-20 09:47:33 +00:00
|
|
|
|
2021-03-08 05:03:35 +00:00
|
|
|
#ifdef _MSC_VER
|
2020-10-26 08:24:44 +00:00
|
|
|
#define LOVR_THREAD_LOCAL __declspec(thread)
|
2019-01-04 10:18:21 +00:00
|
|
|
#else
|
2019-05-20 11:05:39 +00:00
|
|
|
#define LOVR_THREAD_LOCAL __thread
|
2019-01-18 16:44:03 +00:00
|
|
|
#endif
|
2018-12-13 03:35:18 +00:00
|
|
|
|
2023-03-06 00:16:59 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
#define LOVR_NORETURN [[noreturn]]
|
|
|
|
#else
|
|
|
|
#define LOVR_NORETURN _Noreturn
|
|
|
|
#endif
|
|
|
|
|
2019-06-21 04:43:40 +00:00
|
|
|
#ifndef M_PI
|
|
|
|
#define M_PI 3.14159265358979
|
|
|
|
#endif
|
|
|
|
|
2018-09-27 18:45:43 +00:00
|
|
|
#define MAX(a, b) (a > b ? a : b)
|
|
|
|
#define MIN(a, b) (a < b ? a : b)
|
|
|
|
#define CLAMP(x, min, max) MAX(min, MIN(max, x))
|
2020-10-26 08:03:19 +00:00
|
|
|
#define ALIGN(p, n) (((uintptr_t) (p) + (n - 1)) & ~(n - 1))
|
2022-03-22 00:00:30 +00:00
|
|
|
#define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
|
2019-05-20 11:15:24 +00:00
|
|
|
#define CHECK_SIZEOF(T) int(*_o)[sizeof(T)]=1
|
2022-05-11 19:47:12 +00:00
|
|
|
#define BREAK() __asm("int $3")
|
2018-11-25 02:04:27 +00:00
|
|
|
|
2024-03-11 21:38:00 +00:00
|
|
|
// Allocation
|
|
|
|
void* lovrMalloc(size_t size);
|
|
|
|
void* lovrCalloc(size_t size);
|
|
|
|
void* lovrRealloc(void* data, size_t size);
|
|
|
|
void lovrFree(void* data);
|
|
|
|
|
2024-03-27 19:48:35 +00:00
|
|
|
// Refcounting (to be refcounted, a struct must have a uint32_t refcount as its first field)
|
|
|
|
void lovrRetain(void* ref);
|
|
|
|
void lovrRelease(void* ref, void (*destructor)(void*));
|
|
|
|
|
|
|
|
// Defer
|
|
|
|
uint32_t lovrDeferPush(void);
|
|
|
|
void lovrDeferPop(uint32_t base);
|
|
|
|
void lovrDefer(void (*fn)(void*), void* arg);
|
|
|
|
void lovrErrDefer(void (*fn)(void*), void* arg);
|
|
|
|
void lovrDeferRelease(void* ref, void (*destructor)(void*));
|
|
|
|
|
|
|
|
// Exceptions
|
|
|
|
void lovrTry(void (*fn)(void*), void* arg, void (*catch)(void*, const char*, va_list), void* catchArg);
|
2023-03-06 00:16:59 +00:00
|
|
|
LOVR_NORETURN void lovrThrow(const char* format, ...);
|
2024-03-03 11:37:14 +00:00
|
|
|
#define lovrAssert(c, ...) do { if (!(c)) { lovrThrow(__VA_ARGS__); } } while(0)
|
2022-04-27 07:05:14 +00:00
|
|
|
#define lovrUnreachable() lovrThrow("Unreachable")
|
2021-06-05 17:12:00 +00:00
|
|
|
#ifdef LOVR_UNCHECKED
|
|
|
|
#define lovrCheck(c, ...) ((void) 0)
|
|
|
|
#else
|
|
|
|
#define lovrCheck lovrAssert
|
|
|
|
#endif
|
|
|
|
|
lovr.log;
lovr.log is a new callback that is invoked whenever LÖVR wants to
send the project a message. For example, this could be a performance
warning from the graphics module, an error message from one of the
headset backends, or an API deprecation notice.
The callback's signature is (message, level, tag). The message is a
string containing the message to log, level is a string that is currently
one of "debug", "info", "warn", "error", and tag is an optional string
that is used to indicate the source of the message for grouping purposes.
The default implementation of the callback just prints the message,
but the callback can be overridden to do things like filter messages,
write them to a file, or even render them in VR. Projects can also
invoke the callback directly to log their own messages.
2020-07-06 22:20:55 +00:00
|
|
|
// Logging
|
2024-03-27 19:48:35 +00:00
|
|
|
typedef void fn_log(void*, int, const char*, const char*, va_list);
|
lovr.log;
lovr.log is a new callback that is invoked whenever LÖVR wants to
send the project a message. For example, this could be a performance
warning from the graphics module, an error message from one of the
headset backends, or an API deprecation notice.
The callback's signature is (message, level, tag). The message is a
string containing the message to log, level is a string that is currently
one of "debug", "info", "warn", "error", and tag is an optional string
that is used to indicate the source of the message for grouping purposes.
The default implementation of the callback just prints the message,
but the callback can be overridden to do things like filter messages,
write them to a file, or even render them in VR. Projects can also
invoke the callback directly to log their own messages.
2020-07-06 22:20:55 +00:00
|
|
|
enum { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR };
|
2024-03-27 19:48:35 +00:00
|
|
|
void lovrSetLogCallback(fn_log* callback, void* userdata);
|
lovr.log;
lovr.log is a new callback that is invoked whenever LÖVR wants to
send the project a message. For example, this could be a performance
warning from the graphics module, an error message from one of the
headset backends, or an API deprecation notice.
The callback's signature is (message, level, tag). The message is a
string containing the message to log, level is a string that is currently
one of "debug", "info", "warn", "error", and tag is an optional string
that is used to indicate the source of the message for grouping purposes.
The default implementation of the callback just prints the message,
but the callback can be overridden to do things like filter messages,
write them to a file, or even render them in VR. Projects can also
invoke the callback directly to log their own messages.
2020-07-06 22:20:55 +00:00
|
|
|
void lovrLog(int level, const char* tag, const char* format, ...);
|
|
|
|
|
2021-02-09 01:25:05 +00:00
|
|
|
// Dynamic Array
|
2024-03-27 19:48:35 +00:00
|
|
|
#define arr_t(T) struct { T* data; size_t length, capacity; }
|
|
|
|
#define arr_init(a) (a)->data = NULL, (a)->length = 0, (a)->capacity = 0
|
|
|
|
#define arr_free(a) if ((a)->data) lovrFree((a)->data)
|
|
|
|
#define arr_reserve(a, n) _arr_reserve((void**) &((a)->data), n, &(a)->capacity, sizeof(*(a)->data))
|
2021-02-09 01:25:05 +00:00
|
|
|
#define arr_expand(a, n) arr_reserve(a, (a)->length + n)
|
2022-12-03 09:20:02 +00:00
|
|
|
#define arr_push(a, x) arr_reserve(a, (a)->length + 1), (a)->data[(a)->length] = x, (a)->length++
|
2021-02-09 01:25:05 +00:00
|
|
|
#define arr_pop(a) (a)->data[--(a)->length]
|
|
|
|
#define arr_append(a, p, n) arr_reserve(a, (a)->length + n), memcpy((a)->data + (a)->length, p, n * sizeof(*(p))), (a)->length += n
|
2021-02-12 15:16:36 +00:00
|
|
|
#define arr_splice(a, i, n) memmove((a)->data + (i), (a)->data + ((i) + n), ((a)->length - (i) - (n)) * sizeof(*(a)->data)), (a)->length -= n
|
2021-02-09 01:25:05 +00:00
|
|
|
#define arr_clear(a) (a)->length = 0
|
|
|
|
|
2024-03-27 19:48:35 +00:00
|
|
|
static inline void _arr_reserve(void** data, size_t n, size_t* capacity, size_t stride) {
|
2021-02-09 01:25:05 +00:00
|
|
|
if (*capacity >= n) return;
|
|
|
|
if (*capacity == 0) *capacity = 1;
|
|
|
|
while (*capacity < n) *capacity *= 2;
|
2024-03-27 19:48:35 +00:00
|
|
|
*data = lovrRealloc(*data, *capacity * stride);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hash function (FNV1a)
|
|
|
|
static inline uint64_t hash64(const void* data, size_t length) {
|
|
|
|
const uint8_t* bytes = (const uint8_t*) data;
|
|
|
|
uint64_t hash = 0xcbf29ce484222325;
|
|
|
|
for (size_t i = 0; i < length; i++) {
|
|
|
|
hash = (hash ^ bytes[i]) * 0x100000001b3;
|
|
|
|
}
|
|
|
|
return hash;
|
2021-02-09 01:25:05 +00:00
|
|
|
}
|
2021-02-09 03:55:51 +00:00
|
|
|
|
2024-03-06 23:08:32 +00:00
|
|
|
// Hashmap (does not support removal)
|
2022-03-30 19:31:39 +00:00
|
|
|
typedef struct {
|
|
|
|
uint64_t* hashes;
|
|
|
|
uint64_t* values;
|
|
|
|
uint32_t size;
|
|
|
|
uint32_t used;
|
|
|
|
} map_t;
|
|
|
|
|
|
|
|
#define MAP_NIL UINT64_MAX
|
|
|
|
|
|
|
|
void map_init(map_t* map, uint32_t n);
|
|
|
|
void map_free(map_t* map);
|
|
|
|
uint64_t map_get(map_t* map, uint64_t hash);
|
|
|
|
void map_set(map_t* map, uint64_t hash, uint64_t value);
|
|
|
|
|
2021-02-09 03:55:51 +00:00
|
|
|
// UTF-8
|
|
|
|
size_t utf8_decode(const char *s, const char *e, unsigned *pch);
|
|
|
|
void utf8_encode(uint32_t codepoint, char str[4]);
|
2022-04-27 07:19:44 +00:00
|
|
|
|
|
|
|
// f16
|
|
|
|
typedef float float32;
|
|
|
|
typedef uint16_t float16;
|
|
|
|
void float16Init(void);
|
|
|
|
float16 float32to16(float32 f);
|
|
|
|
float32 float16to32(float16 f);
|