diff --git a/CMakeLists.txt b/CMakeLists.txt index 258e5029..e742e439 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -316,6 +316,7 @@ endif() set(LOVR_SRC src/main.c + src/core/arr.c src/core/luax.c src/core/maf.c src/core/platform.c @@ -324,7 +325,6 @@ set(LOVR_SRC src/core/util.c src/api/l_lovr.c src/lib/map/map.c - src/lib/vec/vec.c src/lib/sds/sds.c ) diff --git a/src/api/l_collider.c b/src/api/l_collider.c index 58205959..f4b513b5 100644 --- a/src/api/l_collider.c +++ b/src/api/l_collider.c @@ -31,10 +31,11 @@ static int l_lovrColliderRemoveShape(lua_State* L) { static int l_lovrColliderGetShapes(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); - lua_newtable(L); - vec_void_t* shapes = lovrColliderGetShapes(collider); - for (int i = 0; i < shapes->length; i++) { - luax_pushshape(L, shapes->data[i]); + size_t count; + Shape** shapes = lovrColliderGetShapes(collider, &count); + lua_createtable(L, count, 0); + for (size_t i = 0; i < count; i++) { + luax_pushshape(L, shapes[i]); lua_rawseti(L, -2, i + 1); } return 1; @@ -42,10 +43,11 @@ static int l_lovrColliderGetShapes(lua_State* L) { static int l_lovrColliderGetJoints(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); - lua_newtable(L); - vec_void_t* joints = lovrColliderGetJoints(collider); - for (int i = 0; i < joints->length; i++) { - luax_pushjoint(L, joints->data[i]); + size_t count; + Joint** joints = lovrColliderGetJoints(collider, &count); + lua_createtable(L, count, 0); + for (size_t i = 0; i < count; i++) { + luax_pushjoint(L, joints[i]); lua_rawseti(L, -2, i + 1); } return 1; diff --git a/src/api/l_curve.c b/src/api/l_curve.c index fbb899f8..b226dcdb 100644 --- a/src/api/l_curve.c +++ b/src/api/l_curve.c @@ -33,13 +33,14 @@ static int l_lovrCurveRender(lua_State* L) { lovrAssert(points, "Out of memory"); lovrCurveRender(curve, t1, t2, points, n); lua_createtable(L, n, 0); - for (int i = 0; i < n; i += 4) { + int j = 1; + for (int i = 0; i < 4 * n; i += 4) { lua_pushnumber(L, points[i + 0]); - lua_rawseti(L, -2, i + 1); + lua_rawseti(L, -2, j++); lua_pushnumber(L, points[i + 1]); - lua_rawseti(L, -2, i + 2);; + lua_rawseti(L, -2, j++); lua_pushnumber(L, points[i + 2]); - lua_rawseti(L, -2, i + 3); + lua_rawseti(L, -2, j++); } free(points); return 1; @@ -62,7 +63,7 @@ static int l_lovrCurveGetPointCount(lua_State* L) { static int l_lovrCurveGetPoint(lua_State* L) { Curve* curve = luax_checktype(L, 1, Curve); - int index = luaL_checkinteger(L, 2) - 1; + size_t index = luaL_checkinteger(L, 2) - 1; lovrAssert(index >= 0 && index < lovrCurveGetPointCount(curve), "Invalid Curve point index: %d", index + 1); float point[4]; lovrCurveGetPoint(curve, index, point); @@ -74,7 +75,7 @@ static int l_lovrCurveGetPoint(lua_State* L) { static int l_lovrCurveSetPoint(lua_State* L) { Curve* curve = luax_checktype(L, 1, Curve); - int index = luaL_checkinteger(L, 2) - 1; + size_t index = luaL_checkinteger(L, 2) - 1; lovrAssert(index >= 0 && index < lovrCurveGetPointCount(curve), "Invalid Curve point index: %d", index + 1); float point[4]; luax_readvec3(L, 3, point, NULL); @@ -86,7 +87,7 @@ static int l_lovrCurveAddPoint(lua_State* L) { Curve* curve = luax_checktype(L, 1, Curve); float point[4]; int i = luax_readvec3(L, 2, point, NULL); - int index = lua_isnoneornil(L, i) ? lovrCurveGetPointCount(curve) : luaL_checkinteger(L, i) - 1; + size_t index = lua_isnoneornil(L, i) ? lovrCurveGetPointCount(curve) : luaL_checkinteger(L, i) - 1; lovrAssert(index >= 0 && index <= lovrCurveGetPointCount(curve), "Invalid Curve point index: %d", index + 1); lovrCurveAddPoint(curve, point, index); return 0; @@ -94,7 +95,7 @@ static int l_lovrCurveAddPoint(lua_State* L) { static int l_lovrCurveRemovePoint(lua_State* L) { Curve* curve = luax_checktype(L, 1, Curve); - int index = luaL_checkinteger(L, 2) - 1; + size_t index = luaL_checkinteger(L, 2) - 1; lovrAssert(index >= 0 && index < lovrCurveGetPointCount(curve), "Invalid Curve point index: %d", index + 1); lovrCurveRemovePoint(curve, index); return 0; diff --git a/src/api/l_data.c b/src/api/l_data.c index ed460208..eda8fa2e 100644 --- a/src/api/l_data.c +++ b/src/api/l_data.c @@ -7,6 +7,7 @@ #include "data/textureData.h" #include "core/ref.h" #include +#include static int l_lovrDataNewBlob(lua_State* L) { size_t size; diff --git a/src/api/l_filesystem.c b/src/api/l_filesystem.c index 59daaf42..47649265 100644 --- a/src/api/l_filesystem.c +++ b/src/api/l_filesystem.c @@ -1,8 +1,10 @@ #include "api.h" #include "filesystem/filesystem.h" +#include "filesystem/file.h" #include "data/blob.h" #include "core/ref.h" #include +#include #include "platform.h" // Returns a Blob, leaving stack unchanged. The Blob must be released when finished. @@ -32,65 +34,28 @@ static int pushDirectoryItem(void* userdata, const char* path, const char* filen return 1; } -static int l_lovrFilesystemLoad(lua_State* L); +typedef struct { + File file; + char buffer[4096]; +} luax_Reader; -static int moduleLoader(lua_State* L) { - const char* module = luaL_gsub(L, lua_tostring(L, -1), ".", "/"); - lua_pop(L, 2); - - char* path; int i; - vec_foreach(lovrFilesystemGetRequirePath(), path, i) { - const char* filename = luaL_gsub(L, path, "?", module); - if (lovrFilesystemIsFile(filename)) { - return l_lovrFilesystemLoad(L); - } - lua_pop(L, 1); - } - - return 0; +static const char* readCallback(lua_State* L, void* data, size_t* size) { + luax_Reader* reader = data; + *size = lovrFileRead(&reader->file, reader->buffer, sizeof(reader->buffer)); + return *size == 0 ? NULL : reader->buffer; } -static const char* libraryExtensions[] = { -#ifdef _WIN32 - ".dll", NULL -#elif __APPLE__ - ".so", ".dylib", NULL -#else - ".so", NULL -#endif -}; - -static int libraryLoader(lua_State* L) { - const char* modulePath = luaL_gsub(L, lua_tostring(L, -1), ".", "/"); - const char* moduleFunction = luaL_gsub(L, lua_tostring(L, -1), ".", "_"); - char* hyphen = strchr(moduleFunction, '-'); - moduleFunction = hyphen ? hyphen + 1 : moduleFunction; - lua_pop(L, 3); - - char* path; int i; - vec_foreach(lovrFilesystemGetCRequirePath(), path, i) { - for (const char** extension = libraryExtensions; *extension != NULL; extension++) { - char buffer[64]; - snprintf(buffer, 63, "%s%s", modulePath, *extension); - const char* filename = luaL_gsub(L, path, "??", buffer); - filename = luaL_gsub(L, filename, "?", modulePath); - lua_pop(L, 2); - - if (lovrFilesystemIsFile(filename)) { - char fullPath[LOVR_PATH_MAX]; - const char* realPath = lovrFilesystemGetRealDirectory(filename); - snprintf(fullPath, LOVR_PATH_MAX - 1, "%s%c%s", realPath, lovrDirSep, filename); - lua_getglobal(L, "package"); - lua_getfield(L, -1, "loadlib"); - lua_pushstring(L, fullPath); - lua_pushfstring(L, "luaopen_%s", moduleFunction); - lua_call(L, 2, 1); - return 1; - } - } +static int luax_loadfile(lua_State* L, const char* path, const char* debug) { + luax_Reader reader; + lovrFileInit(&reader.file, path); + lovrAssert(lovrFileOpen(&reader.file, OPEN_READ), "Could not open file %s", path); + int status = lua_load(L, readCallback, &reader, debug); + lovrFileDestroy(&reader.file); + switch (status) { + case LUA_ERRMEM: return luaL_error(L, "Memory allocation error: %s", lua_tostring(L, -1)); + case LUA_ERRSYNTAX: return luaL_error(L, "Syntax error: %s", lua_tostring(L, -1)); + default: return 1; } - - return 0; } static int l_lovrFilesystemAppend(lua_State* L) { @@ -167,19 +132,9 @@ static int l_lovrFilesystemGetRealDirectory(lua_State* L) { return 1; } -static void pushRequirePath(lua_State* L, vec_str_t* path) { - char* pattern; int i; - vec_foreach(path, pattern, i) { - lua_pushstring(L, pattern); - lua_pushliteral(L, ";"); - } - lua_pop(L, 1); - lua_concat(L, path->length * 2 - 1); -} - static int l_lovrFilesystemGetRequirePath(lua_State* L) { - pushRequirePath(L, lovrFilesystemGetRequirePath()); - pushRequirePath(L, lovrFilesystemGetCRequirePath()); + lua_pushstring(L, lovrFilesystemGetRequirePath()); + lua_pushstring(L, lovrFilesystemGetCRequirePath()); return 2; } @@ -246,23 +201,9 @@ static int l_lovrFilesystemIsFused(lua_State* L) { static int l_lovrFilesystemLoad(lua_State* L) { const char* path = luaL_checkstring(L, 1); - size_t size; - char* content = lovrFilesystemRead(path, -1, &size); - - if (!content) { - return luaL_error(L, "Could not read file '%s'", path); - } - - char debug[LOVR_PATH_MAX]; - snprintf(debug, LOVR_PATH_MAX, "@%s", path); - - int status = luaL_loadbuffer(L, content, size, debug); - free(content); - switch (status) { - case LUA_ERRMEM: return luaL_error(L, "Memory allocation error: %s", lua_tostring(L, -1)); - case LUA_ERRSYNTAX: return luaL_error(L, "Syntax error: %s", lua_tostring(L, -1)); - default: return 1; - } + lua_pushfstring(L, "@%s", path); + const char* debug = lua_tostring(L, -1); + return luax_loadfile(L, path, debug); } static int l_lovrFilesystemMount(lua_State* L) { @@ -318,8 +259,8 @@ static int l_lovrFilesystemSetIdentity(lua_State* L) { } static int l_lovrFilesystemSetRequirePath(lua_State* L) { - if (lua_type(L, 1) == LUA_TSTRING) lovrFilesystemSetRequirePath(luaL_checkstring(L, 1)); - if (lua_type(L, 2) == LUA_TSTRING) lovrFilesystemSetCRequirePath(luaL_checkstring(L, 2)); + if (lua_type(L, 1) == LUA_TSTRING) lovrFilesystemSetRequirePath(lua_tostring(L, 1)); + if (lua_type(L, 2) == LUA_TSTRING) lovrFilesystemSetCRequirePath(lua_tostring(L, 2)); return 0; } @@ -379,6 +320,129 @@ static const luaL_Reg lovrFilesystem[] = { { NULL, NULL } }; +static int luaLoader(lua_State* L) { + const char* module = lua_tostring(L, 1); + const char* p = lovrFilesystemGetRequirePath(); + + char buffer[1024] = { '@' }; + char* debug = &buffer[0]; + char* filename = &buffer[1]; + char* f = filename; + size_t n = sizeof(buffer) - 1; + + // Loop over the require path, character by character, and: + // - Replace question marks with the module that's being required, converting '.' to '/'. + // - If there's a semicolon/eof, treat it as the end of a potential filename and try to load it. + // The filename buffer has an '@' before it so it can also be used as the debug label for the Lua + // chunk without additional memory allocation. + + while (1) { + if (*p == ';' || *p == '\0') { + *f = '\0'; + + if (lovrFilesystemIsFile(filename)) { + return luax_loadfile(L, filename, debug); + } + + if (*p == '\0') { + break; + } else { + p++; + f = filename; + n = sizeof(buffer) - 1; + } + } else if (*p == '?') { + for (const char* m = module; n && *m; n--, m++) { + *f++ = *m == '.' ? '/' : *m; + } + p++; + } else { + *f++ = *p++; + n--; + } + + lovrAssert(n > 0, "Tried to require a filename that was too long (%s)", module); + } + + return 0; +} + +static int libLoader(lua_State* L) { +#ifdef _WIN32 + const char* extension = ".dll"; +#else + const char* extension = ".so"; +#endif + + const char* module = lua_tostring(L, 1); + const char* hyphen = strchr(module, '-'); + const char* symbol = hyphen ? hyphen + 1 : module; + const char* p = lovrFilesystemGetCRequirePath(); + + char filename[1024]; + char* f = filename; + size_t n = sizeof(filename); + + lua_getglobal(L, "package"); + while (1) { + if (*p == ';' || *p == '\0') { + *f = '\0'; + + if (lovrFilesystemIsFile(filename)) { + lua_getfield(L, -1, "loadlib"); + + // Synthesize the absolute path to the library on disk (outside of physfs) + luaL_Buffer buffer; + luaL_buffinit(L, &buffer); + luaL_addstring(&buffer, lovrFilesystemGetRealDirectory(filename)); + luaL_addchar(&buffer, lovrDirSep); + luaL_addstring(&buffer, filename); + luaL_pushresult(&buffer); + + // Synthesize the symbol to load: luaopen_ followed by the module name with dots converted + // to underscores, starting after the first hyphen (if there is one). + luaL_buffinit(L, &buffer); + luaL_addstring(&buffer, "luaopen_"); + for (const char* s = symbol; *s; s++) { + luaL_addchar(&buffer, *s == '.' ? '_' : *s); + } + luaL_pushresult(&buffer); + + // Finally call package.loadlib with the library path and symbol name + lua_call(L, 2, 1); + return 1; + } + + if (*p == '\0') { + break; + } else { + p++; + f = filename; + n = sizeof(filename); + } + } else if (*p == '?') { + for (const char* m = module; n && *m; n--, m++) { + *f++ = *m == '.' ? lovrDirSep : *m; + } + p++; + + if (*p == '?') { + for (const char* e = extension; n && *e; n--, e++) { + *f++ = *e; + } + p++; + } + } else { + *f++ = *p++; + n--; + } + + lovrAssert(n > 0, "Tried to require a filename that was too long (%s)", module); + } + + return 0; +} + int luaopen_lovr_filesystem(lua_State* L) { lua_getglobal(L, "arg"); if (lua_istable(L, -1)) { @@ -401,7 +465,7 @@ int luaopen_lovr_filesystem(lua_State* L) { lua_newtable(L); luaL_register(L, NULL, lovrFilesystem); - luax_registerloader(L, moduleLoader, 2); - luax_registerloader(L, libraryLoader, 3); + luax_registerloader(L, luaLoader, 2); + luax_registerloader(L, libLoader, 3); return 1; } diff --git a/src/api/l_graphics.c b/src/api/l_graphics.c index e164e7ca..40198cbf 100644 --- a/src/api/l_graphics.c +++ b/src/api/l_graphics.c @@ -11,6 +11,7 @@ #include "data/rasterizer.h" #include "data/textureData.h" #include "filesystem/filesystem.h" +#include "core/arr.h" #include "core/ref.h" #include "util.h" #include @@ -443,7 +444,7 @@ static int l_lovrGraphicsGetStats(lua_State* L) { lua_pushinteger(L, stats->shaderSwitches); lua_setfield(L, 1, "shaderswitches"); lua_createtable(L, 0, stats->timers.length); - for (int i = 0; i < stats->timers.length; i++) { + for (size_t i = 0; i < stats->timers.length; i++) { lua_pushstring(L, stats->timers.data[i].label); lua_pushnumber(L, stats->timers.data[i].time); lua_settable(L, -3); @@ -1010,8 +1011,8 @@ static void luax_checkuniformtype(lua_State* L, int index, UniformType* baseType } static int l_lovrGraphicsNewShaderBlock(lua_State* L) { - vec_uniform_t uniforms; - vec_init(&uniforms); + arr_uniform_t uniforms; + arr_init(&uniforms); BlockType type = luaL_checkoption(L, 1, NULL, BlockTypes); @@ -1039,7 +1040,7 @@ static int l_lovrGraphicsNewShaderBlock(lua_State* L) { } lovrAssert(uniform.count >= 1, "Uniform count must be positive, got %d for '%s'", uniform.count, uniform.name); - vec_push(&uniforms, uniform); + arr_push(&uniforms, uniform); // Pop the table, leaving the key for lua_next to nom lua_pop(L, 1); @@ -1063,7 +1064,7 @@ static int l_lovrGraphicsNewShaderBlock(lua_State* L) { Buffer* buffer = lovrBufferCreate(size, NULL, type == BLOCK_COMPUTE ? BUFFER_SHADER_STORAGE : BUFFER_UNIFORM, usage, readable); ShaderBlock* block = lovrShaderBlockCreate(type, buffer, &uniforms); luax_pushtype(L, ShaderBlock, block); - vec_deinit(&uniforms); + arr_free(&uniforms); lovrRelease(Buffer, buffer); lovrRelease(ShaderBlock, block); return 1; diff --git a/src/api/l_headset.c b/src/api/l_headset.c index 5aa9e1fe..6a4bfb1f 100644 --- a/src/api/l_headset.c +++ b/src/api/l_headset.c @@ -3,6 +3,7 @@ #include "data/modelData.h" #include "graphics/model.h" #include "graphics/texture.h" +#include "core/arr.h" #include "core/maf.h" #include "core/ref.h" #include @@ -230,12 +231,17 @@ static int l_lovrHeadsetGetBoundsGeometry(lua_State* L) { lua_settop(L, 1); } else { lua_settop(L, 0); - lua_createtable(L, count, 0); + lua_createtable(L, count / 4, 0); } - for (uint32_t i = 0; i < count; i++) { - lua_pushnumber(L, points[i]); - lua_rawseti(L, 1, i + 1); + int j = 1; + for (uint32_t i = 0; i < count; i += 4) { + lua_pushnumber(L, points[i + 0]); + lua_rawseti(L, 1, j++); + lua_pushnumber(L, points[i + 1]); + lua_rawseti(L, 1, j++); + lua_pushnumber(L, points[i + 2]); + lua_rawseti(L, 1, j++); } return 1; @@ -608,8 +614,8 @@ int luaopen_lovr_headset(lua_State* L) { luax_pushconf(L); lua_getfield(L, -1, "headset"); - vec_t(HeadsetDriver) drivers; - vec_init(&drivers); + arr_t(HeadsetDriver, 8) drivers; + arr_init(&drivers); float offset = 1.7f; int msaa = 4; @@ -620,7 +626,7 @@ int luaopen_lovr_headset(lua_State* L) { int n = luax_len(L, -1); for (int i = 0; i < n; i++) { lua_rawgeti(L, -1, i + 1); - vec_push(&drivers, luaL_checkoption(L, -1, NULL, HeadsetDrivers)); + arr_push(&drivers, luaL_checkoption(L, -1, NULL, HeadsetDrivers)); lua_pop(L, 1); } lua_pop(L, 1); @@ -640,7 +646,7 @@ int luaopen_lovr_headset(lua_State* L) { luax_atexit(L, lovrHeadsetDestroy); } - vec_deinit(&drivers); + arr_free(&drivers); lua_pop(L, 2); headsetRenderData.ref = LUA_NOREF; diff --git a/src/api/l_math.c b/src/api/l_math.c index 49a97ae1..6d20916a 100644 --- a/src/api/l_math.c +++ b/src/api/l_math.c @@ -79,16 +79,9 @@ float* luax_newmathtype(lua_State* L, MathType type) { } static int l_lovrMathNewCurve(lua_State* L) { + Curve* curve = lovrCurveCreate(); int top = lua_gettop(L); - if (top == 1 && lua_type(L, 1) == LUA_TNUMBER) { - Curve* curve = lovrCurveCreate(luaL_checkinteger(L, 1)); - luax_pushtype(L, Curve, curve); - return 1; - } - - Curve* curve = lovrCurveCreate(3); - if (lua_istable(L, 1)) { int pointIndex = 0; int length = luax_len(L, 1); diff --git a/src/api/l_thread_module.c b/src/api/l_thread_module.c index 762586c0..2c96ade5 100644 --- a/src/api/l_thread_module.c +++ b/src/api/l_thread_module.c @@ -5,6 +5,7 @@ #include "thread/channel.h" #include "core/ref.h" #include +#include static int threadRunner(void* data) { Thread* thread = (Thread*) data; diff --git a/src/core/arr.c b/src/core/arr.c new file mode 100644 index 00000000..4ff53d7d --- /dev/null +++ b/src/core/arr.c @@ -0,0 +1,22 @@ +#include "arr.h" +#include "util.h" +#include +#include + +void _arr_reserve(void** data, void* temp, size_t n, size_t* capacity, size_t stride) { + size_t oldCapacity = *capacity; + + while (*capacity < n) { + *capacity <<= 1; + lovrAssert(*capacity > 0, "Out of memory"); + } + + if (*data == temp) { + *data = realloc(NULL, *capacity * stride); + lovrAssert(*data, "Out of memory"); + memcpy(*data, temp, oldCapacity * stride); + } else { + *data = realloc(*data, *capacity * stride); + lovrAssert(*data, "Out of memory"); + } +} diff --git a/src/core/arr.h b/src/core/arr.h new file mode 100644 index 00000000..49ed173d --- /dev/null +++ b/src/core/arr.h @@ -0,0 +1,42 @@ +#include + +#pragma once + +// A dynamic array that uses the stack initially and switches to the heap if it gets big enough. + +#define arr_t(T, n)\ + struct { T *data; T temp[n]; size_t length, capacity; } + +#define arr_init(a)\ + (a)->data = (a)->temp,\ + (a)->length = 0,\ + (a)->capacity = sizeof((a)->temp) / sizeof((a)->temp[0]) + +#define arr_free(a)\ + if ((a)->data != (a)->temp) free((a)->data) + +#define arr_reserve(a, n)\ + n > (a)->capacity ?\ + _arr_reserve((void**) &((a)->data), (a)->temp, n, &(a)->capacity, sizeof(*(a)->data)) :\ + (void) 0 + +#define arr_push(a, x)\ + arr_reserve(a, (a)->length + 1),\ + (a)->data[(a)->length++] = x + +#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 + +#define arr_splice(a, i, n)\ + memmove((a)->data + i, (a)->data + (i + n), n * sizeof(*(a)->data)),\ + (a)->length -= n + +#define arr_clear(a)\ + (a)->length = 0 + +void _arr_reserve(void** data, void* temp, size_t n, size_t* capacity, size_t stride); diff --git a/src/lib/vec/LICENSE b/src/lib/vec/LICENSE deleted file mode 100644 index 03b65555..00000000 --- a/src/lib/vec/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2014 rxi - - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/src/lib/vec/vec.c b/src/lib/vec/vec.c deleted file mode 100644 index 399104e9..00000000 --- a/src/lib/vec/vec.c +++ /dev/null @@ -1,114 +0,0 @@ -/** - * Copyright (c) 2014 rxi - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the MIT license. See LICENSE for details. - */ - -#include "vec.h" - - -int vec_expand_(char **data, int *length, int *capacity, int memsz) { - if (*length + 1 > *capacity) { - void *ptr; - int n = (*capacity == 0) ? 1 : *capacity << 1; - ptr = realloc(*data, n * memsz); - if (ptr == NULL) return -1; - *data = ptr; - *capacity = n; - } - return 0; -} - - -int vec_reserve_(char **data, int *length, int *capacity, int memsz, int n) { - (void) length; - if (n > *capacity) { - void *ptr = realloc(*data, n * memsz); - if (ptr == NULL) return -1; - *data = ptr; - *capacity = n; - } - return 0; -} - - -int vec_reserve_po2_( - char **data, int *length, int *capacity, int memsz, int n -) { - int n2 = 1; - if (n == 0) return 0; - while (n2 < n) n2 <<= 1; - return vec_reserve_(data, length, capacity, memsz, n2); -} - - -int vec_compact_(char **data, int *length, int *capacity, int memsz) { - if (*length == 0) { - free(*data); - *data = NULL; - *capacity = 0; - return 0; - } else { - void *ptr; - int n = *length; - ptr = realloc(*data, n * memsz); - if (ptr == NULL) return -1; - *capacity = n; - *data = ptr; - } - return 0; -} - - -int vec_insert_(char **data, int *length, int *capacity, int memsz, - int idx -) { - int err = vec_expand_(data, length, capacity, memsz); - if (err) return err; - memmove(*data + (idx + 1) * memsz, - *data + idx * memsz, - (*length - idx) * memsz); - return 0; -} - - -void vec_splice_(char **data, int *length, int *capacity, int memsz, - int start, int count -) { - (void) capacity; - memmove(*data + start * memsz, - *data + (start + count) * memsz, - (*length - start - count) * memsz); -} - - -void vec_swapsplice_(char **data, int *length, int *capacity, int memsz, - int start, int count -) { - (void) capacity; - memmove(*data + start * memsz, - *data + (*length - count) * memsz, - count * memsz); -} - - -void vec_swap_(char **data, int *length, int *capacity, int memsz, - int idx1, int idx2 -) { - unsigned char *a, *b, tmp; - int count; - (void) length; - (void) capacity; - if (idx1 == idx2) return; - a = (unsigned char*) *data + idx1 * memsz; - b = (unsigned char*) *data + idx2 * memsz; - count = memsz; - while (count--) { - tmp = *a; - *a = *b; - *b = tmp; - a++, b++; - } -} - diff --git a/src/lib/vec/vec.h b/src/lib/vec/vec.h deleted file mode 100644 index 0c0cb3cf..00000000 --- a/src/lib/vec/vec.h +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Copyright (c) 2014 rxi - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the MIT license. See LICENSE for details. - */ - -#ifndef VEC_H -#define VEC_H - -#include -#include - -#define VEC_VERSION "0.2.1" - - -#define vec_unpack_(v)\ - (char**)&(v)->data, &(v)->length, &(v)->capacity, sizeof(*(v)->data) - - -#define vec_t(T)\ - struct { T *data; int length, capacity; } - - -#define vec_init(v)\ - memset((v), 0, sizeof(*(v))) - - -#define vec_deinit(v)\ - ( free((v)->data),\ - vec_init(v) ) - - -#define vec_push(v, val)\ - ( vec_expand_(vec_unpack_(v)) ? -1 :\ - ((v)->data[(v)->length++] = (val), 0) ) - - -#define vec_pop(v)\ - (v)->data[--(v)->length] - - -#define vec_splice(v, start, count)\ - ( vec_splice_(vec_unpack_(v), start, count),\ - (v)->length -= (count) ) - - -#define vec_swapsplice(v, start, count)\ - ( vec_swapsplice_(vec_unpack_(v), start, count),\ - (v)->length -= (count) ) - - -#define vec_insert(v, idx, val)\ - ( vec_insert_(vec_unpack_(v), idx) ? -1 :\ - ((v)->data[idx] = (val), 0), (v)->length++, 0 ) - - -#define vec_sort(v, fn)\ - qsort((v)->data, (v)->length, sizeof(*(v)->data), fn) - - -#define vec_swap(v, idx1, idx2)\ - vec_swap_(vec_unpack_(v), idx1, idx2) - - -#define vec_truncate(v, len)\ - ((v)->length = (len) < (v)->length ? (len) : (v)->length) - - -#define vec_clear(v)\ - ((v)->length = 0) - - -#define vec_first(v)\ - (v)->data[0] - - -#define vec_last(v)\ - (v)->data[(v)->length - 1] - - -#define vec_reserve(v, n)\ - vec_reserve_(vec_unpack_(v), n) - - -#define vec_compact(v)\ - vec_compact_(vec_unpack_(v)) - - -#define vec_pusharr(v, arr, count)\ - do {\ - int i__, n__ = (count);\ - if (vec_reserve_po2_(vec_unpack_(v), (v)->length + n__) != 0) break;\ - for (i__ = 0; i__ < n__; i__++) {\ - (v)->data[(v)->length++] = (arr)[i__];\ - }\ - } while (0) - - -#define vec_extend(v, v2)\ - vec_pusharr((v), (v2)->data, (v2)->length) - - -#define vec_find(v, val, idx)\ - do {\ - for ((idx) = 0; (idx) < (v)->length; (idx)++) {\ - if ((v)->data[(idx)] == (val)) break;\ - }\ - if ((idx) == (v)->length) (idx) = -1;\ - } while (0) - - -#define vec_remove(v, val)\ - do {\ - int idx__;\ - vec_find(v, val, idx__);\ - if (idx__ != -1) vec_splice(v, idx__, 1);\ - } while (0) - - -#define vec_reverse(v)\ - do {\ - int i__ = (v)->length / 2;\ - while (i__--) {\ - vec_swap((v), i__, (v)->length - (i__ + 1));\ - }\ - } while (0) - - -#define vec_foreach(v, var, iter)\ - if ( (v)->length > 0 )\ - for ( (iter) = 0;\ - (iter) < (v)->length && (((var) = (v)->data[(iter)]), 1);\ - ++(iter)) - - -#define vec_foreach_rev(v, var, iter)\ - if ( (v)->length > 0 )\ - for ( (iter) = (v)->length - 1;\ - (iter) >= 0 && (((var) = (v)->data[(iter)]), 1);\ - --(iter)) - - -#define vec_foreach_ptr(v, var, iter)\ - if ( (v)->length > 0 )\ - for ( (iter) = 0;\ - (iter) < (v)->length && (((var) = &(v)->data[(iter)]), 1);\ - ++(iter)) - - -#define vec_foreach_ptr_rev(v, var, iter)\ - if ( (v)->length > 0 )\ - for ( (iter) = (v)->length - 1;\ - (iter) >= 0 && (((var) = &(v)->data[(iter)]), 1);\ - --(iter)) - - - -int vec_expand_(char **data, int *length, int *capacity, int memsz); -int vec_reserve_(char **data, int *length, int *capacity, int memsz, int n); -int vec_reserve_po2_(char **data, int *length, int *capacity, int memsz, - int n); -int vec_compact_(char **data, int *length, int *capacity, int memsz); -int vec_insert_(char **data, int *length, int *capacity, int memsz, - int idx); -void vec_splice_(char **data, int *length, int *capacity, int memsz, - int start, int count); -void vec_swapsplice_(char **data, int *length, int *capacity, int memsz, - int start, int count); -void vec_swap_(char **data, int *length, int *capacity, int memsz, - int idx1, int idx2); - - -typedef vec_t(void*) vec_void_t; -typedef vec_t(char*) vec_str_t; -typedef vec_t(int) vec_int_t; -typedef vec_t(char) vec_char_t; -typedef vec_t(float) vec_float_t; -typedef vec_t(double) vec_double_t; - -#endif diff --git a/src/modules/audio/audio.c b/src/modules/audio/audio.c index 3fe61ab1..7a08121a 100644 --- a/src/modules/audio/audio.c +++ b/src/modules/audio/audio.c @@ -1,10 +1,10 @@ #include "audio/audio.h" #include "audio/source.h" #include "data/audioStream.h" +#include "core/arr.h" #include "core/maf.h" #include "core/ref.h" #include "util.h" -#include "lib/vec/vec.h" #include #include #include @@ -15,10 +15,10 @@ static struct { bool spatialized; ALCdevice* device; ALCcontext* context; - vec_void_t sources; float LOVR_ALIGN(16) orientation[4]; float LOVR_ALIGN(16) position[4]; float LOVR_ALIGN(16) velocity[4]; + arr_t(Source*, 32) sources; } state; ALenum lovrAudioConvertFormat(uint32_t bitDepth, uint32_t channelCount) { @@ -58,7 +58,7 @@ bool lovrAudioInit() { state.device = device; state.context = context; - vec_init(&state.sources); + arr_init(&state.sources); return state.initialized = true; } @@ -67,16 +67,17 @@ void lovrAudioDestroy() { alcMakeContextCurrent(NULL); alcDestroyContext(state.context); alcCloseDevice(state.device); - for (int i = 0; i < state.sources.length; i++) { + for (size_t i = 0; i < state.sources.length; i++) { lovrRelease(Source, state.sources.data[i]); } - vec_deinit(&state.sources); + arr_free(&state.sources); memset(&state, 0, sizeof(state)); } void lovrAudioUpdate() { - int i; Source* source; - vec_foreach_rev(&state.sources, source, i) { + for (size_t i = state.sources.length; i-- > 0;) { + Source* source = state.sources.data[i]; + if (lovrSourceGetType(source) == SOURCE_STATIC) { continue; } @@ -95,7 +96,7 @@ void lovrAudioUpdate() { } } else if (isStopped) { lovrAudioStreamRewind(lovrSourceGetStream(source)); - vec_splice(&state.sources, i, 1); + arr_splice(&state.sources, i, 1); lovrRelease(Source, source); } } @@ -104,7 +105,7 @@ void lovrAudioUpdate() { void lovrAudioAdd(Source* source) { if (!lovrAudioHas(source)) { lovrRetain(source); - vec_push(&state.sources, source); + arr_push(&state.sources, source); } } @@ -141,9 +142,13 @@ float lovrAudioGetVolume() { } bool lovrAudioHas(Source* source) { - int index; - vec_find(&state.sources, source, index); - return index >= 0; + for (size_t i = 0; i < state.sources.length; i++) { + if (state.sources.data[i] == source) { + return true; + } + } + + return false; } bool lovrAudioIsSpatialized() { @@ -151,23 +156,20 @@ bool lovrAudioIsSpatialized() { } void lovrAudioPause() { - int i; Source* source; - vec_foreach(&state.sources, source, i) { - lovrSourcePause(source); + for (size_t i = 0; i < state.sources.length; i++) { + lovrSourcePause(state.sources.data[i]); } } void lovrAudioResume() { - int i; Source* source; - vec_foreach(&state.sources, source, i) { - lovrSourceResume(source); + for (size_t i = 0; i < state.sources.length; i++) { + lovrSourceResume(state.sources.data[i]); } } void lovrAudioRewind() { - int i; Source* source; - vec_foreach(&state.sources, source, i) { - lovrSourceRewind(source); + for (size_t i = 0; i < state.sources.length; i++) { + lovrSourceRewind(state.sources.data[i]); } } @@ -205,8 +207,7 @@ void lovrAudioSetVolume(float volume) { } void lovrAudioStop() { - int i; Source* source; - vec_foreach(&state.sources, source, i) { - lovrSourceStop(source); + for (size_t i = 0; i < state.sources.length; i++) { + lovrSourceStop(state.sources.data[i]); } } diff --git a/src/modules/data/modelData_obj.c b/src/modules/data/modelData_obj.c index f7be167e..3fb343d6 100644 --- a/src/modules/data/modelData_obj.c +++ b/src/modules/data/modelData_obj.c @@ -2,27 +2,27 @@ #include "data/blob.h" #include "data/textureData.h" #include "filesystem/filesystem.h" +#include "core/arr.h" #include "core/maf.h" #include "core/ref.h" #include "lib/map/map.h" -#include "lib/vec/vec.h" #include #include #include -typedef vec_t(ModelMaterial) vec_material_t; - typedef struct { int material; int start; int count; } objGroup; -typedef vec_t(objGroup) vec_group_t; +typedef arr_t(ModelMaterial, 1) arr_material_t; +typedef arr_t(TextureData*, 1) arr_texturedata_t; +typedef arr_t(objGroup, 1) arr_group_t; #define STARTS_WITH(a, b) !strncmp(a, b, strlen(b)) -static void parseMtl(char* path, vec_void_t* textures, vec_material_t* materials, map_int_t* names, char* base) { +static void parseMtl(char* path, arr_texturedata_t* textures, arr_material_t* materials, map_int_t* names, char* base) { size_t length = 0; char* data = lovrFilesystemRead(path, -1, &length); lovrAssert(data && length > 0, "Unable to read mtl from '%s'", path); @@ -36,18 +36,18 @@ static void parseMtl(char* path, vec_void_t* textures, vec_material_t* materials bool hasName = sscanf(s + 7, "%s\n%n", name, &lineLength); lovrAssert(hasName, "Bad OBJ: Expected a material name"); map_set(names, name, materials->length); - vec_push(materials, ((ModelMaterial) { + arr_push(materials, ((ModelMaterial) { .scalars[SCALAR_METALNESS] = 1.f, .scalars[SCALAR_ROUGHNESS] = 1.f, .colors[COLOR_DIFFUSE] = { 1.f, 1.f, 1.f, 1.f }, .colors[COLOR_EMISSIVE] = { 0.f, 0.f, 0.f, 0.f } })); - memset(&vec_last(materials).textures, 0xff, MAX_MATERIAL_TEXTURES * sizeof(int)); + memset(&materials->data[materials->length - 1].textures, 0xff, MAX_MATERIAL_TEXTURES * sizeof(int)); } else if (STARTS_WITH(s, "Kd")) { float r, g, b; int count = sscanf(s + 2, "%f %f %f\n%n", &r, &g, &b, &lineLength); lovrAssert(count == 3, "Bad OBJ: Expected 3 components for diffuse color"); - ModelMaterial* material = &vec_last(materials); + ModelMaterial* material = &materials->data[materials->length - 1]; material->colors[COLOR_DIFFUSE] = (Color) { r, g, b, 1.f }; } else if (STARTS_WITH(s, "map_Kd")) { @@ -56,7 +56,7 @@ static void parseMtl(char* path, vec_void_t* textures, vec_material_t* materials bool hasFilename = sscanf(s + 7, "%s\n%n", filename, &lineLength); lovrAssert(hasFilename, "Bad OBJ: Expected a texture filename"); char path[1024]; - snprintf(path, 1023, "%s%s", base, filename); + snprintf(path, sizeof(path), "%s%s", base, filename); size_t size = 0; void* data = lovrFilesystemRead(path, -1, &size); lovrAssert(data && size > 0, "Unable to read texture from %s", path); @@ -65,11 +65,11 @@ static void parseMtl(char* path, vec_void_t* textures, vec_material_t* materials // Load texture, assign to material TextureData* texture = lovrTextureDataCreateFromBlob(blob, true); lovrAssert(materials->length > 0, "Tried to set a material property without declaring a material first"); - ModelMaterial* material = &vec_last(materials); + ModelMaterial* material = &materials->data[materials->length - 1]; material->textures[TEXTURE_DIFFUSE] = textures->length; material->filters[TEXTURE_DIFFUSE].mode = FILTER_TRILINEAR; material->wraps[TEXTURE_DIFFUSE] = (TextureWrap) { .s = WRAP_REPEAT, .t = WRAP_REPEAT }; - vec_push(textures, texture); + arr_push(textures, texture); lovrRelease(Blob, blob); } else { char* newline = memchr(s, '\n', length); @@ -92,29 +92,29 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source) { return NULL; } - vec_group_t groups; - vec_void_t textures; - vec_material_t materials; + arr_group_t groups; + arr_texturedata_t textures; + arr_material_t materials; map_int_t materialNames; - vec_float_t vertexBlob; - vec_int_t indexBlob; + arr_t(float, 1) vertexBlob; + arr_t(int, 1) indexBlob; map_int_t vertexMap; - vec_float_t positions; - vec_float_t normals; - vec_float_t uvs; + arr_t(float, 1) positions; + arr_t(float, 1) normals; + arr_t(float, 1) uvs; - vec_init(&groups); - vec_init(&textures); - vec_init(&materials); + arr_init(&groups); + arr_init(&textures); + arr_init(&materials); map_init(&materialNames); - vec_init(&vertexBlob); - vec_init(&indexBlob); + arr_init(&vertexBlob); + arr_init(&indexBlob); map_init(&vertexMap); - vec_init(&positions); - vec_init(&normals); - vec_init(&uvs); + arr_init(&positions); + arr_init(&normals); + arr_init(&uvs); - vec_push(&groups, ((objGroup) { .material = -1 })); + arr_push(&groups, ((objGroup) { .material = -1 })); char base[1024]; lovrAssert(strlen(source->name) < sizeof(base), "OBJ filename is too long"); @@ -130,17 +130,17 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source) { float x, y, z; int count = sscanf(data + 2, "%f %f %f\n%n", &x, &y, &z, &lineLength); lovrAssert(count == 3, "Bad OBJ: Expected 3 coordinates for vertex position"); - vec_pusharr(&positions, ((float[3]) { x, y, z }), 3); + arr_append(&positions, ((float[3]) { x, y, z }), 3); } else if (STARTS_WITH(data, "vn ")) { float x, y, z; int count = sscanf(data + 3, "%f %f %f\n%n", &x, &y, &z, &lineLength); lovrAssert(count == 3, "Bad OBJ: Expected 3 coordinates for vertex normal"); - vec_pusharr(&normals, ((float[3]) { x, y, z }), 3); + arr_append(&normals, ((float[3]) { x, y, z }), 3); } else if (STARTS_WITH(data, "vt ")) { float u, v; int count = sscanf(data + 3, "%f %f\n%n", &u, &v, &lineLength); lovrAssert(count == 2, "Bad OBJ: Expected 2 coordinates for texture coordinate"); - vec_pusharr(&uvs, ((float[2]) { u, v }), 2); + arr_append(&uvs, ((float[2]) { u, v }), 2); } else if (STARTS_WITH(data, "f ")) { char* s = data + 2; for (int i = 0; i < 3; i++) { @@ -150,29 +150,29 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source) { *space = '\0'; // I'll be back int* index = map_get(&vertexMap, s); if (index) { - vec_push(&indexBlob, *index); + arr_push(&indexBlob, *index); } else { int v, vt, vn; int newIndex = vertexBlob.length / 8; - vec_push(&indexBlob, newIndex); + arr_push(&indexBlob, newIndex); map_set(&vertexMap, s, newIndex); // Can be improved if (sscanf(s, "%d/%d/%d", &v, &vt, &vn) == 3) { - vec_pusharr(&vertexBlob, positions.data + 3 * (v - 1), 3); - vec_pusharr(&vertexBlob, normals.data + 3 * (vn - 1), 3); - vec_pusharr(&vertexBlob, uvs.data + 2 * (vt - 1), 2); + arr_append(&vertexBlob, positions.data + 3 * (v - 1), 3); + arr_append(&vertexBlob, normals.data + 3 * (vn - 1), 3); + arr_append(&vertexBlob, uvs.data + 2 * (vt - 1), 2); } else if (sscanf(s, "%d//%d", &v, &vn) == 2) { - vec_pusharr(&vertexBlob, positions.data + 3 * (v - 1), 3); - vec_pusharr(&vertexBlob, normals.data + 3 * (vn - 1), 3); - vec_pusharr(&vertexBlob, ((float[2]) { 0 }), 2); + arr_append(&vertexBlob, positions.data + 3 * (v - 1), 3); + arr_append(&vertexBlob, normals.data + 3 * (vn - 1), 3); + arr_append(&vertexBlob, ((float[2]) { 0 }), 2); } else if (sscanf(s, "%d/%d", &v, &vt) == 2) { - vec_pusharr(&vertexBlob, positions.data + 3 * (v - 1), 3); - vec_pusharr(&vertexBlob, ((float[3]) { 0 }), 3); - vec_pusharr(&vertexBlob, uvs.data + 2 * (vt - 1), 2); + arr_append(&vertexBlob, positions.data + 3 * (v - 1), 3); + arr_append(&vertexBlob, ((float[3]) { 0 }), 3); + arr_append(&vertexBlob, uvs.data + 2 * (vt - 1), 2); } else if (sscanf(s, "%d", &v) == 1) { - vec_pusharr(&vertexBlob, positions.data + 3 * (v - 1), 3); - vec_pusharr(&vertexBlob, ((float[5]) { 0 }), 5); + arr_append(&vertexBlob, positions.data + 3 * (v - 1), 3); + arr_append(&vertexBlob, ((float[5]) { 0 }), 5); } else { lovrThrow("Bad OBJ: Unknown face format"); } @@ -181,14 +181,14 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source) { s = space + 1; } } - vec_last(&groups).count += 3; + groups.data[groups.length - 1].count += 3; lineLength = s - data; } else if (STARTS_WITH(data, "mtllib ")) { char filename[1024]; bool hasName = sscanf(data + 7, "%1024s\n%n", filename, &lineLength); lovrAssert(hasName, "Bad OBJ: Expected filename after mtllib"); char path[1024]; - snprintf(path, 1023, "%s%s", base, filename); + snprintf(path, sizeof(path), "%s%s", base, filename); parseMtl(path, &textures, &materials, &materialNames, base); } else if (STARTS_WITH(data, "usemtl ")) { char name[128]; @@ -197,10 +197,10 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source) { lovrAssert(hasName, "Bad OBJ: Expected a material name"); // If the last group didn't have any faces, just reuse it, otherwise make a new group - objGroup* group = &vec_last(&groups); + objGroup* group = &groups.data[groups.length - 1]; if (group->count > 0) { int start = group->start + group->count; // Don't put this in the compound literal (realloc) - vec_push(&groups, ((objGroup) { + arr_push(&groups, ((objGroup) { .material = material ? *material : -1, .start = start, .count = 0 @@ -276,7 +276,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source) { .components = 2 }; - for (int i = 0; i < groups.length; i++) { + for (size_t i = 0; i < groups.length; i++) { objGroup* group = &groups.data[i]; model->attributes[3 + i] = (ModelAttribute) { .buffer = 1, @@ -287,7 +287,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source) { }; } - for (int i = 0; i < groups.length; i++) { + for (size_t i = 0; i < groups.length; i++) { objGroup* group = &groups.data[i]; model->primitives[i] = (ModelPrimitive) { .mode = DRAW_TRIANGLES, @@ -307,13 +307,13 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source) { .primitiveCount = groups.length }; - vec_deinit(&groups); - vec_deinit(&textures); - vec_deinit(&materials); + arr_free(&groups); + arr_free(&textures); + arr_free(&materials); map_deinit(&materialNames); map_deinit(&vertexMap); - vec_deinit(&positions); - vec_deinit(&normals); - vec_deinit(&uvs); + arr_free(&positions); + arr_free(&normals); + arr_free(&uvs); return model; } diff --git a/src/modules/data/rasterizer.c b/src/modules/data/rasterizer.c index 74a5d2c7..19ec2f46 100644 --- a/src/modules/data/rasterizer.c +++ b/src/modules/data/rasterizer.c @@ -7,6 +7,7 @@ #include "lib/stb/stb_truetype.h" #include #include +#include #include Rasterizer* lovrRasterizerInit(Rasterizer* rasterizer, Blob* blob, float size) { diff --git a/src/modules/data/textureData.c b/src/modules/data/textureData.c index 1e304264..443700a4 100644 --- a/src/modules/data/textureData.c +++ b/src/modules/data/textureData.c @@ -285,7 +285,8 @@ static bool parseDDS(uint8_t* data, size_t size, TextureData* textureData) { uint32_t width = textureData->width = header->width; uint32_t height = textureData->height = header->height; - uint32_t mipmapCount = MAX(header->mipMapCount, 1); + uint32_t mipmapCount = textureData->mipmapCount = MAX(header->mipMapCount, 1); + textureData->mipmaps = malloc(mipmapCount * sizeof(Mipmap)); size_t blockBytes = 0; switch (textureData->format) { @@ -303,12 +304,11 @@ static bool parseDDS(uint8_t* data, size_t size, TextureData* textureData) { // Overflow check if (mipmapSize == 0 || (offset + mipmapSize) > size) { - vec_deinit(&textureData->mipmaps); + free(textureData->mipmaps); return false; } - Mipmap mipmap = { .width = width, .height = height, .data = &data[offset], .size = mipmapSize }; - vec_push(&textureData->mipmaps, mipmap); + textureData->mipmaps[i] = (Mipmap) { .width = width, .height = height, .data = &data[offset], .size = mipmapSize }; offset += mipmapSize; width = MAX(width >> 1, 1); height = MAX(height >> 1, 1); @@ -363,18 +363,12 @@ static bool parseKTX(uint8_t* bytes, size_t size, TextureData* textureData) { uint32_t width = textureData->width = data.ktx->pixelWidth; uint32_t height = textureData->height = data.ktx->pixelHeight; - uint32_t mipmapCount = data.ktx->numberOfMipmapLevels; - vec_reserve(&textureData->mipmaps, mipmapCount); + uint32_t mipmapCount = textureData->mipmapCount = data.ktx->numberOfMipmapLevels; + textureData->mipmaps = malloc(mipmapCount * sizeof(Mipmap)); data.u8 += sizeof(KTXHeader) + data.ktx->bytesOfKeyValueData; for (uint32_t i = 0; i < mipmapCount; i++) { - vec_push(&textureData->mipmaps, ((Mipmap) { - .width = width, - .height = height, - .data = data.u8 + sizeof(uint32_t), - .size = *data.u32 - })); - + textureData->mipmaps[i] = (Mipmap) { .width = width, .height = height, .data = data.u8 + sizeof(uint32_t), .size = *data.u32 }; width = MAX(width >> 1, 1u); height = MAX(height >> 1, 1u); data.u8 = (uint8_t*) ALIGN(data.u8 + sizeof(uint32_t) + *data.u32 + 3, 4); @@ -425,13 +419,13 @@ static bool parseASTC(uint8_t* bytes, size_t size, TextureData* textureData) { textureData->width = data.astc->width[0] + (data.astc->width[1] << 8) + (data.astc->width[2] << 16); textureData->height = data.astc->height[0] + (data.astc->height[1] << 8) + (data.astc->height[2] << 16); - - vec_push(&textureData->mipmaps, ((Mipmap) { + textureData->mipmaps = malloc(sizeof(Mipmap)); + textureData->mipmaps[0] = (Mipmap) { .width = textureData->width, .height = textureData->height, .data = data.astc + 1, .size = size - sizeof(*data.astc) - })); + }; return true; } @@ -448,13 +442,10 @@ TextureData* lovrTextureDataInit(TextureData* textureData, uint32_t width, uint3 textureData->blob.data = malloc(size); lovrAssert(textureData->blob.data, "Out of memory"); memset(textureData->blob.data, value, size); - vec_init(&textureData->mipmaps); return textureData; } TextureData* lovrTextureDataInitFromBlob(TextureData* textureData, Blob* blob, bool flip) { - vec_init(&textureData->mipmaps); - if (parseDDS(blob->data, blob->size, textureData)) { textureData->source = blob; lovrRetain(blob); @@ -488,6 +479,7 @@ TextureData* lovrTextureDataInitFromBlob(TextureData* textureData, Blob* blob, b textureData->width = width; textureData->height = height; + textureData->mipmapCount = 0; return textureData; } @@ -574,6 +566,6 @@ bool lovrTextureDataEncode(TextureData* textureData, const char* filename) { void lovrTextureDataDestroy(void* ref) { TextureData* textureData = ref; lovrRelease(Blob, textureData->source); - vec_deinit(&textureData->mipmaps); + free(textureData->mipmaps); lovrBlobDestroy(ref); } diff --git a/src/modules/data/textureData.h b/src/modules/data/textureData.h index 039d8005..13d26b00 100644 --- a/src/modules/data/textureData.h +++ b/src/modules/data/textureData.h @@ -1,6 +1,5 @@ #include "data/blob.h" #include "util.h" -#include "lib/vec/vec.h" #include #include @@ -48,15 +47,14 @@ typedef struct { void* data; } Mipmap; -typedef vec_t(Mipmap) vec_mipmap_t; - typedef struct TextureData { Blob blob; uint32_t width; uint32_t height; Blob* source; TextureFormat format; - vec_mipmap_t mipmaps; + Mipmap* mipmaps; + uint32_t mipmapCount; } TextureData; TextureData* lovrTextureDataInit(TextureData* textureData, uint32_t width, uint32_t height, uint8_t value, TextureFormat format); diff --git a/src/modules/event/event.c b/src/modules/event/event.c index 2fd9891e..c9edc17e 100644 --- a/src/modules/event/event.c +++ b/src/modules/event/event.c @@ -1,14 +1,14 @@ #include "event/event.h" #include "platform.h" +#include "core/arr.h" #include "core/ref.h" -#include "lib/vec/vec.h" #include #include static struct { bool initialized; - vec_t(EventPump) pumps; - vec_t(Event) events; + arr_t(Event, 8) events; + size_t head; } state; void lovrVariantDestroy(Variant* variant) { @@ -21,47 +21,35 @@ void lovrVariantDestroy(Variant* variant) { bool lovrEventInit() { if (state.initialized) return false; - vec_init(&state.pumps); - vec_init(&state.events); - lovrEventAddPump(lovrPlatformPollEvents); + arr_init(&state.events); return state.initialized = true; } void lovrEventDestroy() { if (!state.initialized) return; - vec_deinit(&state.pumps); - vec_deinit(&state.events); + arr_free(&state.events); memset(&state, 0, sizeof(state)); } -void lovrEventAddPump(EventPump pump) { - vec_push(&state.pumps, pump); -} - -void lovrEventRemovePump(EventPump pump) { - vec_remove(&state.pumps, pump); -} - void lovrEventPump() { - int i; EventPump pump; - vec_foreach(&state.pumps, pump, i) { - pump(); - } + lovrPlatformPollEvents(); } void lovrEventPush(Event event) { - vec_insert(&state.events, 0, event); + arr_push(&state.events, event); } bool lovrEventPoll(Event* event) { - if (state.events.length == 0) { + if (state.head == state.events.length) { + state.head = state.events.length = 0; return false; } - *event = vec_pop(&state.events); + *event = state.events.data[state.head++]; return true; } void lovrEventClear() { - vec_clear(&state.events); + arr_clear(&state.events); + state.head = 0; } diff --git a/src/modules/event/event.h b/src/modules/event/event.h index 6dec9849..b0956dfd 100644 --- a/src/modules/event/event.h +++ b/src/modules/event/event.h @@ -70,14 +70,10 @@ typedef struct { EventData data; } Event; -typedef void (*EventPump)(void); - void lovrVariantDestroy(Variant* variant); bool lovrEventInit(void); void lovrEventDestroy(void); -void lovrEventAddPump(EventPump pump); -void lovrEventRemovePump(EventPump pump); void lovrEventPump(void); void lovrEventPush(Event event); bool lovrEventPoll(Event* event); diff --git a/src/modules/filesystem/file.c b/src/modules/filesystem/file.c index 5c401783..e5e5a839 100644 --- a/src/modules/filesystem/file.c +++ b/src/modules/filesystem/file.c @@ -4,6 +4,8 @@ File* lovrFileInit(File* file ,const char* path) { file->path = path; + file->handle = NULL; + file->mode = 0; return file; } diff --git a/src/modules/filesystem/filesystem.c b/src/modules/filesystem/filesystem.c index 3a8e3117..090d9a17 100644 --- a/src/modules/filesystem/filesystem.c +++ b/src/modules/filesystem/filesystem.c @@ -31,13 +31,12 @@ const char lovrDirSep = '/'; static struct { bool initialized; + bool fused; char* source; const char* identity; char* savePathRelative; char* savePathFull; - bool isFused; - char* requirePath[2]; - vec_str_t requirePattern[2]; + char requirePath[2][1024]; } state; bool lovrFilesystemInit(const char* argExe, const char* argGame, const char* argRoot) { @@ -52,16 +51,14 @@ bool lovrFilesystemInit(const char* argExe, const char* argGame, const char* arg state.source = malloc(LOVR_PATH_MAX * sizeof(char)); lovrAssert(state.source, "Out of memory"); state.identity = NULL; - state.isFused = true; - vec_init(&state.requirePattern[0]); - vec_init(&state.requirePattern[1]); + state.fused = true; lovrFilesystemSetRequirePath("?.lua;?/init.lua;lua_modules/?.lua;lua_modules/?/init.lua;deps/?.lua;deps/?/init.lua"); lovrFilesystemSetCRequirePath("??;lua_modules/??;deps/??"); // Try to mount either an archive fused to the executable or an archive from the command line lovrFilesystemGetExecutablePath(state.source, LOVR_PATH_MAX); if (!lovrFilesystemMount(state.source, NULL, 1, argRoot)) { // Attempt to load fused. If that fails... - state.isFused = false; + state.fused = false; if (argGame) { strncpy(state.source, argGame, LOVR_PATH_MAX); @@ -82,10 +79,6 @@ void lovrFilesystemDestroy() { free(state.source); free(state.savePathFull); free(state.savePathRelative); - for (int i = 0; i < 2; i++) { - free(state.requirePath[i]); - vec_deinit(&state.requirePattern[i]); - } PHYSFS_deinit(); memset(&state, 0, sizeof(state)); } @@ -151,12 +144,12 @@ const char* lovrFilesystemGetRealDirectory(const char* path) { return PHYSFS_getRealDir(path); } -vec_str_t* lovrFilesystemGetRequirePath() { - return &state.requirePattern[0]; +const char* lovrFilesystemGetRequirePath() { + return state.requirePath[0]; } -vec_str_t* lovrFilesystemGetCRequirePath() { - return &state.requirePattern[1]; +const char* lovrFilesystemGetCRequirePath() { + return state.requirePath[1]; } const char* lovrFilesystemGetSaveDirectory() { @@ -213,7 +206,7 @@ bool lovrFilesystemIsFile(const char* path) { } bool lovrFilesystemIsFused() { - return state.isFused; + return state.fused; } // Returns zero on success, nonzero on failure @@ -227,7 +220,7 @@ bool lovrFilesystemMount(const char* path, const char* mountpoint, bool append, void* lovrFilesystemRead(const char* path, size_t bytes, size_t* bytesRead) { File file; - lovrFileInit(memset(&file, 0, sizeof(File)), path); + lovrFileInit(&file, path); if (!lovrFileOpen(&file, OPEN_READ)) { return NULL; @@ -293,30 +286,12 @@ bool lovrFilesystemSetIdentity(const char* identity) { return PHYSFS_mount(state.savePathFull, NULL, 0); } -static void setRequirePath(int i, const char* requirePath) { - if (state.requirePath[i]) { - free(state.requirePath[i]); - vec_clear(&state.requirePattern[i]); - } - - char* p = state.requirePath[i] = strdup(requirePath); - - while (1) { - vec_push(&state.requirePattern[i], p); - if ((p = strchr(p, ';')) != NULL) { - *p++ = '\0'; - } else { - break; - } - } -} - void lovrFilesystemSetRequirePath(const char* requirePath) { - setRequirePath(0, requirePath); + strncpy(state.requirePath[0], requirePath, sizeof(state.requirePath[0]) - 1); } void lovrFilesystemSetCRequirePath(const char* requirePath) { - setRequirePath(1, requirePath); + strncpy(state.requirePath[1], requirePath, sizeof(state.requirePath[1]) - 1); } bool lovrFilesystemUnmount(const char* path) { diff --git a/src/modules/filesystem/filesystem.h b/src/modules/filesystem/filesystem.h index df38be38..59c344ed 100644 --- a/src/modules/filesystem/filesystem.h +++ b/src/modules/filesystem/filesystem.h @@ -1,6 +1,6 @@ -#include "lib/vec/vec.h" #include #include +#include #pragma once @@ -19,8 +19,8 @@ int lovrFilesystemGetExecutablePath(char* path, uint32_t size); const char* lovrFilesystemGetIdentity(void); long lovrFilesystemGetLastModified(const char* path); const char* lovrFilesystemGetRealDirectory(const char* path); -vec_str_t* lovrFilesystemGetRequirePath(void); -vec_str_t* lovrFilesystemGetCRequirePath(void); +const char* lovrFilesystemGetRequirePath(); +const char* lovrFilesystemGetCRequirePath(); const char* lovrFilesystemGetSaveDirectory(void); size_t lovrFilesystemGetSize(const char* path); const char* lovrFilesystemGetSource(void); diff --git a/src/modules/graphics/animator.c b/src/modules/graphics/animator.c index 8e4b86ac..c27b3959 100644 --- a/src/modules/graphics/animator.c +++ b/src/modules/graphics/animator.c @@ -13,12 +13,12 @@ Animator* lovrAnimatorInit(Animator* animator, ModelData* data) { lovrRetain(data); animator->data = data; map_init(&animator->animations); - vec_init(&animator->tracks); - vec_reserve(&animator->tracks, data->animationCount); + arr_init(&animator->tracks); + arr_reserve(&animator->tracks, data->animationCount); animator->speed = 1.f; for (uint32_t i = 0; i < data->animationCount; i++) { - vec_push(&animator->tracks, ((Track) { + arr_push(&animator->tracks, ((Track) { .time = 0.f, .speed = 1.f, .alpha = 1.f, @@ -38,12 +38,12 @@ Animator* lovrAnimatorInit(Animator* animator, ModelData* data) { void lovrAnimatorDestroy(void* ref) { Animator* animator = ref; lovrRelease(ModelData, animator->data); - vec_deinit(&animator->tracks); + arr_free(&animator->tracks); } void lovrAnimatorReset(Animator* animator) { - Track* track; int i; - vec_foreach_ptr(&animator->tracks, track, i) { + for (size_t i = 0; i < animator->tracks.length; i++) { + Track* track = &animator->tracks.data[i]; track->time = 0.f; track->speed = 1.f; track->playing = false; @@ -53,8 +53,8 @@ void lovrAnimatorReset(Animator* animator) { } void lovrAnimatorUpdate(Animator* animator, float dt) { - Track* track; int i; - vec_foreach_ptr(&animator->tracks, track, i) { + for (size_t i = 0; i < animator->tracks.length; i++) { + Track* track = &animator->tracks.data[i]; if (track->playing) { track->time += dt * track->speed * animator->speed; float duration = animator->data->animations[i].duration; @@ -247,7 +247,7 @@ int32_t lovrAnimatorGetPriority(Animator* animator, uint32_t animation) { void lovrAnimatorSetPriority(Animator* animator, uint32_t animation, int32_t priority) { Track* track = &animator->tracks.data[animation]; track->priority = priority; - vec_sort(&animator->tracks, trackSortCallback); + qsort(animator->tracks.data, animator->tracks.length, sizeof(Track), trackSortCallback); } float lovrAnimatorGetSpeed(Animator* animator, uint32_t animation) { diff --git a/src/modules/graphics/animator.h b/src/modules/graphics/animator.h index 51589606..0a333099 100644 --- a/src/modules/graphics/animator.h +++ b/src/modules/graphics/animator.h @@ -1,5 +1,5 @@ +#include "core/arr.h" #include "lib/map/map.h" -#include "lib/vec/vec.h" #include #include @@ -16,12 +16,10 @@ typedef struct { bool looping; } Track; -typedef vec_t(Track) vec_track_t; - typedef struct Animator { struct ModelData* data; map_t(uint32_t) animations; - vec_track_t tracks; + arr_t(Track, 1) tracks; float speed; } Animator; diff --git a/src/modules/graphics/graphics.h b/src/modules/graphics/graphics.h index 4c7a62d7..65724ed3 100644 --- a/src/modules/graphics/graphics.h +++ b/src/modules/graphics/graphics.h @@ -1,5 +1,6 @@ #include "graphics/font.h" #include "graphics/shader.h" +#include "core/arr.h" #include "core/maf.h" #include "util.h" #include "platform.h" @@ -307,7 +308,7 @@ typedef struct { typedef struct { int shaderSwitches; int drawCalls; - vec_t(GpuTimer) timers; + arr_t(GpuTimer, 4) timers; } GpuStats; typedef struct { diff --git a/src/modules/graphics/opengl.c b/src/modules/graphics/opengl.c index d6d78785..38b0d93d 100644 --- a/src/modules/graphics/opengl.c +++ b/src/modules/graphics/opengl.c @@ -10,7 +10,6 @@ #include "data/modelData.h" #include "core/ref.h" #include "lib/map/map.h" -#include "lib/vec/vec.h" #include #include #include @@ -82,7 +81,7 @@ static struct { Image images[MAX_IMAGES]; float viewports[2][4]; uint32_t viewportCount; - vec_void_t incoherents[MAX_BARRIERS]; + arr_t(void*, 2) incoherents[MAX_BARRIERS]; map_t(TimerList) timers; GpuFeatures features; GpuLimits limits; @@ -420,18 +419,18 @@ static void lovrGpuSync(uint8_t flags) { } if (i == BARRIER_BLOCK) { - for (int j = 0; j < state.incoherents[i].length; j++) { + for (size_t j = 0; j < state.incoherents[i].length; j++) { Buffer* buffer = state.incoherents[i].data[j]; buffer->incoherent &= ~(1 << i); } } else { - for (int j = 0; j < state.incoherents[i].length; j++) { + for (size_t j = 0; j < state.incoherents[i].length; j++) { Texture* texture = state.incoherents[i].data[j]; texture->incoherent &= ~(1 << i); } } - vec_clear(&state.incoherents[i]); + arr_clear(&state.incoherents[i]); switch (i) { case BARRIER_BLOCK: bits |= GL_SHADER_STORAGE_BARRIER_BIT; break; @@ -453,11 +452,11 @@ static void lovrGpuDestroySyncResource(void* resource, uint8_t incoherent) { return; } - for (int i = 0; i < MAX_BARRIERS; i++) { + for (uint32_t i = 0; i < MAX_BARRIERS; i++) { if (incoherent & (1 << i)) { - for (int j = 0; j < state.incoherents[i].length; j++) { + for (size_t j = 0; j < state.incoherents[i].length; j++) { if (state.incoherents[i].data[j] == resource) { - vec_swapsplice(&state.incoherents[i], j, 1); + arr_splice(&state.incoherents[i], j, 1); break; } } @@ -839,23 +838,21 @@ static void lovrGpuBindPipeline(Pipeline* pipeline) { } static void lovrGpuBindShader(Shader* shader) { - UniformBlock* block; - Uniform* uniform; - int i; - lovrGpuUseProgram(shader->program); // Figure out if we need to wait for pending writes on resources to complete #ifndef LOVR_WEBGL uint8_t flags = 0; - vec_foreach_ptr(&shader->blocks[BLOCK_COMPUTE], block, i) { + for (size_t i = 0; i < shader->blocks[BLOCK_COMPUTE].length; i++) { + UniformBlock* block = &shader->blocks[BLOCK_COMPUTE].data[i]; if (block->source && (block->source->incoherent >> BARRIER_BLOCK) & 1) { flags |= 1 << BARRIER_BLOCK; break; } } - vec_foreach_ptr(&shader->uniforms, uniform, i) { + for (size_t i = 0; i < shader->uniforms.length; i++) { + Uniform* uniform = &shader->uniforms.data[i]; if (uniform->type == UNIFORM_SAMPLER) { for (int i = 0; i < uniform->count; i++) { Texture* texture = uniform->value.textures[i]; @@ -883,7 +880,9 @@ static void lovrGpuBindShader(Shader* shader) { #endif // Bind uniforms - vec_foreach_ptr(&shader->uniforms, uniform, i) { + for (size_t i = 0; i < shader->uniforms.length; i++) { + Uniform* uniform = &shader->uniforms.data[i]; + if (uniform->type != UNIFORM_SAMPLER && uniform->type != UNIFORM_IMAGE && !uniform->dirty) { continue; } @@ -930,7 +929,7 @@ static void lovrGpuBindShader(Shader* shader) { if (texture && image->access != ACCESS_READ) { for (Barrier barrier = BARRIER_BLOCK + 1; barrier < MAX_BARRIERS; barrier++) { texture->incoherent |= 1 << barrier; - vec_push(&state.incoherents[barrier], texture); + arr_push(&state.incoherents[barrier], texture); } } @@ -951,11 +950,12 @@ static void lovrGpuBindShader(Shader* shader) { // Bind uniform blocks for (BlockType type = BLOCK_UNIFORM; type <= BLOCK_COMPUTE; type++) { - vec_foreach_ptr(&shader->blocks[type], block, i) { + for (size_t i = 0; i < shader->blocks[type].length; i++) { + UniformBlock* block = &shader->blocks[type].data[i]; if (block->source) { if (type == BLOCK_COMPUTE && block->access != ACCESS_READ) { block->source->incoherent |= (1 << BARRIER_BLOCK); - vec_push(&state.incoherents[BARRIER_BLOCK], block->source); + arr_push(&state.incoherents[BARRIER_BLOCK], block->source); } lovrBufferUnmap(block->source); @@ -1059,7 +1059,7 @@ void lovrGpuInit(getProcAddressProc getProcAddress) { #endif for (int i = 0; i < MAX_BARRIERS; i++) { - vec_init(&state.incoherents[i]); + arr_init(&state.incoherents[i]); } } @@ -1072,7 +1072,7 @@ void lovrGpuDestroy() { lovrRelease(Texture, state.images[i].texture); } for (int i = 0; i < MAX_BARRIERS; i++) { - vec_deinit(&state.incoherents[i]); + arr_free(&state.incoherents[i]); } memset(&state, 0, sizeof(state)); } @@ -1183,7 +1183,7 @@ void lovrGpuDraw(DrawCommand* draw) { void lovrGpuPresent() { state.stats.drawCalls = state.stats.shaderSwitches = 0; - vec_clear(&state.stats.timers); + arr_clear(&state.stats.timers); #ifdef __APPLE__ // For some reason instancing doesn't work on macOS unless you reset the shader every frame lovrGpuUseProgram(0); @@ -1284,7 +1284,7 @@ void lovrGpuTock(const char* label) { } glGetQueryObjectui64v(timer->timers[timer->oldest], GL_QUERY_RESULT, &timer->ns); - vec_push(&state.stats.timers, ((GpuTimer) { .label = label, .time = timer->ns / 1e9 })); + arr_push(&state.stats.timers, ((GpuTimer) { .label = label, .time = timer->ns / 1e9 })); timer->oldest = (timer->oldest + 1) % 4; } } @@ -1445,16 +1445,16 @@ void lovrTextureReplacePixels(Texture* texture, TextureData* textureData, uint32 if (isTextureFormatCompressed(textureData->format)) { lovrAssert(width == maxWidth && height == maxHeight, "Compressed texture pixels must be fully replaced"); lovrAssert(mipmap == 0, "Unable to replace a specific mipmap of a compressed texture"); - Mipmap m; int i; - vec_foreach(&textureData->mipmaps, m, i) { + for (uint32_t i = 0; i < textureData->mipmapCount; i++) { + Mipmap* m = textureData->mipmaps + i; switch (texture->type) { case TEXTURE_2D: case TEXTURE_CUBE: - glCompressedTexImage2D(binding, i, glInternalFormat, m.width, m.height, 0, m.size, m.data); + glCompressedTexImage2D(binding, i, glInternalFormat, m->width, m->height, 0, m->size, m->data); break; case TEXTURE_ARRAY: case TEXTURE_VOLUME: - glCompressedTexSubImage3D(binding, i, x, y, slice, m.width, m.height, 1, glInternalFormat, m.size, m.data); + glCompressedTexSubImage3D(binding, i, x, y, slice, m->width, m->height, 1, glInternalFormat, m->size, m->data); break; } } @@ -1795,42 +1795,42 @@ static void lovrShaderSetupUniforms(Shader* shader) { glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &blockCount); lovrAssert(blockCount <= MAX_BLOCK_BUFFERS, "Shader has too many uniform blocks (%d) the max is %d", blockCount, MAX_BLOCK_BUFFERS); map_init(&shader->blockMap); - vec_block_t* uniformBlocks = &shader->blocks[BLOCK_UNIFORM]; - vec_init(uniformBlocks); - vec_reserve(uniformBlocks, blockCount); + arr_block_t* uniformBlocks = &shader->blocks[BLOCK_UNIFORM]; + arr_init(uniformBlocks); + arr_reserve(uniformBlocks, (size_t) blockCount); for (int i = 0; i < blockCount; i++) { UniformBlock block = { .slot = i, .source = NULL }; glUniformBlockBinding(program, i, block.slot); - vec_init(&block.uniforms); + arr_init(&block.uniforms); char name[LOVR_MAX_UNIFORM_LENGTH]; glGetActiveUniformBlockName(program, i, LOVR_MAX_UNIFORM_LENGTH, NULL, name); int blockId = (i << 1) + BLOCK_UNIFORM; map_set(&shader->blockMap, name, blockId); - vec_push(uniformBlocks, block); + arr_push(uniformBlocks, block); } // Shader storage buffers and their buffer variables - vec_block_t* computeBlocks = &shader->blocks[BLOCK_COMPUTE]; - vec_init(computeBlocks); + arr_block_t* computeBlocks = &shader->blocks[BLOCK_COMPUTE]; + arr_init(computeBlocks); #ifndef LOVR_WEBGL if (GLAD_GL_ARB_shader_storage_buffer_object && GLAD_GL_ARB_program_interface_query) { // Iterate over compute blocks, setting their binding and pushing them onto the block vector - int computeBlockCount; + int32_t computeBlockCount; glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &computeBlockCount); lovrAssert(computeBlockCount <= MAX_BLOCK_BUFFERS, "Shader has too many compute blocks (%d) the max is %d", computeBlockCount, MAX_BLOCK_BUFFERS); - vec_reserve(computeBlocks, computeBlockCount); + arr_reserve(computeBlocks, (size_t) computeBlockCount); for (int i = 0; i < computeBlockCount; i++) { UniformBlock block = { .slot = i, .source = NULL }; glShaderStorageBlockBinding(program, i, block.slot); - vec_init(&block.uniforms); + arr_init(&block.uniforms); char name[LOVR_MAX_UNIFORM_LENGTH]; glGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, i, LOVR_MAX_UNIFORM_LENGTH, NULL, name); int blockId = (i << 1) + BLOCK_COMPUTE; map_set(&shader->blockMap, name, blockId); - vec_push(computeBlocks, block); + arr_push(computeBlocks, block); } // Iterate over buffer variables, pushing them onto the uniform list of the correct block @@ -1854,7 +1854,7 @@ static void lovrShaderSetupUniforms(Shader* shader) { } else { uniform.size = 4 * (uniform.components == 3 ? 4 : uniform.components); } - vec_push(&computeBlocks->data[values[blockIndex]].uniforms, uniform); + arr_push(&computeBlocks->data[values[blockIndex]].uniforms, uniform); } } #endif @@ -1864,7 +1864,7 @@ static void lovrShaderSetupUniforms(Shader* shader) { int textureSlot = 0; int imageSlot = 0; map_init(&shader->uniformMap); - vec_init(&shader->uniforms); + arr_init(&shader->uniforms); glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniformCount); for (uint32_t i = 0; i < (uint32_t) uniformCount; i++) { Uniform uniform; @@ -1910,7 +1910,7 @@ static void lovrShaderSetupUniforms(Shader* shader) { uniform.size = 4 * (uniform.components == 3 ? 4 : uniform.components); } - vec_push(&block->uniforms, uniform); + arr_push(&block->uniforms, uniform); continue; } else if (uniform.location == -1) { continue; @@ -1971,7 +1971,7 @@ static void lovrShaderSetupUniforms(Shader* shader) { } map_set(&shader->uniformMap, uniform.name, shader->uniforms.length); - vec_push(&shader->uniforms, uniform); + arr_push(&shader->uniforms, uniform); textureSlot += uniform.type == UNIFORM_SAMPLER ? uniform.count : 0; imageSlot += uniform.type == UNIFORM_IMAGE ? uniform.count : 0; } @@ -2115,18 +2115,17 @@ void lovrShaderDestroy(void* ref) { Shader* shader = ref; lovrGraphicsFlushShader(shader); glDeleteProgram(shader->program); - for (int i = 0; i < shader->uniforms.length; i++) { + for (size_t i = 0; i < shader->uniforms.length; i++) { free(shader->uniforms.data[i].value.data); } for (BlockType type = BLOCK_UNIFORM; type <= BLOCK_COMPUTE; type++) { - UniformBlock* block; int i; - vec_foreach_ptr(&shader->blocks[type], block, i) { - lovrRelease(Buffer, block->source); + for (size_t i = 0; i < shader->blocks[type].length; i++) { + lovrRelease(Buffer, shader->blocks[type].data[i].source); } } - vec_deinit(&shader->uniforms); - vec_deinit(&shader->blocks[BLOCK_UNIFORM]); - vec_deinit(&shader->blocks[BLOCK_COMPUTE]); + arr_free(&shader->uniforms); + arr_free(&shader->blocks[BLOCK_UNIFORM]); + arr_free(&shader->blocks[BLOCK_COMPUTE]); map_deinit(&shader->attributes); map_deinit(&shader->uniformMap); map_deinit(&shader->blockMap); diff --git a/src/modules/graphics/shader.c b/src/modules/graphics/shader.c index bdcd9265..3a480ae7 100644 --- a/src/modules/graphics/shader.c +++ b/src/modules/graphics/shader.c @@ -159,11 +159,11 @@ void lovrShaderSetBlock(Shader* shader, const char* name, Buffer* buffer, size_t // ShaderBlock // Calculates uniform size and byte offsets using std140 rules, returning the total buffer size -size_t lovrShaderComputeUniformLayout(vec_uniform_t* uniforms) { +size_t lovrShaderComputeUniformLayout(arr_uniform_t* uniforms) { size_t size = 0; - Uniform* uniform; int i; - vec_foreach_ptr(uniforms, uniform, i) { + for (size_t i = 0; i < uniforms->length; i++) { int align; + Uniform* uniform = &uniforms->data[i]; if (uniform->count > 1 || uniform->type == UNIFORM_MATRIX) { align = 16 * (uniform->type == UNIFORM_MATRIX ? uniform->components : 1); uniform->size = align * uniform->count; @@ -177,14 +177,14 @@ size_t lovrShaderComputeUniformLayout(vec_uniform_t* uniforms) { return size; } -ShaderBlock* lovrShaderBlockInit(ShaderBlock* block, BlockType type, Buffer* buffer, vec_uniform_t* uniforms) { - vec_init(&block->uniforms); +ShaderBlock* lovrShaderBlockInit(ShaderBlock* block, BlockType type, Buffer* buffer, arr_uniform_t* uniforms) { + arr_init(&block->uniforms); map_init(&block->uniformMap); - Uniform* uniform; int i; - vec_extend(&block->uniforms, uniforms); - vec_foreach_ptr(&block->uniforms, uniform, i) { - map_set(&block->uniformMap, uniform->name, i); + arr_append(&block->uniforms, uniforms->data, uniforms->length); + + for (size_t i = 0; i < block->uniforms.length; i++) { + map_set(&block->uniformMap, block->uniforms.data[i].name, i); } block->type = type; @@ -196,7 +196,7 @@ ShaderBlock* lovrShaderBlockInit(ShaderBlock* block, BlockType type, Buffer* buf void lovrShaderBlockDestroy(void* ref) { ShaderBlock* block = ref; lovrRelease(Buffer, block->buffer); - vec_deinit(&block->uniforms); + arr_free(&block->uniforms); map_deinit(&block->uniformMap); } @@ -215,7 +215,7 @@ char* lovrShaderBlockGetShaderCode(ShaderBlock* block, const char* blockName, si size += 1; // " " size += strlen(blockName); size += 3; // " {\n" - for (int i = 0; i < block->uniforms.length; i++) { + for (size_t i = 0; i < block->uniforms.length; i++) { size += tab; size += getUniformTypeLength(&block->uniforms.data[i]); size += 1; // " " @@ -231,7 +231,7 @@ char* lovrShaderBlockGetShaderCode(ShaderBlock* block, const char* blockName, si // Concatenate char* s = code; s += sprintf(s, "layout(std140) %s %s {\n", block->type == BLOCK_UNIFORM ? "uniform" : "buffer", blockName); - for (int i = 0; i < block->uniforms.length; i++) { + for (size_t i = 0; i < block->uniforms.length; i++) { const Uniform* uniform = &block->uniforms.data[i]; if (uniform->count > 1) { s += sprintf(s, " %s %s[%d];\n", getUniformTypeName(uniform), uniform->name, uniform->count); diff --git a/src/modules/graphics/shader.h b/src/modules/graphics/shader.h index 10fabad5..44c9267a 100644 --- a/src/modules/graphics/shader.h +++ b/src/modules/graphics/shader.h @@ -1,7 +1,7 @@ #include "graphics/texture.h" #include "graphics/opengl.h" +#include "core/arr.h" #include "lib/map/map.h" -#include "lib/vec/vec.h" #include #pragma once @@ -89,17 +89,17 @@ typedef struct Uniform { bool dirty; } Uniform; -typedef vec_t(Uniform) vec_uniform_t; +typedef arr_t(Uniform, 8) arr_uniform_t; typedef struct { BlockType type; - vec_uniform_t uniforms; + arr_uniform_t uniforms; map_int_t uniformMap; struct Buffer* buffer; } ShaderBlock; typedef struct { - vec_uniform_t uniforms; + arr_uniform_t uniforms; UniformAccess access; struct Buffer* source; size_t offset; @@ -107,12 +107,12 @@ typedef struct { int slot; } UniformBlock; -typedef vec_t(UniformBlock) vec_block_t; +typedef arr_t(UniformBlock, 1) arr_block_t; typedef struct Shader { ShaderType type; - vec_uniform_t uniforms; - vec_block_t blocks[2]; + arr_uniform_t uniforms; + arr_block_t blocks[2]; map_int_t attributes; map_int_t uniformMap; map_int_t blockMap; @@ -142,9 +142,9 @@ void lovrShaderSetBlock(Shader* shader, const char* name, struct Buffer* buffer, // ShaderBlock -size_t lovrShaderComputeUniformLayout(vec_uniform_t* uniforms); +size_t lovrShaderComputeUniformLayout(arr_uniform_t* uniforms); -ShaderBlock* lovrShaderBlockInit(ShaderBlock* block, BlockType type, struct Buffer* buffer, vec_uniform_t* uniforms); +ShaderBlock* lovrShaderBlockInit(ShaderBlock* block, BlockType type, struct Buffer* buffer, arr_uniform_t* uniforms); #define lovrShaderBlockCreate(...) lovrShaderBlockInit(lovrAlloc(ShaderBlock), __VA_ARGS__) void lovrShaderBlockDestroy(void* ref); BlockType lovrShaderBlockGetType(ShaderBlock* block); diff --git a/src/modules/headset/openvr.c b/src/modules/headset/openvr.c index 843ae5f1..af516b22 100644 --- a/src/modules/headset/openvr.c +++ b/src/modules/headset/openvr.c @@ -86,7 +86,7 @@ static struct { RenderModel_t* deviceModels[16]; RenderModel_TextureMap_t* deviceTextures[16]; Canvas* canvas; - vec_float_t boundsGeometry; + float boundsGeometry[16]; float clipNear; float clipFar; float offset; @@ -205,7 +205,6 @@ static bool openvr_init(float offset, uint32_t msaa) { state.offset = state.compositor->GetTrackingSpace() == ETrackingUniverseOrigin_TrackingUniverseStanding ? 0. : offset; state.msaa = msaa; - vec_init(&state.boundsGeometry); return true; } @@ -221,7 +220,6 @@ static void openvr_destroy(void) { state.deviceModels[i] = NULL; state.deviceTextures[i] = NULL; } - vec_deinit(&state.boundsGeometry); VR_ShutdownInternal(); memset(&state, 0, sizeof(state)); } @@ -272,16 +270,13 @@ static void openvr_getBoundsDimensions(float* width, float* depth) { static const float* openvr_getBoundsGeometry(uint32_t* count) { struct HmdQuad_t quad; if (state.chaperone->GetPlayAreaRect(&quad)) { - vec_clear(&state.boundsGeometry); - for (int i = 0; i < 4; i++) { - vec_push(&state.boundsGeometry, quad.vCorners[i].v[0]); - vec_push(&state.boundsGeometry, quad.vCorners[i].v[1]); - vec_push(&state.boundsGeometry, quad.vCorners[i].v[2]); + state.boundsGeometry[4 * i + 0] = quad.vCorners[i].v[0]; + state.boundsGeometry[4 * i + 1] = quad.vCorners[i].v[1]; + state.boundsGeometry[4 * i + 2] = quad.vCorners[i].v[2]; } - *count = state.boundsGeometry.length; - return state.boundsGeometry.data; + return *count = 16, state.boundsGeometry; } return NULL; diff --git a/src/modules/math/curve.c b/src/modules/math/curve.c index 59296c7c..5a2bd475 100644 --- a/src/modules/math/curve.c +++ b/src/modules/math/curve.c @@ -4,7 +4,7 @@ #include // Explicit curve evaluation, unroll simple cases to avoid pow overhead -static void evaluate(float* P, int n, float t, vec3 p) { +static void evaluate(float* P, size_t n, float t, vec3 p) { if (n == 2) { p[0] = P[0] + (P[4] - P[0]) * t; p[1] = P[1] + (P[5] - P[1]) * t; @@ -32,7 +32,7 @@ static void evaluate(float* P, int n, float t, vec3 p) { } else { float b = 1.f; p[0] = p[1] = p[2] = p[3] = 0.f; - for (int i = 0; i < n; i++, b *= (float) (n - i) / i) { + for (size_t i = 0; i < n; i++, b *= (float) (n - i) / i) { float c1 = powf(1 - t, n - (i + 1)); float c2 = powf(t, i); p[0] += b * c1 * c2 * P[i * 4 + 0]; @@ -43,15 +43,14 @@ static void evaluate(float* P, int n, float t, vec3 p) { } } -Curve* lovrCurveInit(Curve* curve, int sizeHint) { - vec_init(&curve->points); - lovrAssert(!vec_reserve(&curve->points, sizeHint * 4), "Out of memory"); +Curve* lovrCurveInit(Curve* curve) { + arr_init(&curve->points); return curve; } void lovrCurveDestroy(void* ref) { Curve* curve = ref; - vec_deinit(&curve->points); + arr_free(&curve->points); } void lovrCurveEvaluate(Curve* curve, float t, vec3 p) { @@ -62,18 +61,18 @@ void lovrCurveEvaluate(Curve* curve, float t, vec3 p) { void lovrCurveGetTangent(Curve* curve, float t, vec3 p) { float q[4]; - int n = curve->points.length / 4; + size_t n = curve->points.length / 4; evaluate(curve->points.data, n - 1, t, q); evaluate(curve->points.data + 4, n - 1, t, p); vec3_add(p, vec3_scale(q, -1.f)); vec3_normalize(p); } -void lovrCurveRender(Curve* curve, float t1, float t2, vec3 points, int n) { +void lovrCurveRender(Curve* curve, float t1, float t2, vec3 points, uint32_t n) { lovrAssert(curve->points.length >= 8, "Need at least 2 points to render a Curve"); lovrAssert(t1 >= 0.f && t2 <= 1.f, "Curve render interval must be within [0, 1]"); float step = 1.f / (n - 1); - for (int i = 0; i < n; i++) { + for (uint32_t i = 0; i < n; i++) { evaluate(curve->points.data, curve->points.length / 4, t1 + (t2 - t1) * i * step, points + 4 * i); } } @@ -82,13 +81,14 @@ Curve* lovrCurveSlice(Curve* curve, float t1, float t2) { lovrAssert(curve->points.length >= 8, "Need at least 2 points to slice a Curve"); lovrAssert(t1 >= 0.f && t2 <= 1.f, "Curve slice interval must be within [0, 1]"); - Curve* new = lovrCurveCreate(curve->points.length / 4); + Curve* new = lovrCurveCreate(); + arr_reserve(&new->points, curve->points.length); new->points.length = curve->points.length; - int n = curve->points.length / 4; + size_t n = curve->points.length / 4; // Right half of split at t1 - for (int i = 0; i < n - 1; i++) { + for (size_t i = 0; i < n - 1; i++) { evaluate(curve->points.data + 4 * i, n - i, t1, new->points.data + 4 * i); } @@ -96,29 +96,29 @@ Curve* lovrCurveSlice(Curve* curve, float t1, float t2) { // Split segment at t2, taking left half float t = (t2 - t1) / (1.f - t1); - for (int i = n - 1; i >= 1; i--) { + for (size_t i = n - 1; i >= 1; i--) { evaluate(new->points.data, i + 1, t, new->points.data + 4 * i); } return new; } -int lovrCurveGetPointCount(Curve* curve) { +size_t lovrCurveGetPointCount(Curve* curve) { return curve->points.length / 4; } -void lovrCurveGetPoint(Curve* curve, int index, vec3 point) { +void lovrCurveGetPoint(Curve* curve, size_t index, vec3 point) { vec3_init(point, curve->points.data + 4 * index); } -void lovrCurveSetPoint(Curve* curve, int index, vec3 point) { +void lovrCurveSetPoint(Curve* curve, size_t index, vec3 point) { vec3_init(curve->points.data + 4 * index, point); } -void lovrCurveAddPoint(Curve* curve, vec3 point, int index) { +void lovrCurveAddPoint(Curve* curve, vec3 point, size_t index) { // Reserve enough memory for 4 more floats, then record destination once memory is allocated - lovrAssert(!vec_reserve(&curve->points, curve->points.length + 4), "Out of memory"); + arr_reserve(&curve->points, curve->points.length + 4); float* dest = curve->points.data + index * 4; // Shift remaining points over (if any) to create empty space @@ -131,6 +131,6 @@ void lovrCurveAddPoint(Curve* curve, vec3 point, int index) { memcpy(dest, point, 4 * sizeof(float)); } -void lovrCurveRemovePoint(Curve* curve, int index) { - vec_swapsplice(&curve->points, index * 4, 4); +void lovrCurveRemovePoint(Curve* curve, size_t index) { + arr_splice(&curve->points, index * 4, 4); } diff --git a/src/modules/math/curve.h b/src/modules/math/curve.h index 59c92faf..6fe1ef59 100644 --- a/src/modules/math/curve.h +++ b/src/modules/math/curve.h @@ -1,19 +1,19 @@ +#include "core/arr.h" #include "core/maf.h" -#include "lib/vec/vec.h" typedef struct { - vec_float_t points; + arr_t(float, 16) points; } Curve; -Curve* lovrCurveInit(Curve* curve, int sizeHint); -#define lovrCurveCreate(...) lovrCurveInit(lovrAlloc(Curve), __VA_ARGS__) +Curve* lovrCurveInit(Curve* curve); +#define lovrCurveCreate(...) lovrCurveInit(lovrAlloc(Curve)) void lovrCurveDestroy(void* ref); void lovrCurveEvaluate(Curve* curve, float t, vec3 point); void lovrCurveGetTangent(Curve* curve, float t, vec3 point); -void lovrCurveRender(Curve* curve, float t1, float t2, vec3 points, int n); +void lovrCurveRender(Curve* curve, float t1, float t2, vec3 points, uint32_t n); Curve* lovrCurveSlice(Curve* curve, float t1, float t2); -int lovrCurveGetPointCount(Curve* curve); -void lovrCurveGetPoint(Curve* curve, int index, vec3 point); -void lovrCurveSetPoint(Curve* curve, int index, vec3 point); -void lovrCurveAddPoint(Curve* curve, vec3 point, int index); -void lovrCurveRemovePoint(Curve* curve, int index); +size_t lovrCurveGetPointCount(Curve* curve); +void lovrCurveGetPoint(Curve* curve, size_t index, vec3 point); +void lovrCurveSetPoint(Curve* curve, size_t index, vec3 point); +void lovrCurveAddPoint(Curve* curve, vec3 point, size_t index); +void lovrCurveRemovePoint(Curve* curve, size_t index); diff --git a/src/modules/physics/physics.c b/src/modules/physics/physics.c index 1a7d3122..018bc71b 100644 --- a/src/modules/physics/physics.c +++ b/src/modules/physics/physics.c @@ -11,8 +11,8 @@ static void defaultNearCallback(void* data, dGeomID a, dGeomID b) { static void customNearCallback(void* data, dGeomID shapeA, dGeomID shapeB) { World* world = data; - vec_push(&world->overlaps, dGeomGetData(shapeA)); - vec_push(&world->overlaps, dGeomGetData(shapeB)); + arr_push(&world->overlaps, dGeomGetData(shapeA)); + arr_push(&world->overlaps, dGeomGetData(shapeB)); } static void raycastCallback(void* data, dGeomID a, dGeomID b) { @@ -50,7 +50,7 @@ World* lovrWorldInit(World* world, float xg, float yg, float zg, bool allowSleep world->space = dHashSpaceCreate(0); dHashSpaceSetLevels(world->space, -4, 8); world->contactGroup = dJointGroupCreate(0); - vec_init(&world->overlaps); + arr_init(&world->overlaps); lovrWorldSetGravity(world, xg, yg, zg); lovrWorldSetSleepingAllowed(world, allowSleep); map_init(&world->tags); @@ -68,7 +68,7 @@ World* lovrWorldInit(World* world, float xg, float yg, float zg, bool allowSleep void lovrWorldDestroy(void* ref) { World* world = ref; lovrWorldDestroyData(world); - vec_deinit(&world->overlaps); + arr_free(&world->overlaps); map_deinit(&world->tags); } @@ -110,7 +110,7 @@ void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* u } void lovrWorldComputeOverlaps(World* world) { - vec_clear(&world->overlaps); + arr_clear(&world->overlaps); dSpaceCollide(world->space, world, customNearCallback); } @@ -120,8 +120,8 @@ int lovrWorldGetNextOverlap(World* world, Shape** a, Shape** b) { return 0; } - *a = vec_pop(&world->overlaps); - *b = vec_pop(&world->overlaps); + *a = arr_pop(&world->overlaps); + *b = arr_pop(&world->overlaps); return 1; } @@ -278,8 +278,8 @@ Collider* lovrColliderInit(Collider* collider, World* world, float x, float y, f collider->restitution = 0; collider->tag = NO_TAG; dBodySetData(collider->body, collider); - vec_init(&collider->shapes); - vec_init(&collider->joints); + arr_init(&collider->shapes); + arr_init(&collider->joints); lovrColliderSetPosition(collider, x, y, z); @@ -300,8 +300,8 @@ Collider* lovrColliderInit(Collider* collider, World* world, float x, float y, f void lovrColliderDestroy(void* ref) { Collider* collider = ref; lovrColliderDestroyData(collider); - vec_deinit(&collider->shapes); - vec_deinit(&collider->joints); + arr_free(&collider->shapes); + arr_free(&collider->joints); } void lovrColliderDestroyData(Collider* collider) { @@ -309,16 +309,16 @@ void lovrColliderDestroyData(Collider* collider) { return; } - vec_void_t* shapes = lovrColliderGetShapes(collider); - Shape* shape; int i; - vec_foreach(shapes, shape, i) { - lovrColliderRemoveShape(collider, shape); + size_t count; + + Shape** shapes = lovrColliderGetShapes(collider, &count); + for (size_t i = 0; i < count; i++) { + lovrColliderRemoveShape(collider, shapes[i]); } - vec_void_t* joints = lovrColliderGetJoints(collider); - Joint* joint; int j; - vec_foreach(joints, joint, j) { - lovrRelease(Joint, joint); + Joint** joints = lovrColliderGetJoints(collider, &count); + for (size_t i = 0; i < count; i++) { + lovrRelease(Joint, joints[i]); } dBodyDestroy(collider->body); @@ -359,27 +359,27 @@ void lovrColliderRemoveShape(Collider* collider, Shape* shape) { } } -vec_void_t* lovrColliderGetShapes(Collider* collider) { - vec_clear(&collider->shapes); +Shape** lovrColliderGetShapes(Collider* collider, size_t* count) { + arr_clear(&collider->shapes); for (dGeomID geom = dBodyGetFirstGeom(collider->body); geom; geom = dBodyGetNextGeom(geom)) { Shape* shape = dGeomGetData(geom); if (shape) { - vec_push(&collider->shapes, shape); + arr_push(&collider->shapes, shape); } } - return &collider->shapes; + return *count = collider->shapes.length, collider->shapes.data; } -vec_void_t* lovrColliderGetJoints(Collider* collider) { - vec_clear(&collider->joints); +Joint** lovrColliderGetJoints(Collider* collider, size_t* count) { + arr_clear(&collider->joints); int jointCount = dBodyGetNumJoints(collider->body); for (int i = 0; i < jointCount; i++) { Joint* joint = dJointGetData(dBodyGetJoint(collider->body, i)); if (joint) { - vec_push(&collider->joints, joint); + arr_push(&collider->joints, joint); } } - return &collider->joints; + return *count = collider->joints.length, collider->joints.data; } void* lovrColliderGetUserData(Collider* collider) { diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index 3b3b33d4..a2b58753 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -1,4 +1,4 @@ -#include "lib/vec/vec.h" +#include "core/arr.h" #include "lib/map/map.h" #include #include @@ -25,12 +25,14 @@ typedef enum { } JointType; typedef struct Collider Collider; +typedef struct Shape Shape; +typedef struct Joint Joint; typedef struct { dWorldID id; dSpaceID space; dJointGroupID contactGroup; - vec_void_t overlaps; + arr_t(Shape*, 8) overlaps; map_int_t tags; uint16_t masks[MAX_TAGS]; Collider* head; @@ -43,29 +45,29 @@ struct Collider { Collider* next; void* userdata; int tag; - vec_void_t shapes; - vec_void_t joints; + arr_t(Shape*, 2) shapes; + arr_t(Joint*, 2) joints; float friction; float restitution; }; -typedef struct Shape { +struct Shape { ShapeType type; dGeomID id; Collider* collider; void* userdata; -} Shape; +}; typedef Shape SphereShape; typedef Shape BoxShape; typedef Shape CapsuleShape; typedef Shape CylinderShape; -typedef struct Joint { +struct Joint { JointType type; dJointID id; void* userdata; -} Joint; +}; typedef Joint BallJoint; typedef Joint DistanceJoint; @@ -112,8 +114,8 @@ void lovrColliderDestroyData(Collider* collider); World* lovrColliderGetWorld(Collider* collider); void lovrColliderAddShape(Collider* collider, Shape* shape); void lovrColliderRemoveShape(Collider* collider, Shape* shape); -vec_void_t* lovrColliderGetShapes(Collider* collider); -vec_void_t* lovrColliderGetJoints(Collider* collider); +Shape** lovrColliderGetShapes(Collider* collider, size_t* count); +Joint** lovrColliderGetJoints(Collider* collider, size_t* count); void* lovrColliderGetUserData(Collider* collider); void lovrColliderSetUserData(Collider* collider, void* data); const char* lovrColliderGetTag(Collider* collider); diff --git a/src/modules/thread/channel.c b/src/modules/thread/channel.c index 11c2436e..20f1e2b7 100644 --- a/src/modules/thread/channel.c +++ b/src/modules/thread/channel.c @@ -5,7 +5,7 @@ #include Channel* lovrChannelInit(Channel* channel) { - vec_init(&channel->messages); + arr_init(&channel->messages); mtx_init(&channel->lock, mtx_plain | mtx_timed); cnd_init(&channel->cond); return channel; @@ -14,7 +14,7 @@ Channel* lovrChannelInit(Channel* channel) { void lovrChannelDestroy(void* ref) { Channel* channel = ref; lovrChannelClear(channel); - vec_deinit(&channel->messages); + arr_free(&channel->messages); mtx_destroy(&channel->lock); cnd_destroy(&channel->cond); } @@ -24,7 +24,7 @@ bool lovrChannelPush(Channel* channel, Variant variant, double timeout, uint64_t if (channel->messages.length == 0) { lovrRetain(channel); } - vec_insert(&channel->messages, 0, variant); + arr_push(&channel->messages, variant); *id = ++channel->sent; cnd_broadcast(&channel->cond); @@ -47,7 +47,7 @@ bool lovrChannelPush(Channel* channel, Variant variant, double timeout, uint64_t until.tv_nsec = start.tv_nsec + fraction * 1e9; cnd_timedwait(&channel->cond, &channel->lock, &until); timespec_get(&stop, TIME_UTC); - timeout -= (stop.tv_sec - start.tv_sec) + (stop.tv_nsec - start.tv_nsec) / (double) 1e9; + timeout -= (stop.tv_sec - start.tv_sec) + (stop.tv_nsec - start.tv_nsec) / 1e9; } } @@ -60,9 +60,10 @@ bool lovrChannelPop(Channel* channel, Variant* variant, double timeout) { mtx_lock(&channel->lock); do { - if (channel->messages.length > 0) { - *variant = vec_pop(&channel->messages); - if (channel->messages.length == 0) { + if (channel->head < channel->messages.length) { + *variant = channel->messages.data[channel->head++]; + if (channel->head == channel->messages.length) { + channel->head = channel->messages.length = 0; lovrRelease(Channel, channel); } channel->received++; @@ -89,14 +90,14 @@ bool lovrChannelPop(Channel* channel, Variant* variant, double timeout) { timespec_get(&stop, TIME_UTC); timeout -= (stop.tv_sec - start.tv_sec) + (stop.tv_nsec - start.tv_nsec) / (double) 1e9; } - } while (true); + } while (1); } bool lovrChannelPeek(Channel* channel, Variant* variant) { mtx_lock(&channel->lock); - if (channel->messages.length > 0) { - *variant = vec_last(&channel->messages); + if (channel->head < channel->messages.length) { + *variant = channel->messages.data[channel->head]; mtx_unlock(&channel->lock); return true; } @@ -107,18 +108,19 @@ bool lovrChannelPeek(Channel* channel, Variant* variant) { void lovrChannelClear(Channel* channel) { mtx_lock(&channel->lock); - for (int i = 0; i < channel->messages.length; i++) { + for (size_t i = channel->head; i < channel->messages.length; i++) { lovrVariantDestroy(&channel->messages.data[i]); } channel->received = channel->sent; - vec_clear(&channel->messages); + arr_clear(&channel->messages); + channel->head = 0; cnd_broadcast(&channel->cond); mtx_unlock(&channel->lock); } uint64_t lovrChannelGetCount(Channel* channel) { mtx_lock(&channel->lock); - uint64_t length = channel->messages.length; + uint64_t length = channel->messages.length - channel->head; mtx_unlock(&channel->lock); return length; } diff --git a/src/modules/thread/channel.h b/src/modules/thread/channel.h index bac5d6d8..15b53d79 100644 --- a/src/modules/thread/channel.h +++ b/src/modules/thread/channel.h @@ -1,15 +1,17 @@ #include "event/event.h" +#include "core/arr.h" #include "lib/tinycthread/tinycthread.h" -#include "lib/vec/vec.h" #include #include +#include #pragma once typedef struct Channel { mtx_t lock; cnd_t cond; - vec_t(Variant) messages; + arr_t(Variant, 1) messages; + size_t head; uint64_t sent; uint64_t received; } Channel;