Sfoglia il codice sorgente

start with sokol_spine.h functional tests

Andre Weissflog 3 anni fa
parent
commit
5aa8ec98f3

+ 1 - 0
tests/.gitignore

@@ -1,3 +1,4 @@
 build/
 build/
 ext/fips-cimgui/
 ext/fips-cimgui/
 ext/sokol-tools-bin/
 ext/sokol-tools-bin/
+ext/spine-runtimes/

+ 46 - 2
tests/CMakeLists.txt

@@ -5,8 +5,8 @@ set(CMAKE_C_STANDARD 11)
 set(CMAKE_CXX_STANDARD 17)  # needed for UWP
 set(CMAKE_CXX_STANDARD 17)  # needed for UWP
 
 
 # SOKOL_GLCORE33, SOKOL_GLES2, SOKOL_GLES3, SOKOL_D3D11, SOKOL_METAL, SOKOL_WGPU, SOKOL_DUMMY
 # SOKOL_GLCORE33, SOKOL_GLES2, SOKOL_GLES3, SOKOL_D3D11, SOKOL_METAL, SOKOL_WGPU, SOKOL_DUMMY
-set(SOKOL_BACKEND "SOKOL_GLCORE33" CACHE STRING "Select 3D backend API")
-set_property(CACHE SOKOL_BACKEND PROPERTY STRINGS SOKOL_GLCORE33 SOKOL_METAL SOKOL_D3D11)
+set(SOKOL_BACKEND "SOKOL_DUMMY_BACKEND" CACHE STRING "Select 3D backend API")
+set_property(CACHE SOKOL_BACKEND PROPERTY STRINGS SOKOL_GLCORE33 SOKOL_METAL SOKOL_D3D11 SOKOL_DUMMY_BACKEND)
 option(USE_ARC "Enable/disable ARC" OFF)
 option(USE_ARC "Enable/disable ARC" OFF)
 option(USE_ANALYZER "Enable/disable clang analyzer" OFF)
 option(USE_ANALYZER "Enable/disable clang analyzer" OFF)
 
 
@@ -158,6 +158,50 @@ add_library(imgui
     ext/fips-cimgui/cimgui/imgui/imgui_widgets.cpp)
     ext/fips-cimgui/cimgui/imgui/imgui_widgets.cpp)
 target_include_directories(imgui SYSTEM PUBLIC ext/fips-cimgui/cimgui/imgui)
 target_include_directories(imgui SYSTEM PUBLIC ext/fips-cimgui/cimgui/imgui)
 
 
+add_library(spine
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Animation.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/AnimationState.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/AnimationStateData.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Array.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Atlas.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/AtlasAttachmentLoader.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Attachment.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/AttachmentLoader.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Bone.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/BoneData.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/BoundingBoxAttachment.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/ClippingAttachment.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Color.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Debug.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Event.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/EventData.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/IkConstraint.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/IkConstraintData.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Json.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Json.h
+    ext/spine-runtimes/spine-c/spine-c/src/spine/MeshAttachment.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/PathAttachment.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/PathConstraint.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/PathConstraintData.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/PointAttachment.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/RegionAttachment.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Sequence.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Skeleton.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/SkeletonBinary.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/SkeletonBounds.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/SkeletonClipping.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/SkeletonData.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/SkeletonJson.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Skin.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Slot.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/SlotData.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/TransformConstraint.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/TransformConstraintData.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/Triangulator.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/VertexAttachment.c
+    ext/spine-runtimes/spine-c/spine-c/src/spine/extension.c)
+target_include_directories(spine SYSTEM PUBLIC ext/spine-runtimes/spine-c/spine-c/include)
+
 add_library(nuklear ext/nuklear.c)
 add_library(nuklear ext/nuklear.c)
 
 
 add_subdirectory(compile)
 add_subdirectory(compile)

+ 9 - 0
tests/functional/CMakeLists.txt

