Permalink
Browse files

[0.1.2-10] Garbage collection \:D/ for pmf/img/wav

  • Loading branch information...
iamgreaser committed Nov 25, 2013
1 parent f0c2bda commit 341c2f0549a49960ca559909c5119c0a2d67a500
Showing with 194 additions and 50 deletions.
  1. +8 −1 include/common.h
  2. +5 −3 pkg/base/version.lua
  3. +28 −0 src/img.c
  4. +16 −8 src/lua_fetch.h
  5. +43 −22 src/lua_image.h
  6. +39 −13 src/lua_model.h
  7. +9 −3 src/lua_wav.h
  8. +23 −0 src/model.c
  9. +23 −0 src/wav.c
View
@@ -19,7 +19,7 @@
#define VERSION_X 1
#define VERSION_Y 2
#define VERSION_A 0
-#define VERSION_Z 9
+#define VERSION_Z 10
// Remember to bump "Z" basically every time you change the engine!
// Remember to bump the version in Lua too!
// Remember to document API changes in a new version!
@@ -38,6 +38,9 @@
// MUST BE A POWER OF TWO
#define WAV_CHN_COUNT 128
+// WARNING: This will eventually be disabled in 0.1.3.
+#define ALLOW_EXPLICIT_FREE
+
//define RENDER_FACE_COUNT 2
#ifndef _MSC_VER
@@ -450,6 +453,7 @@ float equal_power_right(float pan);
// img.c
void img_free(img_t *img);
+void img_gc_set(lua_State *L);
img_t *img_parse_tga(int len, const char *data);
img_t *img_load_tga(const char *fname);
@@ -518,6 +522,7 @@ void model_bone_free(model_bone_t *bone);
model_t *model_new(int bonemax);
model_t *model_extend(model_t *pmf, int bonemax);
void model_free(model_t *pmf);
+void model_gc_set(lua_State *L);
model_t *model_parse_pmf(int len, const char *data);
model_t *model_load_pmf(const char *fname);
int model_save_pmf(model_t *pmf, const char *fname);
@@ -594,6 +599,7 @@ extern float icesackit_vol;
wav_t *wav_parse(char *buf, int len);
wav_t *wav_load(const char *fname);
void wav_kill(wav_t *wav);
+void wav_gc_set(lua_State *L);
#ifndef DEDI
extern int wav_mfreq;
extern int wav_bufsize;
@@ -605,3 +611,4 @@ void wav_chn_kill(wavchn_t *chn);
int wav_init(void);
void wav_deinit(void);
#endif
+
View
@@ -20,9 +20,9 @@
-- Thanks. --GM
VERSION_ENGINE = {
- cmp={0,1,2,0,9},
- num=4259840+9,
- str="0.1.2-9",
+ cmp={0,1,2,0,10},
+ num=4259840+10,
+ str="0.1.2-10",
}
-- 0.1: 4194304
@@ -126,5 +126,7 @@ VERSION_BUGS = {
{intro=nil, fix=4259840+6, msg="JSON writing not supported"},
{intro=nil, fix=4259840+7, msg="General JSON support is broken"},
{intro=nil, fix=4259840+9, msg="UDP sending can crash if DNS lookup fails"},
+{intro=nil, fix=4259840+10, msg="Garbage collection not supported"},
+{intro=4259840+10, fix=nil, msg="Garbage collection incomplete (only pmf/img/wav supported)"},
}
View
@@ -42,9 +42,37 @@ uint32_t img_convert_color_to_32(uint32_t v, int bits)
void img_free(img_t *img)
{
+#ifdef USE_OPENGL
+ if(img->tex != 0)
+ glDeleteTextures(1, &(img->tex));
+#endif
+
free(img);
}
+int img_gc_lua(lua_State *L)
+{
+ img_t **img_ud = (img_t **)lua_touserdata(L, 1);
+ img_t *img = *img_ud;
+ if(img != NULL)
+ {
+#ifdef ALLOW_EXPLICIT_FREE
+ printf("Freeing img @ %p\n", img);
+#endif
+ img_free(img);
+ }
+
+ return 0;
+}
+
+void img_gc_set(lua_State *L)
+{
+ lua_newtable(L);
+ lua_pushcfunction(L, img_gc_lua);
+ lua_setfield(L, -2, "__gc");
+ lua_setmetatable(L, -2);
+}
+
img_t *img_parse_tga(int len, const char *data)
{
// TODO: make this routine safer
View
@@ -84,28 +84,32 @@ int icelua_fnaux_fetch_immediate(lua_State *L, const char *ftype, const char *fn
if(pmf == NULL)
return 0;
- lua_pushlightuserdata(L, pmf);
+ *(model_t **)lua_newuserdata(L, sizeof(void *)) = pmf;
+ model_gc_set(L);
return 1;
} else if(!strcmp(ftype, "tga")) {
img_t *img = img_load_tga(fname);
if(img == NULL)
return 0;
- lua_pushlightuserdata(L, img);
+ *(img_t **)lua_newuserdata(L, sizeof(void *)) = img;
+ img_gc_set(L);
return 1;
} else if(!strcmp(ftype, "png")) {
img_t *img = img_load_png(fname);
if(img == NULL)
return 0;
- lua_pushlightuserdata(L, img);
+ *(img_t **)lua_newuserdata(L, sizeof(void *)) = img;
+ img_gc_set(L);
return 1;
} else if(!strcmp(ftype, "wav")) {
wav_t *wav = wav_load(fname);
if(wav == NULL)
return 0;
- lua_pushlightuserdata(L, wav);
+ *(wav_t **)lua_newuserdata(L, sizeof(void *)) = wav;
+ wav_gc_set(L);
return 1;
} else if(!strcmp(ftype, "it")) {
it_module_t *mus = sackit_module_load(fname);
@@ -279,7 +283,8 @@ int icelua_fn_common_fetch_poll(lua_State *L)
break;
}
- lua_pushlightuserdata(L, pmf);
+ *(model_t **)lua_newuserdata(L, sizeof(void *)) = pmf;
+ model_gc_set(L);
ret = 1;
} break;
@@ -294,7 +299,8 @@ int icelua_fn_common_fetch_poll(lua_State *L)
break;
}
- lua_pushlightuserdata(L, img);
+ *(img_t **)lua_newuserdata(L, sizeof(void *)) = img;
+ img_gc_set(L);
ret = 1;
} break;
@@ -309,7 +315,8 @@ int icelua_fn_common_fetch_poll(lua_State *L)
break;
}
- lua_pushlightuserdata(L, img);
+ *(img_t **)lua_newuserdata(L, sizeof(void *)) = img;
+ img_gc_set(L);
ret = 1;
} break;
@@ -324,7 +331,8 @@ int icelua_fn_common_fetch_poll(lua_State *L)
break;
}
- lua_pushlightuserdata(L, wav);
+ *(wav_t **)lua_newuserdata(L, sizeof(void *)) = wav;
+ wav_gc_set(L);
ret = 1;
} break;
View
@@ -26,9 +26,12 @@ int icelua_fn_client_img_blit(lua_State *L)
float scalex, scaley;
uint32_t color;
- img_t *img = (img_t*)lua_touserdata(L, 1);
- if(img == NULL || img->udtype != UD_IMG)
+ if(lua_islightuserdata(L, 1) || !lua_isuserdata(L, 1))
return luaL_error(L, "not an image");
+ img_t **img_ud = (img_t**)lua_touserdata(L, 1);
+ if(img_ud == NULL || (*img_ud)->udtype != UD_IMG)
+ return luaL_error(L, "not an image");
+ img_t *img = *img_ud;
dx = lua_tointeger(L, 2);
dy = lua_tointeger(L, 3);
@@ -57,12 +60,18 @@ int icelua_fn_client_img_blit_to(lua_State *L)
float scalex, scaley;
uint32_t color;
- img_t *dest = (img_t*)lua_touserdata(L, 1);
- if(dest == NULL || dest->udtype != UD_IMG)
+ if(lua_islightuserdata(L, 1) || !lua_isuserdata(L, 1))
+ return luaL_error(L, "not an image");
+ if(lua_islightuserdata(L, 2) || !lua_isuserdata(L, 2))
+ return luaL_error(L, "not an image");
+ img_t **dest_ud = (img_t**)lua_touserdata(L, 1);
+ if(dest_ud == NULL || (*dest_ud)->udtype != UD_IMG)
return luaL_error(L, "not an image");
- img_t *source = (img_t*)lua_touserdata(L, 2);
- if(source == NULL || source->udtype != UD_IMG)
+ img_t **source_ud = (img_t**)lua_touserdata(L, 2);
+ if(source_ud == NULL || (*source_ud)->udtype != UD_IMG)
return luaL_error(L, "not an image");
+ img_t *dest = *dest_ud;
+ img_t *source = *source_ud;
dx = lua_tointeger(L, 3);
dy = lua_tointeger(L, 4);
@@ -112,9 +121,10 @@ int icelua_fn_common_img_load(lua_State *L)
lua_pushvalue(L, 1);
lua_call(L, 2, 1);
- img_t *img = (img_t*)lua_touserdata(L, -1);
- if(img == NULL)
+ img_t **img_ud = (img_t**)lua_touserdata(L, -1);
+ if(img_ud == NULL)
return 0;
+ img_t *img = *img_ud;
lua_pushinteger(L, img->head.width);
lua_pushinteger(L, img->head.height);
@@ -165,17 +175,21 @@ int icelua_fn_common_img_new(lua_State *L)
img->tex_dirty = 1;
#endif
- lua_pushlightuserdata(L, img);
+ *(img_t **)lua_newuserdata(L, sizeof(void *)) = img;
+ img_gc_set(L);
return 1;
}
int icelua_fn_common_img_pixel_set(lua_State *L)
{
int top = icelua_assert_stack(L, 4, 4);
- img_t *img = (img_t*)lua_touserdata(L, 1);
- if(img == NULL || img->udtype != UD_IMG)
+ if(lua_islightuserdata(L, 1) || !lua_isuserdata(L, 1))
+ return luaL_error(L, "not an image");
+ img_t **img_ud = (img_t**)lua_touserdata(L, 1);
+ if(img_ud == NULL || (*img_ud)->udtype != UD_IMG)
return luaL_error(L, "not an image");
+ img_t *img = *img_ud;
int x = lua_tointeger(L, 2);
int y = lua_tointeger(L, 3);
uint32_t color = lua_tointeger(L, 4);
@@ -203,9 +217,12 @@ int icelua_fn_common_img_fill(lua_State *L)
int top = icelua_assert_stack(L, 2, 2);
- img_t *img = (img_t*)lua_touserdata(L, 1);
- if(img == NULL || img->udtype != UD_IMG)
+ if(lua_islightuserdata(L, 1) || !lua_isuserdata(L, 1))
+ return luaL_error(L, "not an image");
+ img_t **img_ud = (img_t**)lua_touserdata(L, 1);
+ if(img_ud == NULL || (*img_ud)->udtype != UD_IMG)
return luaL_error(L, "not an image");
+ img_t *img = *img_ud;
uint32_t color = lua_tointeger(L, 2);
int iw = img->head.width;
@@ -227,16 +244,17 @@ int icelua_fn_common_img_free(lua_State *L)
{
int top = icelua_assert_stack(L, 1, 1);
- img_t *img = (img_t*)lua_touserdata(L, 1);
- if(img == NULL || img->udtype != UD_IMG)
+ if(lua_islightuserdata(L, 1) || !lua_isuserdata(L, 1))
return luaL_error(L, "not an image");
+ img_t **img_ud = (img_t**)lua_touserdata(L, 1);
+ if(img_ud == NULL || (*img_ud)->udtype != UD_IMG)
+ return luaL_error(L, "not an image");
+ img_t *img = *img_ud;
-#ifdef USE_OPENGL
- if(img->tex != 0)
- glDeleteTextures(1, &(img->tex));
-#endif
-
+#ifdef ALLOW_EXPLICIT_FREE
img_free(img);
+ *img_ud = NULL;
+#endif
return 0;
}
@@ -245,9 +263,12 @@ int icelua_fn_common_img_get_dims(lua_State *L)
{
int top = icelua_assert_stack(L, 1, 1);
- img_t *img = (img_t*)lua_touserdata(L, 1);
- if(img == NULL || img->udtype != UD_IMG)
+ if(lua_islightuserdata(L, 1) || !lua_isuserdata(L, 1))
+ return luaL_error(L, "not an image");
+ img_t **img_ud = (img_t**)lua_touserdata(L, 1);
+ if(img_ud == NULL || (*img_ud)->udtype != UD_IMG)
return luaL_error(L, "not an image");
+ img_t *img = *img_ud;
lua_pushinteger(L, img->head.width);
lua_pushinteger(L, img->head.height);
Oops, something went wrong.

0 comments on commit 341c2f0

Please sign in to comment.