mirror of https://github.com/bjornbytes/lovr.git
Refcounted modules;
This allows them to be initialized/destroyed from multiple threads in any order. Previously, the first thread to require a module had to be the last thread to use the module, otherwise it would be destroyed too early. There are still a few issues. If the main thread doesn't require a module, it won't pick up the conf.lua settings. Also graphics isn't handling the shader cache writing properly. And I think this breaks the headset-graphics refcounting. But these will be fixed in future commits.
This commit is contained in:
parent
3a16e0c290
commit
08d6b2ad28
|
@ -346,13 +346,11 @@ int luaopen_lovr_audio(lua_State* L) {
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
if (lovrAudioInit(spatializer, sampleRate)) {
|
if (lovrAudioInit(spatializer, sampleRate) && start) {
|
||||||
luax_atexit(L, lovrAudioDestroy);
|
lovrAudioSetDevice(AUDIO_PLAYBACK, NULL, 0, NULL, AUDIO_SHARED);
|
||||||
if (start) {
|
lovrAudioStart(AUDIO_PLAYBACK);
|
||||||
lovrAudioSetDevice(AUDIO_PLAYBACK, NULL, 0, NULL, AUDIO_SHARED);
|
|
||||||
lovrAudioStart(AUDIO_PLAYBACK);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
luax_atexit(L, lovrAudioDestroy);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,9 +280,7 @@ int luaopen_lovr_event(lua_State* L) {
|
||||||
lua_pushcfunction(L, nextEvent);
|
lua_pushcfunction(L, nextEvent);
|
||||||
pollRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
pollRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
if (lovrEventInit()) {
|
lovrEventInit();
|
||||||
luax_atexit(L, lovrEventDestroy);
|
luax_atexit(L, lovrEventDestroy);
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -561,6 +561,13 @@ static int libLoaderAllInOne(lua_State* L) {
|
||||||
extern const luaL_Reg lovrFile[];
|
extern const luaL_Reg lovrFile[];
|
||||||
|
|
||||||
int luaopen_lovr_filesystem(lua_State* L) {
|
int luaopen_lovr_filesystem(lua_State* L) {
|
||||||
|
lua_newtable(L);
|
||||||
|
luax_register(L, lovrFilesystem);
|
||||||
|
luax_registertype(L, File);
|
||||||
|
luax_registerloader(L, luaLoader, 2);
|
||||||
|
luax_registerloader(L, libLoader, 3);
|
||||||
|
luax_registerloader(L, libLoaderAllInOne, 4);
|
||||||
|
|
||||||
const char* archive = NULL;
|
const char* archive = NULL;
|
||||||
|
|
||||||
lua_getglobal(L, "arg");
|
lua_getglobal(L, "arg");
|
||||||
|
@ -571,15 +578,7 @@ int luaopen_lovr_filesystem(lua_State* L) {
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
if (lovrFilesystemInit(archive)) {
|
lovrFilesystemInit(archive);
|
||||||
luax_atexit(L, lovrFilesystemDestroy);
|
luax_atexit(L, lovrFilesystemDestroy);
|
||||||
}
|
|
||||||
|
|
||||||
lua_newtable(L);
|
|
||||||
luax_register(L, lovrFilesystem);
|
|
||||||
luax_registertype(L, File);
|
|
||||||
luax_registerloader(L, luaLoader, 2);
|
|
||||||
luax_registerloader(L, libLoader, 3);
|
|
||||||
luax_registerloader(L, libLoaderAllInOne, 4);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -359,17 +359,14 @@ static int l_lovrGraphicsInitialize(lua_State* L) {
|
||||||
config.cacheData = luax_readfile(".lovrshadercache", &config.cacheSize);
|
config.cacheData = luax_readfile(".lovrshadercache", &config.cacheSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lovrGraphicsInit(&config)) {
|
lovrGraphicsInit(&config);
|
||||||
luax_atexit(L, lovrGraphicsDestroy);
|
luax_atexit(L, lovrGraphicsDestroy);
|
||||||
|
|
||||||
// Finalizers run in the opposite order they were added, so this has to go last
|
if (shaderCache) { // Finalizers run in the opposite order they were added, so this has to go last
|
||||||
if (shaderCache) {
|
luax_atexit(L, luax_writeshadercache);
|
||||||
luax_atexit(L, luax_writeshadercache);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(config.cacheData);
|
free(config.cacheData);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -387,9 +387,8 @@ int luaopen_lovr_math(lua_State* L) {
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
// Module
|
// Module
|
||||||
if (lovrMathInit()) {
|
lovrMathInit();
|
||||||
luax_atexit(L, lovrMathDestroy);
|
luax_atexit(L, lovrMathDestroy);
|
||||||
}
|
|
||||||
|
|
||||||
// Each Lua state gets its own thread-local Pool
|
// Each Lua state gets its own thread-local Pool
|
||||||
pool = lovrPoolCreate();
|
pool = lovrPoolCreate();
|
||||||
|
|
|
@ -178,8 +178,7 @@ int luaopen_lovr_physics(lua_State* L) {
|
||||||
luax_registertype(L, CylinderShape);
|
luax_registertype(L, CylinderShape);
|
||||||
luax_registertype(L, MeshShape);
|
luax_registertype(L, MeshShape);
|
||||||
luax_registertype(L, TerrainShape);
|
luax_registertype(L, TerrainShape);
|
||||||
if (lovrPhysicsInit()) {
|
lovrPhysicsInit();
|
||||||
luax_atexit(L, lovrPhysicsDestroy);
|
luax_atexit(L, lovrPhysicsDestroy);
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,8 +88,7 @@ int luaopen_lovr_thread(lua_State* L) {
|
||||||
luax_register(L, lovrThreadModule);
|
luax_register(L, lovrThreadModule);
|
||||||
luax_registertype(L, Thread);
|
luax_registertype(L, Thread);
|
||||||
luax_registertype(L, Channel);
|
luax_registertype(L, Channel);
|
||||||
if (lovrThreadModuleInit()) {
|
lovrThreadModuleInit();
|
||||||
luax_atexit(L, lovrThreadModuleDestroy);
|
luax_atexit(L, lovrThreadModuleDestroy);
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,7 @@ static const luaL_Reg lovrTimer[] = {
|
||||||
int luaopen_lovr_timer(lua_State* L) {
|
int luaopen_lovr_timer(lua_State* L) {
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
luax_register(L, lovrTimer);
|
luax_register(L, lovrTimer);
|
||||||
if (lovrTimerInit()) {
|
lovrTimerInit();
|
||||||
luax_atexit(L, lovrTimerDestroy);
|
luax_atexit(L, lovrTimerDestroy);
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "core/maf.h"
|
#include "core/maf.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "lib/miniaudio/miniaudio.h"
|
#include "lib/miniaudio/miniaudio.h"
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
@ -41,7 +42,7 @@ struct Source {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
bool initialized;
|
uint32_t ref;
|
||||||
ma_mutex lock;
|
ma_mutex lock;
|
||||||
ma_context context;
|
ma_context context;
|
||||||
ma_device devices[2];
|
ma_device devices[2];
|
||||||
|
@ -193,7 +194,7 @@ static Spatializer* spatializers[] = {
|
||||||
// Entry
|
// Entry
|
||||||
|
|
||||||
bool lovrAudioInit(const char* spatializer, uint32_t sampleRate) {
|
bool lovrAudioInit(const char* spatializer, uint32_t sampleRate) {
|
||||||
if (state.initialized) return false;
|
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||||
|
|
||||||
state.sampleRate = sampleRate;
|
state.sampleRate = sampleRate;
|
||||||
|
|
||||||
|
@ -221,12 +222,11 @@ bool lovrAudioInit(const char* spatializer, uint32_t sampleRate) {
|
||||||
state.absorption[2] = .0182f;
|
state.absorption[2] = .0182f;
|
||||||
|
|
||||||
quat_identity(state.orientation);
|
quat_identity(state.orientation);
|
||||||
|
return true;
|
||||||
return state.initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrAudioDestroy(void) {
|
void lovrAudioDestroy(void) {
|
||||||
if (!state.initialized) return;
|
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||||
for (size_t i = 0; i < 2; i++) {
|
for (size_t i = 0; i < 2; i++) {
|
||||||
ma_device_uninit(&state.devices[i]);
|
ma_device_uninit(&state.devices[i]);
|
||||||
free(state.deviceInfo[i]);
|
free(state.deviceInfo[i]);
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#include "event/event.h"
|
#include "event/event.h"
|
||||||
#include "thread/thread.h"
|
#include "thread/thread.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
bool initialized;
|
uint32_t ref;
|
||||||
arr_t(Event) events;
|
arr_t(Event) events;
|
||||||
size_t head;
|
size_t head;
|
||||||
} state;
|
} state;
|
||||||
|
@ -20,13 +21,13 @@ void lovrVariantDestroy(Variant* variant) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lovrEventInit(void) {
|
bool lovrEventInit(void) {
|
||||||
if (state.initialized) return false;
|
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||||
arr_init(&state.events, arr_alloc);
|
arr_init(&state.events, arr_alloc);
|
||||||
return state.initialized = true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrEventDestroy(void) {
|
void lovrEventDestroy(void) {
|
||||||
if (!state.initialized) return;
|
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||||
for (size_t i = state.head; i < state.events.length; i++) {
|
for (size_t i = state.head; i < state.events.length; i++) {
|
||||||
Event* event = &state.events.data[i];
|
Event* event = &state.events.data[i];
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "core/os.h"
|
#include "core/os.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "lib/miniz/miniz_tinfl.h"
|
#include "lib/miniz/miniz_tinfl.h"
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -67,7 +68,7 @@ struct File {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
bool initialized;
|
uint32_t ref;
|
||||||
Archive* archives;
|
Archive* archives;
|
||||||
size_t savePathLength;
|
size_t savePathLength;
|
||||||
char savePath[1024];
|
char savePath[1024];
|
||||||
|
@ -132,8 +133,7 @@ static bool sanitize(const char* path, char* buffer, size_t* length) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lovrFilesystemInit(const char* archive) {
|
bool lovrFilesystemInit(const char* archive) {
|
||||||
if (state.initialized) return false;
|
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||||
state.initialized = true;
|
|
||||||
|
|
||||||
lovrFilesystemSetRequirePath("?.lua;?/init.lua");
|
lovrFilesystemSetRequirePath("?.lua;?/init.lua");
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ bool lovrFilesystemInit(const char* archive) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrFilesystemDestroy(void) {
|
void lovrFilesystemDestroy(void) {
|
||||||
if (!state.initialized) return;
|
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||||
Archive* archive = state.archives;
|
Archive* archive = state.archives;
|
||||||
while (archive) {
|
while (archive) {
|
||||||
Archive* next = archive->next;
|
Archive* next = archive->next;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "monkey.h"
|
#include "monkey.h"
|
||||||
#include "shaders.h"
|
#include "shaders.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -547,7 +548,7 @@ typedef struct {
|
||||||
} ScratchTexture;
|
} ScratchTexture;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
bool initialized;
|
uint32_t ref;
|
||||||
bool active;
|
bool active;
|
||||||
bool presentable;
|
bool presentable;
|
||||||
bool timingEnabled;
|
bool timingEnabled;
|
||||||
|
@ -618,7 +619,7 @@ static void onMessage(void* context, const char* message, bool severe);
|
||||||
// Entry
|
// Entry
|
||||||
|
|
||||||
bool lovrGraphicsInit(GraphicsConfig* config) {
|
bool lovrGraphicsInit(GraphicsConfig* config) {
|
||||||
if (state.initialized) return false;
|
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||||
|
|
||||||
gpu_config gpu = {
|
gpu_config gpu = {
|
||||||
.debug = config->debug,
|
.debug = config->debug,
|
||||||
|
@ -803,12 +804,11 @@ bool lovrGraphicsInit(GraphicsConfig* config) {
|
||||||
#ifdef LOVR_USE_GLSLANG
|
#ifdef LOVR_USE_GLSLANG
|
||||||
glslang_initialize_process();
|
glslang_initialize_process();
|
||||||
#endif
|
#endif
|
||||||
state.initialized = true;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrGraphicsDestroy(void) {
|
void lovrGraphicsDestroy(void) {
|
||||||
if (!state.initialized) return;
|
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||||
#ifndef LOVR_DISABLE_HEADSET
|
#ifndef LOVR_DISABLE_HEADSET
|
||||||
// If there's an active headset session it needs to be stopped so it can clean up its Pass and
|
// If there's an active headset session it needs to be stopped so it can clean up its Pass and
|
||||||
// swapchain textures before gpu_destroy is called. This is really hacky and should be solved
|
// swapchain textures before gpu_destroy is called. This is really hacky and should be solved
|
||||||
|
@ -889,7 +889,7 @@ void lovrGraphicsDestroy(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lovrGraphicsIsInitialized(void) {
|
bool lovrGraphicsIsInitialized(void) {
|
||||||
return state.initialized;
|
return state.ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrGraphicsGetDevice(GraphicsDevice* device) {
|
void lovrGraphicsGetDevice(GraphicsDevice* device) {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#include "headset/headset.h"
|
#include "headset/headset.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
HeadsetInterface* lovrHeadsetInterface = NULL;
|
HeadsetInterface* lovrHeadsetInterface = NULL;
|
||||||
static bool initialized = false;
|
static uint32_t ref;
|
||||||
|
|
||||||
bool lovrHeadsetInit(HeadsetConfig* config) {
|
bool lovrHeadsetInit(HeadsetConfig* config) {
|
||||||
if (initialized) return false;
|
if (atomic_fetch_add(&ref, 1)) return false;
|
||||||
initialized = true;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < config->driverCount; i++) {
|
for (size_t i = 0; i < config->driverCount; i++) {
|
||||||
HeadsetInterface* interface = NULL;
|
HeadsetInterface* interface = NULL;
|
||||||
|
@ -35,12 +35,12 @@ bool lovrHeadsetInit(HeadsetConfig* config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrHeadsetDestroy(void) {
|
void lovrHeadsetDestroy(void) {
|
||||||
if (!initialized) return;
|
if (atomic_fetch_sub(&ref, 1) != 1) return;
|
||||||
initialized = false;
|
|
||||||
if (lovrHeadsetInterface) {
|
if (lovrHeadsetInterface) {
|
||||||
lovrHeadsetInterface->destroy();
|
lovrHeadsetInterface->destroy();
|
||||||
lovrHeadsetInterface = NULL;
|
lovrHeadsetInterface = NULL;
|
||||||
}
|
}
|
||||||
|
ref = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrLayerDestroy(void* ref) {
|
void lovrLayerDestroy(void* ref) {
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "lib/noise/simplexnoise1234.h"
|
#include "lib/noise/simplexnoise1234.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <stdatomic.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
struct Curve {
|
struct Curve {
|
||||||
uint32_t ref;
|
uint32_t ref;
|
||||||
|
@ -31,20 +31,20 @@ struct RandomGenerator {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
bool initialized;
|
uint32_t ref;
|
||||||
RandomGenerator* generator;
|
RandomGenerator* generator;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
bool lovrMathInit(void) {
|
bool lovrMathInit(void) {
|
||||||
if (state.initialized) return false;
|
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||||
state.generator = lovrRandomGeneratorCreate();
|
state.generator = lovrRandomGeneratorCreate();
|
||||||
Seed seed = { .b64 = (uint64_t) time(0) };
|
Seed seed = { .b64 = (uint64_t) time(0) };
|
||||||
lovrRandomGeneratorSetSeed(state.generator, seed);
|
lovrRandomGeneratorSetSeed(state.generator, seed);
|
||||||
return state.initialized = true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrMathDestroy(void) {
|
void lovrMathDestroy(void) {
|
||||||
if (!state.initialized) return;
|
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||||
lovrRelease(state.generator, lovrRandomGeneratorDestroy);
|
lovrRelease(state.generator, lovrRandomGeneratorDestroy);
|
||||||
memset(&state, 0, sizeof(state));
|
memset(&state, 0, sizeof(state));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "physics.h"
|
#include "physics.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <ode/ode.h>
|
#include <ode/ode.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
struct World {
|
struct World {
|
||||||
|
@ -138,21 +139,20 @@ static void onInfoMessage(int num, const char* format, va_list args) {
|
||||||
lovrLog(LOG_INFO, "PHY", message);
|
lovrLog(LOG_INFO, "PHY", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool initialized = false;
|
static uint32_t ref;
|
||||||
|
|
||||||
bool lovrPhysicsInit(void) {
|
bool lovrPhysicsInit(void) {
|
||||||
if (initialized) return false;
|
if (atomic_fetch_add(&ref, 1)) return false;
|
||||||
dInitODE();
|
dInitODE();
|
||||||
dSetErrorHandler(onErrorMessage);
|
dSetErrorHandler(onErrorMessage);
|
||||||
dSetDebugHandler(onDebugMessage);
|
dSetDebugHandler(onDebugMessage);
|
||||||
dSetMessageHandler(onInfoMessage);
|
dSetMessageHandler(onInfoMessage);
|
||||||
return initialized = true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrPhysicsDestroy(void) {
|
void lovrPhysicsDestroy(void) {
|
||||||
if (!initialized) return;
|
if (atomic_fetch_sub(&ref, 1) != 1) return;
|
||||||
dCloseODE();
|
dCloseODE();
|
||||||
initialized = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char** tags, uint32_t tagCount) {
|
World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char** tags, uint32_t tagCount) {
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
#include "event/event.h"
|
#include "event/event.h"
|
||||||
#include "core/os.h"
|
#include "core/os.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
bool initialized;
|
uint32_t ref;
|
||||||
bool keyRepeat;
|
bool keyRepeat;
|
||||||
bool prevKeyState[OS_KEY_COUNT];
|
bool prevKeyState[OS_KEY_COUNT];
|
||||||
bool keyState[OS_KEY_COUNT];
|
bool keyState[OS_KEY_COUNT];
|
||||||
|
@ -84,20 +85,19 @@ static void onQuit(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lovrSystemInit(void) {
|
bool lovrSystemInit(void) {
|
||||||
if (state.initialized) return false;
|
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||||
os_on_key(onKey);
|
os_on_key(onKey);
|
||||||
os_on_text(onText);
|
os_on_text(onText);
|
||||||
os_on_mouse_button(onMouseButton);
|
os_on_mouse_button(onMouseButton);
|
||||||
os_on_mouse_move(onMouseMove);
|
os_on_mouse_move(onMouseMove);
|
||||||
os_on_mousewheel_move(onWheelMove);
|
os_on_mousewheel_move(onWheelMove);
|
||||||
os_on_permission(onPermission);
|
os_on_permission(onPermission);
|
||||||
state.initialized = true;
|
|
||||||
os_get_mouse_position(&state.mouseX, &state.mouseY);
|
os_get_mouse_position(&state.mouseX, &state.mouseY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrSystemDestroy(void) {
|
void lovrSystemDestroy(void) {
|
||||||
if (!state.initialized) return;
|
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||||
os_on_key(NULL);
|
os_on_key(NULL);
|
||||||
os_on_text(NULL);
|
os_on_text(NULL);
|
||||||
os_on_permission(NULL);
|
os_on_permission(NULL);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "core/os.h"
|
#include "core/os.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <threads.h>
|
#include <threads.h>
|
||||||
|
@ -32,20 +33,20 @@ struct Channel {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
bool initialized;
|
uint32_t ref;
|
||||||
mtx_t channelLock;
|
mtx_t channelLock;
|
||||||
map_t channels;
|
map_t channels;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
bool lovrThreadModuleInit(void) {
|
bool lovrThreadModuleInit(void) {
|
||||||
if (state.initialized) return false;
|
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||||
mtx_init(&state.channelLock, mtx_plain);
|
mtx_init(&state.channelLock, mtx_plain);
|
||||||
map_init(&state.channels, 0);
|
map_init(&state.channels, 0);
|
||||||
return state.initialized = true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrThreadModuleDestroy(void) {
|
void lovrThreadModuleDestroy(void) {
|
||||||
if (!state.initialized) return;
|
if (atomic_fetch_sub(&state.ref, 1)) return;
|
||||||
for (size_t i = 0; i < state.channels.size; i++) {
|
for (size_t i = 0; i < state.channels.size; i++) {
|
||||||
if (state.channels.values[i] != MAP_NIL) {
|
if (state.channels.values[i] != MAP_NIL) {
|
||||||
lovrRelease((Channel*) (uintptr_t) state.channels.values[i], lovrChannelDestroy);
|
lovrRelease((Channel*) (uintptr_t) state.channels.values[i], lovrChannelDestroy);
|
||||||
|
@ -53,7 +54,7 @@ void lovrThreadModuleDestroy(void) {
|
||||||
}
|
}
|
||||||
mtx_destroy(&state.channelLock);
|
mtx_destroy(&state.channelLock);
|
||||||
map_free(&state.channels);
|
map_free(&state.channels);
|
||||||
state.initialized = false;
|
memset(&state, 0, sizeof(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel* lovrThreadGetChannel(const char* name) {
|
Channel* lovrThreadGetChannel(const char* name) {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#include "timer/timer.h"
|
#include "timer/timer.h"
|
||||||
#include "core/os.h"
|
#include "core/os.h"
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
bool initialized;
|
uint32_t ref;
|
||||||
double epoch;
|
double epoch;
|
||||||
double lastTime;
|
double lastTime;
|
||||||
double time;
|
double time;
|
||||||
|
@ -14,14 +15,13 @@ static struct {
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
bool lovrTimerInit(void) {
|
bool lovrTimerInit(void) {
|
||||||
if (state.initialized) return false;
|
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||||
state.initialized = true;
|
|
||||||
state.epoch = os_get_time();
|
state.epoch = os_get_time();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrTimerDestroy(void) {
|
void lovrTimerDestroy(void) {
|
||||||
if (!state.initialized) return;
|
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||||
memset(&state, 0, sizeof(state));
|
memset(&state, 0, sizeof(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue