diff --git a/src/android/i_video.c b/src/android/i_video.c index 44e1cbac0..b8bb4fefb 100644 --- a/src/android/i_video.c +++ b/src/android/i_video.c @@ -19,6 +19,7 @@ boolean allow_fullscreen = false; consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; void I_StartupGraphics(void){} +void I_StartupHardwareGraphics(void){} void I_ShutdownGraphics(void){} diff --git a/src/console.c b/src/console.c index f34958835..db07c05d3 100644 --- a/src/console.c +++ b/src/console.c @@ -20,6 +20,7 @@ #include "g_input.h" #include "hu_stuff.h" #include "keys.h" +#include "r_main.h" #include "r_defs.h" #include "sounds.h" #include "st_stuff.h" @@ -1285,7 +1286,7 @@ void CONS_Printf(const char *fmt, ...) con_scrollup = 0; // if not in display loop, force screen update - if (con_startup) + if (con_startup && (!setrenderneeded)) { #ifdef _WINDOWS patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH); @@ -1609,7 +1610,11 @@ void CON_Drawer(void) } if (con_recalc) + { CON_RecalcSize(); + if (con_curlines <= 0) + CON_ClearHUD(); + } if (con_curlines > 0) CON_DrawConsole(); diff --git a/src/d_main.c b/src/d_main.c index a51ce0098..d8b2e2934 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -108,6 +108,8 @@ boolean devparm = false; // started game with -devparm boolean singletics = false; // timedemo boolean lastdraw = false; +static void D_CheckRendererState(void); + postimg_t postimgtype = postimg_none; INT32 postimgparam; postimg_t postimgtype2 = postimg_none; @@ -211,7 +213,7 @@ INT16 wipetypepost = -1; static void D_Display(void) { - INT32 setrenderstillneeded = setrenderneeded; + INT32 setrenderstillneeded = 0; boolean forcerefresh = false; static boolean wipe = false; INT32 wipedefindex = 0; @@ -222,13 +224,36 @@ static void D_Display(void) if (nodrawers) return; // for comparative timing/profiling + // Jimita: Switching renderers works by checking + // if the game has to do it right when the frame + // needs to render. If so, five things will happen: + // 1. Interface functions will be called so + // that switching to OpenGL creates a + // GL context, and switching to Software + // allocates screen buffers. + // 2. Software will set drawer functions, + // and OpenGL will load textures and + // create plane polygons, if necessary. + // 3. Functions related to switching video + // modes (resolution) are called. + // 4. Patch data is freed from memory, + // and recached if necessary. + // 5. The frame is ready to be drawn! + // stop movie if needs to change renderer if (setrenderneeded && (moviemode != MM_OFF)) M_StopMovie(); - // check for change of screen size (video mode) - if ((setmodeneeded || setrenderneeded) && !wipe) + // check for change of renderer or screen size (video mode) + if ((setrenderneeded || setmodeneeded) && !wipe) + { + if (setrenderneeded) + { + CONS_Debug(DBG_RENDER, "setrenderneeded set (%d)\n", setrenderneeded); + setrenderstillneeded = setrenderneeded; + } SCR_SetMode(); // change video mode + } if (vid.recalc || setrenderstillneeded) SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc() @@ -240,6 +265,9 @@ static void D_Display(void) forcerefresh = true; // force background redraw } + // Jimita + D_CheckRendererState(); + // draw buffered stuff to screen // Used only by linux GGI version I_UpdateNoBlit(); @@ -526,13 +554,26 @@ static void D_Display(void) I_FinishUpdate(); // page flip or blit buffer } - if (needpatchrecache) - R_ReloadHUDGraphics(); - needpatchflush = false; needpatchrecache = false; } +// Jimita: Check the renderer's state +// after a possible renderer switch. +void D_CheckRendererState(void) +{ + // flush all patches from memory + // (also frees memory tagged with PU_CACHE) + // (which are not necessarily patches but I don't care) + if (needpatchflush) + Z_FlushCachedPatches(); + + // some patches have been freed, + // so cache them again + if (needpatchrecache) + R_ReloadHUDGraphics(); +} + // ========================================================================= // D_SRB2Loop // ========================================================================= @@ -580,8 +621,7 @@ void D_SRB2Loop(void) // hack to start on a nice clear console screen. COM_ImmedExecute("cls;version"); - if (rendermode == render_soft) - V_DrawScaledPatch(0, 0, 0, (patch_t *)W_CacheLumpNum(W_GetNumForName("CONSBACK"), PU_CACHE)); + V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_CACHE)); I_FinishUpdate(); // page flip or blit buffer for (;;) @@ -1225,6 +1265,16 @@ void D_SRB2Main(void) // set user default mode or mode set at cmdline SCR_CheckDefaultMode(); + // Jimita: Does the render mode need to change? + if ((setrenderneeded != 0) && (setrenderneeded != rendermode)) + { + needpatchflush = true; + needpatchrecache = true; + VID_CheckRenderer(); + SCR_ChangeRendererCVars(setrenderneeded); + } + D_CheckRendererState(); + wipegamestate = gamestate; savedata.lives = 0; // flag this as not-used diff --git a/src/djgppdos/i_video.c b/src/djgppdos/i_video.c index 6a7641174..15fa0129d 100644 --- a/src/djgppdos/i_video.c +++ b/src/djgppdos/i_video.c @@ -335,3 +335,8 @@ void I_StartupGraphics(void) graphics_started = true; } + +void I_StartupHardwareGraphics(void) +{ + // oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo y +} diff --git a/src/doomdef.h b/src/doomdef.h index 6e7db2143..fbc747980 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -616,4 +616,7 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// SRB2CB itself ported this from PrBoom+ #define NEWCLIP +/// Cache patches in Lua in a way that renderer switching will work flawlessly. +//#define LUA_PATCH_SAFETY + #endif // __DOOMDEF__ diff --git a/src/dummy/i_video.c b/src/dummy/i_video.c index b8f40bed3..fafeee000 100644 --- a/src/dummy/i_video.c +++ b/src/dummy/i_video.c @@ -11,6 +11,7 @@ boolean allow_fullscreen = false; consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; void I_StartupGraphics(void){} +void I_StartupHardwareGraphics(void){} void I_ShutdownGraphics(void){} diff --git a/src/f_finale.c b/src/f_finale.c index e302d24ba..61478cd6f 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1528,29 +1528,8 @@ void F_GameEvaluationTicker(void) #define INFLECTIONPOINT (6*TICRATE) #define SPARKLLOOPTIME 15 // must be odd -void F_StartEnding(void) +static void F_CacheEnding(void) { - G_SetGamestate(GS_ENDING); - wipetypepost = INT16_MAX; - - // Just in case they're open ... somehow - M_ClearMenus(true); - - // Save before the credits sequence. - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0) - G_SaveGame((UINT32)cursaveslot); - - gameaction = ga_nothing; - paused = false; - CON_ToggleOff(); - S_StopMusic(); // todo: placeholder - S_StopSounds(); - - finalecount = -10; // what? this totally isn't a hack. why are you asking? - - memset(sparkloffs, 0, sizeof(INT32)*3*2); - sparklloop = 0; - endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_PATCH); endegrk[0] = W_CachePatchName("ENDEGRK0", PU_PATCH); @@ -1615,6 +1594,43 @@ void F_StartEnding(void) } } +static void F_CacheGoodEnding(void) +{ + endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH); + endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH); + + endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH); + endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH); + + endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH); +} + +void F_StartEnding(void) +{ + G_SetGamestate(GS_ENDING); + wipetypepost = INT16_MAX; + + // Just in case they're open ... somehow + M_ClearMenus(true); + + // Save before the credits sequence. + if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0) + G_SaveGame((UINT32)cursaveslot); + + gameaction = ga_nothing; + paused = false; + CON_ToggleOff(); + S_StopMusic(); // todo: placeholder + S_StopSounds(); + + finalecount = -10; // what? this totally isn't a hack. why are you asking? + + memset(sparkloffs, 0, sizeof(INT32)*3*2); + sparklloop = 0; + + F_CacheEnding(); +} + void F_EndingTicker(void) { if (++finalecount > INFLECTIONPOINT*2) @@ -1625,15 +1641,7 @@ void F_EndingTicker(void) } if (goodending && finalecount == INFLECTIONPOINT) // time to swap some assets - { - endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH); - endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH); - - endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH); - endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH); - - endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH); - } + F_CacheGoodEnding(); if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again { @@ -1652,6 +1660,13 @@ void F_EndingDrawer(void) INT32 x, y, i, j, parallaxticker; patch_t *rockpat; + if (needpatchrecache) + { + F_CacheEnding(); + if (goodending && finalecount >= INFLECTIONPOINT) // time to swap some assets + F_CacheGoodEnding(); + } + if (!goodending || finalecount < INFLECTIONPOINT) rockpat = W_CachePatchName("ROID0000", PU_PATCH); else diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 483932492..00bc70678 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -836,8 +836,10 @@ static INT32 SolveTProblem(void) return 0; CONS_Debug(DBG_RENDER, "Solving T-joins. This may take a while. Please wait...\n"); +#ifdef HWR_LOADING_SCREEN CON_Drawer(); //let the user know what we are doing I_FinishUpdate(); // page flip or blit buffer +#endif numsplitpoly = 0; @@ -964,9 +966,9 @@ void HWR_CreatePlanePolygons(INT32 bspnum) CONS_Debug(DBG_RENDER, "Creating polygons, please wait...\n"); #ifdef HWR_LOADING_SCREEN ls_count = ls_percent = 0; // reset the loading status -#endif CON_Drawer(); //let the user know what we are doing I_FinishUpdate(); // page flip or blit buffer +#endif HWR_ClearPolys(); diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 258e3bb0d..640474c20 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -776,9 +776,18 @@ static void FreeMipmapColormap(INT32 patchnum, void *patch) } } -void HWR_FreeTextureCache(void) +void HWR_FreeColormaps(void) { INT32 i; + + // Alam: free the Z_Blocks before freeing it's users + // free all skin after each level: must be done after pfnClearMipMapCache! + for (i = 0; i < numwadfiles; i++) + M_AATreeIterate(wadfiles[i]->hwrcache, FreeMipmapColormap); +} + +void HWR_FreeTextureCache(void) +{ // free references to the textures HWD.pfnClearMipMapCache(); @@ -787,15 +796,6 @@ void HWR_FreeTextureCache(void) Z_FreeTag(PU_HWRCACHE); Z_FreeTag(PU_HWRCACHE_UNLOCKED); - // Alam: free the Z_Blocks before freeing it's users - - // free all skin after each level: must be done after pfnClearMipMapCache! - // temp fix, idk why this crashes - // is it because the colormaps were already freed anyway? - if (!needpatchrecache) - for (i = 0; i < numwadfiles; i++) - M_AATreeIterate(wadfiles[i]->hwrcache, FreeMipmapColormap); - // now the heap don't have any 'user' pointing to our // texturecache info, we can free it if (gr_textures) @@ -849,6 +849,7 @@ GLTexture_t *HWR_GetTexture(INT32 tex) if ((unsigned)tex >= gr_numtextures) I_Error("HWR_GetTexture: tex >= numtextures\n"); #endif + // Jimita if (needpatchrecache && (!gr_textures)) HWR_PrepLevelCache(gr_numtextures); diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 9656e54e9..e8399fcd8 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -98,6 +98,7 @@ void HWR_FreePolyPool(void); // -------- void HWR_InitTextureCache(void); void HWR_FreeTextureCache(void); +void HWR_FreeColormaps(void); void HWR_FreeExtraSubsectors(void); void HWR_GetFlat(lumpnum_t flatlumpnum); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index ae20ee3ec..217749d64 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6442,13 +6442,18 @@ static void Command_GrStats_f(void) //added by Hurdler: console varibale that are saved void HWR_AddCommands(void) { - CV_RegisterVar(&cv_grrounddown); - CV_RegisterVar(&cv_grfov); - CV_RegisterVar(&cv_grfogdensity); - CV_RegisterVar(&cv_grfiltermode); - CV_RegisterVar(&cv_granisotropicmode); - CV_RegisterVar(&cv_grcorrecttricks); - CV_RegisterVar(&cv_grsolvetjoin); + static boolean alreadycalled = false; + if (!alreadycalled) + { + CV_RegisterVar(&cv_grrounddown); + CV_RegisterVar(&cv_grfov); + CV_RegisterVar(&cv_grfogdensity); + CV_RegisterVar(&cv_grfiltermode); + CV_RegisterVar(&cv_granisotropicmode); + CV_RegisterVar(&cv_grcorrecttricks); + CV_RegisterVar(&cv_grsolvetjoin); + } + alreadycalled = true; } static inline void HWR_AddEngineCommands(void) @@ -6515,6 +6520,7 @@ void HWR_Shutdown(void) HWR_FreeExtraSubsectors(); HWR_FreePolyPool(); HWR_FreeTextureCache(); + HWR_FreeColormaps(); HWD.pfnFlushScreenTextures(); } diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 7f43f858a..2e6d03cd2 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -887,7 +887,7 @@ void HWR_InitMD2(void) } } // no sprite/player skin name found?!? - CONS_Printf("Unknown sprite/player skin %s detected in md2.dat\n", name); + //CONS_Printf("Unknown sprite/player skin %s detected in md2.dat\n", name); md2found: // move on to next line... continue; diff --git a/src/i_video.h b/src/i_video.h index a62f3ff64..c57977306 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -44,6 +44,7 @@ extern boolean highcolor; /** \brief setup video mode */ void I_StartupGraphics(void); +void I_StartupHardwareGraphics(void); /** \brief restore old video mode */ diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 560b73819..1fc47c404 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -36,6 +36,11 @@ static UINT8 hud_enabled[(hud_MAX/8)+1]; static UINT8 hudAvailable; // hud hooks field +#ifdef LUA_PATCH_SAFETY +static patchinfo_t *patchinfo, *patchinfohead; +static int numluapatches; +#endif + // must match enum hud in lua_hud.h static const char *const hud_disable_options[] = { "stagetitle", @@ -248,12 +253,17 @@ static int colormap_get(lua_State *L) static int patch_get(lua_State *L) { +#ifdef LUA_PATCH_SAFETY patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); +#else + patchinfo_t *patch = *((patchinfo_t **)luaL_checkudata(L, 1, META_PATCH)); +#endif enum patch field = luaL_checkoption(L, 2, NULL, patch_opt); // patches are CURRENTLY always valid, expected to be cached with PU_STATIC // this may change in the future, so patch.valid still exists - I_Assert(patch != NULL); + if (!patch) + return LUA_ErrInvalid(L, "patch_t"); switch (field) { @@ -350,8 +360,59 @@ static int libd_patchExists(lua_State *L) static int libd_cachePatch(lua_State *L) { +#ifdef LUA_PATCH_SAFETY + int i; + lumpnum_t lumpnum; + patchinfo_t *luapat; + patch_t *realpatch; + HUDONLY - LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_STATIC), META_PATCH); + + luapat = patchinfohead; + lumpnum = W_CheckNumForName(luaL_checkstring(L, 1)); + if (lumpnum == LUMPERROR) + lumpnum = W_GetNumForName("MISSING"); + + for (i = 0; i < numluapatches; i++) + { + // check if already cached + if (luapat->wadnum == WADFILENUM(lumpnum) && luapat->lumpnum == LUMPNUM(lumpnum)) + { + LUA_PushUserdata(L, luapat, META_PATCH); + return 1; + } + luapat = luapat->next; + if (!luapat) + break; + } + + if (numluapatches > 0) + { + patchinfo->next = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL); + patchinfo = patchinfo->next; + } + else + { + patchinfo = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL); + patchinfohead = patchinfo; + } + + realpatch = W_CachePatchNum(lumpnum, PU_PATCH); + + patchinfo->width = realpatch->width; + patchinfo->height = realpatch->height; + patchinfo->leftoffset = realpatch->leftoffset; + patchinfo->topoffset = realpatch->topoffset; + + patchinfo->wadnum = WADFILENUM(lumpnum); + patchinfo->lumpnum = LUMPNUM(lumpnum); + + LUA_PushUserdata(L, patchinfo, META_PATCH); + numluapatches++; +#else + HUDONLY + LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); +#endif return 1; } @@ -511,12 +572,22 @@ static int libd_draw(lua_State *L) { INT32 x, y, flags; patch_t *patch; +#ifdef LUA_PATCH_SAFETY + patchinfo_t *luapat; +#endif const UINT8 *colormap = NULL; HUDONLY x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); +#ifdef LUA_PATCH_SAFETY + luapat = *((patchinfo_t **)luaL_checkudata(L, 3, META_PATCH)); + patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH); +#else patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH)); + if (!patch) + return LUA_ErrInvalid(L, "patch_t"); +#endif flags = luaL_optinteger(L, 4, 0); if (!lua_isnoneornil(L, 5)) colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP)); @@ -532,6 +603,9 @@ static int libd_drawScaled(lua_State *L) fixed_t x, y, scale; INT32 flags; patch_t *patch; +#ifdef LUA_PATCH_SAFETY + patchinfo_t *luapat; +#endif const UINT8 *colormap = NULL; HUDONLY @@ -540,7 +614,14 @@ static int libd_drawScaled(lua_State *L) scale = luaL_checkinteger(L, 3); if (scale < 0) return luaL_error(L, "negative scale"); +#ifdef LUA_PATCH_SAFETY + luapat = *((patchinfo_t **)luaL_checkudata(L, 4, META_PATCH)); + patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH); +#else patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH)); + if (!patch) + return LUA_ErrInvalid(L, "patch_t"); +#endif flags = luaL_optinteger(L, 5, 0); if (!lua_isnoneornil(L, 6)) colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP)); @@ -930,6 +1011,10 @@ int LUA_HudLib(lua_State *L) { memset(hud_enabled, 0xff, (hud_MAX/8)+1); +#ifdef LUA_PATCH_SAFETY + numluapatches = 0; +#endif + lua_newtable(L); // HUD registry table lua_newtable(L); luaL_register(L, NULL, lib_draw); diff --git a/src/m_menu.c b/src/m_menu.c index d0d2cb1e9..f8d5789b5 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -289,6 +289,7 @@ static void M_ChangeControl(INT32 choice); // Video & Sound menu_t OP_VideoOptionsDef, OP_VideoModeDef, OP_ColorOptionsDef; #ifdef HWRENDER +static void M_OpenGLOptionsMenu(void); menu_t OP_OpenGLOptionsDef, OP_OpenGLFogDef, OP_OpenGLColorDef; #endif menu_t OP_SoundOptionsDef; @@ -1202,7 +1203,7 @@ static menuitem_t OP_VideoOptionsMenu[] = #ifdef HWRENDER {IT_HEADER, NULL, "Renderer", NULL, 200}, - {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 206}, + {IT_CALL|IT_STRING, NULL, "OpenGL Options...", M_OpenGLOptionsMenu, 206}, #endif }; @@ -1950,6 +1951,14 @@ menu_t OP_MonitorToggleDef = }; #ifdef HWRENDER +static void M_OpenGLOptionsMenu(void) +{ + if (rendermode == render_opengl) + M_SetupNextMenu(&OP_OpenGLOptionsDef); + else + M_StartMessage(M_GetText("You must be in OpenGL mode\nto access this menu.\n\n(Press a key)\n"), NULL, MM_NOTHING); +} + menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE( MN_OP_MAIN + (MN_OP_VIDEO << 6) + (MN_OP_OPENGL << 12), "M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 30); @@ -3523,9 +3532,7 @@ void M_Init(void) #ifdef HWRENDER // Permanently hide some options based on render mode - if (rendermode == render_soft) - OP_VideoOptionsMenu[4].status = IT_DISABLED; - else if (rendermode == render_opengl) + if (rendermode == render_opengl) OP_ScreenshotOptionsMenu[op_screenshot_colorprofile].status = IT_GRAYEDOUT; #endif @@ -5647,6 +5654,7 @@ static void M_DrawAddons(void) return; } + // Jimita: Load addons menu patches. if (needpatchrecache) M_LoadAddonsPatches(); diff --git a/src/p_setup.c b/src/p_setup.c index 592ce4d8c..09276f1e8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2955,6 +2955,12 @@ boolean P_SetupLevel(boolean skipprecip) P_SpawnPrecipitation(); #ifdef HWRENDER // not win32 only 19990829 by Kin + // Jimita: Free extrasubsectors regardless of renderer. + // Maybe we're not in OpenGL anymore. + if (extrasubsectors) + free(extrasubsectors); + extrasubsectors = NULL; + // stuff like HWR_CreatePlanePolygons is called there if (rendermode == render_opengl) HWR_SetupLevel(); #endif @@ -3219,7 +3225,9 @@ void HWR_SetupLevel(void) #endif // Correct missing sidedefs & deep water trick HWR_CorrectSWTricks(); - HWR_CreatePlanePolygons((INT32)numnodes - 1); + // Jimita: Don't call this more than once! + if (!extrasubsectors) + HWR_CreatePlanePolygons((INT32)numnodes - 1); } #endif diff --git a/src/r_data.c b/src/r_data.c index d829700b4..484c0e2d4 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -95,8 +95,6 @@ size_t numspritelumps, max_spritelumps; // textures INT32 numtextures = 0; // total number of textures found, -boolean needpatchflush = false; -boolean needpatchrecache = false; // size of following tables texture_t **textures = NULL; @@ -1674,7 +1672,6 @@ lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) ///////////////////// // This code creates the colormap array used by software renderer ///////////////////// - //if (rendermode == render_soft) { double r, g, b, cbrightness; int p; diff --git a/src/r_data.h b/src/r_data.h index a077c1fdc..b6b0a16a1 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -149,7 +149,5 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap); #define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a)) extern INT32 numtextures; -extern boolean needpatchflush; -extern boolean needpatchrecache; #endif diff --git a/src/r_defs.h b/src/r_defs.h index def7b46f3..9a87d76df 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -723,6 +723,7 @@ typedef struct #pragma pack() #endif + typedef enum { SRF_SINGLE = 0, // 0-angle for all rotations @@ -733,6 +734,24 @@ typedef enum SRF_NONE = 0xff // Initial value } spriterotateflags_t; // SRF's up! +// Same as a patch_t, except just the header +// and the wadnum/lumpnum combination that points +// to wherever the patch is in memory. +struct patchinfo_s +{ + INT16 width; // bounding box size + INT16 height; + INT16 leftoffset; // pixels to the left of origin + INT16 topoffset; // pixels below the origin + + UINT16 wadnum; // the software patch lump num for when the patch + UINT16 lumpnum; // was flushed, and we need to re-create it + + // next patchinfo_t in memory + struct patchinfo_s *next; +}; +typedef struct patchinfo_s patchinfo_t; + // // Sprites are patches with a special naming convention so they can be // recognized by R_InitSprites. diff --git a/src/r_main.c b/src/r_main.c index 20e074b82..d1952994c 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1150,9 +1150,11 @@ void R_RenderPlayerView(player_t *player) free(masks); } +// Jimita #ifdef HWRENDER void R_InitHardwareMode(void) { + HWR_AddCommands(); if (gamestate == GS_LEVEL) { HWR_SetupLevel(); @@ -1163,7 +1165,7 @@ void R_InitHardwareMode(void) void R_ReloadHUDGraphics(void) { - W_FlushCachedPatches(); + CONS_Debug(DBG_RENDER, "R_ReloadHUDGraphics()...\n"); ST_LoadGraphics(); HU_LoadGraphics(); ST_ReloadSkinFaceGraphics(); @@ -1239,7 +1241,7 @@ void R_RegisterEngineStuff(void) #endif #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) HWR_AddCommands(); #endif } diff --git a/src/screen.c b/src/screen.c index 33e4dc897..c4c02da04 100644 --- a/src/screen.c +++ b/src/screen.c @@ -60,7 +60,7 @@ void (*twosmultipatchtransfunc)(void); // for cols with transparent pixels AND t // ------------------ viddef_t vid; INT32 setmodeneeded; //video mode change needed if > 0 (the mode number to set + 1) -INT32 setrenderneeded = 0; +UINT8 setrenderneeded = 0; static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, {24, "24 bits"}, {32, "32 bits"}, {0, NULL}}; @@ -70,11 +70,11 @@ consvar_t cv_scr_height = {"scr_height", "800", CV_SAVE, CV_Unsigned, NULL, 0, N consvar_t cv_scr_depth = {"scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static void SCR_ChangeRenderer (void); +static void SCR_ActuallyChangeRenderer(void); static CV_PossibleValue_t cv_renderer_t[] = {{1, "Software"}, {2, "OpenGL"}, {0, NULL}}; -consvar_t cv_renderer = {"renderer", "Software", CV_CALL, cv_renderer_t, SCR_ChangeRenderer, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_renderer = {"renderer", "Software", CV_SAVE|CV_CALL, cv_renderer_t, SCR_ChangeRenderer, 0, NULL, NULL, 0, 0, NULL}; -static void SCR_ChangeFullscreen (void); +static void SCR_ChangeFullscreen(void); consvar_t cv_fullscreen = {"fullscreen", "Yes", CV_SAVE|CV_CALL, CV_YesNo, SCR_ChangeFullscreen, 0, NULL, NULL, 0, 0, NULL}; @@ -170,6 +170,7 @@ void SCR_SetMode(void) if (!(setmodeneeded || setrenderneeded) || WipeInAction) return; // should never happen and don't change it during a wipe, BAD! + // Jimita if (setrenderneeded) { needpatchflush = true; @@ -374,6 +375,8 @@ void SCR_CheckDefaultMode(void) // see note above setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; } + + SCR_ActuallyChangeRenderer(); } // sets the modenum as the new default video mode to be saved in the config file @@ -403,27 +406,47 @@ void SCR_ChangeFullscreen(void) #endif } +static int target_renderer = 0; + +void SCR_ActuallyChangeRenderer(void) +{ + setrenderneeded = target_renderer; + // setting the same renderer twice WILL crash your game, so let's not, please + if (rendermode == setrenderneeded) + setrenderneeded = 0; +} + +// Jimita void SCR_ChangeRenderer(void) { setrenderneeded = 0; if (con_startup) { - if (rendermode == render_soft) - CV_StealthSetValue(&cv_renderer, 1); - else if (rendermode == render_opengl) - CV_StealthSetValue(&cv_renderer, 2); + target_renderer = cv_renderer.value; + if (M_CheckParm("-opengl")) + target_renderer = rendermode = render_opengl; + else if (M_CheckParm("-software")) + target_renderer = rendermode = render_soft; + // set cv_renderer back + SCR_ChangeRendererCVars(rendermode); return; } if (cv_renderer.value == 1) - setrenderneeded = render_soft; + target_renderer = render_soft; else if (cv_renderer.value == 2) - setrenderneeded = render_opengl; + target_renderer = render_opengl; + SCR_ActuallyChangeRenderer(); +} - // setting the same renderer twice WILL crash your game, so let's not, please - if (rendermode == setrenderneeded) - setrenderneeded = 0; +void SCR_ChangeRendererCVars(INT32 mode) +{ + // set cv_renderer back + if (mode == render_soft) + CV_StealthSetValue(&cv_renderer, 1); + else if (mode == render_opengl) + CV_StealthSetValue(&cv_renderer, 2); } boolean SCR_IsAspectCorrect(INT32 width, INT32 height) diff --git a/src/screen.h b/src/screen.h index 6f8b02bae..a70fbe69d 100644 --- a/src/screen.h +++ b/src/screen.h @@ -144,7 +144,10 @@ extern boolean R_SSE2; // ---------------- extern viddef_t vid; extern INT32 setmodeneeded; // mode number to set if needed, or 0 -extern INT32 setrenderneeded; + +void SCR_ChangeRenderer(void); +void SCR_ChangeRendererCVars(INT32 mode); +extern UINT8 setrenderneeded; extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index c8f4fdc31..e442a36d5 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -170,7 +170,6 @@ static void Impl_VideoSetupBuffer(void); static SDL_bool Impl_CreateWindow(SDL_bool fullscreen); //static void Impl_SetWindowName(const char *title); static void Impl_SetWindowIcon(void); -static void I_StartupGraphicsGL(void); static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen) { @@ -1263,12 +1262,7 @@ void VID_PrepareModeList(void) #endif } -// SOMETIME IN -// THE FUTURE -// WHEN I ACTUALLY RENDER -// THIS FRAME -static int renderflags; -static SDL_bool Impl_CreateContext(int flags) +static SDL_bool Impl_CreateContext(void) { // Renderer-specific stuff #ifdef HWRENDER @@ -1287,7 +1281,7 @@ static SDL_bool Impl_CreateContext(int flags) #endif if (rendermode == render_soft) { - flags = 0; // Use this to set SDL_RENDERER_* flags now + int flags = 0; // Use this to set SDL_RENDERER_* flags now if (usesdl2soft) flags |= SDL_RENDERER_SOFTWARE; else if (cv_vidwait.value) @@ -1307,17 +1301,13 @@ static SDL_bool Impl_CreateContext(int flags) void VID_CheckRenderer(void) { + if (dedicated) + return; + if (setrenderneeded) { rendermode = setrenderneeded; - Impl_CreateContext(renderflags); - if (rendermode == render_soft) - { -#ifdef HWRENDER - HWR_FreeTextureCache(); -#endif - SCR_SetDrawFuncs(); - } + Impl_CreateContext(); } SDLSetMode(vid.width, vid.height, USE_FULLSCREEN); @@ -1330,12 +1320,18 @@ void VID_CheckRenderer(void) bufSurface = NULL; } Impl_VideoSetupBuffer(); +#ifdef HWRENDER + HWR_FreeTextureCache(); +#endif + SCR_SetDrawFuncs(); } +#ifdef HWRENDER else if (rendermode == render_opengl) { - I_StartupGraphicsGL(); + I_StartupHardwareGraphics(); R_InitHardwareMode(); } +#endif } INT32 VID_SetMode(INT32 modeNum) @@ -1345,29 +1341,15 @@ INT32 VID_SetMode(INT32 modeNum) vid.recalc = 1; vid.bpp = 1; - if (modeNum >= 0 && modeNum < MAXWINMODES) - { - vid.width = windowedModes[modeNum][0]; - vid.height = windowedModes[modeNum][1]; - vid.modenum = modeNum; - } - else - { - // just set the desktop resolution as a fallback - SDL_DisplayMode mode; - SDL_GetWindowDisplayMode(window, &mode); - if (mode.w >= 2048) - { - vid.width = 1920; - vid.height = 1200; - } - else - { - vid.width = mode.w; - vid.height = mode.h; - } - vid.modenum = -1; - } + if (modeNum < 0) + modeNum = 0; + if (modeNum >= MAXWINMODES) + modeNum = MAXWINMODES-1; + + vid.width = windowedModes[modeNum][0]; + vid.height = windowedModes[modeNum][1]; + vid.modenum = modeNum; + //Impl_SetWindowName("SRB2 "VERSIONSTRING); VID_CheckRenderer(); return SDL_TRUE; @@ -1390,8 +1372,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) flags |= SDL_WINDOW_BORDERLESS; #ifdef HWRENDER - if (rendermode == render_opengl) - flags |= SDL_WINDOW_OPENGL; + flags |= SDL_WINDOW_OPENGL; #endif // Create a window @@ -1404,8 +1385,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) return SDL_FALSE; } - renderflags = flags; - return Impl_CreateContext(flags); + return Impl_CreateContext(); } /* @@ -1474,51 +1454,6 @@ static void Impl_VideoSetupBuffer(void) } } -static void I_StartupGraphicsGL(void) -{ -#ifdef HWRENDER - static boolean glstartup = false; - if (!glstartup) - { - HWD.pfnInit = hwSym("Init",NULL); - HWD.pfnFinishUpdate = NULL; - HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); - HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); - HWD.pfnSetBlend = hwSym("SetBlend",NULL); - HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); - HWD.pfnSetTexture = hwSym("SetTexture",NULL); - HWD.pfnReadRect = hwSym("ReadRect",NULL); - HWD.pfnGClipRect = hwSym("GClipRect",NULL); - HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); - HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); - HWD.pfnSetPalette = hwSym("SetPalette",NULL); - HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); - HWD.pfnDrawMD2 = hwSym("DrawMD2",NULL); - HWD.pfnDrawMD2i = hwSym("DrawMD2i",NULL); - HWD.pfnSetTransform = hwSym("SetTransform",NULL); - HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); -#ifdef SHUFFLE - HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); -#endif - HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); - HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); - HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); - HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); - HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL); - HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); - HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); - HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); - // check gl renderer lib - if (HWD.pfnGetRenderVersion() != VERSION) - I_Error("%s", M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n")); - if (!HWD.pfnInit(I_Error)) // let load the OpenGL library - rendermode = render_soft; - else - glstartup = true; - } -#endif -} - void I_StartupGraphics(void) { if (dedicated) @@ -1560,9 +1495,11 @@ void I_StartupGraphics(void) framebuffer = SDL_TRUE; } +#ifdef HWRENDER if (M_CheckParm("-opengl")) rendermode = render_opengl; else if (M_CheckParm("software")) +#endif rendermode = render_soft; usesdl2soft = M_CheckParm("-softblit"); @@ -1571,7 +1508,7 @@ void I_StartupGraphics(void) //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2); VID_Command_ModeList_f(); #ifdef HWRENDER - I_StartupGraphicsGL(); + I_StartupHardwareGraphics(); #endif // Fury: we do window initialization after GL setup to allow @@ -1631,6 +1568,51 @@ void I_StartupGraphics(void) graphics_started = true; } +void I_StartupHardwareGraphics(void) +{ +#ifdef HWRENDER + static boolean glstartup = false; + if (!glstartup) + { + HWD.pfnInit = hwSym("Init",NULL); + HWD.pfnFinishUpdate = NULL; + HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); + HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); + HWD.pfnSetBlend = hwSym("SetBlend",NULL); + HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); + HWD.pfnSetTexture = hwSym("SetTexture",NULL); + HWD.pfnReadRect = hwSym("ReadRect",NULL); + HWD.pfnGClipRect = hwSym("GClipRect",NULL); + HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); + HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); + HWD.pfnSetPalette = hwSym("SetPalette",NULL); + HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); + HWD.pfnDrawMD2 = hwSym("DrawMD2",NULL); + HWD.pfnDrawMD2i = hwSym("DrawMD2i",NULL); + HWD.pfnSetTransform = hwSym("SetTransform",NULL); + HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL); +#ifdef SHUFFLE + HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); +#endif + HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); + HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); + HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); + HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); + HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL); + HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); + HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); + HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); + // check gl renderer lib + if (HWD.pfnGetRenderVersion() != VERSION) + I_Error("%s", M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n")); + if (!HWD.pfnInit(I_Error)) // let load the OpenGL library + rendermode = render_soft; + else + glstartup = true; + } +#endif +} + void I_ShutdownGraphics(void) { const rendermode_t oldrendermode = rendermode; diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index 38be7a6b8..83be8d827 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -239,6 +239,11 @@ void I_StartupGraphics(void) if (!dedicated) graphics_started = true; } +void I_StartupHardwareGraphics(void) +{ + // oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo y +} + // ------------------ // I_ShutdownGraphics // Close the screen, restore previous video mode. diff --git a/src/y_inter.c b/src/y_inter.c index 632cf8795..5bc911c3f 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -144,6 +144,7 @@ static patch_t *interpic = NULL; // custom picture defined in map header static boolean usetile; boolean usebuffer = false; static boolean useinterpic; +static boolean safetorender = true; static INT32 timer; static INT32 intertic; @@ -159,6 +160,7 @@ static void Y_CalculateTimeRaceWinners(void); static void Y_CalculateMatchWinners(void); static void Y_FollowIntermission(void); static void Y_UnloadData(void); +static void Y_CleanupData(void); // Stuff copy+pasted from st_stuff.c #define ST_DrawNumFromHud(h,n) V_DrawTallNum(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f, n) @@ -220,31 +222,41 @@ void Y_IntermissionDrawer(void) if (intertype == int_none || rendermode == render_none) return; - if (!usebuffer) + // Jimita + if (needpatchrecache) + { + Y_CleanupData(); + safetorender = false; + } + + if (!usebuffer || !safetorender) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - if (useinterpic) - V_DrawScaledPatch(0, 0, 0, interpic); - else if (!usetile) + if (safetorender) { - if (rendermode == render_soft && usebuffer) - VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); + if (useinterpic) + V_DrawScaledPatch(0, 0, 0, interpic); + else if (!usetile) + { + if (rendermode == render_soft && usebuffer) + VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); #ifdef HWRENDER - else if(rendermode != render_soft && usebuffer) - { - HWR_DrawIntermissionBG(); - } + else if(rendermode != render_soft && usebuffer) + { + HWR_DrawIntermissionBG(); + } #endif - else - { - if (widebgpatch && rendermode == render_soft && vid.width / vid.dupx == 400) - V_DrawScaledPatch(0, 0, V_SNAPTOLEFT, widebgpatch); else - V_DrawScaledPatch(0, 0, 0, bgpatch); + { + if (widebgpatch && rendermode == render_soft && vid.width / vid.dupx == 400) + V_DrawScaledPatch(0, 0, V_SNAPTOLEFT, widebgpatch); + else + V_DrawScaledPatch(0, 0, 0, bgpatch); + } } + else + V_DrawPatchFill(bgtile); } - else - V_DrawPatchFill(bgtile); if (intertype == int_coop) { @@ -293,14 +305,17 @@ void Y_IntermissionDrawer(void) bonusy = 150; // Total - V_DrawScaledPatch(152, bonusy, 0, data.coop.ptotal); - V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.total); + if (safetorender) + { + V_DrawScaledPatch(152, bonusy, 0, data.coop.ptotal); + V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.total); + } bonusy -= (3*SHORT(tallnum[0]->height)/2) + 1; // Draw bonuses for (i = 3; i >= 0; --i) { - if (data.coop.bonuses[i].display) + if (data.coop.bonuses[i].display && safetorender) { V_DrawScaledPatch(152, bonusy, 0, data.coop.bonuspatches[i]); V_DrawTallNum(BASEVIDWIDTH - 68, bonusy + 1, 0, data.coop.bonuses[i].points); @@ -516,7 +531,8 @@ void Y_IntermissionDrawer(void) char strtime[10]; // draw the header - V_DrawScaledPatch(112, 2, 0, data.match.result); + if (safetorender) + V_DrawScaledPatch(112, 2, 0, data.match.result); // draw the level name V_DrawCenteredString(BASEVIDWIDTH/2, 20, 0, data.match.levelstring); @@ -1126,6 +1142,8 @@ void Y_StartIntermission(void) I_Error("endtic is dirty"); #endif + safetorender = true; + if (!multiplayer) { timer = 0; @@ -1350,7 +1368,7 @@ void Y_StartIntermission(void) data.spec.cemerald = W_CachePatchName("GOTEMALL", PU_PATCH); data.spec.headx = 70; data.spec.nowsuper = players[consoleplayer].skin - ? NULL : W_CachePatchName("NOWSUPER", PU_STATIC); + ? NULL : W_CachePatchName("NOWSUPER", PU_PATCH); } else { @@ -2077,7 +2095,8 @@ static void Y_FollowIntermission(void) G_AfterIntermission(); } -#define UNLOAD(x) Z_ChangeTag(x, PU_CACHE); x = NULL +#define UNLOAD(x) if (x) {Z_ChangeTag(x, PU_CACHE);} x = NULL; +#define CLEANUP(x) x = NULL; // // Y_UnloadData @@ -2128,5 +2147,47 @@ static void Y_UnloadData(void) //are not handled break; } - +} + +static void Y_CleanupData(void) +{ + // unload the background patches + CLEANUP(bgpatch); + CLEANUP(widebgpatch); + CLEANUP(bgtile); + CLEANUP(interpic); + + switch (intertype) + { + case int_coop: + // unload the coop and single player patches + CLEANUP(data.coop.bonuspatches[3]); + CLEANUP(data.coop.bonuspatches[2]); + CLEANUP(data.coop.bonuspatches[1]); + CLEANUP(data.coop.bonuspatches[0]); + CLEANUP(data.coop.ptotal); + break; + case int_spec: + // unload the special stage patches + //CLEANUP(data.spec.cemerald); + //CLEANUP(data.spec.nowsuper); + CLEANUP(data.spec.bonuspatches[1]); + CLEANUP(data.spec.bonuspatches[0]); + CLEANUP(data.spec.pscore); + CLEANUP(data.spec.pcontinues); + break; + case int_match: + case int_race: + CLEANUP(data.match.result); + break; + case int_ctf: + CLEANUP(data.match.blueflag); + CLEANUP(data.match.redflag); + break; + default: + //without this default, + //int_none, int_tag, int_chaos, and int_classicrace + //are not handled + break; + } } diff --git a/src/z_zone.c b/src/z_zone.c index 001c69bb3..e0ed1b296 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -490,6 +490,38 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) // Utility functions // ----------------- +// for renderer switching, free a bunch of stuff +boolean needpatchflush = false; +boolean needpatchrecache = false; + +// flush all patches from memory +// (also frees memory tagged with PU_CACHE) +// (which are not necessarily patches but I don't care) +void Z_FlushCachedPatches(void) +{ + CONS_Debug(DBG_RENDER, "Z_FlushCachedPatches()...\n"); + Z_FreeTag(PU_CACHE); + Z_FreeTag(PU_PATCH); + Z_FreeTag(PU_HUDGFX); + Z_FreeTag(PU_HWRPATCHINFO); + Z_FreeTag(PU_HWRPATCHCOLMIPMAP); + Z_FreeTag(PU_HWRCACHE); + Z_FreeTag(PU_HWRCACHE_UNLOCKED); + Z_FreeTag(PU_HWRPATCHINFO_UNLOCKED); +} + +// +// Z_CheckMemCleanup +// +// TODO: Currently blocks >= PU_PURGELEVEL are freed every +// CLEANUPCOUNT. It might be better to keep track of +// the total size of all purgable memory and free it when the +// size exceeds some value. +// +// This was in Z_Malloc, but was freeing data at +// unsafe times. Now it is only called when it is safe +// to cleanup memory. + // starting value of nextcleanup #define CLEANUPCOUNT 2000 diff --git a/src/z_zone.h b/src/z_zone.h index af8ca1241..15c7b8ad3 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -142,4 +142,9 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag); char *Z_StrDup(const char *in); #define Z_Unlock(p) (void)p // TODO: remove this now that NDS code has been removed +// For renderer switching +extern boolean needpatchflush; +extern boolean needpatchrecache; +void Z_FlushCachedPatches(void); + #endif