@@ -1,7 +1,14 @@
 if (NOT ANDROID AND NOT UWP)
 if (NOT ANDROID AND NOT UWP)
 
 
 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/comsi.s3m DESTINATION ${CMAKE_BINARY_DIR})
 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/comsi.s3m DESTINATION ${CMAKE_BINARY_DIR})
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/spineboy-pro.json DESTINATION ${CMAKE_BINARY_DIR})
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/spineboy.atlas DESTINATION ${CMAKE_BINARY_DIR})
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/spineboy.png DESTINATION ${CMAKE_BINARY_DIR})
+
 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/comsi.s3m DESTINATION ${CMAKE_BINARY_DIR}/Debug)
 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/comsi.s3m DESTINATION ${CMAKE_BINARY_DIR}/Debug)
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/spineboy-pro.json DESTINATION ${CMAKE_BINARY_DIR}/Debug)
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/spineboy.atlas DESTINATION ${CMAKE_BINARY_DIR}/Debug)
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/spineboy.png DESTINATION ${CMAKE_BINARY_DIR}/Debug)
 
 
 set(c_sources
 set(c_sources
     sokol_args_test.c
     sokol_args_test.c
@@ -12,9 +19,11 @@ set(c_sources
     sokol_gl_test.c
     sokol_gl_test.c
     sokol_shape_test.c
     sokol_shape_test.c
     sokol_color_test.c
     sokol_color_test.c
+    sokol_spine_test.c
     sokol_test.c
     sokol_test.c
 )
 )
 add_executable(sokol-test ${c_sources})
 add_executable(sokol-test ${c_sources})
+target_link_libraries(sokol-test PUBLIC spine)
 configure_c(sokol-test)
 configure_c(sokol-test)
 
 
 endif()
 endif()

+ 3 - 0
tests/functional/assets/readme.txt

@@ -0,0 +1,3 @@
+Spine examples taken from:
+
+https://github.com/EsotericSoftware/spine-runtimes/tree/4.1/examples

File diff suppressed because it is too large
+ 541 - 0
tests/functional/assets/spineboy-pro.json


+ 101 - 0
tests/functional/assets/spineboy.atlas

@@ -0,0 +1,101 @@
+spineboy.png
+	size: 1024, 256
+	filter: Linear, Linear
+	scale: 0.5
+crosshair
+	bounds: 813, 160, 45, 45
+eye-indifferent
+	bounds: 569, 2, 47, 45
+eye-surprised
+	bounds: 643, 7, 47, 45
+	rotate: 90
+front-bracer
+	bounds: 811, 51, 29, 40
+front-fist-closed
+	bounds: 807, 93, 38, 41
+front-fist-open
+	bounds: 815, 210, 43, 44
+front-foot
+	bounds: 706, 64, 63, 35
+	rotate: 90
+front-shin
+	bounds: 80, 11, 41, 92
+front-thigh
+	bounds: 754, 12, 23, 56
+front-upper-arm
+	bounds: 618, 5, 23, 49
+goggles
+	bounds: 214, 20, 131, 83
+gun
+	bounds: 347, 14, 105, 102
+	rotate: 90
+head
+	bounds: 80, 105, 136, 149
+hoverboard-board
+	bounds: 2, 8, 246, 76
+	rotate: 90
+hoverboard-thruster
+	bounds: 478, 2, 30, 32
+hoverglow-small
+	bounds: 218, 117, 137, 38
+	rotate: 90
+mouth-grind
+	bounds: 775, 80, 47, 30
+	rotate: 90
+mouth-oooo
+	bounds: 779, 31, 47, 30
+	rotate: 90
+mouth-smile
+	bounds: 783, 207, 47, 30
+	rotate: 90
+muzzle-glow
+	bounds: 779, 4, 25, 25
+muzzle-ring
+	bounds: 451, 14, 25, 105
+muzzle01
+	bounds: 664, 60, 67, 40
+	rotate: 90
+muzzle02
+	bounds: 580, 56, 68, 42
+	rotate: 90
+muzzle03
+	bounds: 478, 36, 83, 53
+	rotate: 90
+muzzle04
+	bounds: 533, 49, 75, 45
+	rotate: 90
+muzzle05
+	bounds: 624, 56, 68, 38
+	rotate: 90
+neck
+	bounds: 806, 8, 18, 21
+portal-bg
+	bounds: 258, 121, 133, 133
+portal-flare1
+	bounds: 690, 2, 56, 30
+	rotate: 90
+portal-flare2
+	bounds: 510, 3, 57, 31
+portal-flare3
+	bounds: 722, 4, 58, 30
+	rotate: 90
+portal-shade
+	bounds: 393, 121, 133, 133
+portal-streaks1
+	bounds: 528, 126, 126, 128
+portal-streaks2
+	bounds: 656, 129, 125, 125
+rear-bracer
+	bounds: 826, 13, 28, 36
+rear-foot
+	bounds: 743, 70, 57, 30
+	rotate: 90
+rear-shin
+	bounds: 174, 14, 38, 89
+rear-thigh
+	bounds: 783, 158, 28, 47
+rear-upper-arm
+	bounds: 783, 136, 20, 44
+	rotate: 90
+torso
+	bounds: 123, 13, 49, 90

BIN
tests/functional/assets/spineboy.png


+ 2 - 0
tests/functional/force_dummy_backend.h

@@ -16,5 +16,7 @@
 #if defined(SOKOL_WGPU)
 #if defined(SOKOL_WGPU)
 #undef SOKOL_WGPU
 #undef SOKOL_WGPU
 #endif
 #endif
+#ifndef SOKOL_DUMMY_BACKEND
 #define SOKOL_DUMMY_BACKEND
 #define SOKOL_DUMMY_BACKEND
+#endif
 
 

+ 2 - 0
tests/functional/sokol_audio_test.c

@@ -2,7 +2,9 @@
 //  sokol_audio_test.c
 //  sokol_audio_test.c
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 #define SOKOL_IMPL
 #define SOKOL_IMPL
+#ifndef SOKOL_DUMMY_BACKEND
 #define SOKOL_DUMMY_BACKEND
 #define SOKOL_DUMMY_BACKEND
+#endif
 #include "sokol_audio.h"
 #include "sokol_audio.h"
 #include "utest.h"
 #include "utest.h"
 
 

+ 94 - 0
tests/functional/sokol_spine_test.c

@@ -0,0 +1,94 @@
+//------------------------------------------------------------------------------
+//  sokol_spine_test.c
+//------------------------------------------------------------------------------
+#include "sokol_gfx.h"
+#define SOKOL_SPINE_IMPL
+#include "spine/spine.h"
+#include "sokol_spine.h"
+#include "utest.h"
+
+#define T(b) EXPECT_TRUE(b)
+
+static void init() {
+    sg_setup(&(sg_desc){0});
+    sspine_setup(&(sspine_desc){0});
+}
+
+static void shutdown() {
+    sspine_shutdown();
+    sg_shutdown();
+}
+
+static sspine_range load_data(const char* path) {
+    assert(path);
+    FILE* fp = fopen(path, "rb");
+    assert(fp);
+    fseek(fp, 0, SEEK_END);
+    size_t size = (size_t)ftell(fp);
+    fseek(fp, 0, SEEK_SET);
+    void* ptr = malloc(size);
+    fread(ptr, size, 1, fp);
+    fclose(fp);
+    return (sspine_range) { .ptr = ptr, .size = size };
+}
+
+static void free_data(sspine_range r) {
+    free((void*)r.ptr);
+}
+
+UTEST(sokol_spine, default_init_shutdown) {
+    // FIXME!
+    T(true);
+}
+
+UTEST(sokol_spine, make_atlas_fail_no_data) {
+    init();
+    sspine_atlas atlas = sspine_make_atlas(&(sspine_atlas_desc){0});
+    T(atlas.id != SSPINE_INVALID_ID);
+    T(sspine_get_atlas_state(atlas) == SSPINE_RESOURCESTATE_FAILED);
+    T(!sspine_atlas_valid(atlas));
+    shutdown();
+}
+
+// an invalid atlas must return zero number of images
+UTEST(sokol_spine, failed_atlas_no_images) {
+    init();
+    sspine_atlas atlas = sspine_make_atlas(&(sspine_atlas_desc){0});
+    T(atlas.id != SSPINE_INVALID_ID);
+    T(!sspine_atlas_valid(atlas));
+    T(sspine_get_num_images(atlas) == 0);
+    shutdown();
+
+}
+
+// NOTE: spine-c doesn't detect wrong/corrupt atlas file data, so we can't test for that
+
+UTEST(sokol_spine, make_atlas_ok) {
+    init();
+    sspine_range data = load_data("spineboy.atlas");
+    sspine_atlas atlas = sspine_make_atlas(&(sspine_atlas_desc){
+        .data = data
+    });
+    free_data(data);
+    T(sspine_get_atlas_state(atlas) == SSPINE_RESOURCESTATE_VALID);
+    T(sspine_atlas_valid(atlas));
+    shutdown();
+}
+
+UTEST(sokol_spine, atlas_image_info) {
+    init();
+    sspine_range data = load_data("spineboy.atlas");
+    sspine_atlas atlas = sspine_make_atlas(&(sspine_atlas_desc){
+        .data = data
+    });
+    free_data(data);
+    T(sspine_atlas_valid(atlas));
+    T(sspine_get_num_images(atlas) == 1);
+    const sspine_image_info img_info = sspine_get_image_info(atlas, 0);
+    T(img_info.image.id != SG_INVALID_ID);
+    T(sg_query_image_state(img_info.image) == SG_RESOURCESTATE_ALLOC);
+    T(strcmp(img_info.filename, "spineboy.png") == 0);
+    T(img_info.min_filter == SG_FILTER_LINEAR);
+    T(img_info.mag_filter == SG_FILTER_LINEAR);
+    shutdown();
+}

+ 3 - 0
tests/test_common.sh

@@ -2,6 +2,9 @@ prepare() {
     if [ ! -d "ext/fips-cimgui" ] ; then
     if [ ! -d "ext/fips-cimgui" ] ; then
         git clone --depth 1 --recursive https://github.com/fips-libs/fips-cimgui ext/fips-cimgui
         git clone --depth 1 --recursive https://github.com/fips-libs/fips-cimgui ext/fips-cimgui
     fi
     fi
+    if [ ! -d "ext/spine-runtimes" ] ; then
+        git clone --depth 1 --recursive https://github.com/EsotericSoftware/spine-runtimes/ ext/spine-runtimes
+    fi
 }
 }
 
 
 setup_emsdk() {
 setup_emsdk() {

+ 76 - 42
util/sokol_spine.h

@@ -104,7 +104,9 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-// FIXME: track events, event call back (in instance desc)
+enum {
+    SSPINE_INVALID_ID = 0,
+};
 
 
 typedef struct sspine_context { uint32_t id; } sspine_context;
 typedef struct sspine_context { uint32_t id; } sspine_context;
 typedef struct sspine_atlas { uint32_t id; } sspine_atlas;
 typedef struct sspine_atlas { uint32_t id; } sspine_atlas;
@@ -407,6 +409,18 @@ typedef struct {
 } _sspine_t;
 } _sspine_t;
 static _sspine_t _sspine;
 static _sspine_t _sspine;
 
 
+// dummy spine-c platform implementation functions
+void _spAtlasPage_createTexture(spAtlasPage* self, const char* path) {
+    // nothing to do here
+    (void)self; (void)path;
+}
+
+char* _spUtil_readFile(const char* path, int* length) {
+    (void)path;
+    *length = 0;
+    return 0;
+}
+
 //=== MEMORY MANAGEMENT FUNCTIONS ==============================================
 //=== MEMORY MANAGEMENT FUNCTIONS ==============================================
 static void _sspine_clear(void* ptr, size_t size) {
 static void _sspine_clear(void* ptr, size_t size) {
     SOKOL_ASSERT(ptr && (size > 0));
     SOKOL_ASSERT(ptr && (size > 0));
@@ -521,7 +535,7 @@ static uint32_t _sspine_slot_init(_sspine_pool_t* pool, _sspine_slot_t* slot, in
     */
     */
     SOKOL_ASSERT(pool && pool->gen_ctrs);
     SOKOL_ASSERT(pool && pool->gen_ctrs);
     SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < pool->size));
     SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < pool->size));
