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
|
2022-10-16 04:49:25 +00:00
|
|
|
#define LOVR_VERSION_MINOR 16
|
2019-05-20 09:47:33 +00:00
|
|
|
#define LOVR_VERSION_PATCH 0
|
2022-10-16 04:49:25 +00:00
|
|
|
#define LOVR_VERSION_ALIAS "Toad Rage"
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
// Error handling
|
2019-06-02 07:20:10 +00:00
|
|
|
typedef void errorFn(void*, 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
|
|
|
void lovrSetErrorCallback(errorFn* callback, void* userdata);
|
2022-03-25 19:10:45 +00:00
|
|
|
_Noreturn void lovrThrow(const char* format, ...);
|
2019-04-05 09:50:11 +00:00
|
|
|
#define lovrAssert(c, ...) if (!(c)) { lovrThrow(__VA_ARGS__); }
|
2022-04-27 07:05:14 +00:00
|
|
|
#define lovrUnreachable() lovrThrow("Unreachable")
|
2020-05-19 19:49:40 +00:00
|
|
|
|
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
|
|
|
|
typedef void logFn(void*, int, const char*, const char*, va_list);
|
|
|
|
enum { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR };
|
|
|
|
void lovrSetLogCallback(logFn* callback, void* userdata);
|
|
|
|
void lovrLog(int level, const char* tag, const char* format, ...);
|
|
|
|
|
|
|
|
// Hash function (FNV1a)
|
2020-12-25 19:29:22 +00:00
|
|
|
static inline uint64_t hash64(const void* data, size_t length) {
|
2020-05-19 19:49:40 +00:00
|
|
|
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 00:23:18 +00:00
|
|
|
|
|
|
|
// Refcounting
|
2021-02-11 23:37:55 +00:00
|
|
|
void lovrRetain(void* ref);
|
|
|
|
void lovrRelease(void* ref, void (*destructor)(void*));
|
2021-02-09 01:25:05 +00:00
|
|
|
|
|
|
|
// Dynamic Array
|
|
|
|
typedef void* arr_allocator(void* data, size_t size);
|
|
|
|
#define arr_t(T) struct { T* data; arr_allocator* alloc; size_t length, capacity; }
|
|
|
|
#define arr_init(a, allocator) (a)->data = NULL, (a)->length = 0, (a)->capacity = 0, (a)->alloc = allocator
|
2021-02-09 15:15:43 +00:00
|
|
|
#define arr_free(a) if ((a)->data) (a)->alloc((a)->data, 0)
|
2021-02-09 01:25:05 +00:00
|
|
|
#define arr_reserve(a, n) _arr_reserve((void**) &((a)->data), n, &(a)->capacity, sizeof(*(a)->data), (a)->alloc)
|
|
|
|
#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
|
|
|
|
|
2022-03-14 19:27:58 +00:00
|
|
|
void* arr_alloc(void* data, size_t size);
|
|
|
|
|
2021-02-09 01:25:05 +00:00
|
|
|
static inline void _arr_reserve(void** data, size_t n, size_t* capacity, size_t stride, arr_allocator* allocator) {
|
|
|
|
if (*capacity >= n) return;
|
|
|
|
if (*capacity == 0) *capacity = 1;
|
|
|
|
while (*capacity < n) *capacity *= 2;
|
|
|
|
*data = allocator(*data, *capacity * stride);
|
|
|
|
lovrAssert(*data, "Out of memory");
|
|
|
|
}
|
2021-02-09 03:55:51 +00:00
|
|
|
|
2022-03-30 19:31:39 +00:00
|
|
|
// Hashmap
|
|
|
|
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);
|
|
|
|
void map_remove(map_t* map, uint64_t hash);
|
|
|
|
|
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);
|