diff options
author | Mitchell Stokes <mogurijin@gmail.com> | 2013-08-11 01:17:46 +0400 |
---|---|---|
committer | Mitchell Stokes <mogurijin@gmail.com> | 2013-08-11 01:17:46 +0400 |
commit | 3627541894e2875b74d974abfe9ead60b68c4d05 (patch) | |
tree | b4b24fc9e43b6873ea60ff1acc4793847a118d29 /source | |
parent | 4c136881a5a17f411ea05588ee86479f94cc2429 (diff) |
BGE: Fixing the memory leaks reported when the BlenderPlayer exits.
They were caused by not having a free_windowmanager_cb set and by not having registered SpaceTypes, which meant data allocated for thosse SpaceTypes could not be freed. These were solved by defining a free_windowmanager_cb for the player that just frees wmWindows, and by making sure we only allocate memory for registered SpaceTypes.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_screen.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/screen.c | 5 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 46 | ||||
-rw-r--r-- | source/gameengine/GamePlayer/ghost/GPG_ghost.cpp | 10 |
4 files changed, 47 insertions, 15 deletions
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index b5a6c6fb821..c883bdf74e0 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -254,6 +254,7 @@ struct SpaceType *BKE_spacetype_from_id(int spaceid); struct ARegionType *BKE_regiontype_from_id(struct SpaceType *st, int regionid); const struct ListBase *BKE_spacetypes_list(void); void BKE_spacetype_register(struct SpaceType *st); +int BKE_spacetype_exists(int spaceid); void BKE_spacetypes_free(void); /* only for quitting blender */ /* spacedata */ diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 01f57b95378..fe2f52d79fd 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -136,6 +136,11 @@ void BKE_spacetype_register(SpaceType *st) BLI_addtail(&spacetypes, st); } +int BKE_spacetype_exists(int spaceid) +{ + return BKE_spacetype_from_id(spaceid) != NULL; +} + /* ***************** Space handling ********************** */ void BKE_spacedata_freelist(ListBase *lb) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 66fd58c42dc..1f8bbfbec88 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6138,20 +6138,26 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) ui_list->type = NULL; } - ar->regiondata = newdataadr(fd, ar->regiondata); - if (ar->regiondata) { - if (spacetype == SPACE_VIEW3D) { - RegionView3D *rv3d = ar->regiondata; - - rv3d->localvd = newdataadr(fd, rv3d->localvd); - rv3d->clipbb = newdataadr(fd, rv3d->clipbb); - - rv3d->depths = NULL; - rv3d->gpuoffscreen = NULL; - rv3d->ri = NULL; - rv3d->render_engine = NULL; - rv3d->sms = NULL; - rv3d->smooth_timer = NULL; + if (spacetype == SPACE_EMPTY) { + /* unkown space type, don't leak regiondata */ + ar->regiondata = NULL; + } + else { + ar->regiondata = newdataadr(fd, ar->regiondata); + if (ar->regiondata) { + if (spacetype == SPACE_VIEW3D) { + RegionView3D *rv3d = ar->regiondata; + + rv3d->localvd = newdataadr(fd, rv3d->localvd); + rv3d->clipbb = newdataadr(fd, rv3d->clipbb); + + rv3d->depths = NULL; + rv3d->gpuoffscreen = NULL; + rv3d->ri = NULL; + rv3d->render_engine = NULL; + rv3d->sms = NULL; + rv3d->smooth_timer = NULL; + } } } @@ -6238,6 +6244,11 @@ static bool direct_link_screen(FileData *fd, bScreen *sc) sa->handlers.first = sa->handlers.last = NULL; sa->type = NULL; /* spacetype callbacks */ sa->region_active_win = -1; + + /* if we do not have the spacetype registered (game player), we cannot + * free it, so don't allocate any new memory for such spacetypes. */ + if (!BKE_spacetype_exists(sa->spacetype)) + sa->spacetype = SPACE_EMPTY; for (ar = sa->regionbase.first; ar; ar = ar->next) direct_link_region(fd, ar, sa->spacetype); @@ -6255,7 +6266,12 @@ static bool direct_link_screen(FileData *fd, bScreen *sc) for (sl = sa->spacedata.first; sl; sl = sl->next) { link_list(fd, &(sl->regionbase)); - + + /* if we do not have the spacetype registered (game player), we cannot + * free it, so don't allocate any new memory for such spacetypes. */ + if (!BKE_spacetype_exists(sl->spacetype)) + sl->spacetype = SPACE_EMPTY; + for (ar = sl->regionbase.first; ar; ar = ar->next) direct_link_region(fd, ar, sl->spacetype); diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 817a4d8efac..ccbcdd25639 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -118,6 +118,14 @@ static void mem_error_cb(const char *errorStr) fflush(stderr); } +// library.c will only free window managers with a callback function. +// We don't actually use a wmWindowManager, but loading a blendfile +// loads wmWindows, so we need to free those. +static void wm_free(bContext *C, wmWindowManager *wm) +{ + BLI_freelistN(&wm->windows); +} + #ifdef WIN32 typedef enum { SCREEN_SAVER_MODE_NONE = 0, @@ -501,6 +509,8 @@ int main(int argc, char** argv) sound_init_once(); + set_free_windowmanager_cb(wm_free); + /* if running blenderplayer the last argument can't be parsed since it has to be the filename. */ isBlenderPlayer = !BLO_is_a_runtime(argv[0]); if (isBlenderPlayer) |