-    SOKOL_ASSERT((slot->state == SSPINE_RESOURCESTATE_INITIAL) && (slot->id == SG_INVALID_ID));
+    SOKOL_ASSERT((slot->state == SSPINE_RESOURCESTATE_INITIAL) && (slot->id == SSPINE_INVALID_ID));
     uint32_t ctr = ++pool->gen_ctrs[slot_index];
     uint32_t ctr = ++pool->gen_ctrs[slot_index];
     slot->id = (ctr<<_SSPINE_SLOT_SHIFT)|(slot_index & _SSPINE_SLOT_MASK);
     slot->id = (ctr<<_SSPINE_SLOT_SHIFT)|(slot_index & _SSPINE_SLOT_MASK);
     slot->state = SSPINE_RESOURCESTATE_ALLOC;
     slot->state = SSPINE_RESOURCESTATE_ALLOC;
@@ -570,7 +584,7 @@ static sspine_context _sspine_make_context_handle(uint32_t id) {
 }
 }
 
 
 static _sspine_context_t* _sspine_context_at(uint32_t id) {
 static _sspine_context_t* _sspine_context_at(uint32_t id) {
-    SOKOL_ASSERT(SG_INVALID_ID != id);
+    SOKOL_ASSERT(SSPINE_INVALID_ID != id);
     const _sspine_context_pool_t* p = &_sspine.context_pool;
     const _sspine_context_pool_t* p = &_sspine.context_pool;
     int slot_index = _sspine_slot_index(id);
     int slot_index = _sspine_slot_index(id);
     SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < p->pool.size));
     SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < p->pool.size));
