First round of asset refactoring

This commit is contained in:
2026-06-05 13:18:08 -05:00
parent 3c8b6cb2cc
commit a9e664492f
14 changed files with 144 additions and 102 deletions
+4 -4
View File
@@ -5,7 +5,7 @@
#include "easing.h" #include "easing.h"
#include "assert/assert.h" #include "assert/assert.h"
#include <math.h> #include "util/math.h"
const easingfn_t EASING_FUNCTIONS[EASING_COUNT] = { const easingfn_t EASING_FUNCTIONS[EASING_COUNT] = {
easingLinear, easingLinear,
@@ -36,15 +36,15 @@ float_t easingLinear(const float_t t) {
} }
float_t easingInSine(const float_t t) { float_t easingInSine(const float_t t) {
return 1.0f - cosf(t * EASING_PI * 0.5f); return 1.0f - cosf(t * MATH_PI * 0.5f);
} }
float_t easingOutSine(const float_t t) { float_t easingOutSine(const float_t t) {
return sinf(t * EASING_PI * 0.5f); return sinf(t * MATH_PI * 0.5f);
} }
float_t easingInOutSine(const float_t t) { float_t easingInOutSine(const float_t t) {
return -(cosf(EASING_PI * t) - 1.0f) * 0.5f; return -(cosf(MATH_PI * t) - 1.0f) * 0.5f;
} }
float_t easingInQuad(const float_t t) { float_t easingInQuad(const float_t t) {
+28 -22
View File
@@ -9,13 +9,16 @@
#include "log/log.h" #include "log/log.h"
#include "util/string.h" #include "util/string.h"
#include "util/memory.h" #include "util/memory.h"
#ifdef DUSK_THREAD_PTHREAD #ifdef DUSK_THREAD_PTHREAD
#include "thread/thread.h" pthread_t ASSERT_MAIN_THREAD_ID = 0;
#endif #endif
#ifndef DUSK_ASSERTIONS_FAKED #ifndef DUSK_ASSERTIONS_FAKED
void assertInit(void) { void assertInit(void) {
assertMainThreadInit(); #ifdef DUSK_THREAD_PTHREAD
ASSERT_MAIN_THREAD_ID = pthread_self();
#endif
} }
#ifdef DUSK_TEST_ASSERT #ifdef DUSK_TEST_ASSERT
@@ -140,25 +143,28 @@
assertTrueImpl(file, line, stringCompare(a, b) == 0, message); assertTrueImpl(file, line, stringCompare(a, b) == 0, message);
} }
#ifdef DUSK_THREAD_PTHREAD void assertIsMainThreadImpl(
void assertMainThreadInit(void) { const char *file,
THREAD_MAIN_THREAD_ID = pthread_self(); const int32_t line,
} const char *message
) {
#ifdef DUSK_THREAD_PTHREAD
assertTrueImpl(
file, line, pthread_self() == ASSERT_MAIN_THREAD_ID, message
);
#endif
}
void assertIsMainThreadImpl( void assertNotMainThreadImpl(
const char *file, const char *file,
const int32_t line, const int32_t line,
const char *message const char *message
) { ) {
assertTrueImpl(file, line, pthread_self() == THREAD_MAIN_THREAD_ID, message); #ifdef DUSK_THREAD_PTHREAD
} assertTrueImpl(
file, line, pthread_self() != ASSERT_MAIN_THREAD_ID, message
void assertNotMainThreadImpl( );
const char *file, #endif
const int32_t line, }
const char *message
) {
assertTrueImpl(file, line, pthread_self() != THREAD_MAIN_THREAD_ID, message);
}
#endif
#endif #endif
+46 -46
View File
@@ -16,6 +16,11 @@
#endif #endif
#endif #endif
#ifdef DUSK_THREAD_PTHREAD
#include "thread/thread.h"
extern pthread_t ASSERT_MAIN_THREAD_ID;
#endif
#ifndef DUSK_ASSERTIONS_FAKED #ifndef DUSK_ASSERTIONS_FAKED
/** /**
* Initializes the assert system. Must be the very first call in engine * Initializes the assert system. Must be the very first call in engine
@@ -23,51 +28,6 @@
*/ */
void assertInit(void); void assertInit(void);
/**
* Records the calling thread as the main (game) thread. Call once, early
* in engine startup, before any assertIsMainThread / assertNotMainThread
* checks are made.
*/
#ifdef DUSK_THREAD_PTHREAD
void assertMainThreadInit(void);
#else
#define assertMainThreadInit() ((void)0)
#endif
/**
* Asserts that the current thread is the main thread.
*
* @param message Message to throw against assertion failure.
*/
#ifdef DUSK_THREAD_PTHREAD
void assertIsMainThreadImpl(
const char *file,
const int32_t line,
const char *message
);
#define assertIsMainThread(message) \
assertIsMainThreadImpl(__FILE__, __LINE__, message)
#else
#define assertIsMainThread(message) ((void)0)
#endif
/**
* Asserts that the current thread is NOT the main thread.
*
* @param message Message to throw against assertion failure.
*/
#ifdef DUSK_THREAD_PTHREAD
void assertNotMainThreadImpl(
const char *file,
const int32_t line,
const char *message
);
#define assertNotMainThread(message) \
assertNotMainThreadImpl(__FILE__, __LINE__, message)
#else
#define assertNotMainThread(message) ((void)0)
#endif
/** /**
* Assert a given value to be true. * Assert a given value to be true.
* *
@@ -172,6 +132,28 @@
const char *message const char *message
); );
/**
* Asserts that the current thread is the main thread.
*
* @param message Message to throw against assertion failure.
*/
void assertIsMainThreadImpl(
const char *file,
const int32_t line,
const char *message
);
/**
* Asserts that the current thread is NOT the main thread.
*
* @param message Message to throw against assertion failure.
*/
void assertNotMainThreadImpl(
const char *file,
const int32_t line,
const char *message
);
/** /**
* Asserts a given value to be true. * Asserts a given value to be true.
* *
@@ -256,6 +238,22 @@
#define assertStringEqual(a, b, message) \ #define assertStringEqual(a, b, message) \
assertStringEqualImpl(__FILE__, __LINE__, a, b, message) assertStringEqualImpl(__FILE__, __LINE__, a, b, message)
/**
* Asserts that the current thread is the main thread.
*
* @param message Message to throw against assertion failure.
*/
#define assertIsMainThread(message) \
assertIsMainThreadImpl(__FILE__, __LINE__, message)
/**
* Asserts that the current thread is NOT the main thread.
*
* @param message Message to throw against assertion failure.
*/
#define assertNotMainThread(message) \
assertNotMainThreadImpl(__FILE__, __LINE__, message)
#else #else
// If assertions are faked, we define the macros to do nothing. // If assertions are faked, we define the macros to do nothing.
#define assertInit() ((void)0) #define assertInit() ((void)0)
@@ -270,11 +268,13 @@
#define assertDeprecated(message) ((void)0) #define assertDeprecated(message) ((void)0)
#define assertStrLenMax(str, len, message) ((void)0) #define assertStrLenMax(str, len, message) ((void)0)
#define assertStrLenMin(str, len, message) ((void)0) #define assertStrLenMin(str, len, message) ((void)0)
#define assertStringEqual(a, b, message) ((void)0)
#define assertIsMainThread(message) ((void)0)
#define assertNotMainThread(message) ((void)0)
#endif #endif
// Static Assertions // Static Assertions
#define assertStructSize(struct, size) \ #define assertStructSize(struct, size) \
_Static_assert(sizeof(struct) == size, "Size of " #struct " must be " #size) _Static_assert(sizeof(struct) == size, "Size of " #struct " must be " #size)
+42
View File
@@ -117,6 +117,48 @@ errorret_t assetFileDispose(assetfile_t *file) {
errorOk(); errorOk();
} }
errorret_t assetFileReadEntire(
assetfile_t *file,
uint8_t **outBuffer,
size_t *outSize
) {
assertNotNull(file, "Asset file cannot be NULL.");
assertNotNull(outBuffer, "outBuffer cannot be NULL.");
assertNotNull(outSize, "outSize cannot be NULL.");
assertTrue(file->size > 0, "Asset file has no size; call assetFileInit first.");
// File should be closed currently.
assertNull(file->zipFile, "Asset file must be closed before reading entire.");
// Open file
errorret_t ret = assetFileOpen(file);
if(errorIsNotOk(ret)) {
errorChain(ret);
}
// Set output.
size_t size = (size_t)file->size;
uint8_t *buffer = (uint8_t *)memoryAllocate(size);
// Read entire file.
ret = assetFileRead(file, buffer, size);
if(errorIsNotOk(ret)) {
memoryFree(buffer);
errorChain(ret);
}
// Close the file.
ret = assetFileClose(file);
if(errorIsNotOk(ret)) {
memoryFree(buffer);
errorChain(ret);
}
*outBuffer = buffer;
*outSize = size;
errorOk();
}
// Line Reader; // Line Reader;
void assetFileLineReaderInit( void assetFileLineReaderInit(
assetfilelinereader_t *reader, assetfilelinereader_t *reader,
+15
View File
@@ -92,6 +92,21 @@ errorret_t assetFileClose(assetfile_t *file);
*/ */
errorret_t assetFileDispose(assetfile_t *file); errorret_t assetFileDispose(assetfile_t *file);
/**
* Reads the entire contents of the asset file into a newly allocated buffer.
* The caller is responsible for freeing the buffer with memoryFree.
*
* @param file The asset file to read. Must be initialized but not open.
* @param outBuffer Receives a pointer to the allocated buffer.
* @param outSize Receives the number of bytes written to the buffer.
* @return An error code if the file could not be read.
*/
errorret_t assetFileReadEntire(
assetfile_t *file,
uint8_t **outBuffer,
size_t *outSize
);
typedef struct { typedef struct {
assetfile_t *file; assetfile_t *file;
uint8_t *readBuffer; uint8_t *readBuffer;
+2 -3
View File
@@ -29,7 +29,8 @@ void assetEntryInit(
entry->state = ASSET_ENTRY_STATE_NOT_STARTED; entry->state = ASSET_ENTRY_STATE_NOT_STARTED;
if(input) { if(input) {
entry->inputData = *input; entry->inputData = *input;
entry->input = &entry->inputData; } else {
memoryZero(&entry->inputData, sizeof(assetloaderinput_t));
} }
refInit(&entry->refs, entry, NULL, NULL, NULL); refInit(&entry->refs, entry, NULL, NULL, NULL);
@@ -54,8 +55,6 @@ void assetEntryLock(assetentry_t *entry) {
assertNotNull(entry, "Entry cannot be NULL"); assertNotNull(entry, "Entry cannot be NULL");
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type."); assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
entry->wasLocked = true;
refLock(&entry->refs); refLock(&entry->refs);
} }
-14
View File
@@ -26,26 +26,12 @@ typedef enum {
typedef struct assetentry_s assetentry_t; typedef struct assetentry_s assetentry_t;
struct assetentry_s { struct assetentry_s {
// Filename and cache key
char_t name[ASSET_FILE_NAME_MAX]; char_t name[ASSET_FILE_NAME_MAX];
// What type of asset is this?
assetloadertype_t type; assetloadertype_t type;
// Data
assetloaderoutput_t data; assetloaderoutput_t data;
// What state is this asset entry in currently?
assetentrystate_t state; assetentrystate_t state;
// What is referencing this asset entry.
ref_t refs; ref_t refs;
// True once assetEntryLock has been called at least once. The reaper only
// collects entries that have been explicitly locked (and later unlocked to
// zero). Entries that nobody has ever locked are left alone so raw-pointer
// callers (tests, requireLoaded before locking) are not surprised.
bool_t wasLocked;
// Owned copy of the loader input. input points here when non-NULL.
assetloaderinput_t inputData; assetloaderinput_t inputData;
// Pointer to inputData, or NULL if no input was provided.
assetloaderinput_t *input;
/** /**
* Fired once when loading completes successfully (params = assetentry_t *). * Fired once when loading completes successfully (params = assetentry_t *).
* Always invoked on the main thread. * Always invoked on the main thread.
-4
View File
@@ -13,13 +13,9 @@
typedef struct assetentry_s assetentry_t; typedef struct assetentry_s assetentry_t;
typedef struct assetloading_s { typedef struct assetloading_s {
// Protects entry pointer and entry->state from concurrent access.
threadmutex_t mutex; threadmutex_t mutex;
// What type of asset is being loaded.
assetloadertype_t type; assetloadertype_t type;
// Referral back to the asset entry that will be kept alive after load done.
assetentry_t *entry; assetentry_t *entry;
// Information used during the load operation only.
assetloaderloading_t loading; assetloaderloading_t loading;
} assetloading_t; } assetloading_t;
@@ -21,7 +21,7 @@ errorret_t assetMeshLoaderAsync(assetloading_t *loading) {
assetmeshoutput_t *out = &loading->entry->data.mesh; assetmeshoutput_t *out = &loading->entry->data.mesh;
assetfile_t *file = &loading->loading.mesh.file; assetfile_t *file = &loading->loading.mesh.file;
assetmeshinputaxis_t axis = loading->entry->input->mesh; assetmeshinputaxis_t axis = loading->entry->inputData.mesh;
assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL)); assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL));
assetLoaderErrorChain(loading, assetFileOpen(file)); assetLoaderErrorChain(loading, assetFileOpen(file));
@@ -77,7 +77,7 @@ errorret_t assetTextureLoaderAsync(assetloading_t *loading) {
// Determine channels // Determine channels
int channelsDesired; int channelsDesired;
switch(loading->entry->input->texture) { switch(loading->entry->inputData.texture) {
case TEXTURE_FORMAT_RGBA: case TEXTURE_FORMAT_RGBA:
channelsDesired = 4; channelsDesired = 4;
break; break;
@@ -148,7 +148,7 @@ errorret_t assetTextureLoaderSync(assetloading_t *loading) {
(texture_t*)&loading->entry->data.texture, (texture_t*)&loading->entry->data.texture,
loading->loading.texture.width, loading->loading.texture.width,
loading->loading.texture.height, loading->loading.texture.height,
loading->entry->input->texture, loading->entry->inputData.texture,
(texturedata_t){ (texturedata_t){
.rgbaColors = (color_t*)loading->loading.texture.data .rgbaColors = (color_t*)loading->loading.texture.data
} }
+1 -1
View File
@@ -98,8 +98,8 @@ errorret_t engineDispose(void) {
consoleDispose(); consoleDispose();
errorChain(displayDispose()); errorChain(displayDispose());
// errorChain(saveDispose()); // errorChain(saveDispose());
errorChain(assetDispose());
errorChain(scriptDispose()); errorChain(scriptDispose());
errorChain(assetDispose());
errorOk(); errorOk();
} }
-2
View File
@@ -96,8 +96,6 @@ bool_t threadShouldStop(thread_t *thread) {
} }
#ifdef DUSK_THREAD_PTHREAD #ifdef DUSK_THREAD_PTHREAD
pthread_t THREAD_MAIN_THREAD_ID = 0;
void * threadHandler(thread_t *thread) { void * threadHandler(thread_t *thread) {
assertNotNull(thread, "Thread cannot be NULL."); assertNotNull(thread, "Thread cannot be NULL.");
-2
View File
@@ -89,8 +89,6 @@ void threadStop(thread_t *thread);
bool_t threadShouldStop(thread_t *thread); bool_t threadShouldStop(thread_t *thread);
#ifdef DUSK_THREAD_PTHREAD #ifdef DUSK_THREAD_PTHREAD
extern pthread_t THREAD_MAIN_THREAD_ID;
/** /**
* Handles the thread's lifecycle for pthreads. * Handles the thread's lifecycle for pthreads.
* @param thread Pointer to the thread structure to handle. * @param thread Pointer to the thread structure to handle.
+2
View File
@@ -8,6 +8,8 @@
#pragma once #pragma once
#include "dusk.h" #include "dusk.h"
#define MATH_PI M_PI
/** /**
* Finds the next power of two greater than or equal to the given value. * Finds the next power of two greater than or equal to the given value.
* *