@@ -578,7 +592,7 @@ static _sspine_context_t* _sspine_context_at(uint32_t id) {
 }
 }
 
 
 static _sspine_context_t* _sspine_lookup_context(uint32_t id) {
 static _sspine_context_t* _sspine_lookup_context(uint32_t id) {
-    if (SG_INVALID_ID != id) {
+    if (SSPINE_INVALID_ID != id) {
         _sspine_context_t* ctx = _sspine_context_at(id);
         _sspine_context_t* ctx = _sspine_context_at(id);
         if (ctx->slot.id == id) {
         if (ctx->slot.id == id) {
             return ctx;
             return ctx;
@@ -597,7 +611,7 @@ static sspine_context _sspine_alloc_context(void) {
     }
     }
     else {
     else {
         // pool exhausted
         // pool exhausted
-        res = _sspine_make_context_handle(SG_INVALID_ID);
+        res = _sspine_make_context_handle(SSPINE_INVALID_ID);
     }
     }
     return res;
     return res;
 }
 }
@@ -608,10 +622,15 @@ static sspine_resource_state _sspine_init_context(_sspine_context_t* ctx, const
     return SSPINE_RESOURCESTATE_FAILED;
     return SSPINE_RESOURCESTATE_FAILED;
 }
 }
 
 
+static void _sspine_deinit_context(_sspine_context_t* ctx) {
+    // FIXME
+    (void)ctx;
+}
+
 static void _sspine_destroy_context(sspine_context ctx_id) {
 static void _sspine_destroy_context(sspine_context ctx_id) {
     _sspine_context_t* ctx = _sspine_lookup_context(ctx_id.id);
     _sspine_context_t* ctx = _sspine_lookup_context(ctx_id.id);
     if (ctx) {
     if (ctx) {
-        // FIXME
+        _sspine_deinit_context(ctx);
         _sspine_context_pool_t* p = &_sspine.context_pool;
         _sspine_context_pool_t* p = &_sspine.context_pool;
         _sspine_clear(ctx, sizeof(_sspine_context_t));
         _sspine_clear(ctx, sizeof(_sspine_context_t));
         _sspine_pool_free_index(&p->pool, _sspine_slot_index(ctx_id.id));
         _sspine_pool_free_index(&p->pool, _sspine_slot_index(ctx_id.id));
@@ -654,7 +673,7 @@ static sspine_atlas _sspine_make_atlas_handle(uint32_t id) {
 }
 }
 
 
 static _sspine_atlas_t* _sspine_atlas_at(uint32_t id) {
 static _sspine_atlas_t* _sspine_atlas_at(uint32_t id) {
-    SOKOL_ASSERT(SG_INVALID_ID != id);
+    SOKOL_ASSERT(SSPINE_INVALID_ID != id);
     const _sspine_atlas_pool_t* p = &_sspine.atlas_pool;
     const _sspine_atlas_pool_t* p = &_sspine.atlas_pool;
     int slot_index = _sspine_slot_index(id);
     int slot_index = _sspine_slot_index(id);
     SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < p->pool.size));
     SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < p->pool.size));
@@ -662,7 +681,7 @@ static _sspine_atlas_t* _sspine_atlas_at(uint32_t id) {
 }
 }
 
 
 static _sspine_atlas_t* _sspine_lookup_atlas(uint32_t id) {
 static _sspine_atlas_t* _sspine_lookup_atlas(uint32_t id) {
-    if (SG_INVALID_ID != id) {
+    if (SSPINE_INVALID_ID != id) {
         _sspine_atlas_t* atlas = _sspine_atlas_at(id);
         _sspine_atlas_t* atlas = _sspine_atlas_at(id);
         if (atlas->slot.id == id) {
         if (atlas->slot.id == id) {
             return atlas;
             return atlas;
@@ -681,16 +700,11 @@ static sspine_atlas _sspine_alloc_atlas(void) {
     }
     }
     else {
     else {
         // pool exhausted
         // pool exhausted
-        res = _sspine_make_atlas_handle(SG_INVALID_ID);
+        res = _sspine_make_atlas_handle(SSPINE_INVALID_ID);
     }
     }
     return res;
     return res;
 }
 }
 
 
-void _spAtlasPage_createTexture(spAtlasPage* self, const char* path) {
-    // nothing to do here
-    (void)self; (void)path;
-}
-
 void _spAtlasPage_disposeTexture(spAtlasPage* self) {
 void _spAtlasPage_disposeTexture(spAtlasPage* self) {
     if (self->rendererObject != 0) {
     if (self->rendererObject != 0) {
         const sg_image img = { (uint32_t)(uintptr_t)self->rendererObject };
         const sg_image img = { (uint32_t)(uintptr_t)self->rendererObject };
@@ -707,6 +721,8 @@ static sspine_resource_state _sspine_init_atlas(_sspine_atlas_t* atlas, const ss
         return SSPINE_RESOURCESTATE_FAILED;
         return SSPINE_RESOURCESTATE_FAILED;
     }
     }
 
 
+    // NOTE: Spine doesn't detect when invalid or corrupt data is passed here,
+    // not much we can do about this...
     atlas->sp_atlas = spAtlas_create((const char*)desc->data.ptr, (int)desc->data.size, "", 0);
     atlas->sp_atlas = spAtlas_create((const char*)desc->data.ptr, (int)desc->data.size, "", 0);
     if (0 == atlas->sp_atlas) {
     if (0 == atlas->sp_atlas) {
         return SSPINE_RESOURCESTATE_FAILED;
         return SSPINE_RESOURCESTATE_FAILED;
@@ -725,12 +741,17 @@ static sspine_resource_state _sspine_init_atlas(_sspine_atlas_t* atlas, const ss
     return SSPINE_RESOURCESTATE_VALID;
     return SSPINE_RESOURCESTATE_VALID;
 }
 }
 
 
+static void _sspine_deinit_atlas(_sspine_atlas_t* atlas) {
+    if (atlas->sp_atlas) {
+        spAtlas_dispose(atlas->sp_atlas);
+        atlas->sp_atlas = 0;
+    }
+}
+
 static void _sspine_destroy_atlas(sspine_atlas atlas_id) {
 static void _sspine_destroy_atlas(sspine_atlas atlas_id) {
     _sspine_atlas_t* atlas = _sspine_lookup_atlas(atlas_id.id);
     _sspine_atlas_t* atlas = _sspine_lookup_atlas(atlas_id.id);
     if (atlas) {
     if (atlas) {
-        if (atlas->sp_atlas) {
-            spAtlas_dispose(atlas->sp_atlas);
-        }
+        _sspine_deinit_atlas(atlas);
         _sspine_atlas_pool_t* p = &_sspine.atlas_pool;
         _sspine_atlas_pool_t* p = &_sspine.atlas_pool;
         _sspine_clear(atlas, sizeof(_sspine_atlas_t));
         _sspine_clear(atlas, sizeof(_sspine_atlas_t));
         _sspine_pool_free_index(&p->pool, _sspine_slot_index(atlas_id.id));
         _sspine_pool_free_index(&p->pool, _sspine_slot_index(atlas_id.id));
@@ -767,7 +788,7 @@ static sspine_skeleton _sspine_make_skeleton_handle(uint32_t id) {
 }
 }
 
 
 static _sspine_skeleton_t* _sspine_skeleton_at(uint32_t id) {
 static _sspine_skeleton_t* _sspine_skeleton_at(uint32_t id) {
-    SOKOL_ASSERT(SG_INVALID_ID != id);
+    SOKOL_ASSERT(SSPINE_INVALID_ID != id);
     const _sspine_skeleton_pool_t* p = &_sspine.skeleton_pool;
     const _sspine_skeleton_pool_t* p = &_sspine.skeleton_pool;
     int slot_index = _sspine_slot_index(id);
     int slot_index = _sspine_slot_index(id);
     SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < p->pool.size));
     SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < p->pool.size));
@@ -775,7 +796,7 @@ static _sspine_skeleton_t* _sspine_skeleton_at(uint32_t id) {
 }
 }
 
 
 static _sspine_skeleton_t* _sspine_lookup_skeleton(uint32_t id) {
 static _sspine_skeleton_t* _sspine_lookup_skeleton(uint32_t id) {
-    if (SG_INVALID_ID != id) {
+    if (SSPINE_INVALID_ID != id) {
         _sspine_skeleton_t* skeleton = _sspine_skeleton_at(id);
         _sspine_skeleton_t* skeleton = _sspine_skeleton_at(id);
         if (skeleton->slot.id == id) {
         if (skeleton->slot.id == id) {
             return skeleton;
             return skeleton;
@@ -794,7 +815,7 @@ static sspine_skeleton _sspine_alloc_skeleton(void) {
     }
     }
     else {
     else {
         // pool exhausted
         // pool exhausted
-        res = _sspine_make_skeleton_handle(SG_INVALID_ID);
+        res = _sspine_make_skeleton_handle(SSPINE_INVALID_ID);
     }
     }
     return res;
     return res;
 }
 }
@@ -844,15 +865,21 @@ static sspine_resource_state _sspine_init_skeleton(_sspine_skeleton_t* skeleton,
     return SSPINE_RESOURCESTATE_VALID;
     return SSPINE_RESOURCESTATE_VALID;
 }
 }
 
 
+static void _sspine_deinit_skeleton(_sspine_skeleton_t* skeleton) {
+    if (skeleton->sp_anim_data) {
+        spAnimationStateData_dispose(skeleton->sp_anim_data);
+        skeleton->sp_anim_data = 0;
+    }
+    if (skeleton->sp_skel_data) {
+        spSkeletonData_dispose(skeleton->sp_skel_data);
+        skeleton->sp_skel_data = 0;
+    }
+}
+
 static void _sspine_destroy_skeleton(sspine_skeleton skeleton_id) {
 static void _sspine_destroy_skeleton(sspine_skeleton skeleton_id) {
     _sspine_skeleton_t* skeleton = _sspine_lookup_skeleton(skeleton_id.id);
     _sspine_skeleton_t* skeleton = _sspine_lookup_skeleton(skeleton_id.id);
     if (skeleton) {
     if (skeleton) {
-        if (skeleton->sp_anim_data) {
-            spAnimationStateData_dispose(skeleton->sp_anim_data);
-        }
-        if (skeleton->sp_skel_data) {
-            spSkeletonData_dispose(skeleton->sp_skel_data);
-        }
+        _sspine_deinit_skeleton(skeleton);
         _sspine_skeleton_pool_t* p = &_sspine.skeleton_pool;
         _sspine_skeleton_pool_t* p = &_sspine.skeleton_pool;
         _sspine_clear(skeleton, sizeof(_sspine_skeleton_t));
         _sspine_clear(skeleton, sizeof(_sspine_skeleton_t));
         _sspine_pool_free_index(&p->pool, _sspine_slot_index(skeleton_id.id));
         _sspine_pool_free_index(&p->pool, _sspine_slot_index(skeleton_id.id));
@@ -889,7 +916,7 @@ static sspine_instance _sspine_make_instance_handle(uint32_t id) {
 }
 }
 
 
 static _sspine_instance_t* _sspine_instance_at(uint32_t id) {
 static _sspine_instance_t* _sspine_instance_at(uint32_t id) {
-    SOKOL_ASSERT(SG_INVALID_ID != id);
+    SOKOL_ASSERT(SSPINE_INVALID_ID != id);
     const _sspine_instance_pool_t* p = &_sspine.instance_pool;
     const _sspine_instance_pool_t* p = &_sspine.instance_pool;
     int slot_index = _sspine_slot_index(id);
     int slot_index = _sspine_slot_index(id);
     SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < p->pool.size));
     SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < p->pool.size));
@@ -897,7 +924,7 @@ static _sspine_instance_t* _sspine_instance_at(uint32_t id) {
 }
 }
 
 
 static _sspine_instance_t* _sspine_lookup_instance(uint32_t id) {
 static _sspine_instance_t* _sspine_lookup_instance(uint32_t id) {
-    if (SG_INVALID_ID != id) {
+    if (SSPINE_INVALID_ID != id) {
         _sspine_instance_t* instance = _sspine_instance_at(id);
         _sspine_instance_t* instance = _sspine_instance_at(id);
         if (instance->slot.id == id) {
         if (instance->slot.id == id) {
             return instance;
             return instance;
@@ -916,7 +943,7 @@ static sspine_instance _sspine_alloc_instance(void) {
     }
     }
     else {
     else {
         // pool exhausted
         // pool exhausted
-        res = _sspine_make_instance_handle(SG_INVALID_ID);
+        res = _sspine_make_instance_handle(SSPINE_INVALID_ID);
     }
     }
     return res;
     return res;
 }
 }
@@ -954,18 +981,25 @@ static sspine_resource_state _sspine_init_instance(_sspine_instance_t* instance,
     return SSPINE_RESOURCESTATE_VALID;
     return SSPINE_RESOURCESTATE_VALID;
 }
 }
 
 
+static void _sspine_deinit_instance(_sspine_instance_t* instance) {
+    if (instance->sp_clip) {
+        spSkeletonClipping_dispose(instance->sp_clip);
+        instance->sp_clip = 0;
+    }
+    if (instance->sp_anim) {
+        spAnimationState_dispose(instance->sp_anim);
+        instance->sp_anim = 0;
+    }
+    if (instance->sp_skel) {
+        spSkeleton_dispose(instance->sp_skel);
+        instance->sp_skel = 0;
+    }
+}
+
 static void _sspine_destroy_instance(sspine_instance instance_id) {
 static void _sspine_destroy_instance(sspine_instance instance_id) {
     _sspine_instance_t* instance = _sspine_lookup_instance(instance_id.id);
     _sspine_instance_t* instance = _sspine_lookup_instance(instance_id.id);
     if (instance) {
     if (instance) {
-        if (instance->sp_clip) {
-            spSkeletonClipping_dispose(instance->sp_clip);
-        }
-        if (instance->sp_anim) {
-            spAnimationState_dispose(instance->sp_anim);
-        }
-        if (instance->sp_skel) {
-            spSkeleton_dispose(instance->sp_skel);
-        }
+        _sspine_deinit_instance(instance);
         _sspine_instance_pool_t* p = &_sspine.instance_pool;
         _sspine_instance_pool_t* p = &_sspine.instance_pool;
         _sspine_clear(instance, sizeof(_sspine_instance_t));
         _sspine_clear(instance, sizeof(_sspine_instance_t));
         _sspine_pool_free_index(&p->pool, _sspine_slot_index(instance_id.id));
         _sspine_pool_free_index(&p->pool, _sspine_slot_index(instance_id.id));
@@ -1099,7 +1133,7 @@ SOKOL_API_IMPL sspine_context sspine_make_context(const sspine_context_desc* des
         ctx->slot.state = _sspine_init_context(ctx, &desc_def);
         ctx->slot.state = _sspine_init_context(ctx, &desc_def);
         SOKOL_ASSERT((ctx->slot.state == SSPINE_RESOURCESTATE_VALID) || (ctx->slot.state == SSPINE_RESOURCESTATE_FAILED));
         SOKOL_ASSERT((ctx->slot.state == SSPINE_RESOURCESTATE_VALID) || (ctx->slot.state == SSPINE_RESOURCESTATE_FAILED));
         if (ctx->slot.state == SSPINE_RESOURCESTATE_FAILED) {
         if (ctx->slot.state == SSPINE_RESOURCESTATE_FAILED) {
-            _sspine_destroy_context(ctx_id);
+            _sspine_deinit_context(ctx);
         }
         }
     }
     }
     else {
     else {
@@ -1152,7 +1186,7 @@ SOKOL_API_IMPL sspine_atlas sspine_make_atlas(const sspine_atlas_desc* desc) {
         atlas->slot.state = _sspine_init_atlas(atlas, &desc_def);
         atlas->slot.state = _sspine_init_atlas(atlas, &desc_def);
         SOKOL_ASSERT((atlas->slot.state == SSPINE_RESOURCESTATE_VALID) || (atlas->slot.state == SSPINE_RESOURCESTATE_FAILED));
         SOKOL_ASSERT((atlas->slot.state == SSPINE_RESOURCESTATE_VALID) || (atlas->slot.state == SSPINE_RESOURCESTATE_FAILED));
         if (atlas->slot.state == SSPINE_RESOURCESTATE_FAILED) {
         if (atlas->slot.state == SSPINE_RESOURCESTATE_FAILED) {
-            _sspine_destroy_atlas(atlas_id);
+            _sspine_deinit_atlas(atlas);
         }
         }
     }
     }
     else {
     else {
@@ -1177,7 +1211,7 @@ SOKOL_API_IMPL sspine_skeleton sspine_make_skeleton(const sspine_skeleton_desc*
         skeleton->slot.state = _sspine_init_skeleton(skeleton, &desc_def);
         skeleton->slot.state = _sspine_init_skeleton(skeleton, &desc_def);
         SOKOL_ASSERT((skeleton->slot.state == SSPINE_RESOURCESTATE_VALID) || (skeleton->slot.state == SSPINE_RESOURCESTATE_FAILED));
         SOKOL_ASSERT((skeleton->slot.state == SSPINE_RESOURCESTATE_VALID) || (skeleton->slot.state == SSPINE_RESOURCESTATE_FAILED));
         if (skeleton->slot.state == SSPINE_RESOURCESTATE_FAILED) {
         if (skeleton->slot.state == SSPINE_RESOURCESTATE_FAILED) {
-            _sspine_destroy_skeleton(skeleton_id);
+            _sspine_deinit_skeleton(skeleton);
         }
         }
     }
     }
     else {
     else {
@@ -1202,7 +1236,7 @@ SOKOL_API_IMPL sspine_instance sspine_make_instance(const sspine_instance_desc*
         instance->slot.state = _sspine_init_instance(instance, &desc_def);
         instance->slot.state = _sspine_init_instance(instance, &desc_def);
         SOKOL_ASSERT((instance->slot.state == SSPINE_RESOURCESTATE_VALID) || (instance->slot.state == SSPINE_RESOURCESTATE_FAILED));
         SOKOL_ASSERT((instance->slot.state == SSPINE_RESOURCESTATE_VALID) || (instance->slot.state == SSPINE_RESOURCESTATE_FAILED));
         if (instance->slot.state == SSPINE_RESOURCESTATE_FAILED) {
         if (instance->slot.state == SSPINE_RESOURCESTATE_FAILED) {
-            _sspine_destroy_instance(instance_id);
+            _sspine_deinit_instance(instance);
         }
         }
     }
     }
     else {
     else {

Some files were not shown because too many files changed in this diff